Click
Click builds CLIs with decorators. It handles help text, type conversion, subcommands, and terminal output better than raw argparse.
Search across all documentation pages
Click builds CLIs with decorators. It handles help text, type conversion, subcommands, and terminal output better than raw argparse.
import click
@click.command()
@click.option("--name", default="World", help="Who to greet")
def hello(name):
click.echo(f"Hello, {name}!")
if __name__ == "__main__":
hello()When to reach for this:
import click
@click.group()
@click.option("--verbose", "-v", is_flag=True)
@click.pass_context
def cli(ctx, verbose):
ctx.ensure_object(dict)
ctx.obj["verbose"] = verbose
@cli.command()
@click.argument("filename", type=click.Path(exists=True))
@click.option("--format", type=click.Choice(["json", "csv"]), default="json")
@click.pass_context
def convert(ctx, filename, format):
if ctx.obj["verbose"]:
click.echo(f"Converting {filename} to {format}", err=True)
# conversion logic
click.echo(f"Done: {filename}")
@cli.command()
@click.option("--force", is_flag=True, help="Skip confirmation")
def clean(force):
if not force and not click.confirm("Delete all temp files?"):
raise click.Abort()
click.echo("Cleaned.")
if __name__ == "__main__":
cli()What this demonstrates:
@click.group() for subcommandsclick.Path(exists=True) validates file pathsclick.Choice restricts option valuesclick.confirm for interactive promptserr=True sends verbose output to stderr| Feature | Click | argparse |
|---|---|---|
| Syntax | Decorators | Imperative |
| Help formatting | Rich | Basic |
| Testing | CliRunner | parse_args |
| Prompts | Built-in | Manual |
click.echo - encoding issues on Windows. Fix: always click.echo, not print.pass_context - parent options unavailable. Fix: @click.pass_context and ctx.obj.CliRunner in pytest.[project.scripts].| Alternative | Use When | Don't Use When |
|---|---|---|
| Typer | Type hints preferred | No typing in project |
| argparse | Zero dependencies | Rich CLI needed |
| cyclopts | Dataclass config | Team knows Click |
Typer if you use type hints everywhere. Click for more control and maturity.
from click.testing import CliRunner; runner = CliRunner(); runner.invoke(cli, ["convert", "f.txt"]).
@click.group() + install completion: _MYAPP_COMPLETE=bash_source myapp.
Let exceptions propagate for tracebacks, or catch and raise click.ClickException("msg") for clean errors.
Multiple @click.argument() decorators in order.
@click.option("--host", envvar="HOST", default="localhost").
with click.progressbar(items) as bar: ....
Use @click.command() with asyncio.run() inside, or asyncclick fork.
@click.version_option() decorator.
Groups can contain groups: @cli.group() inside another group.
Stack versions: This page was written for Python 3.14.0, FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 19, 2026