Skip to content

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

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: