Commands & groups

Drop-in replacement

The whole namespace of click_extra is a superset of both click and cloup namespaces. Click Extra’s main decorators, functions and classes extends and enhance Click and Cloup ones. Those left untouched by Click Extra are directly proxied to Cloup or Click.

This means if you want to upgrade an existing CLI to Click Extra, you can often replace imports of the click namespace by click_extra and it will work as expected.

Click and Cloup inheritance

At the module level, click_extra imports all elements from click.*, then all elements from the cloup.* namespace.

Which means all elements not redefined by Click Extra fallback to Cloup. And if Cloup itself does not redefine them, they fallback to Click.

For the types Click Extra does re-implement, each subclasses its Cloup counterpart, which in turn subclasses Click’s (arrows point from a child to the parent it inherits from):

        flowchart TB
    subgraph CE["click_extra (extends and overrides)"]
        direction LR
        XCmd["Command"]
        XGrp["Group"]
        XOpt["Option"]
        XArg["Argument"]
        XCtx["Context"]
        XSty["Style"]
    end
    subgraph CL["cloup (first fallback)"]
        direction LR
        CCmd["cloup.Command"]
        CGrp["cloup.Group"]
        COpt["cloup.Option"]
        CArg["cloup.Argument"]
        CCtx["cloup.Context"]
        CSty["cloup.Style"]
    end
    subgraph CK["click (base)"]
        direction LR
        KCmd["click.Command"]
        KGrp["click.Group"]
        KOpt["click.Option"]
        KArg["click.Argument"]
        KCtx["click.Context"]
        KSty["click.style()"]
    end
    XCmd --> CCmd --> KCmd
    XGrp --> CGrp --> KGrp
    XOpt --> COpt --> KOpt
    XArg --> CArg --> KArg
    XCtx --> CCtx --> KCtx
    XSty --> CSty -.->|wraps| KSty
    

For example:

  • click_extra.echo is a direct alias to click.echo because neither Click Extra or Cloup re-implements an echo helper.

  • @cloup.option_group is a specific feature of Cloup that is only implemented by it. It is not modified by Click Extra, and Click does not implement it. Still, @click_extra.option_group is a direct alias to Cloup’s one.

  • @click_extra.timer_option is a new decorator only implemented by Click Extra. So it is not a proxy of anything.

  • As for @click_extra.version_option, it is a re-implementation of @click.version_option, and so overrides it. If you want to use its original version, import it directly from click namespace.

Here is some of the main decorators of Click Extra and how they wraps and extends Cloup and Click ones:

Decorators from click_extra

Wrapped decorator

Base class

@command

@cloup.command

click_extra.Command

@group

@cloup.group

click_extra.Group

@lazy_group

@click_extra.group

click_extra.LazyGroup

@option

@cloup.option

click_extra.Option

@argument

@cloup.argument

click_extra.Argument

@version_option

@click_extra.option

click_extra.VersionOption

@color_option

@click_extra.option

click_extra.ColorOption

@config_option

@click_extra.option

click_extra.ConfigOption

@no_config_option

@click_extra.option

click_extra.NoConfigOption

@show_params_option

@click_extra.option

click_extra.ShowParamsOption

@table_format_option

@click_extra.option

click_extra.TableFormatOption

@telemetry_option

@click_extra.option

click_extra.TelemetryOption

@timer_option

@click_extra.option

click_extra.TimerOption

@verbose_option

@click_extra.option

click_extra.VerboseOption

@verbosity_option

@click_extra.option

click_extra.VerbosityOption

@option_group

@cloup.option_group

cloup.OptionGroup

@pass_context

@click.pass_context

-

@help_option

@click.help_option

-

Same for the main classes and functions, where some are re-implemented by Click Extra, and others are direct aliases to Cloup or Click ones:

Classes from click_extra

Alias to

Parent class

Command

-

cloup.Command

Group

-

cloup.Group

LazyGroup

-

click_extra.Group

Option

-

cloup.Option

Argument

-

cloup.Argument

Context

-

cloup.Context

HelpFormatter

-

cloup.HelpFormatter

HelpTheme

-

cloup.HelpTheme

CliRunner

-

click.testing.CliRunner

Result

-

click.testing.Result

VersionOption

-

click_extra.ExtraOption

Style

-

cloup.Style

echo

click.echo

ParameterSource

click.core.ParameterSource

UNSET

click._utils.UNSET

Choice

click.Choice

EnumChoice

-

click.Choice

Hint

You can inspect the implementation details in:

Default options

The @command and @group decorators are pre-configured with a set of default options. The --help/-h option is added separately through help_option_names, which is why it survives even when default_params() is reset:

Tip

Each default option publishes its resolved value on ctx.meta so you can pick it up from anywhere in your CLI. See the available keys table for the full inventory and worked examples.

Remove default options

You can remove all default options by resetting the params argument to None:

from click_extra import command

@command(params=None)
def bare_cli():
    pass

Which results in:

$ bare-cli --help
Usage: bare-cli [OPTIONS]

Options:
  -h, --help  Show this message and exit.

As you can see, all options are stripped out, but the coloring and formatting of the help message is preserved.

Change default options

To override the default options, you can provide the params= argument to the command. But note how we use classes instead of option decorators:

from click_extra import command, ConfigOption, VerbosityOption

@command(
    params=[
        ConfigOption(default="ex.yml"),
        VerbosityOption(default="DEBUG"),
    ]
)
def cli():
    pass

And now you get:

$ cli --help
Usage: cli [OPTIONS]

Options:
  --config CONFIG_PATH  Location of the configuration file. Supports local path
                        with glob patterns or remote URL.  [default: ex.yml]
  --verbosity LEVEL     Either CRITICAL, ERROR, WARNING, INFO, DEBUG.  [default:
                        DEBUG]
  -h, --help            Show this message and exit.

This let you replace the preset options by your own set, tweak their order and fine-tune their defaults.

Duplicate options

