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.

Metadata

Release files for cli-core-yo 2.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cli-core-yo 2.2.0
File Size Uploaded Provenance Actions
cli_core_yo-2.2.0.tar.gz 70.7 kB Without provenance Details for cli_core_yo-2.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for cli-core-yo 2.2.0
File Interpreter ABI Platform Actions
cli_core_yo-2.2.0-py3-none-any.whl Python 3 none any Details for cli_core_yo-2.2.0-py3-none-any.whl

Total release size: 112.5 kB

Release files / cli_core_yo-2.2.0.tar.gz

Download URL cli_core_yo-2.2.0.tar.gz
Size 70.7 kB
Tags Source
SHA-256 checksum
How to use checksums
55864cd0e0ec88e0c048fd14d5ab5c73d9257856a555ff23bfaa4f4c81fbfd7c
BLAKE2b-256 checksum
How to use checksums
090c66682b274861027d319a85021ebf2572553353780b4709f13bb2e62c3fb2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.4

Release files / cli_core_yo-2.2.0-py3-none-any.whl

Download URL cli_core_yo-2.2.0-py3-none-any.whl
Size 41.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5d404ae4926600462b9da1353d4110666bff12d2efa0db6088798376a2166d9b
BLAKE2b-256 checksum
How to use checksums
ba5f1b55648820e11e980d77e7a142a540f8685928158bb62eb674462072bb0c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.4

Security for cli-core-yo 2.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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