base-cli¶
base-cli is the production lifecycle layer for Click and Typer Python CLIs. It gives commands a consistent lifecycle, context, logging, cleanup, configuration, and test boundary while leaving application policy in the consuming project.
It is for teams shipping operational CLIs that need repeatable diagnostics and automation contracts across commands. It is not a parser replacement or an application scaffold: Click and Typer still own parsing and command definitions, while the consuming project owns its domain policy and services.
Quick start¶
Install the package:
python -m pip install base-cli
Create a command:
from __future__ import annotations
import base_cli
app = base_cli.App(name="hello", version="0.1.0")
@app.command()
@base_cli.option("--name", default="world", show_default=True)
def hello(ctx: base_cli.Context, name: str) -> int:
ctx.log.info("greeting %s", name)
print(f"Hello, {name}!")
return base_cli.ExitCode.SUCCESS
if __name__ == "__main__":
raise SystemExit(base_cli.run_app(app))
Run it with:
python hello.py --name Ada
The command receives a context with structured logging, per-run paths, configuration, environment metadata, and deterministic cleanup. The same lifecycle can be attached to an existing Click tree or an optional Typer application.
Choose a path¶
- Use the framework choice guide to compare base-cli with the underlying parser and decide whether its lifecycle boundary fits.
- Follow the five-minute consumer quickstart for a
minimal public
App,run_app(), human output, and JSON invocation. - Start with the adopter readiness guide for a production evaluation.
- See the adoption and compatibility evidence guide for dated CI results and the permissioned-adopter program.
- Read API stability and the migration guide before upgrading across a compatibility boundary.
- Browse the complete public API reference for exported symbols, signatures, and usage shapes.
- Follow consumer profiles when your application owns project discovery or configuration policy.
- Use the Typer adapter to bring an existing Typer command tree under the same lifecycle.
- Use
@app.async_command()when a command calls async APIs; see the consumer profile contract for loop ownership and cancellation rules. - Review the JSON contracts and output contracts before building automation around command output.
- Use the strict JSON consumer guide to validate envelope and NDJSON records with a cross-language parser.
- Use the optional output dependency guide to map YAML and other integrations to their explicit extras and fallbacks.
Design principles¶
base-cli is intentionally thin: Click owns parsing and command execution,
while the framework supplies reusable lifecycle behavior. It avoids import-time
filesystem writes, keeps logs on stderr, preserves application-owned state,
and treats optional integrations as explicit extras.
Continue with the framework guides:
- API overview for the supported public surface and compatibility policy.
- Reference applications for complete consumer patterns.
- Installation and packaging for dependency extras, distribution checks, and release guidance.