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.md
source 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
    ,
    --json
    , or
    --quiet
    output modes
  • packaging a CLI with
    pyproject.toml
    entry points

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

  1. Choose framework — use Typer for new projects (type-hint based, auto-generates help); use Click for complex option inheritance or plugins.
  2. Define app and commands — create
    app = typer.Typer()
    and decorate functions with
    @app.command()
    .
  3. Add typed arguments — use
    Annotated[str, typer.Argument(help="...")]
    for positional args,
    typer.Option
    for flags.
  4. Implement callbacks — use
    @app.callback()
    for shared state (verbosity, config path) passed via
    typer.Context
    .
  5. Format output — use
    rich.console.Console
    for tables/panels,
    json.dumps(indent=2)
    for
    --json
    , plain text for
    --quiet
    .
  6. Handle errors — catch expected exceptions, print with
    rich.console.print("[red]Error:[/red] ...")
    , raise
    typer.Exit(code=1)
    .
  7. Add completions — Typer auto-generates shell completions; run
    myapp --install-completion
    .
  8. Package — add
    [project.scripts]
    in
    pyproject.toml
    :
    myapp = "myapp.cli:app"
    . Install with
    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
    Annotated
    types (Typer >= 0.9) instead of default value syntax.
  • Never call
    sys.exit()
    directly — use
    raise typer.Exit(code=N)
    .
  • Test CLI commands with
    typer.testing.CliRunner
    or Click's
    CliRunner
    .
  • Pin CLI deps in
    pyproject.toml
    with
    >=
    lower bounds, not exact pins.

References

Related skills

  • cli-development-go
    — Go CLI patterns
  • bash
    — shell scripting
  • tui-development
    — interactive terminal UIs