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.0.0.tar.gz (62.5 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.0.0-py3-none-any.whl (36.9 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for cli_core_yo-2.0.0.tar.gz
Algorithm Hash digest
SHA256 95f26f9ee2f21526f8827ff1f0622780752c1bfe7a73cf88a0726606fb1af84b
MD5 d6458ee33a704d160d050a0c18de7c88
BLAKE2b-256 8c68525d43af16f8e09692ab8f1efac9adb5df7a3826aafe054e591c74422862

See more details on using hashes here.

File details

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

File metadata

  • Download URL: cli_core_yo-2.0.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.13.11

File hashes

Hashes for cli_core_yo-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6509e985e5d9510d634187c321b4b0f85839ba282b5afd6de66a18abb7e549fc
MD5 0cdfd25b3bd49681c9129325ead5ae52
BLAKE2b-256 f0b147b57542b6b73cc32e5dbb40ff7703877de1e9e8279b7e99f35a6562f0c1

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