Skip to content

CLI Output Contract v1 (Incur-aligned)

Status: Revised after incur behavior validation
Scope: All @spectratools/*-cli packages

1) Purpose

This document defines the output contract we expect across spectra-tools CLIs without re-implementing behavior already provided by incur.

v1 policy is now split into:

  1. Framework contract (inherited from incur) — required as-is.
  2. Spectra package policy — conventions we enforce in docs/tests and package command design.

2) Incur-native runtime contract (required)

These are framework semantics and must be treated as source-of-truth unless we intentionally upgrade/change incur.

2.1 Global built-ins (do not reimplement)

Every CLI already gets:

  • Built-in commands: completions, mcp add, skills add
  • Built-in flags: --format, --json, --verbose, --llms, --mcp, --schema, --filter-output, --token-count, --token-limit, --token-offset, --help, --version

2.2 Output format defaults

  • Default format is toon.
  • --json is alias for --format json.
  • Supported formats are framework-defined (toon, json, yaml, md, jsonl).

2.3 Envelope semantics

In CLI mode:

  • --format json (or --json) without --verbose:
    • success → data only
    • error → error object only
  • --format json --verbose:
    • full envelope (ok, data|error, meta)

Representative verbose JSON shape:

json
{
  "ok": true,
  "data": { "...": "..." },
  "meta": {
    "command": "registration create",
    "duration": "1ms"
  }
}

Notes:

  • meta.cta may be present when command returns CTA via c.ok(..., { cta }) / c.error(..., { cta }).
  • meta.nextOffset may be present with token truncation (--token-limit + --verbose).

2.4 Error/exit behavior

  • Framework errors serialize through the same output channel selected by format.
  • Non-success exits are framework-managed (commonly 1 unless explicitly overridden).
  • Domain-specific codes (e.g. NO_PRIVATE_KEY, INVALID_IDENTIFIER) remain valuable and should stay stable.

2.5 Discovery and integration

  • skills add, mcp add, --llms, and --mcp are built-in and should be documented/used directly.

3) Spectra package policy (v1)

3.1 Machine-consumption profiles

We support two explicit machine profiles:

  1. Data profile (default for scripts): --json
    • parse direct data on success, direct error object on failure.
  2. Envelope profile (for orchestration/telemetry): --json --verbose
    • parse ok/data/error/meta envelope.

3.2 Human default

  • Keep incur default toon output for interactive usage.
  • Do not force a cross-repo default switch to JSON.

3.3 Pagination policy

  • Use incur token pagination when output-size pagination is needed:
    • --token-count, --token-limit, --token-offset
  • Keep command/domain pagination flags (--limit, --max-results, --page, --offset, cursor args) command-specific.
  • Do not introduce new cross-cutting global page flags in v1.

3.4 Mutating commands and dry-run

  • --dry-run is a package-level feature, not an incur global.
  • Add it only on mutating commands where preview semantics are clear and testable.
  • When implemented, docs/tests must prove no side effects occur.

3.5 CTA usage

  • Prefer incur-native CTA support (c.ok / c.error metadata) rather than custom top-level CTA envelope shims.

4) Incur Alignment Notes

  1. table is not an incur global output mode; do not define contract requirements around it.
  2. A custom always-on envelope (ok/data/meta/error) in non-verbose JSON would fight framework defaults.
  3. skills add, mcp add, and --llms are first-class built-ins; do not duplicate them in package code.
  4. Global verbosity/quiet policy should not assume flags that incur does not provide globally.

5) Explicit "do not duplicate framework features"

Do not build repo-level abstractions that duplicate or override incur unless there is a versioned product decision to diverge. Specifically, do not add:

  • custom global flag parser for built-in incur flags
  • custom output envelope wrapper that changes non-verbose JSON semantics
  • custom replacements for skills add, mcp add, or --llms
  • synthetic global pagination flags when token pagination already exists

If we need behavior beyond incur, document it as an intentional extension with package scope and tests.


6) Contract examples

6.1 Data profile

bash
erc8004 registration create --name Test --json
json
{
  "name": "Test",
  "erc8004": { "version": "0.1.0" }
}

6.2 Envelope profile

bash
erc8004 registration create --name Test --json --verbose
json
{
  "ok": true,
  "data": {
    "name": "Test",
    "erc8004": { "version": "0.1.0" }
  },
  "meta": {
    "command": "registration create",
    "duration": "1ms"
  }
}

7) Backward compatibility impact

This revision reduces migration risk versus the earlier draft by aligning with current runtime behavior:

  • no forced default-format change to JSON
  • no mandatory custom envelope layer
  • no immediate global pagination/quiet flag refactor

Primary follow-on work is docs/test alignment plus targeted command-level improvements (dry-run where it matters, stable domain error codes, CTA consistency).