Completion makes large CLIs discoverable and is expected of polished tools.
Click has built-in completion for bash (4.4+), zsh, fish and, since 8.5, PowerShell. It works for installed entry points (not python script.py). Completion is activated by an environment variable named after the program: for my-tool it is _MY_TOOL_COMPLETE.
Users generate a script once and source it from their shell config:
_MY_TOOL_COMPLETE=bash_source my-tool > ~/.my-tool-complete.bash
echo '. ~/.my-tool-complete.bash' >> ~/.bashrcwith zsh_source, fish_source or powershell_source for the other shells. Document this in your README or offer a completion subcommand that prints it.
Out of the box Click completes subcommand names, option names, Choice values, and file paths for Path and File types.
For dynamic values (git branches, server names), pass shell_complete=fn to a parameter. The function receives (ctx, param, incomplete) and returns a list of strings or click.shell_completion.CompletionItem objects (which can carry help text shown by zsh and fish). Filter by the incomplete prefix yourself.
Completion runs your program with ctx.resilient_parsing = True: callbacks and prompts are skipped and errors suppressed. Keep completion functions fast, avoid side effects, and remember that your module is imported on every keypress-triggered completion, which is a strong reason to keep top-level imports light.
Example
import click
from click.shell_completion import CompletionItem
ENVIRONMENTS = {"dev": "local cluster", "staging": "pre-prod", "prod": "live!"}
def complete_env(ctx, param, incomplete):
return [CompletionItem(name, help=desc)
for name, desc in ENVIRONMENTS.items() if name.startswith(incomplete)]
@click.command()
@click.argument("env", shell_complete=complete_env)
@click.option("--format", type=click.Choice(["json", "table"]))
def status(env, format):
click.echo(f"{env}: ok")
items = complete_env(None, None, "st")
print([(i.value, i.help) for i in items]) # [('staging', 'pre-prod')]
# Users enable it once for the installed command `status`:
# eval "$(_STATUS_COMPLETE=bash_source status)"Remember
- Built-in completion for bash, zsh, fish and (8.5+) PowerShell via _PROG_COMPLETE
- Choices, subcommands and paths complete automatically
- shell_complete=fn returns CompletionItems for dynamic values
Watch out for
- Doing slow network calls in shell_complete without caching, making Tab hang.