Standardize machine-readable CLI output: --json on all subcommands, documented exit codes, shell completion
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 9
- Forks
- 17
- Avg merge
- 21h 36m
- Merged PRs (30d)
- 22
Description
Summary
Bring the CLI to a consistent scripting contract: every subcommand that produces data supports --json, exit codes are defined and documented, and shell completion (already available via Typer) is documented and verified.
Priority: P2 · Confidence: Medium
Why this matters
The CLI is a primary adopter touchpoint and increasingly an automation surface (CI checks, budget gates, pipelines). Today --json exists on some commands but not others, so scripts must scrape Rich-formatted text for the rest; exit-code semantics are implicit, so budget-check-style gating in user CI is guesswork. A uniform contract makes every subcommand composable and is cheap to deliver because the pattern already exists in-tree.
Current evidence
src/contextweaver/__main__.py:--jsonoptions exist at lines ~465 and ~570 (route and one other command), whilestatsuses a--format rich|textenum (lines ~433–447) andbuild/ingest/replay/eval/budget-checkhave no machine-readable mode (verified by search — only twojson_outputdeclarations).- Two different conventions already coexist (
--jsonflag vs--formatenum) — an inconsistency to resolve deliberately. - No exit-code documentation anywhere in README/docs for the CLI.
- Adjacent open issues: #398 (new
inspectcommand) and #395 (gatewaydoctor) will both want this contract; neither defines it.
External context
CLI conventions for tooling consumed by scripts: stable JSON on stdout, human rendering elsewhere or behind a flag, exit 0 success / documented non-zero classes. Typer provides --install-completion out of the box — it only needs docs and a smoke test.
Proposed implementation
- Decide the convention (recommend
--jsoneverywhere; keep--formatas alias where it exists, fold via the deprecation machinery later). - Add
--jsontobuild,ingest,replay,stats,eval,budget-check— emitting the existingto_dict()payloads (BuildStats, eval reports, etc.); JSON goes to stdout, logs/progress to stderr. - Define and document exit codes: 0 success; 1 check-failed (budget-check over budget, eval below threshold); 2 usage error (Typer default); 3 input/data error. Audit current behavior against this and adjust.
- Document
contextweaver --install-completionin README/quickstart; add a CLI-reference docs section listing every subcommand's JSON shape and exit codes.
AI-agent execution notes
- Inspect first:
__main__.pyend-to-end (all 10 subcommands + themcpsub-app),_mcp_cli.py, existingjson_outputimplementations as the pattern,tests/test_cli.py. - Run:
pytest tests/test_cli.py tests/test_mcp_serve_cli.py -q; manualcontextweaver build --json | python -m json.toolsmoke for each command. - Add tests: each subcommand's
--jsonoutput parses and contains expected keys; exit codes per class (useCliRunner); stdout purity (no Rich artifacts in JSON mode). - Preserve: default human-readable output unchanged;
print()exemption applies only to__main__.py/_demos.py. - Do not redesign command semantics — output/exit contract only.
Acceptance criteria
- All data-producing subcommands support
--jsonwith parseable, documented output. - Exit-code table documented and enforced by tests.
- Completion installation documented and smoke-tested.
Test plan
CliRunner-based tests per command for JSON validity and exit codes; a round-trip test (build --json output consumed by route/stats where applicable); full make ci.
Documentation plan
New "CLI reference" docs page (or README CLI section expansion) with the contract table; CHANGELOG.
Migration and compatibility notes
Human-readable defaults unchanged. If any current non-zero exit behavior shifts to match the documented classes, list each change in CHANGELOG. --format remains as a deprecated alias until the deprecation machinery handles it.
Risks and tradeoffs
JSON shapes become a compatibility surface — anchor them to the existing to_dict() serializations (already schema-governed via make schemas) rather than inventing CLI-specific shapes. Two-convention cleanup creates minor churn now to avoid permanent inconsistency.
Suggested labels
developer-experience, enhancement, area/cli
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Inspect src/contextweaver/main.py end to end, _mcp_cli.py, existing json_output implementations, and tests/test_cli.py plus tests/test_mcp_serve_cli.py. Run the named pytest suites first and use the existing to_dict() payloads as the reference. Done means every data-producing subcommand has parseable documented JSON, tested exit codes, clean stdout, documented completion, and unchanged human-readable defaults.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- cli, developer-experience, documentation, testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100