Skip to main content

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)

CLI Syntax Validation (Opt-In)

Downstream test suites and CI jobs can validate a declared command surface without changing app construction or runtime behavior. create_app() and run() never invoke this validator automatically.

from cli_core_yo.validation import (
    CliSyntaxValidationConfig,
    CommandPolicyExpectation,
    validate_cli,
)

report = validate_cli(
    app,
    CliSyntaxValidationConfig(
        required_root_flags=("--json", "--dry-run"),
        required_commands=("version", "info"),
        policy_expectations={
            "version": CommandPolicyExpectation(
                supports_json=True,
                runtime_guard="exempt",
            )
        },
        mode="fail",
    ),
)
assert report.is_valid
assert report.exit_code == 0

report.to_dict() returns a machine-readable command tree and finding list for CI output. Use mode="warn" during migration to retain findings while keeping the report exit code at zero. Intentional, temporary deviations can be declared with FindingAllowance; they remain in the report but do not fail the gate.

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.

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.2.0.tar.gz (70.7 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.2.0-py3-none-any.whl (41.7 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for cli_core_yo-2.2.0.tar.gz
Algorithm Hash digest
SHA256 55864cd0e0ec88e0c048fd14d5ab5c73d9257856a555ff23bfaa4f4c81fbfd7c
MD5 67260e5d66077e1706ffbec5223bb6d3
BLAKE2b-256 090c66682b274861027d319a85021ebf2572553353780b4709f13bb2e62c3fb2

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for cli_core_yo-2.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5d404ae4926600462b9da1353d4110666bff12d2efa0db6088798376a2166d9b
MD5 276291324ff0d4a32a3312974ac848cc
BLAKE2b-256 ba5f1b55648820e11e980d77e7a142a540f8685928158bb62eb674462072bb0c

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

2.2.0 This release

2 files

2.1.1

2 files

2.1.0

2 files

2.0.0

2 files

1.3.1

2 files

1.3.0

2 files

1.2.2

2 files

1.2.0

2 files

1.1.2

2 files

1.1.0

2 files

1.0.10

2 files

1.0.8

2 files

1.0.4

2 files

1.0.3

2 files

1.0.1

2 files

1.0.0

2 files

0.5.3

2 files

0.5.2

2 files

0.5.1

2 files

0.5.0

2 files

0.4.0

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.1

2 files

0.2.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page