Most real tools have several actions (init, run, deploy); groups organise them under one entry point.
A group is a command that dispatches to subcommands:
@click.group()
def cli(): ...
@cli.command()
def init(): ...Now cli init runs init, and cli --help lists the subcommands with their short help. Commands can also be defined separately and attached with cli.add_command(cmd), which is how large CLIs split commands across modules.
Options declared on the group belong before the subcommand: cli --verbose init, not cli init --verbose. The group's function runs first (useful for setup such as configuring logging), then the subcommand's.
Groups nest: a subcommand can itself be a group, giving cli db migrate.
Useful settings:
invoke_without_command=Truelets the group run when called alone; checkctx.invoked_subcommandto know whether a subcommand follows.chain=Trueallows several subcommands in one invocation, likecli build test deploy.@cli.command("custom-name")sets a name different from the function's; Click also converts underscores to dashes automatically.no_args_is_help=Trueshows help instead of an error when no subcommand is given (the default for groups).
Commands are listed alphabetically in help by default. Sharing state between the group and its subcommands is done with the context object, covered next.
Example
import click
@click.group()
@click.option("--verbose", is_flag=True, help="Print extra details.")
def cli(verbose):
"""Manage the project."""
if verbose:
click.echo("[verbose mode]")
@cli.command()
@click.argument("name")
def init(name):
click.echo(f"Initialised {name}")
@cli.group()
def db():
"""Database commands."""
@db.command("migrate")
@click.option("--to", default="head")
def db_migrate(to):
click.echo(f"Migrating to {to}")
cli.main(["--verbose", "init", "demo"], standalone_mode=False) # [verbose mode] / Initialised demo
cli.main(["db", "migrate", "--to", "042"], standalone_mode=False) # Migrating to 042Remember
- @click.group() plus @group.command() builds subcommands
- Group options go before the subcommand name
- Groups nest; add_command assembles commands from other modules
Watch out for
- Passing a group option after the subcommand (cli init --verbose), which the subcommand rejects.