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,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.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a plain, 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 [dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --show-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]
  --man                        Show the command's man page (roff) 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:485: UserWarning: The parameter --version is used more than once. Remove its duplicate as parameters should be unique.
  self._resolve_color_eagerly(ctx, args)
/home/runner/work/click-extra/click-extra/.venv/lib/python3.14/site-packages/click/core.py:1262: 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:1085: 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

Notice how the options above are ordered in the help message.

The default behavior of @command is to order options in the way they are provided to the params= argument of the decorator. Then adds to that list the additional option decorators positioned after the @command decorator.

After that, there is a final sorting step applied by Command. This is done by the extra_option_at_end option, which is True by default.

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,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.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a plain, 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 [dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --show-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]
  --man                        Show the command's man page (roff) 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,pyproj
                               ect.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.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a plain, 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 [dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --show-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]
  --man                        Show the command's man page (roff) 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

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,pyp
                               roject.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.
  --accessible                 Accessibility mode: disable colors and render
                               tables in a plain, 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 [dark|dracula|light|manpage|monokai|nord|solarized_dark]
                               Color theme used for help screens.  [default:
                               dark]
  --show-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]
  --man                        Show the command's man page (roff) 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.

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
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]
  --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).
  --config CONFIG_PATH  Location of the configuration file. Supports glob
                        pattern of local path and remote URL.  [default:
                        ~/Library/Application
                        Support/wrap.py/*.{toml,yaml,yml,json,ini,xml}]
  --no-config           Ignore all configuration files and only use command line
                        parameters and environment variables.
  --show-params         Show all CLI parameters, their provenance, defaults and
                        value, then exit.
  --table-format [asciidoc|csv|csv-excel|csv-excel-tab|csv-unix|double-grid|double-outline|fancy-grid|fancy-outline|github|grid|heavy-grid|heavy-outline|html|jira|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|tsv|unsafehtml|vertical|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]
  --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.

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_params()[source]

Default additional options added to @command and @group.

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. --accessible

    Hint

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

  6. --color / --no-color

  7. --progress / --no-progress

  8. --theme

  9. --show-params

  10. --table-format FORMAT

  11. --verbosity LEVEL

  12. -v, --verbose

  13. -q, --quiet

  14. --man

  15. --version

  16. -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.

Todo

For bullet-proof handling of edge-cases, we should probably add an indirection layer to have the processing order of options (the one below) different from the presentation order of options in the help screen.

This is probably something that has been requested in issue #544.

Return type:

list[Option]

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.

class click_extra.commands.Command(*args, version_fields=None, config_schema=None, schema_strict=False, fallback_sections=(), config_validators=(), included_params=None, extra_option_at_end=True, populate_auto_envvars=True, extra_keywords=None, excluded_keywords=None, **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.

  • 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.

  • 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.

  • 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 --show-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

context_settings: dict[str, Any]

an optional dictionary with defaults passed to the context.

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

parse_args(ctx, args)[source]

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

Also settles the color options before delegating, so --color / --no-color colorize the eager help and version screens regardless of their position on the command line. See _resolve_color_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, **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.

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

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.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"}
lazy_subcommands: dict[str, str]
list_commands(ctx)[source]

List all commands, including not-yet-loaded lazy subcommands.

Return type:

list[str]

get_command(ctx, cmd_name)[source]

Get a command by name, loading lazily if necessary.

Todo

Allow passing extra parameters to the self.lazy_subcommands so we can register commands with custom settings like Cloup’s section or fallback_to_default_section:

  • section: Section | None = None,

  • fallback_to_default_section: bool = True,

See: https://github.com/janluke/cloup/blob/master/cloup/_sections.py#L169

Return type:

Command | None