8.4 KiB
Roadmap: CLI Output Policy
Purpose
Define a shared CLI output policy before adding machine-readable JSON output to
distributor commands.
Current CLI output is human-readable text. That is appropriate as the default, but upcoming features need a common machine-readable contract so each command does not invent a separate JSON flag, envelope, warning policy, or error shape.
Current Implementation Grounding
The current CLI has these output-producing commands:
version;run;validate;inspect.
Current output is text-only. run has the most complex output because it can
print warnings, pipeline summaries, planned destination actions, partial
destination failures, and a final status line. validate and inspect are
currently local-path commands. version prints a single text line.
Planned distributor manifest create, remote validate and inspect, link
generation, and latest path destinations increase the need for structured
output that scripts can consume consistently.
Goals
- Define one CLI-wide policy for text and JSON output.
- Preserve current human-readable text output as the default.
- Add JSON output consistently across output-producing commands when this roadmap is implemented.
- Keep warning, error, and partial-failure behavior predictable.
- Avoid external dependencies; use Go's standard
encoding/json.
Non-Goals
- Do not add YAML, table, NDJSON, streaming JSON, or template output formats.
- Do not change source manifest, destination state, config, or backend schemas.
- Do not make help or usage output JSON.
- Do not turn ordinary fatal setup errors into structured JSON results.
- Do not add a root-global output flag in the first implementation.
Shared CLI Policy
Each supported command should accept:
--format text
--format json
Policy:
textis the default and preserves existing output unless a feature explicitly changes text output.jsonwrites exactly one JSON document to stdout.- help and usage output remain text-only.
- invalid
--formatvalues are usage errors. --formatis a per-command flag, not a root-global flag.- a command must not accept
--format jsonunless it emits the shared JSON envelope for that command.
The first implementation should add JSON support for all current
output-producing commands rather than leaving a mixed CLI where some commands
support --format and others do not.
Stdout, Stderr, Warnings, and Errors
Text mode keeps the current behavior:
- normal command output goes to stdout;
- warnings may be printed as text;
- command errors are printed to stderr by CLI error handling.
JSON mode:
- successful commands write one JSON document to stdout;
- warnings are included in a top-level
warningsarray and are not duplicated to stderr; - fatal setup errors that prevent construction of a result write text errors to stderr, write no JSON stdout, and exit non-zero;
- commands with meaningful partial results may write a JSON document with
ok: false, structured failure details, and a non-zero exit status.
run --format json should use the partial-result behavior when planning or
execution has begun and one or more destinations fail. This lets automation
inspect successful actions, failed actions, warnings, and final counters even
when the process exits non-zero.
JSON Envelope
All JSON-mode commands should use a common top-level envelope:
{
"schema_version": 1,
"command": "inspect",
"ok": true,
"warnings": [],
"result": {}
}
Envelope fields:
schema_version: integer version of the CLI JSON output schema.command: command name, using the public CLI command path where useful, such asmanifest create.ok: boolean success indicator for the command result.warnings: array of structured warning objects.result: command-specific result object.errors: optional array of structured error objects for commands that can return partial results.
Field rules:
- use stable snake_case field names;
- use RFC3339 timestamps;
- use numeric JSON values for sizes and counts;
- use slash-separated logical paths for bundle, source, destination, and output paths;
- never include secret values;
- keep command-specific data under
result; - add fields compatibly where practical.
Warning objects should include at least:
{
"message": "secret OBJECT_STORAGE_KEY ignored because the real environment already has that variable"
}
Error objects for partial results should include enough context for automation and troubleshooting, such as pipeline id, destination id, backend, bundle path, and message when those values are available.
Command Adoption
version:
- text mode keeps the current version string;
- JSON mode reports application name and version under
result.
validate:
- text mode keeps the current validation summary;
- JSON mode reports bundle count and selected bundle identifiers;
- future remote validation uses the same envelope and adds pipeline/source
context under
result.
inspect:
- text mode keeps human-readable bundle metadata;
- JSON mode reports normalized bundle metadata, including source-relative path, bundle id, created timestamp, digest, file count, total size, and file records.
run:
- text mode keeps the current progress and final status style unless a future feature intentionally changes it;
- JSON mode reports warnings, pipeline summaries, destination action records, output records, final counters, dry-run status, and partial failure records;
- JSON mode may write
ok: falsewith partial results and still exit non-zero.
Future manifest create:
- should use
--format text|json; - text mode should keep concise human success output;
- JSON mode should report the generated manifest summary under
result; - the command should not introduce a separate
--jsonflag.
Relationship To Other Roadmaps
distributor manifest create should depend on this roadmap for JSON summary
output and should not add a command-specific JSON flag.
Remote validate and inspect should use this policy for machine-readable
source validation and inspection.
Link generation should expose primary links through JSON command output only after this policy is implemented or selected for implementation.
Latest path destinations should report fixed-path selection and destructive
replacement summaries through the same run --format json result model.
Testing Expectations
Suggested coverage:
- CLI parsing accepts
--format textand--format jsonfor supported commands; - CLI parsing rejects invalid
--formatvalues as usage errors; - help and usage output remain text-only;
- each JSON-capable command emits exactly one valid JSON document to stdout on success;
- text mode preserves existing output;
- JSON-mode warnings appear in
warningsand are not duplicated to stderr; - fatal setup errors write no JSON stdout and return non-zero;
run --format jsonemits partial-result JSON withok: falseand exits non-zero when one or more destination failures occur after planning begins;- JSON output uses RFC3339 timestamps, numeric sizes and counts, and slash-separated logical paths;
- no JSON output includes secret values;
- documentation consistency checks find no unsupported
--jsonreferences.
Documentation Updates After Implementation
- Update
docs/cli.mdwith the shared--format text|jsonpolicy. - Update command examples only for implemented JSON behavior.
- Update
docs/operations.mdwhere JSON output materially improves automation workflows. - Update
docs/troubleshooting.mdonly for implemented JSON-mode recovery behavior. - Update relevant roadmap files when JSON output is no longer deferred.
Keep this roadmap under docs/roadmap/ until implemented.
Decisions
- Use per-command
--format text|json; do not introduce--json. - Keep
textas the default for backward compatibility. - Implement JSON support for all current output-producing commands when this roadmap is selected.
- Keep help and usage output text-only.
- Put JSON-mode warnings in the top-level
warningsarray. - Allow
run --format jsonto emit partial-result JSON withok: falseand a non-zero exit status. - Keep fatal setup errors as text stderr with no JSON stdout.
Future Work
- Consider a root-global output flag only if the command parser is later refactored around shared root options.
- Consider additional formats only if a concrete consumer requires them.
- Consider a versioned JSON schema reference after the first JSON-capable release.