If you try to add option decorators to a command which already have them by default, you will end up with duplicate entries (as seen in issue #232):

from click_extra import command, version_option

@command
@version_option(fields={"version": "0.1"})
def cli():
    pass

See how the --version option gets duplicated at the end:

$ cli --help
Usage: cli [OPTIONS]

Options:
  --time / --no-time           Measure and print elapsed execution time.
                               [default: no-time]
  --config CONFIG_PATH         Location of the configuration file. Supports
                               local path with glob patterns or remote URL.
                               [default: ~/.config/cli/{*.toml,*.yaml,*.yml,*.js
                               on,*.json5,*.jsonc,*.hjson,*.ini,*.xml,*.plist,*.
                               sqlite,*.sqlite3,*.conf,pyproject.toml}]
  --no-config                  Ignore all configuration files and only use
                               command line parameters and environment
                               variables.
  --validate-config FILE       Validate the configuration file and exit.
  --export-config FORMAT       Export the configuration in the selected format
                               to <stdout>, then exit.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a borderless, screen-reader-friendly
                               format.
  --color [auto|always|never]  Colorize the output. A bare --color is the same
                               as --color=always.  [default: auto]
  --no-color                   Disable colorization (alias of --color=never).
  --progress / --no-progress   Show progress indicators during long operations.
                               Disabled for non-interactive output (pipes, dumb
                               terminals, CI) and by --accessible.  [default:
                               progress]
  --theme [auto|dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --params                     Show all CLI parameters, their provenance,
                               defaults and value, then exit.
  --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.  [default: rounded-
                               outline]
  --verbosity LEVEL            Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                               [default: WARNING]
  -v, --verbose                Increase the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  -q, --quiet                  Decrease the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  --tree                       Show the tree of nested subcommands and exit.
  --man                        Read the command's manual page and exit.
  --help-format [carapace|json|json-full|man|markdown|markdown-full]
                               Render the command in the given format and exit.
  --version                    Show the version and exit.
  --version                    Show the version and exit.
  -h, --help                   Show this message and exit.
/home/runner/work/click-extra/click-extra/click_extra/commands.py:736: UserWarning: The parameter --version is used more than once. Remove its duplicate as parameters should be unique.
  self._resolve_presentation_eagerly(ctx, args)
/home/runner/work/click-extra/click-extra/.venv/lib/python3.14/site-packages/click/core.py:1307: UserWarning: The parameter --version is used more than once. Remove its duplicate as parameters should be unique.
  parser = self.make_parser(ctx)
/home/runner/work/click-extra/click-extra/.venv/lib/python3.14/site-packages/cloup/constraints/_support.py:183: UserWarning: The parameter --version is used more than once. Remove its duplicate as parameters should be unique.
  args = super().parse_args(ctx, args)  # type: ignore
/home/runner/work/click-extra/click-extra/click_extra/highlight.py:131: UserWarning: The parameter --version is used more than once. Remove its duplicate as parameters should be unique.
  kw.metavars.update(command.collect_usage_pieces(ctx))
/home/runner/work/click-extra/click-extra/click_extra/highlight.py:326: UserWarning: The parameter --version is used more than once. Remove its duplicate as parameters should be unique.
  formatter.keywords = self.collect_keywords(ctx)
/home/runner/work/click-extra/click-extra/.venv/lib/python3.14/site-packages/click/core.py:1129: UserWarning: The parameter --version is used more than once. Remove its duplicate as parameters should be unique.
  pieces = self.collect_usage_pieces(ctx)

This is by design: decorators are cumulative, to allow you to add your own options to the preset of @command and @group.

But notice the UserWarning log messages: The parameter --version is used more than once. Remove its duplicate as parameters should be unique.. As it is not a good practice to have duplicate options and you must avoid it. There’s also a non-zero chance for this situation to result in complete failure in a future Click release.

Finally, if the second --version option is placed right before the --help option, it is because Click is adding its own generated --help option at the end of the default_params() list.

Option order

Options are listed in the order they were declared: first whatever the params= argument of the decorator holds, then the option decorators stacked below @command, read bottom-up as Python applies them.

from click_extra import command, option

@command(params=[])
@option("--sugar", help="Grams of sugar.")
@option("--butter", help="Grams of butter.")
@option("--flour", help="Grams of flour.")
def bake(sugar, butter, flour):
    """Bake a cake."""
$ bake --help
Usage: bake [OPTIONS]

  Bake a cake.

Options:
  --sugar TEXT   Grams of sugar.
  --butter TEXT  Grams of butter.
  --flour TEXT   Grams of flour.
  -h, --help     Show this message and exit.

On top of that, Command moves every ExtraOption to the end of the list, so the options you wrote yourself come first and Click Extra’s own trail behind them. That is the extra_option_at_end argument, True by default:

from click_extra import VersionOption, command, option

@command(params=[VersionOption()], extra_option_at_end=False)
@option("--sugar", help="Grams of sugar.")
def keep_declared_order(sugar):
    """Bake a cake."""
$ keep-declared-order --help
Usage: keep-declared-order [OPTIONS]

  Bake a cake.

Options:
  --version     Show the version and exit.
  --sugar TEXT  Grams of sugar.
  -h, --help    Show this message and exit.

Option priorities

The order above is the processing order: it decides when each option’s callback fires, which is why --time sits ahead of everything it measures and --config ahead of the defaults it seeds. Reshuffling the help screen by hand would drag those callbacks along with it.

option_priorities moves an option on the screen alone. It maps a flag, or an option’s destination name, to a number: lowest is shown first, and anything left out sits on the DEFAULT_PRIORITY line at 100. So a number below 100 promotes, and one above demotes:

from click_extra import command, option

@command(params=[], option_priorities={"--flour": 1, "--sugar": 2, "--butter": 3})
@option("--sugar", help="Grams of sugar.")
@option("--butter", help="Grams of butter.")
@option("--flour", help="Grams of flour.")
def measured(sugar, butter, flour):
    """Bake a cake."""
$ measured --help
Usage: measured [OPTIONS]

  Bake a cake.

Options:
  --flour TEXT   Grams of flour.
  --sugar TEXT   Grams of sugar.
  --butter TEXT  Grams of butter.
  -h, --help     Show this message and exit.

The declaration order is untouched underneath:

print([param.name for param in measured.params])

Priorities are floats rather than integers, so a new option can be wedged between two existing ones without renumbering the rest: 1.5 lands between 1 and 2. See DEFAULT_PRIORITY for where that convention comes from.

A priority can also be written against that constant instead of against the literal 100, which reads well when a single option has to clear the crowd it was declared in:

from click_extra import command, option
from click_extra.commands import DEFAULT_PRIORITY

@command(
    params=[],
    option_priorities={
        "--flour": DEFAULT_PRIORITY - 1,
        "--sugar": DEFAULT_PRIORITY + 1,
    },
)
@option("--sugar", help="Grams of sugar.")
@option("--butter", help="Grams of butter.")
@option("--flour", help="Grams of flour.")
def relative(sugar, butter, flour):
    """Bake a cake."""

Mind the sign, as it runs against the screen: the lowest priority is listed first, so subtracting from DEFAULT_PRIORITY raises an option and adding to it lowers one. --butter was left out of the mapping and holds the default line between the two. --help is appended by Click after the sort, so it stays last whatever the mapping says:

$ relative --help
Usage: relative [OPTIONS]

  Bake a cake.

Options:
  --flour TEXT   Grams of flour.
  --butter TEXT  Grams of butter.
  --sugar TEXT   Grams of sugar.
  -h, --help     Show this message and exit.

Positional arguments are never reordered: their sequence is part of the command’s grammar, not a matter of presentation.

Option’s defaults

Because Click Extra inherits from Click, you can override the defaults the same way Click allows you to. Here is a reminder on how to do it.

For example, the --verbosity option defaults to the WARNING level. Now we’d like to change this default to INFO.

If you manage your own --verbosity option, you can pass the default argument to its decorator like we did above:

import click
from click_extra import verbosity_option

@click.command
@verbosity_option(default="INFO")
def cli():
    pass

This also works in its class form:

import click
from click_extra import VerbosityOption

@click.command(params=[VerbosityOption(default="INFO")])
def cli():
    pass

With a @click_extra.command instead of @click.command, it is the same, you also have the alternative to pass a default_map via the context_settings:

import click_extra

@click_extra.command(context_settings={"default_map": {"verbosity": "INFO"}})
def cli():
    pass

Which results in [default: INFO] being featured in the help message:

$ cli --help
Usage: cli [OPTIONS]

Options:
  --time / --no-time           Measure and print elapsed execution time.
                               [default: no-time]
  --config CONFIG_PATH         Location of the configuration file. Supports
                               local path with glob patterns or remote URL.
                               [default: ~/.config/cli/{*.toml,*.yaml,*.yml,*.js
                               on,*.json5,*.jsonc,*.hjson,*.ini,*.xml,*.plist,*.
                               sqlite,*.sqlite3,*.conf,pyproject.toml}]
  --no-config                  Ignore all configuration files and only use
                               command line parameters and environment
                               variables.
  --validate-config FILE       Validate the configuration file and exit.
  --export-config FORMAT       Export the configuration in the selected format
                               to <stdout>, then exit.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a borderless, screen-reader-friendly
                               format.
  --color [auto|always|never]  Colorize the output. A bare --color is the same
                               as --color=always.  [default: auto]
  --no-color                   Disable colorization (alias of --color=never).
  --progress / --no-progress   Show progress indicators during long operations.
                               Disabled for non-interactive output (pipes, dumb
                               terminals, CI) and by --accessible.  [default:
                               progress]
  --theme [auto|dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --params                     Show all CLI parameters, their provenance,
                               defaults and value, then exit.
  --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.  [default: rounded-
                               outline]
  --verbosity LEVEL            Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                               [default: INFO]
  -v, --verbose                Increase the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  -q, --quiet                  Decrease the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  --tree                       Show the tree of nested subcommands and exit.
  --man                        Read the command's manual page and exit.
  --help-format [carapace|json|json-full|man|markdown|markdown-full]
                               Render the command in the given format and exit.
  --version                    Show the version and exit.
  -h, --help                   Show this message and exit.

Tip

The advantage of the context_settings method we demonstrated above, is that it let you change the default of the --verbosity option provided by Click Extra, without having to touch the params argument.

Version fields

Click’s @version_option(prog_name=...) lets you customize the name displayed by --version. But with Click Extra’s default options, the VersionOption is created for you: so there’s no decorator call to pass prog_name to.

The version_fields parameter on @command and @group solves this. It forwards values to the VersionOption in the default params list, without replacing it. It accepts any field from VersionOption.template_fields:

from click_extra import command

@command(name="my-tool", version_fields={"prog_name": "My Tool"})
def my_tool():
    """My Tool CLI."""

The name controls the usage line, while prog_name controls the --version output:

$ my-tool --help
Usage: my-tool [OPTIONS]

  My Tool CLI.

Options:
  --time / --no-time           Measure and print elapsed execution time.
                               [default: no-time]
  --config CONFIG_PATH         Location of the configuration file. Supports
                               local path with glob patterns or remote URL.
                               [default: ~/.config/my-tool/{*.toml,*.yaml,*.yml,
                               *.json,*.json5,*.jsonc,*.hjson,*.ini,*.xml,*.plis
                               t,*.sqlite,*.sqlite3,*.conf,pyproject.toml}]
  --no-config                  Ignore all configuration files and only use
                               command line parameters and environment
                               variables.
  --validate-config FILE       Validate the configuration file and exit.
  --export-config FORMAT       Export the configuration in the selected format
                               to <stdout>, then exit.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a borderless, screen-reader-friendly
                               format.
  --color [auto|always|never]  Colorize the output. A bare --color is the same
                               as --color=always.  [default: auto]
  --no-color                   Disable colorization (alias of --color=never).
  --progress / --no-progress   Show progress indicators during long operations.
                               Disabled for non-interactive output (pipes, dumb
                               terminals, CI) and by --accessible.  [default:
                               progress]
  --theme [auto|dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --params                     Show all CLI parameters, their provenance,
                               defaults and value, then exit.
  --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.  [default: rounded-
                               outline]
  --verbosity LEVEL            Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                               [default: WARNING]
  -v, --verbose                Increase the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  -q, --quiet                  Decrease the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  --tree                       Show the tree of nested subcommands and exit.
  --man                        Read the command's manual page and exit.
  --help-format [carapace|json|json-full|man|markdown|markdown-full]
                               Render the command in the given format and exit.
  --version                    Show the version and exit.
  -h, --help                   Show this message and exit.
$ my-tool --version
My Tool, version None

Hint

When prog_name is not set, --version falls back to the command name, which is Click’s standard behavior.

Multiple fields can be overridden at once, including the version message template:

from click_extra import command

@command(
    version_fields={
        "prog_name": "Acme CLI",
        "version": "42.0",
        "git_branch": "release/42",
    },
)
def acme():
    pass
$ acme --version
Acme CLI, version 42.0

Examples

A command can carry usage examples, as (description, command) pairs. They render in an Examples: section of the help screen, in the man page’s EXAMPLES section, and in every machine-readable rendering:

from click_extra import command, echo, option


@command(
    examples=[
        ("Report the temperature in Fahrenheit", "forecast --units fahrenheit Oslo"),
        ("Report tomorrow's forecast", "forecast --day tomorrow Oslo"),
    ]
)
@option("--units", default="celsius", help="Temperature scale to display.")
def forecast(units):
    """Report the forecast for a city."""
    echo(f"Sunny, in {units}.")
$ forecast --help
Usage: forecast [OPTIONS]

  Report the forecast for a city.

Options:
  --units TEXT                 Temperature scale to display.  [default: celsius]
  --time / --no-time           Measure and print elapsed execution time.
                               [default: no-time]
  --config CONFIG_PATH         Location of the configuration file. Supports
                               local path with glob patterns or remote URL.
                               [default: ~/.config/forecast/{*.toml,*.yaml,*.yml
                               ,*.json,*.json5,*.jsonc,*.hjson,*.ini,*.xml,*.pli
                               st,*.sqlite,*.sqlite3,*.conf,pyproject.toml}]
  --no-config                  Ignore all configuration files and only use
                               command line parameters and environment
                               variables.
  --validate-config FILE       Validate the configuration file and exit.
  --export-config FORMAT       Export the configuration in the selected format
                               to <stdout>, then exit.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a borderless, screen-reader-friendly
                               format.
  --color [auto|always|never]  Colorize the output. A bare --color is the same
                               as --color=always.  [default: auto]
  --no-color                   Disable colorization (alias of --color=never).
  --progress / --no-progress   Show progress indicators during long operations.
                               Disabled for non-interactive output (pipes, dumb
                               terminals, CI) and by --accessible.  [default:
                               progress]
  --theme [auto|dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --params                     Show all CLI parameters, their provenance,
                               defaults and value, then exit.
  --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.  [default: rounded-
                               outline]
  --verbosity LEVEL            Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                               [default: WARNING]
  -v, --verbose                Increase the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  -q, --quiet                  Decrease the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  --tree                       Show the tree of nested subcommands and exit.
  --man                        Read the command's manual page and exit.
  --help-format [carapace|json|json-full|man|markdown|markdown-full]
                               Render the command in the given format and exit.
  --version                    Show the version and exit.
  -h, --help                   Show this message and exit.

Examples:
  Report the temperature in Fahrenheit:
    $ forecast --units fahrenheit Oslo
  Report tomorrow's forecast:
    $ forecast --day tomorrow Oslo

The command lines are emitted verbatim rather than wrapped: an example exists to be copied. Option names, subcommands and CLI names inside them are highlighted by the same pass that highlights them everywhere else on the screen, which is why the assertion above strips the styling before matching.

They reach the machine-readable renderings as structured entries, not as prose to be parsed back out:

$ forecast --help-format json
{
  "name": "forecast",
  "short_help": "Report the forecast for a city.",
  "version": null,
  "synopsis": "forecast [OPTIONS]",
  "description": "Report the forecast for a city.",
  "arguments": [],
  "option_groups": [
    {
      "title": null,
      "help": null,
      "options": [
        {
          "names": [
            "--units"
          ],
          "spec": "--units TEXT",
          "metavar": "TEXT",
          "help": "Temperature scale to display.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--time",
            "--no-time"
          ],
          "spec": "--time / --no-time",
          "metavar": null,
          "help": "Measure and print elapsed execution time.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--config"
          ],
          "spec": "--config CONFIG_PATH",
          "metavar": "CONFIG_PATH",
          "help": "Location of the configuration file. Supports local path with glob patterns or remote URL.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--no-config"
          ],
          "spec": "--no-config",
          "metavar": null,
          "help": "Ignore all configuration files and only use command line parameters and environment variables.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--validate-config"
          ],
          "spec": "--validate-config FILE",
          "metavar": "FILE",
          "help": "Validate the configuration file and exit.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--export-config"
          ],
          "spec": "--export-config FORMAT",
          "metavar": "FORMAT",
          "help": "Export the configuration in the selected format to <stdout>, then exit.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--accessible"
          ],
          "spec": "--accessible",
          "metavar": null,
          "help": "Accessibility mode: disable colors and render tables in a borderless, screen-reader-friendly format.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--color"
          ],
          "spec": "--color[=auto|always|never]",
          "metavar": "[auto|always|never]",
          "help": "Colorize the output. A bare --color is the same as --color=always.",
          "required": false,
          "optional_value": true
        },
        {
          "names": [
            "--no-color"
          ],
          "spec": "--no-color",
          "metavar": null,
          "help": "Disable colorization (alias of --color=never).",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--progress",
            "--no-progress"
          ],
          "spec": "--progress / --no-progress",
          "metavar": null,
          "help": "Show progress indicators during long operations. Disabled for non-interactive output (pipes, dumb terminals, CI) and by --accessible.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--theme"
          ],
          "spec": "--theme [auto|dark|dracula|light|manpage|monokai|nord|solarized_dark]",
          "metavar": "[auto|dark|dracula|light|manpage|monokai|nord|solarized_dark]",
          "help": "Color theme used for help screens.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--params"
          ],
          "spec": "--params",
          "metavar": null,
          "help": "Show all CLI parameters, their provenance, defaults and value, then exit.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--table-format"
          ],
          "spec": "--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]",
          "metavar": "[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]",
          "help": "Rendering style of tables.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--verbosity"
          ],
          "spec": "--verbosity LEVEL",
          "metavar": "LEVEL",
          "help": "Either CRITICAL, ERROR, WARNING, INFO, DEBUG.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--verbose",
            "-v"
          ],
          "spec": "--verbose / -v",
          "metavar": null,
          "help": "Increase the default WARNING verbosity by one level for each additional repetition of the option.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--quiet",
            "-q"
          ],
          "spec": "--quiet / -q",
          "metavar": null,
          "help": "Decrease the default WARNING verbosity by one level for each additional repetition of the option.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--tree"
          ],
          "spec": "--tree",
          "metavar": null,
          "help": "Show the tree of nested subcommands and exit.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--man"
          ],
          "spec": "--man",
          "metavar": null,
          "help": "Read the command's manual page and exit.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--help-format"
          ],
          "spec": "--help-format [carapace|json|json-full|man|markdown|markdown-full]",
          "metavar": "[carapace|json|json-full|man|markdown|markdown-full]",
          "help": "Render the command in the given format and exit.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--version"
          ],
          "spec": "--version",
          "metavar": null,
          "help": "Show the version and exit.",
          "required": false,
          "optional_value": false
        },
        {
          "names": [
            "--help",
            "-h"
          ],
          "spec": "--help / -h",
          "metavar": null,
          "help": "Show this message and exit.",
          "required": false,
          "optional_value": false
        }
      ]
    }
  ],
  "subcommands": [],
  "examples": [
    {
      "description": "Report the temperature in Fahrenheit",
      "command": "forecast --units fahrenheit Oslo"
    },
    {
      "description": "Report tomorrow's forecast",
      "command": "forecast --day tomorrow Oslo"
    }
  ],
  "environment": [
    {
      "variable": "FORECAST_UNITS",
      "help": "Temperature scale to display."
    },
    {
      "variable": "FORECAST_TIME",
      "help": "Measure and print elapsed execution time."
    },
    {
      "variable": "FORECAST_CONFIG",
      "help": "Location of the configuration file. Supports local path with glob patterns or remote URL."
    },
    {
      "variable": "FORECAST_VALIDATE_CONFIG",
      "help": "Validate the configuration file and exit."
    },
    {
      "variable": "FORECAST_EXPORT_CONFIG",
      "help": "Export the configuration in the selected format to <stdout>, then exit."
    },
    {
      "variable": "FORECAST_ACCESSIBLE",
      "help": "Accessibility mode: disable colors and render tables in a borderless, screen-reader-friendly format."
    },
    {
      "variable": "FORECAST_COLOR",
      "help": "Colorize the output. A bare --color is the same as --color=always."
    },
    {
      "variable": "FORECAST_NO_COLOR",
      "help": "Disable colorization (alias of --color=never)."
    },
    {
      "variable": "FORECAST_PROGRESS",
      "help": "Show progress indicators during long operations. Disabled for non-interactive output (pipes, dumb terminals, CI) and by --accessible."
    },
    {
      "variable": "FORECAST_THEME",
      "help": "Color theme used for help screens."
    },
    {
      "variable": "FORECAST_PARAMS",
      "help": "Show all CLI parameters, their provenance, defaults and value, then exit."
    },
    {
      "variable": "FORECAST_TABLE_FORMAT",
      "help": "Rendering style of tables."
    },
    {
      "variable": "FORECAST_VERBOSITY",
      "help": "Either CRITICAL, ERROR, WARNING, INFO, DEBUG."
    },
    {
      "variable": "FORECAST_VERBOSE",
      "help": "Increase the default WARNING verbosity by one level for each additional repetition of the option."
    },
    {
      "variable": "FORECAST_QUIET",
      "help": "Decrease the default WARNING verbosity by one level for each additional repetition of the option."
    },
    {
      "variable": "FORECAST_TREE",
      "help": "Show the tree of nested subcommands and exit."
    },
    {
      "variable": "FORECAST_MAN",
      "help": "Read the command's manual page and exit."
    },
    {
      "variable": "FORECAST_HELP_FORMAT",
      "help": "Render the command in the given format and exit."
    },
    {
      "variable": "FORECAST_VERSION",
      "help": "Show the version and exit."
    },
    {
      "variable": "FORECAST_HELP",
      "help": "Show this message and exit."
    }
  ],
  "files": [
    "~/.config/forecast/{*.toml,*.yaml,*.yml,*.json,*.json5,*.jsonc,*.hjson,*.ini,*.xml,*.plist,*.sqlite,*.sqlite3,*.conf,pyproject.toml}"
  ],
  "exit_status": [
    {
      "code": "0",
      "meaning": "Success."
    },
    {
      "code": "1",
      "meaning": "A runtime error, or an aborted prompt (Ctrl-C, a declined confirmation)."
    },
    {
      "code": "2",
      "meaning": "A usage error: unknown option, invalid value, missing operand, or an unparsable configuration file."
    }
  ]
}

