Migration guide
August 28, 2026 · View on GitHub
This page is the starting point for adopting base-cli in an existing Python
CLI. It collects framework-specific recipes as well as the format for changes
that affect the public base-cli contract. The compatibility rules and
deprecation timeline are defined in api-stability.md.
Choose a migration path
- Click — keep an existing Click command tree and add a shared lifecycle boundary.
- Typer — keep typed Typer declarations and attach the generated command to the lifecycle boundary.
- Cement — keep Cement while evaluating the boundary,
then move command definitions incrementally to Click plus
base-cli. - argparse — keep parser behavior stable while replacing application-owned lifecycle code one command at a time.
The framework choice guide explains the boundary and
the adopter readiness guide is the production handoff
checklist. These recipes assume a pinned base-cli release and a wheel-first
smoke test before changing a user's command behavior.
Common rollout and rollback checklist
- Inventory command names, options, exit codes, configuration precedence, output consumed by automation, and log/diagnostic locations.
- Add
base-clito the lock file and preserve the existing parser and callback tests. Start with one low-risk command. - Attach the existing tree (or add a small
App) and move policy into a consumer-ownedCliProfile. Mark secrets as sensitive. - Add success, usage-error, and unexpected-error contract fixtures. Keep stdout reserved for command output and diagnostics on stderr.
- Run the full platform/dependency matrix, then compare old and new output and retained run metadata in a pilot environment.
- Keep the previous wheel, configuration schema, and output contract available for the documented compatibility window. If the pilot fails, restore the previous entry point and wheel, and retain the evidence for a follow-up issue.
base-cli owns invocation lifecycle, context, logging, redaction, runtime
state, cleanup, history hooks, and versioned output contracts. The parser
(Click, Typer, Cement, or argparse) remains responsible for command trees,
parameters, help, completion, and parser-specific errors. Product callbacks,
services, configuration policy, and domain schemas remain consumer-owned.
Migrating a deprecated API
-
Upgrade to the first release that emits the warning.
-
Replace the old symbol with the alternative named in the warning and in the release notes.
-
Run tests with
BaseCliDeprecationWarningenabled so no old call sites are missed:import warnings from base_cli import BaseCliDeprecationWarning warnings.simplefilter("error", BaseCliDeprecationWarning) -
Remove temporary compatibility shims before the stated removal release.
Warnings are ordinary Python warnings, so applications can instead record or
display them with their normal warnings configuration.
Schema migrations
Versioned JSON envelopes and command framing must not change meaning in place. Add a new schema or protocol version, keep the old version during its support window, and provide an adapter when practical. A schema migration note should include:
- old and new version identifiers;
- field additions, removals, and type changes;
- producer and consumer rollout order; and
- the release where the old version will stop being accepted.
Migration note template
### `old_name` → `new_name`
- **First warning:** 0.x.y
- **Removal target:** 1.0.0
- **Why:** explain the problem in one sentence.
- **Action:** show the smallest before/after example.
- **Compatibility:** describe the temporary adapter or schema version.
For release mechanics, see releasing.md. For the public
surface and deprecation requirements, see api-stability.md.