Generating Man Pages for Your Own Bash Scripts: pandoc, help2man and Installation
AI generated
$_
#!/
Bash · Documentation · CLI Tooling · man
Generating Man Pages for Your Own Bash Scripts
Build a real man page from Markdown or --help text with pandoc or help2man

A --help text disappears the moment the terminal closes, while a man page stays behind as a searchable document in the system, reachable through man at any time. With pandoc converting a Markdown document, or help2man building directly from the --help output, that gap closes for a homegrown Bash script without any manual troff work.

17 min read pandoc · help2man · troff MANPATH · /usr/local/share/man

1. Why a real man page looks more professional than just --help

A --help flag only answers what is useful in this particular terminal window right now, and it disappears from view once the screen scrolls or the window closes. A man page, by contrast, is a standalone document reachable system-wide through man toolname, searchable, and in the same category as the documentation for grep, tar or ssh, which instantly gives a homegrown tool the appearance of a full-fledged system utility.

For users, an existing man page also signals that a tool is taken seriously and maintained, because writing structured documentation takes effort a plain --help flag does not demand. Whoever hands an internal tool off to a larger team, or releases it as an open source project, gains noticeable credibility with a man page, without the tool's core function changing at all.

2. Structure of a man page: the standard sections

Every man page follows a fixed convention of sections, starting with NAME, a one-line description, followed by SYNOPSIS, the compact call syntax with square brackets for optional arguments. Then comes DESCRIPTION with the actual body text, OPTIONS explaining each flag individually, and optionally EXAMPLES, FILES, EXIT STATUS and SEE ALSO for related commands.

This structure is not an end in itself but a convention grown over decades that Unix users are accustomed to: whoever looks for what an option means instinctively flips to OPTIONS, whoever looks for the correct invocation flips to SYNOPSIS. A homegrown man page that sticks to this order is instantly navigable without any explanation.

3. Choosing a source: structured comment block or Markdown

Before the actual man page exists, it needs a source to be generated from, rather than being written raw in troff syntax. Two approaches have become established: a structured comment block at the top of the Bash script itself, from which help2man builds a man page together with the --help output, or a separate Markdown document that pandoc converts directly into man format.

The comment-block approach has the advantage of keeping documentation and code in the same file, so a change to an option can hardly be forgotten without also updating the docs. The separate Markdown document, on the other hand, fits more extensive documentation with many examples better, since Markdown is considerably nicer to write and version than a comment block full of escape characters.

4. Generating a man page from Markdown with pandoc

pandoc converts between an impressive number of document formats, including from Markdown into man format, as long as the Markdown file starts with a YAML frontmatter supplying the title, section number and date for the man header. The actual content sections get written as normal Markdown headings, ## SYNOPSIS, ## OPTIONS and so on, which pandoc automatically translates into the matching troff macros.

The call pandoc mstool.1.md -s -t man -o mstool.1 turns the Markdown source into a finished man page that can immediately be tested locally with man ./mstool.1 before installation. This workflow fits especially well for tools whose documentation is already maintained as Markdown in the repository, since the same source then serves both GitHub rendering and the man page.


---
title: MSTOOL
section: 1
date: August 2026
---

# NAME

mstool - deploy and manage mironsoft services

# SYNOPSIS

**mstool** [**-h**|**--help**] *COMMAND* [*ARGS*...]

# DESCRIPTION

mstool automates deployment, log inspection and rollback for
mironsoft's internal services across staging and production.

# OPTIONS

**-h**, **--help**
: Show usage information and exit.

**--env** *ENVIRONMENT*
: Target environment, one of staging, production, local.

# EXAMPLES

mstool deploy --env staging
: Deploy the current build to the staging environment.

# SEE ALSO

**docker**(1), **aws**(1)

5. Generating automatically from --help and --version with help2man

help2man takes a different approach: instead of maintaining a separate source file, it calls the script itself with --help and --version and builds a man page from that automatically, sorted into the standard sections. That works surprisingly reliably as long as the --help output follows a recognizable structure, for instance a Usage: line followed by indented option descriptions.

The advantage over the Markdown approach is that documentation and actual behavior can practically never drift apart, because the man page gets freshly generated from the live --help output on every run. Extra sections like detailed examples or a SEE ALSO can be fed in through a supplementary .h2m file that help2man inserts at the right spot.


#!/usr/bin/env bash
set -euo pipefail

# mstool must properly support --help and --version before help2man runs
help2man \
  --name="deploy and manage mironsoft services" \
  --section=1 \
  --no-info \
  --output=mstool.1 \
  ./mstool

man ./mstool.1  # check locally before installing

6. Understanding troff/groff basics for writing manually

Both pandoc and help2man produce files in troff format with the man macro package behind the scenes, where section headings are marked with .SH, bold terms with .B and italic terms with .I. For most use cases this format never needs to be touched by hand, but a rough understanding helps when a generated file needs targeted manual adjustment, for instance inserting one extra paragraph.

Whoever wants to write a man page entirely by hand, for instance because neither pandoc nor help2man is available, cannot avoid the basic troff macros: .TH for the header with title and section number, .SH for every main section, and .PP for new paragraphs. For a single internal tool that effort rarely pays off though, when pandoc or help2man can generate the same file automatically.

7. Installing under /usr/local/share/man and MANPATH

Homegrown man pages that are not distributed through a distribution's package manager conventionally belong in /usr/local/share/man/man1/ for section-1 commands, named following the pattern toolname.1. On most Linux distributions that directory is already part of MANPATH by default, so man toolname works immediately without users having to adjust their shell configuration.

