Man-page layout¶
Unix tools are conventionally documented with the section layout of man-pages(7): a one-line NAME, a SYNOPSIS, a prose DESCRIPTION, an itemized OPTIONS list, then ENVIRONMENT, FILES, and EXIT STATUS. A Click Extra command already carries everything those sections need. This page documents one small CLI top-to-bottom in that order, with each section backed by output rendered live from the running command.
from click_extra import Choice, argument, command, echo, option
@command(context_settings={"show_envvar": True})
@argument("city", help="Name of the city to report on.")
@option(
"--units",
type=Choice(["celsius", "fahrenheit"]),
default="celsius",
help="Temperature scale to display.",
)
def weather(city, units):
"""Report the current temperature for a city."""
echo(f"{city}: 21 degrees {units}.")
NAME¶
A man page opens with a single name - one-line description line, the one apropos and whatis index. Click has no dedicated slot for it: the equivalent is the program name paired with the first line of the command’s docstring, which Click also uses as the command’s short help. For this CLI the pairing reads:
weather - report the current temperature for a city
SYNOPSIS¶
The Usage: line is the synopsis. Click Extra styles its tokens along the same typographic split a man page draws between bold literal text and italic replaceable text, documented in literal and replaceable slots: the literal command name weather against the replaceable CITY operand and the [OPTIONS] placeholder.
Click prints the synopsis as the first line of the help screen. The rest of that screen, dissected in the two sections below, supplies the DESCRIPTION and the OPTIONS list:
$ weather --help
Usage: weather [OPTIONS] CITY
Report the current temperature for a city.
Positional arguments:
CITY Name of the city to report on.
Options:
--units [celsius|fahrenheit] Temperature scale to display. [env var:
WEATHER_UNITS; default: celsius]
--time / --no-time Measure and print elapsed execution time. [env
var: WEATHER_TIME; default: no-time]
--config CONFIG_PATH Location of the configuration file. Supports
local path with glob patterns or remote URL.
[env var: WEATHER_CONFIG; default: ~/.config/wea
ther/{*.toml,*.yaml,*.yml,*.json,*.json5,*.jsonc
,*.hjson,*.ini,*.xml,pyproject.toml}]
--no-config Ignore all configuration files and only use
command line parameters and environment
variables. [env var: WEATHER_CONFIG]
--validate-config FILE Validate the configuration file and exit. [env
var: WEATHER_VALIDATE_CONFIG]
--color, --ansi / --no-color, --no-ansi
Strip out all colors and all ANSI codes from
output. [env var: WEATHER_COLOR; default:
color]
--theme [dark|dracula|light|manpage|monokai|nord|solarized_dark]
Color theme used for help screens. [env var:
WEATHER_THEME; default: dark]
--show-params Show all CLI parameters, their provenance,
defaults and value, then exit. [env var:
WEATHER_SHOW_PARAMS]
--table-format [aligned|asciidoc|colon-grid|csv|csv-excel|csv-excel-tab|csv-unix|double-grid|double-outline|fancy-grid|fancy-outline|github|grid|heavy-grid|heavy-outline|hjson|html|jira|json|json5|jsonc|latex|latex-booktabs|latex-longtable|latex-raw|mediawiki|mixed-grid|mixed-outline|moinmoin|orgtbl|outline|pipe|plain|presto|pretty|psql|rounded-grid|rounded-outline|rst|simple|simple-grid|simple-outline|textile|toml|tsv|unsafehtml|vertical|xml|yaml|youtrack]
Rendering style of tables. [env var:
WEATHER_TABLE_FORMAT; default: rounded-outline]
--verbosity LEVEL Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
[env var: WEATHER_VERBOSITY; default: WARNING]
-v, --verbose Increase the default WARNING verbosity by one
level for each additional repetition of the
option. [env var: WEATHER_VERBOSE; default: 0]
--version Show the version and exit. [env var:
WEATHER_VERSION]
-h, --help Show this message and exit.
DESCRIPTION¶
The DESCRIPTION explains what the program does and, in prose, what its operands mean. Click Extra sources it from the command’s docstring, rendered just under the synopsis above: “Report the current temperature for a city.” The CITY operand is the city to report on.
When an argument carries a help= string, Click Extra also itemizes operands in a dedicated Positional arguments: block (the CITY entry above). That is a structured take on operands that goes beyond what man-pages(7) prescribes, which keeps their meaning in the prose description rather than in a list.
OPTIONS¶
The OPTIONS section is the formal, per-item description of each option, rendered as the Options: block above. Every entry pairs the option’s literal name (--units) and its replaceable metavar ([celsius|fahrenheit]) with the help text and a trailing bracket field carrying the option’s environment variable and default. Click Extra injects its own options into the same list (--config, --verbosity, --version, --help, …), so a CLI built on it gets a complete, conventional options section without extra work.
ENVIRONMENT¶
The ENVIRONMENT section lists the variables that change the program’s behavior. Click Extra derives one per option from the command name (the WEATHER_ prefix here) and surfaces it in the help screen’s bracket field ([env var: WEATHER_UNITS; …] above) when show_envvar is enabled. The variable is live: setting it feeds the option, ranked below the command line but above the default in the precedence chain.
$ export WEATHER_UNITS=fahrenheit
$ weather Paris
Paris: 21 degrees fahrenheit.
--show-params prints the full mapping at once: every parameter, the environment variable it reads, its default, its resolved value, and the source that value came from.
$ weather --show-params
╭─────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬─────────────────────────────────────────┬──────────────────────────────────┬─────────────┬────────┬─────────┬──────────────────┬─────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬─────────────╮
│ ID │ Spec. │ Class │ Param type │ Python type │ Hidden │ Exposed │ Allowed in conf? │ Env. vars. │ Default │ Value │ Source │
├─────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────┼──────────────────────────────────┼─────────────┼────────┼─────────┼──────────────────┼─────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────────┤
│ weather.city │ │ click_extra.parameters.Argument │ click.types.StringParamType │ str │ │ ✓ │ ✓ │ │ Sentinel.UNSET │ Sentinel.UNSET │ DEFAULT │
│ weather.color │ --color, --ansi / --no-color, --no-ansi │ click_extra.colorize.ColorOption │ click.types.BoolParamType │ bool │ ✘ │ ✘ │ ✓ │ WEATHER_COLOR │ True │ True │ DEFAULT │
│ weather.config │ --config CONFIG_PATH │ click_extra.config.ConfigOption │ click.types.UnprocessedParamType │ str │ ✘ │ ✘ │ ✘ │ WEATHER_CONFIG │ '/home/runner/.config/weather/{*.toml,*.yaml,*.yml,*.json,*.json5,*.jsonc,*.hjson,*.ini,*.xml,pyproject.toml}' │ '/home/runner/.config/weather/{*.toml,*.yaml,*.yml,*.json,*.json5,*.jsonc,*.hjson,*.ini,*.xml,pyproject.toml}' │ DEFAULT │
│ weather.config │ --no-config │ click_extra.config.NoConfigOption │ click.types.UnprocessedParamType │ str │ ✘ │ ✘ │ ✘ │ WEATHER_CONFIG │ Sentinel.UNSET │ Sentinel.UNSET │ DEFAULT │
│ weather.help │ -h, --help │ click.core.Option │ click.types.BoolParamType │ bool │ ✘ │ ✘ │ ✘ │ WEATHER_HELP │ False │ False │ DEFAULT │
│ weather.show_params │ --show-params │ click_extra.parameters.ShowParamsOption │ click.types.BoolParamType │ bool │ ✘ │ ✘ │ ✘ │ WEATHER_SHOW_PARAMS │ False │ True │ COMMANDLINE │
│ weather.table_format │ --table-format [aligned|asciidoc|colon-grid|csv|csv-excel|csv-excel-tab|csv-unix|double-grid|double-outline|fancy-grid|fancy-outline|github|grid|heavy-grid|heavy-outline|hjson|html|jira|json|json5|jsonc|latex|latex-booktabs|latex-longtable|latex-raw|mediawiki|mixed-grid|mixed-outline|moinmoin|orgtbl|outline|pipe|plain|presto|pretty|psql|rounded-grid|rounded-outline|rst|simple|simple-grid|simple-outline|textile|toml|tsv|unsafehtml|vertical|xml|yaml|youtrack] │ click_extra.table.TableFormatOption │ click_extra.types.EnumChoice │ str │ ✘ │ ✘ │ ✓ │ WEATHER_TABLE_FORMAT │ 'rounded-outline' │ 'rounded-outline' │ DEFAULT │
│ weather.theme │ --theme [dark|dracula|light|manpage|monokai|nord|solarized_dark] │ click_extra.theme.ThemeOption │ click_extra.theme.ThemeChoice │ str │ ✘ │ ✘ │ ✓ │ WEATHER_THEME │ 'dark' │ 'dark' │ DEFAULT │
│ weather.time │ --time / --no-time │ click_extra.timer.TimerOption │ click.types.BoolParamType │ bool │ ✘ │ ✘ │ ✓ │ WEATHER_TIME │ False │ False │ DEFAULT │
│ weather.units │ --units [celsius|fahrenheit] │ click_extra.parameters.Option │ click.types.Choice │ str │ ✘ │ ✓ │ ✓ │ WEATHER_UNITS │ 'celsius' │ 'celsius' │ DEFAULT │
│ weather.validate_config │ --validate-config FILE │ click_extra.config.ValidateConfigOption │ click.types.Path │ str │ ✘ │ ✘ │ ✓ │ WEATHER_VALIDATE_CONFIG │ Sentinel.UNSET │ Sentinel.UNSET │ DEFAULT │
│ weather.verbose │ -v, --verbose │ click_extra.logging.VerboseOption │ click.types.IntRange │ int │ ✘ │ ✘ │ ✓ │ WEATHER_VERBOSE │ 0 │ 0 │ DEFAULT │
│ weather.verbosity │ --verbosity LEVEL │ click_extra.logging.VerbosityOption │ click_extra.types.EnumChoice │ str │ ✘ │ ✘ │ ✓ │ WEATHER_VERBOSITY │ 'WARNING' │ 'WARNING' │ DEFAULT │
│ weather.version │ --version │ click_extra.version.ExtraVersionOption │ click.types.BoolParamType │ bool │ ✘ │ ✘ │ ✘ │ WEATHER_VERSION │ False │ False │ DEFAULT │
╰─────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴─────────────────────────────────────────┴──────────────────────────────────┴─────────────┴────────┴─────────┴──────────────────┴─────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴─────────────╯
FILES¶
The FILES section documents the files a program reads. Click Extra’s --config option resolves a per-platform search path, shown as its default in the OPTIONS block above: the application directory for weather followed by a glob over every supported format (*.toml, *.yaml, *.json, *.ini, *.xml, and pyproject.toml). See the configuration guide for the search order and the precedence rules that govern which file wins.
EXIT STATUS¶
The EXIT STATUS section documents the process return codes. Click Extra inherits Click’s conventional scheme:
Code |
Meaning |
|---|---|
|
Success. |
|
A runtime error, or an aborted prompt ( |
|
A usage error: unknown option, invalid value, missing operand, or an unparsable |
A successful run returns 0:
$ weather Paris
Paris: 21 degrees celsius.
An invalid choice is a usage error, so the command exits 2:
$ weather --units kelvin Paris
Usage: weather [OPTIONS] CITY
Try 'weather --help' for help.
Error: Invalid value for '--units' (env var: '('WEATHER_UNITS',)'): 'kelvin' is not one of 'celsius', 'fahrenheit'.
Generating man pages¶
Every section above is produced mechanically by click_extra.man_page from the command itself. It works on any Click command object (no console_scripts entry point required) and walks the command tree, discovering subcommands dynamically, into one roff page per command. Literal tokens (command and option names) are set bold and replaceable tokens (metavars, operands) italic, following the literal and replaceable slots split; Click’s \b no-rewrap marker becomes a roff .nf / .fi block.
The @man_option decorator adds a --show-man flag that prints a command’s man page and exits:
import click
from click_extra import man_option
@click.command
@man_option
@click.option("--name", help="Who to greet.")
def greet(name):
"""Greet someone."""
click.echo(f"Hello, {name}!")
$ greet --show-man
.\" Generated by Click Extra. Do not edit by hand.
.TH "GREET" "1" "2026-05-26" "" ""
.SH NAME
greet \- Greet someone.
.SH SYNOPSIS
\fBgreet\fR \fI[OPTIONS]\fR
.SH DESCRIPTION
Greet someone.
.SH OPTIONS
.TP
\fB\-\-show\-man\fR
Show the command's man page (roff) and exit.
.TP
\fB\-\-name\fR \fITEXT\fR
Who to greet.
.TP
\fB\-\-help\fR
Show this message and exit.
.SH "EXIT STATUS"
.TP
\fB0\fR
Success.
.TP
\fB1\fR
A runtime error, or an aborted prompt (Ctrl\-C, a declined confirmation).
.TP
\fB2\fR
A usage error: unknown option, invalid value, missing operand, or an unparsable configuration file.
For build-time generation, call the API directly: render_manpage(cli) returns one page’s roff, render_manpages(cli) returns a {filename: roff} mapping for the whole tree, and write_manpages(cli, target_dir) writes one .1 file per command. Dates honor SOURCE_DATE_EPOCH for reproducible builds.
A Debian package can generate and install the pages from its override_dh_installman rule:
override_dh_installman:
python -c "from myapp.cli import cli; from click_extra import write_manpages; write_manpages(cli, 'debian/tmp/manpages')"
dh_installman -O--buildsystem=pybuild
click_extra.man_page API¶
Generate roff/troff man pages from Click commands.
Produces one man page per command, mirroring the man-pages(7) section structure documented in Man-page layout: NAME, SYNOPSIS, DESCRIPTION, OPTIONS, COMMANDS, ENVIRONMENT, FILES and EXIT STATUS.
This is Click Extra’s answer to the unmaintained click-man package. It improves on it by:
working on a command object via
click.Command.make_context(), so it needs noconsole_scriptsentry point;discovering subcommands dynamically through
click.Group.list_commands()/click.Group.get_command()with a live context;honoring Click’s
\bno-rewrap marker (rendered as roff.nf/.fi);rendering boolean flags (
--foo/--no-foo) and skipping hidden commands and options;emitting ENVIRONMENT (from auto-generated env vars), FILES (from the
--configsearch pattern) and EXIT STATUS sections that click-man never grew.
Font selection follows the man typographic convention encoded by
click_extra.theme.LITERAL_STYLES / REPLACEABLE_STYLES:
literal tokens (command and option names) render bold (\fB), replaceable
tokens (metavars, operands) render italic (\fI).
- click_extra.man_page.MAN_SECTION = '1'¶
Default man page section. Section 1 is for executable programs and shell commands, which is what a Click CLI is.
- click_extra.man_page.DEFAULT_EXIT_STATUS: tuple[tuple[str, str], ...] = (('0', 'Success.'), ('1', 'A runtime error, or an aborted prompt (Ctrl-C, a declined confirmation).'), ('2', 'A usage error: unknown option, invalid value, missing operand, or an unparsable configuration file.'))¶
Conventional exit codes shared by every Click Extra CLI.
Mirrors the EXIT STATUS table in Man-page layout. Click returns
2for usage errors (UsageError),1for aborts, and0on success.
- class click_extra.man_page.ManOptionItem(names, metavar, is_choice, help, envvars, required)[source]¶
Bases:
objectA single OPTIONS entry, extracted from a Click option.
- names: tuple[str, ...]¶
All literal spellings: primary
optsfollowed bysecondary_opts(so--foo/--no-fooboolean flags render both).
- is_choice: bool¶
Whether the option’s type is a
click.Choice.
- class click_extra.man_page.ManPage(name, short_help='', section='1', synopsis_pieces=(), description='', operands=(), options=(), subcommands=(), environment=(), files=(), exit_status=(('0', 'Success.'), ('1', 'A runtime error, or an aborted prompt (Ctrl-C, a declined confirmation).'), ('2', 'A usage error: unknown option, invalid value, missing operand, or an unparsable configuration file.')), version=None, date='', manual=None, authors=None, copyright=None)[source]¶
Bases:
objectA whole man page in structured form, ready to render to roff.
One
ManPagemaps to one command (or subcommand). Its fields are the man-pages(7) sections, in the order Man-page layout documents them. Build it withextract_manpage()and serialize withto_roff().- options: tuple[ManOptionItem, ...] = ()¶
The OPTIONS entries.
- subcommands: tuple[tuple[str, str], ...] = ()¶
For groups:
(name, short_help)pairs for the COMMANDS section.
- exit_status: tuple[tuple[str, str], ...] = (('0', 'Success.'), ('1', 'A runtime error, or an aborted prompt (Ctrl-C, a declined confirmation).'), ('2', 'A usage error: unknown option, invalid value, missing operand, or an unparsable configuration file.'))¶
EXIT STATUS entries as
(code, meaning)pairs.
- click_extra.man_page.extract_manpage(command, ctx, *, version=None, date=None, manual=None, authors=None, copyright=None)[source]¶
Build a
ManPagefrom a Click command and its context.The context must have been created for
command(e.g. viaclick.Command.make_context()withresilient_parsing=True), so that auto-generated environment-variable prefixes resolve correctly.- Return type:
- click_extra.man_page.iter_command_contexts(command, prog_name=None, _parent=None, _path=())[source]¶
Walk a command tree, yielding
(path, command, context)for each visible command.Subcommands are discovered dynamically (
click.Group.list_commands()/get_command()), so dynamically-registered commands are included. Hidden commands are skipped. Each context is built withresilient_parsing=Trueto avoid triggering required-argument errors, prompts, or eager-option side effects.
- click_extra.man_page.render_manpage(command, prog_name=None, ctx=None, **overrides)[source]¶
Render a single command’s man page as a roff string.
Reuses
ctxwhen given (e.g. the live invocation context), otherwise builds a throwaway one withresilient_parsing=True. Keyword overrides (version,date,manual,authors,copyright) are passed through toextract_manpage().- Return type:
- click_extra.man_page.render_manpages(command, prog_name=None, **overrides)[source]¶
Render the whole command tree, one man page per (sub)command.
Returns an ordered mapping of
{filename: roff}where each filename is the command path joined by hyphens plus the section suffix (e.g.weather-forecast.1).
- click_extra.man_page.write_manpages(command, target_dir, prog_name=None, **overrides)[source]¶
Render the command tree and write each man page into
target_dir.Creates
target_dirif missing. Returns the list of written paths.
- class click_extra.man_page.ManOption(param_decls=None, is_flag=True, expose_value=False, is_eager=True, help="Show the command's man page (roff) and exit.", **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
--show-manflag that prints the command’s man page (roff) to stdout and exits.Eager and value-less, like
ShowParamsOption. Not part of the default option set: add it explicitly with@man_optionwhen you want a CLI to emit its own man page.