Output contract
ACTIVESummary
| Rule | Behaviour |
|---|---|
| Input | Flags and positionals. Nothing prompts or waits on stdin. |
| --json | Exactly one JSON object on stdout, success or failure. |
| stderr | Progress and logs only. stdout carries the result and nothing else. |
| Exit codes | 0 success, 1 failure, 2 usage error. |
| describe | Every command, flag, default and example, as JSON. |
| --help | Usage, flags and examples for one command, as text. |
The --json envelope
With --json, stdout gets one line of JSON. On success:
{"ok": true, "command": "hello", "result": {"greeting": "Hello, Ada!"}}result is whatever the command returned, or null if it returned nothing. On failure:
{"ok": false, "command": "hello", "error": {"code": "usage", "message": "Missing required flag: --name.", "hint": "Example: my-cli hello --name Ada --json"}}hint is present only when there is one. details appears when a command fails with structured data, such as the findings of a check that didn't pass. command is null if the failure happened before a command was chosen. Check ok or the exit code; both always agree.
Without --json, results print as text: the command's render function if it has one, otherwise a key: value listing. Errors print to stderr as error: ... and hint: ....
Exit codes
| Code | Meaning | Typical error.code |
|---|---|---|
0 | Success. Also --help, describe and --version. | none |
1 | The command ran and failed. | the command's own code, e.g. target_not_empty; internal for an unexpected exception |
2 | Bad input: unknown command, unknown flag, missing required flag, invalid value. Running with no arguments also prints help and exits 2. | usage |
describe and help
Prints the whole CLI as pretty-printed JSON: name, about, the contract, global flags, and each command with its usage line, flags (name, short, type, required, default, description) and examples. It is always JSON, with no envelope, and needs no --json. Read it once at the start of a session instead of guessing flags.
Both print one command's usage, flags, global flags and examples as text. Add --json to get the same information as that command's entry from describe, inside the envelope. my-cli --help lists all commands.
Flags
Global flags work on every command: --json and -h, --help. -v or --version works as the first argument.
String flags take a value: --name Ada or --name=Ada. Boolean flags take none: --shout, never --shout true. Unknown flags are a usage error, so a typo fails instead of being ignored. Missing booleans are false; missing strings take their default or are left undefined.
No prompts
Nothing asks a question. A missing required flag is an immediate usage error (exit 2) whose hint is the command's first example, so the caller learns the right invocation from the failure itself.