A malformed pair raises TypeError at command construction, so a typo surfaces on import rather than on the first --help a user runs.

Subcommand order

A group lists its subcommands alphabetically, as Click does:

from click_extra import group

@group
def kitchen():
    """Run the kitchen."""

@kitchen.command()
def prep():
    """Prep the ingredients."""

@kitchen.command()
def cook():
    """Cook the dish."""

@kitchen.command()
def plate():
    """Plate the dish."""
$ kitchen --help
Usage: kitchen [OPTIONS] COMMAND [ARGS]...

  Run the kitchen.

Options:
  --time / --no-time           Measure and print elapsed execution time.
                               [default: no-time]
  --config CONFIG_PATH         Location of the configuration file. Supports
                               local path with glob patterns or remote URL.
                               [default: ~/.config/kitchen/{*.toml,*.yaml,*.yml,
                               *.json,*.json5,*.jsonc,*.hjson,*.ini,*.xml,*.plis
                               t,*.sqlite,*.sqlite3,*.conf,pyproject.toml}]
  --no-config                  Ignore all configuration files and only use
                               command line parameters and environment
                               variables.
  --validate-config FILE       Validate the configuration file and exit.
  --export-config FORMAT       Export the configuration in the selected format
                               to <stdout>, then exit.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a borderless, screen-reader-friendly
                               format.
  --color [auto|always|never]  Colorize the output. A bare --color is the same
                               as --color=always.  [default: auto]
  --no-color                   Disable colorization (alias of --color=never).
  --progress / --no-progress   Show progress indicators during long operations.
                               Disabled for non-interactive output (pipes, dumb
                               terminals, CI) and by --accessible.  [default:
                               progress]
  --theme [auto|dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --params                     Show all CLI parameters, their provenance,
                               defaults and value, then exit.
  --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.  [default: rounded-
                               outline]
  --verbosity LEVEL            Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                               [default: WARNING]
  -v, --verbose                Increase the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  -q, --quiet                  Decrease the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  --tree                       Show the tree of nested subcommands and exit.
  --man                        Read the command's manual page and exit.
  --help-format [carapace|json|json-full|man|markdown|markdown-full]
                               Render the command in the given format and exit.
  --version                    Show the version and exit.
  -h, --help                   Show this message and exit.

Commands:
  cook   Cook the dish.
  help   Show help for a command.
  plate  Plate the dish.
  prep   Prep the ingredients.

Which reads well for a set of siblings, and poorly for a sequence: a kitchen preps before it cooks and cooks before it plates, and the alphabet says nothing about that.

Declaration order

sort_subcommands=False lists subcommands in the order they were registered instead:

from click_extra import group

@group(sort_subcommands=False)
def pipeline():
    """Run the kitchen."""

@pipeline.command()
def prep():
    """Prep the ingredients."""

@pipeline.command()
def cook():
    """Cook the dish."""

@pipeline.command()
def plate():
    """Plate the dish."""
$ pipeline --help
Usage: pipeline [OPTIONS] COMMAND [ARGS]...

  Run the kitchen.

Options:
  --time / --no-time           Measure and print elapsed execution time.
                               [default: no-time]
  --config CONFIG_PATH         Location of the configuration file. Supports
                               local path with glob patterns or remote URL.
                               [default: ~/.config/pipeline/{*.toml,*.yaml,*.yml
                               ,*.json,*.json5,*.jsonc,*.hjson,*.ini,*.xml,*.pli
                               st,*.sqlite,*.sqlite3,*.conf,pyproject.toml}]
  --no-config                  Ignore all configuration files and only use
                               command line parameters and environment
                               variables.
  --validate-config FILE       Validate the configuration file and exit.
  --export-config FORMAT       Export the configuration in the selected format
                               to <stdout>, then exit.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a borderless, screen-reader-friendly
                               format.
  --color [auto|always|never]  Colorize the output. A bare --color is the same
                               as --color=always.  [default: auto]
  --no-color                   Disable colorization (alias of --color=never).
  --progress / --no-progress   Show progress indicators during long operations.
                               Disabled for non-interactive output (pipes, dumb
                               terminals, CI) and by --accessible.  [default:
                               progress]
  --theme [auto|dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --params                     Show all CLI parameters, their provenance,
                               defaults and value, then exit.
  --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.  [default: rounded-
                               outline]
  --verbosity LEVEL            Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                               [default: WARNING]
  -v, --verbose                Increase the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  -q, --quiet                  Decrease the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  --tree                       Show the tree of nested subcommands and exit.
  --man                        Read the command's manual page and exit.
  --help-format [carapace|json|json-full|man|markdown|markdown-full]
                               Render the command in the given format and exit.
  --version                    Show the version and exit.
  -h, --help                   Show this message and exit.

Commands:
  prep   Prep the ingredients.
  cook   Cook the dish.
  plate  Plate the dish.
  help   Show help for a command.

The auto-generated help subcommand is listed last, wherever it happens to sit in the registration order, mirroring what extra_option_at_end does to options.

Subcommand priorities

Registration order ties the listing to the shape of your source file, which is awkward when subcommands come from several modules or from a plugin scan. subcommand_priorities numbers them instead. Lowest is listed first, and any subcommand left out of the mapping sits on the DEFAULT_PRIORITY line at 100, so a number below 100 promotes and one above demotes:

from click_extra import group

@group(subcommand_priorities={"prep": 1, "plate": 2})
def numbered():
    """Run the kitchen."""

@numbered.command()
def plate():
    """Plate the dish."""

@numbered.command()
def prep():
    """Prep the ingredients."""
$ numbered --help
Usage: numbered [OPTIONS] COMMAND [ARGS]...

  Run the kitchen.

Options:
  --time / --no-time           Measure and print elapsed execution time.
                               [default: no-time]
  --config CONFIG_PATH         Location of the configuration file. Supports
                               local path with glob patterns or remote URL.
                               [default: ~/.config/numbered/{*.toml,*.yaml,*.yml
                               ,*.json,*.json5,*.jsonc,*.hjson,*.ini,*.xml,*.pli
                               st,*.sqlite,*.sqlite3,*.conf,pyproject.toml}]
  --no-config                  Ignore all configuration files and only use
                               command line parameters and environment
                               variables.
  --validate-config FILE       Validate the configuration file and exit.
  --export-config FORMAT       Export the configuration in the selected format
                               to <stdout>, then exit.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a borderless, screen-reader-friendly
                               format.
  --color [auto|always|never]  Colorize the output. A bare --color is the same
                               as --color=always.  [default: auto]
  --no-color                   Disable colorization (alias of --color=never).
  --progress / --no-progress   Show progress indicators during long operations.
                               Disabled for non-interactive output (pipes, dumb
                               terminals, CI) and by --accessible.  [default:
                               progress]
  --theme [auto|dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --params                     Show all CLI parameters, their provenance,
                               defaults and value, then exit.
  --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.  [default: rounded-
                               outline]
  --verbosity LEVEL            Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                               [default: WARNING]
  -v, --verbose                Increase the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  -q, --quiet                  Decrease the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  --tree                       Show the tree of nested subcommands and exit.
  --man                        Read the command's manual page and exit.
  --help-format [carapace|json|json-full|man|markdown|markdown-full]
                               Render the command in the given format and exit.
  --version                    Show the version and exit.
  -h, --help                   Show this message and exit.

Commands:
  prep   Prep the ingredients.
  plate  Plate the dish.
  help   Show help for a command.

Priorities are floats, so a subcommand added later slots between two existing ones without renumbering anything:

from click_extra import group

@group(subcommand_priorities={"prep": 1, "plate": 2, "cook": 1.5})
def wedged():
    """Run the kitchen."""

@wedged.command()
def plate():
    """Plate the dish."""

@wedged.command()
def prep():
    """Prep the ingredients."""

@wedged.command()
def cook():
    """Cook the dish."""
$ wedged --help
Usage: wedged [OPTIONS] COMMAND [ARGS]...

  Run the kitchen.

Options:
  --time / --no-time           Measure and print elapsed execution time.
                               [default: no-time]
  --config CONFIG_PATH         Location of the configuration file. Supports
                               local path with glob patterns or remote URL.
                               [default: ~/.config/wedged/{*.toml,*.yaml,*.yml,*
                               .json,*.json5,*.jsonc,*.hjson,*.ini,*.xml,*.plist
                               ,*.sqlite,*.sqlite3,*.conf,pyproject.toml}]
  --no-config                  Ignore all configuration files and only use
                               command line parameters and environment
                               variables.
  --validate-config FILE       Validate the configuration file and exit.
  --export-config FORMAT       Export the configuration in the selected format
                               to <stdout>, then exit.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a borderless, screen-reader-friendly
                               format.
  --color [auto|always|never]  Colorize the output. A bare --color is the same
                               as --color=always.  [default: auto]
  --no-color                   Disable colorization (alias of --color=never).
  --progress / --no-progress   Show progress indicators during long operations.
                               Disabled for non-interactive output (pipes, dumb
                               terminals, CI) and by --accessible.  [default:
                               progress]
  --theme [auto|dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --params                     Show all CLI parameters, their provenance,
                               defaults and value, then exit.
  --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.  [default: rounded-
                               outline]
  --verbosity LEVEL            Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                               [default: WARNING]
  -v, --verbose                Increase the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  -q, --quiet                  Decrease the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  --tree                       Show the tree of nested subcommands and exit.
  --man                        Read the command's manual page and exit.
  --help-format [carapace|json|json-full|man|markdown|markdown-full]
                               Render the command in the given format and exit.
  --version                    Show the version and exit.
  -h, --help                   Show this message and exit.

Commands:
  prep   Prep the ingredients.
  cook   Cook the dish.
  plate  Plate the dish.
  help   Show help for a command.

See DEFAULT_PRIORITY for where that convention comes from.

As with options, a priority can be written against that constant rather than against the literal 100, which is enough to bookend a listing you are otherwise happy to leave alphabetical:

from click_extra import group
from click_extra.commands import DEFAULT_PRIORITY

@group(
    subcommand_priorities={
        "prep": DEFAULT_PRIORITY - 1,
        "plate": DEFAULT_PRIORITY + 1,
    },
)
def bookended():
    """Run the kitchen."""

@bookended.command()
def plate():
    """Plate the dish."""

@bookended.command()
def prep():
    """Prep the ingredients."""

@bookended.command()
def brine():
    """Brine overnight."""

@bookended.command()
def cook():
    """Cook the dish."""

The same inversion applies: subtracting lifts prep above the pack and adding drops plate below it, while brine and cook stay on the default line and keep the alphabetical tie-break between them. The help subcommand takes a priority like any other, and ties on that same line here:

$ bookended --help
Usage: bookended [OPTIONS] COMMAND [ARGS]...

  Run the kitchen.

Options:
  --time / --no-time           Measure and print elapsed execution time.
                               [default: no-time]
  --config CONFIG_PATH         Location of the configuration file. Supports
                               local path with glob patterns or remote URL.
                               [default: ~/.config/bookended/{*.toml,*.yaml,*.ym
                               l,*.json,*.json5,*.jsonc,*.hjson,*.ini,*.xml,*.pl
                               ist,*.sqlite,*.sqlite3,*.conf,pyproject.toml}]
  --no-config                  Ignore all configuration files and only use
                               command line parameters and environment
                               variables.
  --validate-config FILE       Validate the configuration file and exit.
  --export-config FORMAT       Export the configuration in the selected format
                               to <stdout>, then exit.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a borderless, screen-reader-friendly
                               format.
  --color [auto|always|never]  Colorize the output. A bare --color is the same
                               as --color=always.  [default: auto]
  --no-color                   Disable colorization (alias of --color=never).
  --progress / --no-progress   Show progress indicators during long operations.
                               Disabled for non-interactive output (pipes, dumb
                               terminals, CI) and by --accessible.  [default:
                               progress]
  --theme [auto|dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --params                     Show all CLI parameters, their provenance,
                               defaults and value, then exit.
  --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.  [default: rounded-
                               outline]
  --verbosity LEVEL            Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                               [default: WARNING]
  -v, --verbose                Increase the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  -q, --quiet                  Decrease the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  --tree                       Show the tree of nested subcommands and exit.
  --man                        Read the command's manual page and exit.
  --help-format [carapace|json|json-full|man|markdown|markdown-full]
                               Render the command in the given format and exit.
  --version                    Show the version and exit.
  -h, --help                   Show this message and exit.

Commands:
  prep   Prep the ingredients.
  brine  Brine overnight.
  cook   Cook the dish.
  help   Show help for a command.
  plate  Plate the dish.

One setting for a whole tree

Both knobs are per-group, which means repeating them on every subgroup. sort_subcommands is also a context setting, and a context setting is inherited: declare it once on the root group and every group below it follows, unless one says otherwise.

from click_extra import group

@group(context_settings={"sort_subcommands": False})
def restaurant():
    """Run the restaurant."""

@restaurant.group()
def service():
    """Run the dining room."""

@service.command()
def seat():
    """Seat the guests."""

@service.command()
def pour():
    """Pour the wine."""
$ restaurant service --help
Usage: restaurant service [OPTIONS] COMMAND [ARGS]...

  Run the dining room.

Options:
  -h, --help  Show this message and exit.

Commands:
  seat  Seat the guests.
  pour  Pour the wine.
  help  Show help for a command.

Every rendering agrees

The order settles the help screen and every other rendering of the command tree: --tree, --help-format in all its flavors, the Carapace completion spec and shell completion all read the same listing.

$ pipeline --tree
pipeline                    Run the kitchen.
├── prep                    Prep the ingredients.
├── cook                    Cook the dish.
├── plate                   Plate the dish.
└── help [COMMAND_PATH]...  Show help for a command.

Explicit sections

Cloup’s own Section splits a long listing into titled blocks, and carries its own is_sorted flag. Priorities and sort_subcommands address the default section and the flat listings above; a section you declared yourself is left to Cloup.

help subcommand

Every Group automatically includes a help subcommand. It is the standard way to get help in most major CLIs (git, docker, cargo, npm, kubectl, gh).

mycli help shows the group’s own help, and mycli help <subcommand> shows a specific subcommand’s help:

from click_extra import echo, group, option

@group
def restaurant():
    """Restaurant management CLI."""

@restaurant.command()
@option("--city", help="City to search in.")
def find(city):
    """Find nearby restaurants."""
    echo(f"Searching in {city}...")

@restaurant.command()
@option("--stars", type=int, help="Minimum star rating.")
def rate(stars):
    """Rate a restaurant."""
    echo(f"Minimum stars: {stars}")
$ restaurant help
Usage: restaurant [OPTIONS] COMMAND [ARGS]...

  Restaurant management CLI.

Options:
  --time / --no-time           Measure and print elapsed execution time.
                               [default: no-time]
  --config CONFIG_PATH         Location of the configuration file. Supports
                               local path with glob patterns or remote URL.
                               [default: ~/.config/restaurant/{*.toml,*.yaml,*.y
                               ml,*.json,*.json5,*.jsonc,*.hjson,*.ini,*.xml,*.p
                               list,*.sqlite,*.sqlite3,*.conf,pyproject.toml}]
  --no-config                  Ignore all configuration files and only use
                               command line parameters and environment
                               variables.
  --validate-config FILE       Validate the configuration file and exit.
  --export-config FORMAT       Export the configuration in the selected format
                               to <stdout>, then exit.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a borderless, screen-reader-friendly
                               format.
  --color [auto|always|never]  Colorize the output. A bare --color is the same
                               as --color=always.  [default: auto]
  --no-color                   Disable colorization (alias of --color=never).
  --progress / --no-progress   Show progress indicators during long operations.
                               Disabled for non-interactive output (pipes, dumb
                               terminals, CI) and by --accessible.  [default:
                               progress]
  --theme [auto|dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --params                     Show all CLI parameters, their provenance,
                               defaults and value, then exit.
  --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.  [default: rounded-
                               outline]
  --verbosity LEVEL            Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                               [default: WARNING]
  -v, --verbose                Increase the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  -q, --quiet                  Decrease the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  --tree                       Show the tree of nested subcommands and exit.
  --man                        Read the command's manual page and exit.
  --help-format [carapace|json|json-full|man|markdown|markdown-full]
                               Render the command in the given format and exit.
  --version                    Show the version and exit.
  -h, --help                   Show this message and exit.

Commands:
  find  Find nearby restaurants.
  help  Show help for a command.
  rate  Rate a restaurant.
$ restaurant help find
Usage: restaurant find [OPTIONS]

  Find nearby restaurants.

Options:
  --city TEXT  City to search in.
  -h, --help   Show this message and exit.

The help subcommand also supports nested groups. If mycli has a subgroup admin with a command reset, then mycli help admin reset shows the help for reset.

Searching help

The --search option searches all subcommands for matching options or descriptions:

$ restaurant help --search star
  rate: --stars  Minimum star rating.

Disabling the help subcommand

Pass help_command=False to suppress the auto-injected help subcommand:

from click_extra import group

@group(help_command=False)
def bare_cli():
    """A CLI without the help subcommand."""
$ bare-cli help
Usage: bare-cli [OPTIONS] COMMAND [ARGS]...
Try 'bare-cli --help' for help.

Error: No such command 'help'.

If you register your own help subcommand, it replaces the auto-injected one.

Lazily loading subcommands

Click Extra provides a LazyGroup class and @lazy_group decorator to create command groups that only load their subcommands when they are invoked.

This implementation is based on the one provided in Click’s documentation, so refer to the Lazily loading subcommands section for more details.

Each entry of lazy_subcommands maps a subcommand name to the import path of its command object, written as "<module-name>.<command-object-name>":

from click_extra import lazy_group

@lazy_group(lazy_subcommands={
    "apple": "produce.apple_cli",
    "banana": "produce.banana_cli",
    "carrot": "produce.carrot_cli",
})
def basket():
    """Count the produce."""

Invoking apple imports the module holding it, and leaves the other subcommands alone:

$ basket apple
apples = 3

Registration settings

A bare import path registers its subcommand with Cloup’s defaults, which files it under the default help section. Wrap the path in a LazySubcommand to carry the settings Group.add_command() accepts:

from click_extra import LazySubcommand, Section, lazy_group

fruits = Section("Fruits")
vegetables = Section("Vegetables")

@lazy_group(lazy_subcommands={
    "carrot": LazySubcommand("produce.carrot_cli", section=vegetables),
    "apple": LazySubcommand("produce.apple_cli", section=fruits),
    "banana": LazySubcommand("produce.banana_cli", section=fruits),
})
def sectioned_basket():
    """Count the produce."""

Sections show up in the order they are declared, not in the order their subcommands happen to be imported. LazyGroup registers every section as soon as it reads the declaration, so the ordering holds whatever a run imports:

$ sectioned-basket --help
Usage: sectioned-basket [OPTIONS] COMMAND [ARGS]...

  Count the produce.

Options:
  --time / --no-time           Measure and print elapsed execution time.
                               [default: no-time]
  --config CONFIG_PATH         Location of the configuration file. Supports
                               local path with glob patterns or remote URL.
                               [default: ~/.config/sectioned-basket/{*.toml,*.ya
                               ml,*.yml,*.json,*.json5,*.jsonc,*.hjson,*.ini,*.x
                               ml,*.plist,*.sqlite,*.sqlite3,*.conf,pyproject.to
                               ml}]
  --no-config                  Ignore all configuration files and only use
                               command line parameters and environment
                               variables.
  --validate-config FILE       Validate the configuration file and exit.
  --export-config FORMAT       Export the configuration in the selected format
                               to <stdout>, then exit.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a borderless, screen-reader-friendly
                               format.
  --color [auto|always|never]  Colorize the output. A bare --color is the same
                               as --color=always.  [default: auto]
  --no-color                   Disable colorization (alias of --color=never).
  --progress / --no-progress   Show progress indicators during long operations.
                               Disabled for non-interactive output (pipes, dumb
                               terminals, CI) and by --accessible.  [default:
                               progress]
  --theme [auto|dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --params                     Show all CLI parameters, their provenance,
                               defaults and value, then exit.
  --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.  [default: rounded-
                               outline]
  --verbosity LEVEL            Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                               [default: WARNING]
  -v, --verbose                Increase the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  -q, --quiet                  Decrease the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  --tree                       Show the tree of nested subcommands and exit.
  --man                        Read the command's manual page and exit.
  --help-format [carapace|json|json-full|man|markdown|markdown-full]
                               Render the command in the given format and exit.
  --version                    Show the version and exit.
  -h, --help                   Show this message and exit.

Vegetables:
  carrot  Count the carrots.

Fruits:
  apple   Count the apples.
  banana  Count the bananas.

Other commands:
  help    Show help for a command.

Set fallback_to_default_section=False to keep a subcommand out of every section. It disappears from the help screen, and stays invocable:

from click_extra import LazySubcommand, lazy_group

@lazy_group(lazy_subcommands={
    "apple": "produce.apple_cli",
    "carrot": LazySubcommand(
        "produce.carrot_cli", fallback_to_default_section=False
    ),
})
def stealth_basket():
    """Count the produce."""
$ stealth-basket --help
Usage: stealth-basket [OPTIONS] COMMAND [ARGS]...

  Count the produce.

Options:
  --time / --no-time           Measure and print elapsed execution time.
                               [default: no-time]
  --config CONFIG_PATH         Location of the configuration file. Supports
                               local path with glob patterns or remote URL.
                               [default: ~/.config/stealth-basket/{*.toml,*.yaml
                               ,*.yml,*.json,*.json5,*.jsonc,*.hjson,*.ini,*.xml
                               ,*.plist,*.sqlite,*.sqlite3,*.conf,pyproject.toml
                               }]
  --no-config                  Ignore all configuration files and only use
                               command line parameters and environment
                               variables.
  --validate-config FILE       Validate the configuration file and exit.
  --export-config FORMAT       Export the configuration in the selected format
                               to <stdout>, then exit.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a borderless, screen-reader-friendly
                               format.
  --color [auto|always|never]  Colorize the output. A bare --color is the same
                               as --color=always.  [default: auto]
  --no-color                   Disable colorization (alias of --color=never).
  --progress / --no-progress   Show progress indicators during long operations.
                               Disabled for non-interactive output (pipes, dumb
                               terminals, CI) and by --accessible.  [default:
                               progress]
  --theme [auto|dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --params                     Show all CLI parameters, their provenance,
                               defaults and value, then exit.
  --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.  [default: rounded-
                               outline]
  --verbosity LEVEL            Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                               [default: WARNING]
  -v, --verbose                Increase the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  -q, --quiet                  Decrease the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  --tree                       Show the tree of nested subcommands and exit.
  --man                        Read the command's manual page and exit.
  --help-format [carapace|json|json-full|man|markdown|markdown-full]
                               Render the command in the given format and exit.
  --version                    Show the version and exit.
  -h, --help                   Show this message and exit.

Commands:
  apple  Count the apples.
  help   Show help for a command.
$ stealth-basket carrot
carrots = 7

Lazy loading and the help screen

A help screen prints the short help of every subcommand, so --help imports them all. Lazy loading pays off on a plain mycli apple, which imports the one module carrying apple.

Third-party commands composition

Click Extra is capable of composing with existing Click CLI in various situation.

Wrap other commands

Click allows you to build up a hierarchy of command and subcommands. Click Extra inherits this behavior, which means we are free to assemble multiple third-party subcommands into a top-level one.

For this example, let’s imagine you are working for an operation team that is relying daily on a couple of CLIs. Like dbt to manage your data workflows, and aws-sam-cli to deploy them in the cloud.

For some practical reasons, you’d like to wrap all these commands into a big one. This is how to do it.

Note

Here is how I initialized this example on my machine:

$ git clone https://github.com/kdeldycke/click-extra
(...)

$ cd click-extra
(...)

$ python -m pip install uv
(...)

$ uv venv
(...)

$ source .venv/bin/activate
(...)

$ uv sync --all-extras
(...)

$ uv pip install dbt-core
(...)

$ uv pip install aws-sam-cli
(...)

That way I had the latest Click Extra, dbt and aws-sam-cli installed in the same virtual environment:

$ uv run -- dbt --version
Core:
  - installed: 1.6.1
  - latest:    1.6.2 - Update available!

  Your version of dbt-core is out of date!
  You can find instructions for upgrading here:
  https://docs.getdbt.com/docs/installation

Plugins:
$ uv run -- sam --version
SAM CLI, version 1.97.0

Once you identified the entry points of each commands, you can easily wrap them into a top-level Click Extra CLI, here in a local script I called wrap.py:

wrap.py
import click_extra

from samcli.cli.main import cli as sam_cli
from dbt.cli.main import cli as dbt_cli


@click_extra.group(name="wrap.py")
def main():
    pass


main.add_command(cmd=sam_cli, name="aws_sam")
main.add_command(cmd=dbt_cli, name="dbt")


if __name__ == "__main__":
    main()

And this simple script gets rendered into:

$ uv run -- python ./wrap.py
Usage: wrap.py [OPTIONS] COMMAND [ARGS]...

Options:
  --time / --no-time           Measure and print elapsed execution time.
                               [default: no-time]
  --config CONFIG_PATH         Location of the configuration file. Supports
                               local path with glob patterns or remote URL.
                               [default: ~/Library/Application Support/wrap.py/{
                               *.toml,*.yaml,*.yml,*.json,*.json5,*.jsonc,*.hjso
                               n,*.ini,*.xml,*.plist,*.sqlite,*.sqlite3,*.conf,p
                               yproject.toml}]
  --no-config                  Ignore all configuration files and only use
                               command line parameters and environment
                               variables.
  --validate-config FILE       Validate the configuration file and exit.
  --export-config FORMAT       Export the configuration in the selected format
                               to <stdout>, then exit.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a borderless, screen-reader-friendly
                               format.
  --color [auto|always|never]  Colorize the output. A bare --color is the same
                               as --color=always.  [default: auto]
  --no-color                   Disable colorization (alias of --color=never).
  --progress / --no-progress   Show progress indicators during long operations.
                               Disabled for non-interactive output (pipes, dumb
                               terminals, CI) and by --accessible.  [default:
                               progress]
  --theme [auto|dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --params                     Show all CLI parameters, their provenance,
                               defaults and value, then exit.
  --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.  [default: rounded-
                               outline]
  --verbosity LEVEL            Either CRITICAL, ERROR, WARNING, INFO, DEBUG.
                               [default: WARNING]
  -v, --verbose                Increase the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  -q, --quiet                  Decrease the default WARNING verbosity by one
                               level for each additional repetition of the
                               option.  [default: 0]
  --tree                       Show the tree of nested subcommands and exit.
  --man                        Read the command's manual page and exit.
  --help-format [carapace|json|json-full|man|markdown|markdown-full]
                               Render the command in the given format and exit.
  --version                    Show the version and exit.
  -h, --help                   Show this message and exit.

Commands:
  aws_sam  AWS Serverless Application Model (SAM) CLI
  dbt      An ELT tool for managing your SQL transformations and data models.
  help     Show help for a command.

Here you can see that the top-level CLI gets all the default options and behavior (including coloring) of @group. But it also made available the standalone aws_sam and dbt CLI as standard subcommands.

And they are perfectly functional as-is.

You can compare the output of the aws_sam subcommand with its original one:

$ uv run -- python ./wrap.py aws_sam --help
Usage: wrap.py aws_sam [OPTIONS] COMMAND [ARGS]...

  AWS Serverless Application Model (SAM) CLI

  The AWS Serverless Application Model Command Line Interface (AWS SAM CLI) is
  a command line tool that you can use with AWS SAM templates and supported
  third-party integrations to build and run your serverless applications.

  Learn more: https://docs.aws.amazon.com/serverless-application-model/

Commands:

  Learn:
    docs NEW! Launch the AWS SAM CLI documentation in a browser.

  Create an App:
    init                Initialize an AWS SAM application.

  Develop your App:
    build               Build your AWS serverless function code.
    local               Run your AWS serverless function locally.
    validate            Validate an AWS SAM template.
    sync NEW! Sync an AWS SAM project to AWS.
    remote NEW! Invoke or send an event to cloud resources in your AWS
                        Cloudformation stack.

  Deploy your App:
    package             Package an AWS SAM application.
    deploy              Deploy an AWS SAM application.

  Monitor your App:
    logs                Fetch AWS Cloudwatch logs for AWS Lambda Functions or
                        Cloudwatch Log groups.
    traces              Fetch AWS X-Ray traces.

  And More:
    list NEW! Fetch the state of your AWS serverless application.
    delete              Delete an AWS SAM application and the artifacts created
                        by sam deploy.
    pipeline            Manage the continuous delivery of your AWS serverless
                        application.
    publish             Publish a packaged AWS SAM template to AWS Serverless
                        Application Repository for easy sharing.

Options:

    --beta-features / --no-beta-features
                                    Enable/Disable beta features.
    --debug                         Turn on debug logging to print debug message
                                    generated by AWS SAM CLI and display
                                    timestamps.
    --version                       Show the version and exit.
    --info                          Show system and dependencies information.
    -h, --help                      Show this message and exit.

Examples:

    Get Started:        $wrap.py aws_sam init
$ uv run -- sam --help
Usage: sam [OPTIONS] COMMAND [ARGS]...

  AWS Serverless Application Model (SAM) CLI

  The AWS Serverless Application Model Command Line Interface (AWS SAM CLI) is
  a command line tool that you can use with AWS SAM templates and supported
  third-party integrations to build and run your serverless applications.

  Learn more: https://docs.aws.amazon.com/serverless-application-model/

Commands:

  Learn:
    docs NEW! Launch the AWS SAM CLI documentation in a browser.

  Create an App:
    init                Initialize an AWS SAM application.

  Develop your App:
    build               Build your AWS serverless function code.
    local               Run your AWS serverless function locally.
    validate            Validate an AWS SAM template.
    sync NEW! Sync an AWS SAM project to AWS.
    remote NEW! Invoke or send an event to cloud resources in your AWS
                        Cloudformation stack.

  Deploy your App:
    package             Package an AWS SAM application.
    deploy              Deploy an AWS SAM application.

  Monitor your App:
    logs                Fetch AWS Cloudwatch logs for AWS Lambda Functions or
                        Cloudwatch Log groups.
    traces              Fetch AWS X-Ray traces.

  And More:
    list NEW! Fetch the state of your AWS serverless application.
    delete              Delete an AWS SAM application and the artifacts created
                        by sam deploy.
    pipeline            Manage the continuous delivery of your AWS serverless
                        application.
    publish             Publish a packaged AWS SAM template to AWS Serverless
                        Application Repository for easy sharing.

Options:

    --beta-features / --no-beta-features
                                    Enable/Disable beta features.
    --debug                         Turn on debug logging to print debug message
                                    generated by AWS SAM CLI and display
                                    timestamps.
    --version                       Show the version and exit.
    --info                          Show system and dependencies information.
    -h, --help                      Show this message and exit.

Examples:

    Get Started:        $sam init

Here is the highlighted differences to make them even more obvious:

@@ -1,5 +1,5 @@
-$ uv run -- python ./wrap.py aws_sam --help
-Usage: wrap.py aws_sam [OPTIONS] COMMAND [ARGS]...
+$ uv run -- sam --help
+Usage: sam [OPTIONS] COMMAND [ARGS]...

   AWS Serverless Application Model (SAM) CLI

@@ -56,4 +56,4 @@

 Examples:

-    Get Started:        $wrap.py aws_sam init
+    Get Started:        $sam init

Now that all commands are under the same umbrella, there is no limit to your imagination!

Caution

This might looks janky, but this franken-CLI might be a great way to solve practical problems in your situation.

You can augment them with your custom glue code. Or maybe mashing them up will simplify the re-distribution of these CLIs on your production machines. Or control their common dependencies. Or freeze their versions. Or hard-code some parameters. Or apply monkey-patches. Or chain these commands to create new kind of automation…

There is a miriad of possibilities. If you have some other examples in the same vein, please share them in an issue or even directly via a PR. I’d love to complement this documentation with creative use-cases.

click_extra.commands API

        classDiagram
  ColorizedCommand <|-- HelpCommand
  Command <|-- ColorizedCommand
  Command <|-- Command
  Command <|-- Group
  Group <|-- ColorizedGroup
  Group <|-- Group
  Group <|-- LazyGroup
  _HelpColorsMixin <|-- ColorizedCommand
  _HelpColorsMixin <|-- ColorizedGroup
  _HelpColorsMixin <|-- Command
    

Wraps vanilla Click and Cloup commands with extra features.

Our flavor of commands, groups and context are all subclasses of their vanilla counterparts, but are pre-configured with good and common defaults. You can still use the mixins in here to build up your own custom variants.

click_extra.commands.DEFAULT_PRIORITY: Final[float] = 100.0

Implicit priority of any subcommand or option left unnumbered.

Priorities order the subcommands of a Group and the options of a Command, lowest first. Anything the author did not number sits on this line, so a lone {"prep": 1} promotes prep without displacing the rest, and a number above 100 demotes.

Note

Priorities are floats, not integers, so a new entry can be wedged between two existing ones without renumbering: 1.5 lands between 1 and 2.

That trick is as old as interactive computing. JOSS, which RAND put online in 1963, required every line number to be a pair of integers separated by a period (1.1, 10.12): a page and a line within it, jointly a step. DEC’s FOCAL carried the scheme to the PDP-8, with steps running from 1.01 to 31.99. BASIC numbered lines with plain integers, and its 10, 20, 30 convention is programmers buying back the same insertion room by hand.

click_extra.commands.EXTRA_OPTION_SETTINGS: tuple[str, ...] = ('show_choices', 'show_envvar')

Click Extra context settings forced onto every option when set to non-None.

click_extra.commands.default_params(screen=None)[source]

Default additional options added to @command and @group.

Parameters:

screen (VersionScreen | None) –

a VersionScreen for --version to draw in place of its one-line message. Reach it through the params hook, binding the screen with functools.partial so each decorated command still gets its own fresh option instances:

@group(params=partial(default_params, screen=MY_SCREEN))
def cli():
    pass

Return type:

list[Option]

Caution

The order of options has been carefully crafted to handle subtle edge-cases and avoid leaky states in unit tests.

You can still override this hard-coded order for aesthetic reasons and it should be fine. Your end-users are unlikely to be affected by these sneaky bugs, as the CLI context is going to be naturally reset after each invocation (which is not the case in unit tests).

  1. --time / --no-time

    Hint

    --time is placed at the top of all other eager options so all other options’ processing time can be measured.

  2. --config CONFIG_PATH

    Hint

    --config is at the top so it can have a direct influence on the default behavior and value of the other options.

  3. --no-config

  4. --validate-config CONFIG_PATH

  5. --export-config FORMAT

  6. --accessible

    Hint

    --accessible is placed before --color and --table-format so it can lower their defaults (via default_map) before they are resolved.

  7. --color / --no-color

  8. --progress / --no-progress

  9. --theme

  10. --params

  11. --table-format FORMAT

  12. --verbosity LEVEL

  13. -v, --verbose

  14. -q, --quiet

  15. --tree

  16. --man

  17. --help-format FORMAT

  18. --version

  19. -h, --help

    Attention

    This is the option produced by the @click.decorators.help_option decorator.

    It is not explicitly referenced in the implementation of this function.

    That’s because it’s going to be added by Click itself, at the end of the list of options. By letting Click handle this, we ensure that the help option will take into account the help_option_names setting.

Note

The list below is the processing order, and it is the only one these edge-cases care about. The help screen reads a separate presentation order, which the option_priorities argument of @command and @group reshuffles without touching a single callback. See param_priority(), added for click_extra#544 issue.

class click_extra.commands.Command(*args, version_fields=None, config_schema=None, config_strict=False, schema_strict=False, fallback_sections=(), config_validators=(), included_params=None, excluded_params=None, extra_option_at_end=True, option_priorities=None, populate_auto_envvars=True, extra_keywords=None, excluded_keywords=None, examples=(), **kwargs)[source]

Bases: _HelpColorsMixin, Command

Like cloup.command, with sane defaults and extra help screen colorization.

List of extra parameters:

Parameters:
  • version_fields (dict[str, Any] | None) – dictionary of VersionOption template field overrides forwarded to the version option. Accepts any field from VersionOption.template_fields (like prog_name, version, git_branch). Lets you customize --version output from the command decorator without replacing the default params list.

  • config_strict (bool) – forwarded to the default ConfigOption’s strict setting: configuration keys not matching any CLI parameter raise an error instead of being silently ignored. Like the other config_* and *_params forwards, it spares you from replacing the whole default params list to customize the config option.

  • excluded_params (Sequence[str] | None) – additional parameter IDs to block from configuration files, merged into the default ConfigOption’s excluded_params blocklist. Additive, unlike the option-level excluded_params which replaces the default blocklist entirely. Items are fully-qualified parameter IDs (like mycli.mail_sources). Mutually exclusive with included_params.

  • extra_keywords (HelpKeywords | None) – a HelpKeywords instance whose entries are merged into the auto-collected keyword set. Use this to inject additional strings for help screen highlighting.

  • excluded_keywords (HelpKeywords | None) – a HelpKeywords instance whose entries are removed from the auto-collected keyword set. Use this to suppress highlighting of specific strings.

  • examples (Sequence[Sequence[str]]) – a sequence of (description, command) string pairs showing the command in use. They are rendered in an Examples: section of the help screen, in the man page, and in every –help-format rendering. A malformed pair raises TypeError here, at command construction, rather than on the first --help a user runs.

  • extra_option_at_end (bool) – reorders all parameters attached to the command, by moving all instances of ExtraOption at the end of the parameter list. The original order of the options is preserved among themselves.

  • option_priorities (Mapping[str, float] | None) – maps an option to its priority in the help screen, relative to DEFAULT_PRIORITY, lowest shown first. Keys are matched against each parameter’s long and short flags first, then its destination name, so the --config / --no-config pair (which shares the config destination) stays addressable one flag at a time. Presentation only: self.params, and with it the order callbacks are evaluated in, is left alone. Positional arguments are never reordered, their sequence being part of the command’s grammar.

  • populate_auto_envvars (bool) – forces all parameters to have their auto-generated environment variables registered. This address the shortcoming of click which only evaluates them dynamically. By forcing their registration, the auto-generated environment variables gets displayed in the help screen, fixing click#2483 issue. On Windows, environment variable names are case-insensitive, so we normalize them to uppercase.

By default, these Click context settings are applied:

Additionally, these Cloup context settings are set:

Click Extra also adds its own context_settings:

  • show_choices = None (Click Extra feature)

    If set to True or False, will force that value on all options, so we can globally show or hide choices when prompting a user for input. Only makes sense for options whose prompt property is set.

    Defaults to None, which will leave all options untouched, and let them decide of their own show_choices setting.

  • show_envvar = None (Click Extra feature)

    If set to True or False, will force that value on all options, so we can globally enable or disable the display of environment variables in help screen.

    Defaults to None, which will leave all options untouched, and let them decide of their own show_envvar setting. The rationale being that discoverability of environment variables is enabled by the --params option, which is active by default on extra commands. So there is no need to surcharge the help screen.

    This addresses the click#2313 issue.

To override these defaults, you can pass your own settings with the context_settings parameter:

@command(
    context_settings={
        "show_default": False,
        ...
    }
)
context_class

alias of Context

examples: tuple[tuple[str, str], ...] = ()

(description, command) pairs showing the command in use.

Normalized from the examples constructor argument by normalize_examples(). Declared here so the attribute exists on every command, whether or not its author passed any: the renderers reading it (help screen, man page, and every HELP_FORMATS backend) then need no guard.

option_priorities: dict[str, float]
context_settings: dict[str, Any]

an optional dictionary with defaults passed to the context.

param_priority(param)[source]

Priority of param in the help screen.

Defaults to DEFAULT_PRIORITY, and is otherwise resolved against option_priorities by trying each of the parameter’s flags in turn, then its destination name.

Important

This orders the help screen alone. The order of self.params decides when each callback fires: click.core.iter_params_for_processing sorts on (not is_eager, position on the command line), and every eager option the user did not type ties on that second key, leaving declaration order as the tie-break. That is what puts --time ahead of everything it measures and --accessible ahead of the --color default it lowers, so the two orders have to be free to disagree.

Positional arguments always resolve to the default: their sequence is part of the command’s grammar, not a matter of presentation.

Return type:

float

main(args=None, prog_name=None, **kwargs)[source]

Pre-invocation step that is instantiating the context, then call invoke() within it.

Caution

During context instantiation, each option’s callbacks are called. These might break the execution flow (like --help or --version).

Sets the default CLI’s prog_name to the command’s name if not provided, instead of relying on Click’s auto-detection via the _detect_program_name() method. This is to avoid the CLI being called python -m <module_name>, which is not very user-friendly.

Return type:

Any

make_context(info_name, args, parent=None, **extra)[source]

Intercept the call to the original click.core.Command.make_context so we can keep a copy of the raw, pre-parsed arguments provided to the CLI.

The result are passed to our own Context constructor which is able to initialize the context’s meta property under our own click_extra.context.RAW_ARGS entry. This will be used in ShowParamsOption.print_params() to print the table of parameters fed to the CLI.

See also

See click_extra.context.RAW_ARGS for the full rationale and the upstream-proposal notes (related: click#1279).

Return type:

Any

format_examples(ctx, formatter)[source]

Write an Examples: section listing the command’s examples.

Each entry renders its description, then the command line it describes, indented behind a $ prompt. A command declaring none writes nothing at all, so a help screen only grows the section when it has something to put in it.

The command lines go out verbatim rather than through formatter.write_text(): an example exists to be copied, and Click’s text wrapper would fold a long one onto a second line mid-token. This is the same call the \b no-rewrap marker makes for help prose.

Nothing here styles anything. The lines land in the formatter’s buffer, which getvalue() runs through keyword highlighting on its way out, so the option names, subcommands and CLI names inside an example are painted by the same pass that paints them everywhere else.

Return type:

None

format_epilog(ctx, formatter)[source]

Insert the examples section ahead of the epilog.

Places it after the options and subcommands, which is where a reader arrives once they know what the command accepts, and keeps the author’s own epilog as the last word on the screen.

Return type:

None

parse_args(ctx, args)[source]

Like parent’s parse_args but with better error messages for single-dash multi-character tokens.

Also settles the presentation options before delegating, so --color, --no-color, --accessible and --theme reach the eager help and version screens regardless of their position on the command line. See _resolve_presentation_eagerly.

Return type:

list[str]

class click_extra.commands.ColorizedCommand(name, context_settings=None, callback=None, params=None, help=None, epilog=None, short_help=None, options_metavar='[OPTIONS]', add_help_option=True, no_args_is_help=False, hidden=False, deprecated=False)[source]

Bases: _HelpColorsMixin, Command

Click Command with help colorization but no extra params.

Mixes in _HelpColorsMixin for keyword highlighting and uses Context for the colorized formatter, without inheriting from Command (which would inject default_params).

Use this as a base for lightweight subcommands (like help) or for monkey-patching third-party CLIs (via patch_click()).

context_class

alias of Context

class click_extra.commands.ColorizedGroup(name=None, commands=None, invoke_without_command=False, no_args_is_help=None, subcommand_metavar=None, chain=False, result_callback=None, **kwargs)[source]

Bases: _HelpColorsMixin, Group

Click Group with help colorization but no extra params.

Same as ColorizedCommand but for groups.

context_class

alias of Context

class click_extra.commands.HelpCommand(name, context_settings=None, callback=None, params=None, help=None, epilog=None, short_help=None, options_metavar='[OPTIONS]', add_help_option=True, no_args_is_help=False, hidden=False, deprecated=False)[source]

Bases: ColorizedCommand

Synthetic subcommand that displays help for the parent group or a subcommand.

Auto-injected into every Group. Supports nested resolution: mycli help subgroup subcmd shows the help for subcmd within subgroup.

invoke(ctx)[source]

Resolve the command path and display its help.

Return type:

None

class click_extra.commands.Group(*args, help_command=True, sort_subcommands=None, subcommand_priorities=None, **kwargs)[source]

Bases: Command, Group

Like cloup.Group, with sane defaults and extra help screen colorization.

Like Command.__init__, but auto-injects a help subcommand.

Parameters:
  • help_command (bool) – when True (the default), a help subcommand is automatically registered. Set to False to suppress it, or register your own help subcommand to override it.

  • sort_subcommands (bool | None) – how subcommands sharing a priority are broken apart. True lists them alphabetically, False in the order they were registered. None (the default) defers to the sort_subcommands context setting, then to True. See must_sort_subcommands().

  • subcommand_priorities (Mapping[str, float] | None) – maps a subcommand name to its priority relative to DEFAULT_PRIORITY, lowest listed first. Names left out keep the default priority, so numbering a few subcommands moves only those.

command_class

Makes commands of a Group be instances of Command.

That way all subcommands created from a Group benefits from the same defaults and extra help screen colorization.

See: https://click.palletsprojects.com/en/stable/api/#click.Group.command_class

alias of Command

group_class

Let Group produce sub-groups that are also of Group type.

See: https://click.palletsprojects.com/en/stable/api/#click.Group.group_class

alias of type

subcommand_priorities: dict[str, float]
must_sort_subcommands(ctx)[source]

Resolve whether subcommand listings are alphabetical.

Reads the group’s own sort_subcommands, then the context setting of the same name, then falls back to True. This is the resolution order Cloup uses for align_sections, and it is what lets a single context_settings={"sort_subcommands": False} on the root group reach every subgroup below it instead of being repeated on each.

Return type:

bool

subcommand_priority(name)[source]

Priority of the name subcommand.

Defaults to DEFAULT_PRIORITY.

Return type:

float

list_commands(ctx)[source]

Subcommand names in presentation order.

Sorted on subcommand_priorities first, then broken apart by must_sort_subcommands(): alphabetically, or by registration order. With no priority declared every subcommand ties, leaving the tie-break as the only ordering, which is Click’s plain alphabetical listing.

In registration order the auto-injected help subcommand is listed last, wherever it happens to have been registered: Group.__init__ appends it before any @cli.command() decorator runs, while a commands=[…] constructor argument lands it after, so its natural position says nothing about the author’s intent. Mirrors what extra_option_at_end does to options.

Return type:

list[str]

list_sections(ctx, include_default_section=True)[source]

Like cloup.Group.list_sections, but ordering the default section.

Cloup hard-codes the default section to Section.sorted(…), which is why overriding list_commands() alone leaves the help screen alphabetical: the screen is rendered from sections and never calls it. Rebuild that section from list_commands() instead, and hand it over already ordered.

Note

Sections the author declared themselves are returned untouched. Cloup’s own Section(is_sorted=…) already governs those, and a user holding a Section instance should not have it rewritten underneath them. Priorities and sort_subcommands therefore address the default section and the flat listings (--tree, man pages, completion specs), not the contents of an explicit section.

Return type:

list[Section]

add_command(cmd, name=None, **kwargs)[source]

Like cloup.Group.add_command, but replaces an auto-injected HelpCommand when the user registers their own help subcommand.

Return type:

None

invoke(ctx)[source]

Inject _default_subcommands and _prepend_subcommands from config.

If the user has not provided any subcommands explicitly, and the loaded configuration contains a _default_subcommands list for this group, those subcommands are injected into ctx.protected_args so that Click’s normal Group.invoke() dispatches them.

_prepend_subcommands always prepends subcommands to the invocation, regardless of whether CLI subcommands were provided. Only works with chain=True groups.

Return type:

Any

class click_extra.commands.LazySubcommand(import_path, section=None, fallback_to_default_section=True)[source]

Bases: object

Declaration of a lazily-imported subcommand of a LazyGroup.

Carries the registration settings cloup.Group.add_command() accepts, which a bare import path cannot express. A subcommand needing none of them is declared as a plain string instead.

import_path: str

Where to import the command object from, as "<module-name>.<command-name>".

section: Section | None = None

Help-screen section the subcommand is filed under, once imported.

A section declared here is registered on the group right away, so the help screen orders its sections as they are declared, not as their subcommands happen to be imported. The same Section instance can be shared with eagerly-registered subcommands.

fallback_to_default_section: bool = True

Whether to file the subcommand under the default section when section is None.

Set to False to leave the subcommand out of every section, which hides it from the help screen while keeping it invocable. Cloup calls this an escape hatch for internal code: do not disable it unless you know what you are doing.

class click_extra.commands.LazyGroup(*args, lazy_subcommands=None, **kwargs)[source]

Bases: Group

A Group that supports lazy loading of subcommands.

Hint

This implementation is based on the snippet from Click’s documentation: Defining the lazy group.

It has been extended to work with Click Extra’s config_option in click_extra#1332 issue.

lazy_subcommands maps command names to their import paths.

Tip

lazy_subcommands is a map of the form:

{"<command-name>": "<module-name>.<command-object-name>"}

For example:

{"mycmd": "my_cli.commands.mycmd"}

A subcommand needing registration settings on top of its import path is declared with a LazySubcommand instead of a bare string:

{"mycmd": LazySubcommand("my_cli.commands.mycmd", section=my_section)}

Every section declared that way is registered on the group here, so the help screen orders its sections as the author declared them. Waiting for each subcommand to be imported would instead order them by import, which is alphabetical and says nothing about intent.

lazy_subcommands: dict[str, LazySubcommand]
get_command(ctx, cmd_name)[source]

Get a command by name, loading lazily if necessary.

Return type:

Command | None