Skilllibrary cli-development-python
install
source · Clone the upstream repo
git clone https://github.com/merceralex397-collab/skilllibrary
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/merceralex397-collab/skilllibrary "$T" && mkdir -p ~/.claude/skills && cp -r "$T/10-cli-systems-and-ops/cli-development-python" ~/.claude/skills/merceralex397-collab-skilllibrary-cli-development-python && rm -rf "$T"
manifest:
10-cli-systems-and-ops/cli-development-python/SKILL.mdsource content
Purpose
Build Python CLI tools using Click or Typer with proper argument handling, output formatting, and packaging.
When to use this skill
- creating a new Python CLI tool with commands and subcommands
- adding Click decorators or Typer type hints for argument parsing
- implementing
,--verbose
, or--json
output modes--quiet - packaging a CLI with
entry pointspyproject.toml
Do not use this skill when
- building a Go CLI — prefer
cli-development-go - writing a Bash script — prefer
bash - building an interactive TUI — prefer
tui-development
Procedure
- Choose framework — use Typer for new projects (type-hint based, auto-generates help); use Click for complex option inheritance or plugins.
- Define app and commands — create
and decorate functions withapp = typer.Typer()
.@app.command() - Add typed arguments — use
for positional args,Annotated[str, typer.Argument(help="...")]
for flags.typer.Option - Implement callbacks — use
for shared state (verbosity, config path) passed via@app.callback()
.typer.Context - Format output — use
for tables/panels,rich.console.Console
forjson.dumps(indent=2)
, plain text for--json
.--quiet - Handle errors — catch expected exceptions, print with
, raiserich.console.print("[red]Error:[/red] ...")
.typer.Exit(code=1) - Add completions — Typer auto-generates shell completions; run
.myapp --install-completion - Package — add
in[project.scripts]
:pyproject.toml
. Install withmyapp = "myapp.cli:app"
.pip install -e .
Key patterns
import typer from typing import Annotated from rich.console import Console app = typer.Typer(help="My CLI tool") console = Console() @app.callback() def main(ctx: typer.Context, verbose: Annotated[bool, typer.Option("--verbose", "-v")] = False): ctx.ensure_object(dict) ctx.obj["verbose"] = verbose @app.command() def greet( name: Annotated[str, typer.Argument(help="Name to greet")], count: Annotated[int, typer.Option(help="Repetitions")] = 1, json_out: Annotated[bool, typer.Option("--json")] = False, ): if json_out: import json print(json.dumps({"name": name, "count": count})) else: for _ in range(count): console.print(f"[green]Hello[/green], {name}!")
Decision rules
- Prefer Typer over Click for new projects — less boilerplate, better type safety.
- Use
types (Typer >= 0.9) instead of default value syntax.Annotated - Never call
directly — usesys.exit()
.raise typer.Exit(code=N) - Test CLI commands with
or Click'styper.testing.CliRunner
.CliRunner - Pin CLI deps in
withpyproject.toml
lower bounds, not exact pins.>=
References
Related skills
— Go CLI patternscli-development-go
— shell scriptingbash
— interactive terminal UIstui-development