If the directory is missing from MANPATH on a minimal system, manpath shows the currently searched directories, and an entry can be added through the MANPATH environment variable or the /etc/man_db.conf file. After copying the file, mandb or makewhatis should be run so the new page also becomes discoverable through man -k.


#!/usr/bin/env bash
set -euo pipefail

readonly DEST_DIR="/usr/local/share/man/man1"
sudo mkdir -p "$DEST_DIR"
sudo install -m 644 mstool.1 "${DEST_DIR}/mstool.1"

# Update the man database so man -k finds mstool
sudo mandb -q 2>/dev/null || sudo makewhatis "$DEST_DIR" 2>/dev/null || true

man mstool

8. Integrating into packaging and a Makefile

So the man page never needs manual installation on every deployment, its generation and installation belong in the same Makefile or build script that also builds and installs the actual tool. An make install target that copies both the executable script to /usr/local/bin/ and the man page to /usr/local/share/man/man1/ keeps both artifacts in sync with the same version.

For distribution through a real package format like .deb, the packaging tool itself takes care of correctly placing the man page and automatically calls mandb after installation, so no manual follow-up is needed from the end user.


# Makefile excerpt
PREFIX ?= /usr/local

.PHONY: install
install: mstool.1
	install -Dm755 mstool $(PREFIX)/bin/mstool
	install -Dm644 mstool.1 $(PREFIX)/share/man/man1/mstool.1
	mandb -q 2>/dev/null || true

mstool.1: mstool.1.md
	pandoc mstool.1.md -s -t man -o mstool.1

9. Maintenance: keeping the man page in sync with --help

A man page that gets forgotten when a new option is added is worse than no man page at all, because it actively spreads wrong information and misleads users. The help2man approach solves this structurally, since the man page gets freshly built from the current --help output on every build and therefore cannot go stale, as long as the build step is part of the release pipeline.

With the pandoc approach and a separate Markdown source, a simple CI check helps by comparing the options listed in --help against the options documented in the Markdown file, failing the build when a new option was added without a matching documentation entry. That one automated check prevents the most common cause of stale documentation more reliably than any manual reminder in a pull request review.

Approach Source Freshness Recommendation
pandoc from Markdown Separate .md document Keep in sync manually or via CI check Extensive docs with many examples
help2man from --help Live --help output Always current on every build Fast, automatically synced man page
Manual troff/groff Direct .TH/.SH syntax Only as fresh as last maintained Rarely worth it for a single tool
No man page, just --help No extra artifact Always current, but not discoverable system-wide Only for very small, internal scripts

Mironsoft

Shell automation, DevOps tooling and deployment infrastructure

Shell scripts that hold up in production?

We review existing Bash scripts, spot fragile patterns and replace them with robust Bash patterns: complete error handling, logging and safe parallelization for your deployment stack.

Code Review

ShellCheck analysis and manual review for critical Bash pattern violations.

Refactoring

Retrofitting error handling, logging and safe file operations.

CI Integration

Wiring ShellCheck and BATS into pipelines and building regression tests.

10. Summary

Man Pages for Your Own Bash Scripts: The Essentials at a Glance

Core idea

A man page stays discoverable system-wide through man toolname, while --help is only visible in the current terminal.

The pandoc route

Markdown document with YAML frontmatter, converted with pandoc -s -t man, good for extensive documentation.

The help2man route

Builds the man page automatically from --help and --version, staying structurally in sync with the tool at all times.

Installation

Copy to /usr/local/share/man/man1/toolname.1 and update mandb so man -k finds the tool.

11. FAQ: Man Pages for Your Own Bash Scripts: The Essentials at a Glance

1Why isn't --help enough documentation on its own?
--help is only visible in the current terminal and disappears afterward. A man page is permanently and searchably available system-wide through man toolname, just like any standard Unix command.
2What are the most important sections of a man page?
NAME, SYNOPSIS, DESCRIPTION and OPTIONS are required. EXAMPLES, FILES, EXIT STATUS and SEE ALSO are optional but common and helpful.
3What is the difference between pandoc and help2man?
pandoc converts a separately maintained Markdown document into man format. help2man automatically generates the man page from the tool's own --help and --version output.
4Which approach keeps the documentation more current?
help2man, because the man page is freshly built from the live --help output on every build. With the pandoc approach, an extra check is needed to keep docs and code in sync.
5Do I need to learn troff syntax to write a man page?
No, not if pandoc or help2man handle the conversion. A rough understanding of .SH and .TH helps, though, for targeted manual edits to generated files when needed.
6Where do I install a homegrown man page?
To /usr/local/share/man/man1/toolname.1 for section-1 commands. That directory is already part of MANPATH on most distributions.
7Why does man toolname sometimes not work immediately after installation?
Because the man database has not been updated yet. Running mandb or makewhatis after installation also makes the new page discoverable through man -k.
8How do I keep the man page in sync with the code in a Markdown workflow?
With a CI check that compares the options listed in --help against the options documented in the Markdown file and fails the build on any mismatch.
9Can I integrate man page generation into a Makefile?
Yes. An install target that calls pandoc or help2man and copies the result straight to /usr/local/share/man/man1/ keeps the tool and its documentation in sync on every build.
10Is a man page worth it for a very small internal script?
Not always. For a script with one or two options used by a handful of people, a good --help text is often enough. As user count or option count grows, switching over pays off.