Build Python CLIs with Click using commands, groups, parameters, shell completion, testing, and packaging-aware guidance.
Use this skill when building or reviewing a Python CLI that uses Click directly rather than a higher-level wrapper.
@click.command() and @click.group() designclick.echo()click.testing.CliRunner@click.command() for a leaf command and @click.group() for a
command tree.click.echo() for user-facing text because it handles Unicode
and styles more robustly than raw print().@click.option() and @click.argument() instead of manual
argv parsing.@group.command() for nearby subcommands.group.add_command() when commands live in separate modules or
are registered later.python script.py.shell_complete= or ParamType.shell_complete() for custom
value completion.CliRunner.
runner.invoke() for exit codes, output, and exceptions.runner.isolated_filesystem() for file-based behavior.input= for prompts.import click
@click.group()
def cli():
pass
@cli.command()
@click.option("--count", default=1, help="Number of greetings.")
@click.argument("name")
def hello(count, name):
for _ in range(count):
click.echo(f"Hello {name}!")
if __name__ == "__main__":
cli()
from click.testing import CliRunner
from .hello import hello
def test_hello_world():
runner = CliRunner()
result = runner.invoke(hello, ["Peter"])
assert result.exit_code == 0
assert result.output == "Hello Peter!\n"
from click.testing import CliRunner
from .cat import cat
def test_cat():
runner = CliRunner()
with runner.isolated_filesystem():
with open("hello.txt", "w", encoding="utf-8") as handle:
handle.write("Hello World!")
result = runner.invoke(cat, ["hello.txt"])
assert result.exit_code == 0
assert result.output == "Hello World!\n"
import os
import click
def complete_env_vars(ctx, param, incomplete):
return [name for name in os.environ if name.startswith(incomplete)]
@click.command()
@click.argument("name", shell_complete=complete_env_vars)
def show(name):
click.echo(os.environ[name])
When refining this skill or reviewing advice produced with it:
print() as a conscious exception, not the default recommendation,
when click.echo() would be more robustCliRunner-based tests for normal CLI behavior