Skip to main content

Reusable CLI kernel for building unified command-line interfaces with consistent behavior, output style, help, and extension semantics.

Project description

cli-core-yo

GitHub Release GitHub Tag License: MIT

cli-core-yo v2.0.0 is an opinionated enforcement layer for downstream Python CLIs. It keeps Typer, Click, and Rich as the implementation substrate, but the framework owns root parsing, output mode, dry-run mode, runtime validation, and command policy enforcement.

It is not a standalone service CLI. It is the shared kernel downstream repos embed into their own entrypoints.

Use create_app(spec) when you need the configured CLI object directly, or run(spec, argv=None) when you want process-style execution with an exit code.

v2 Contract

The top-level configuration is an immutable CliSpec.

from cli_core_yo.app import run
from cli_core_yo.spec import CliSpec, PolicySpec, XdgSpec

SPEC = CliSpec(
    prog_name="my-tool",
    app_display_name="My Tool",
    dist_name="my-tool",
    root_help="Unified CLI for My Tool.",
    xdg=XdgSpec(app_dir_name="my-tool"),
    policy=PolicySpec(),
)

raise SystemExit(run(SPEC))

CliSpec in v2 requires:

Field Purpose
prog_name CLI program name
app_display_name Human-facing app name
dist_name Installed distribution name
root_help Root help text
xdg App-scoped XDG directory policy
policy Framework policy profile

Optional sections include config, env, runtime, context, output, plugins, info_hooks, and deploy.

Root Behavior

The framework owns these root options:

  • --json
  • --dry-run
  • --no-color
  • --debug
  • --config PATH
  • --runtime-backend BACKEND
  • --skip-runtime-check
  • any InvocationContextSpec selectors

JSON is root-global. Downstream commands do not define their own --json flags. --dry-run is root-global too, and commands that do not support it fail before execution.

Command Registration

Register downstream behavior through the policy-aware registry.

from cli_core_yo import output
from cli_core_yo.registry import CommandRegistry
from cli_core_yo.spec import CliSpec, CommandPolicy


def greet() -> None:
    output.success("hello")


def register(registry: CommandRegistry, spec: CliSpec) -> None:
    registry.add_command(
        None,
        "greet",
        greet,
        help_text="Say hello.",
        policy=CommandPolicy(),
    )

The supported registry surface is:

  • add_group(name, help_text="", order=None)
  • add_command(group_path, name, callback, *, help_text="", policy, order=None)

add_typer_app() is not part of the v2 contract.

Built-Ins

The framework provides built-ins through the same registry and policy machinery:

  • version
  • info
  • optional config
  • optional env
  • optional runtime

runtime is enabled only when RuntimeSpec is configured. When present, it includes runtime status, runtime check, and runtime explain.

Runtime And Output

Use get_context() inside commands when you need invocation-scoped state.

from cli_core_yo.runtime import get_context


def show_runtime() -> None:
    ctx = get_context()
    print(ctx.spec.prog_name)
    print(ctx.json_mode)
    print(ctx.dry_run)
    print(ctx.backend_name)

Output helpers live in cli_core_yo.output. Human output goes to stdout, diagnostics go to stderr, and JSON output is deterministic UTF-8 with sorted keys, indent=2, and a trailing newline.

Environment hooks that matter at the framework level:

  • NO_COLOR disables ANSI styling
  • CLI_CORE_YO_DEBUG=1 enables traceback diagnostics
  • XDG_CONFIG_HOME, XDG_DATA_HOME, XDG_STATE_HOME, and XDG_CACHE_HOME override XDG resolution

Conformance Helpers

Downstream repos can reuse cli_core_yo.conformance in pytest suites.

from cli_core_yo.app import create_app
from cli_core_yo.conformance import assert_exit_code, assert_json_output, invoke
from cli_core_yo.spec import CliSpec, PolicySpec, XdgSpec

SPEC = CliSpec(
    prog_name="my-tool",
    app_display_name="My Tool",
    dist_name="my-tool",
    root_help="Unified CLI for My Tool.",
    xdg=XdgSpec(app_dir_name="my-tool"),
    policy=PolicySpec(),
)

app = create_app(SPEC)
result = invoke(app, ["--json", "version"])
assert_exit_code(result, 0)
data = assert_json_output(result)
assert "version" in data

The helper module is intentionally small and generic:

  • invoke(app, argv, ...)
  • stdout_text(result)
  • stderr_text(result)
  • json_output(result)
  • assert_exit_code(result, expected)
  • assert_json_output(result, expected=None)
  • assert_no_ansi(text)
  • assert_stdout_only(result)

Development

Bootstrap a local environment from the repo root:

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

Validation commands used by this repo:

python -m pytest tests/ -v --cov=cli_core_yo
ruff check cli_core_yo tests
ruff format --check cli_core_yo tests
mypy cli_core_yo --ignore-missing-imports
python -m build
twine check dist/*

Guidance For AI Agents

  • Treat this repository as the shared CLI framework layer, not as a downstream app.
  • Define exactly one immutable CliSpec in downstream CLIs.
  • Register commands through CommandRegistry with explicit CommandPolicy metadata.
  • Keep JSON and dry-run ownership in the framework, not in downstream callbacks.
  • Do not rely on add_typer_app() or legacy JSON flag behavior.
  • Use cli_core_yo.output for user-facing output and cli_core_yo.conformance for pytest contract checks.

For the repo-specific agent policy, see AI_DIRECTIVE.md.

License

MIT. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cli_core_yo-2.1.0.tar.gz (64.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cli_core_yo-2.1.0-py3-none-any.whl (36.9 kB view details)

Uploaded Python 3

File details

Details for the file cli_core_yo-2.1.0.tar.gz.

File metadata

  • Download URL: cli_core_yo-2.1.0.tar.gz
  • Upload date:
  • Size: 64.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for cli_core_yo-2.1.0.tar.gz
Algorithm Hash digest
SHA256 84934457b0032a367f2b44b29c36a34bd42d180f95b6b249726755cb57222e05
MD5 8ecd83b082e87bd06e1426177bd12074
BLAKE2b-256 6e2cb9ad080603f8e45304246aea5ae1a508fc699ff00253dce2e429e4267e95

See more details on using hashes here.

File details

Details for the file cli_core_yo-2.1.0-py3-none-any.whl.

File metadata

  • Download URL: cli_core_yo-2.1.0-py3-none-any.whl
  • Upload date:
  • Size: 36.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for cli_core_yo-2.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b9a35d2840136abf91cdb2ce632111cb1b5941f64d781458d20ff2440021626a
MD5 2152e531d666728735f6853999d7fa44
BLAKE2b-256 dc3b57613f1830792b3bd5de985e9cca6e25aca805092ad977f54126d59d351b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page