From python-engineering
Develops Python CLI apps with Typer and Rich. Covers app structure, Annotated parameters, subcommands, async patterns, Rich terminal output, and CliRunner testing.
How this skill is triggered — by the user, by Claude, or both
Slash command
/python-engineering:python3-cliThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Consult `python3-core` for standing defaults. Load `python3-testing` for test patterns.
assets/nested-typer-exceptions/nested-typer-exception-explosion.pyassets/nested-typer-exceptions/nested-typer-exception-explosion_corrected_rich_console.pyassets/nested-typer-exceptions/nested-typer-exception-explosion_corrected_typer_echo.pyassets/nested-typer-exceptions/nested-typer-exception-explosion_naive_workaround.pyassets/python-cli-demo.pyassets/typer_examples/console_containers_no_wrap.pyassets/typer_examples/console_no_wrap_example.pyassets/typer_examples/index.mdreferences/architecture-spec-patterns.mdreferences/project-structure.mdreferences/python-version-feature-matrix.mdreferences/quality-gate.mdreferences/rich-advanced-patterns.mdreferences/rich-console-and-markup.mdreferences/rich-logging-and-tracebacks.mdreferences/rich-progress-and-live.mdreferences/rich-renderables.mdreferences/rich-text-and-syntax.mdreferences/testing-spec-guidance.mdreferences/textual/app-and-screens.mdConsult python3-core for standing defaults. Load python3-testing for test patterns.
Annotated[Type, typer.Option(...)] syntax for all CLI paramsrich_help_panel to group options:white_check_mark:) not Unicode literalsuv run <script> over python3 <script>import typer
from rich.console import Console
app = typer.Typer()
console = Console()
@app.command()
def process(
input_file: Annotated[Path, typer.Argument(help="Input file")],
verbose: Annotated[bool, typer.Option("--verbose", "-v")] = False,
) -> None:
"""Process input file."""
...
from rich.console import Console
from rich.table import Table
from rich.measure import Measurement
def get_table_width(table: Table) -> int:
temp = Console(width=9999)
m = Measurement.get(temp, temp.options, table)
return int(m.maximum)
from typer.testing import CliRunner
runner = CliRunner()
def test_app_runs() -> None:
result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
Use semaphores for I/O-bound CLI tasks:
import asyncio
import typer
from typing import Annotated
@app.command()
def fetch(
urls: Annotated[list[str], typer.Argument()],
max_concurrent: Annotated[int, typer.Option()] = 10,
) -> None:
"""Fetch multiple URLs concurrently."""
results = asyncio.run(_fetch_all(urls, max_concurrent))
for result in results:
console.print(result)
async def _fetch_all(urls: list[str], limit: int) -> list[str]:
sem = asyncio.Semaphore(limit)
async with httpx.AsyncClient() as client:
tasks = [_fetch_one(client, u, sem) for u in urls]
return await asyncio.gather(*tasks)
#!/usr/bin/env -S uv --quiet run --active --script
# /// script
# requires-python = ">=3.11"
# dependencies = ["typer>=0.21", "rich>=13.0"]
# ///
references/typer-app-and-commands.md, references/typer-parameters.md, references/typer-parameter-types.md, references/typer-advanced-patterns.md, references/typer-subcommands.md, references/typer-testing.md — Typer commands, arguments, parameters, subcommandsreferences/rich-console-and-markup.md, references/rich-renderables.md, references/rich-text-and-syntax.md, references/rich-advanced-patterns.md, references/rich-progress-and-live.md, references/rich-logging-and-tracebacks.md — Rich tables, panels, progress, live displaysreferences/typer-rich-non-tty-patterns.md, references/typer-rich-tables.md, references/typer-rich-exception-handling.md, references/typer-rich-testing-patterns.md — Typer+Rich integration, non-TTY, width, testingLoad python-engineering:textual when the task involves Textual TUI widgets, screen stack, CSS styling, reactive attributes, Pilot testing, or background workers.
Load python-engineering:typer when the task is focused on Typer commands, parameter configuration, subcommand composition, or Typer-specific documentation.
Load python-engineering:typer-and-rich when the task involves Rich table rendering in non-TTY contexts, Typer/Rich integration pitfalls, or correctness review of CLI output handling.
assets/python-cli-demo.py — complete working exampleassets/typer_examples/index.md — working scripts demonstrating non-TTY display solutions (Panel/Table width, wrapping, cropping)assets/nested-typer-exceptions/ — runnable demos of Typer nested exception anti-patterns and fixesnpx claudepluginhub jamie-bitflight/claude_skills --plugin python-engineeringGuides Typer and Rich best practices for Python CLI apps, covering non-TTY output, table rendering, testing patterns, exception handling, and integration pitfalls.
Guides Typer/Rich CLI development and review with patterns for non-TTY output, table rendering, pytest testing, and exception handling.
Provides Python CLI patterns using Typer for commands/groups/options and Rich for tables, progress bars, panels, and error handling in terminal apps.