CONCEPT Cited by 1 source
Exit code semantics¶
Exit code semantics is the commitment that a CLI's exit
codes and error shapes are documented, consistent, and
load-bearing for agent control flow — agents branch on
$? instead of parsing stderr strings.
Why it matters for agents¶
Agents don't read stderr the way humans do. A human sees "Error: could not connect to api.example.com: connection refused" and knows to retry. An agent that has to parse that string into a plan of action is burning tokens on a stderr-interpretation exercise that should be a constant-time switch.
The canonical framing from the gcx launch post:
"Exit codes and error shapes are documented and consistent, so an agent can branch on failure and recover on its own instead of guessing from a
stderrstring."
The doubled commitment — exit codes AND error shapes —
is the load-bearing detail. Exit codes alone signal
success/failure broadly; error shapes (a stable JSON envelope
with {code, message, retriable, ...}) let the agent
programmatically categorise the failure without LLM-level
parsing.
What the commitment covers¶
| Axis | Commitment |
|---|---|
| Success | Exit 0, zero ambiguity |
| Retryable failure | Distinct non-zero code (typically in a documented range) |
| Non-retryable (input) failure | Distinct non-zero code |
| Authentication / authorisation failure | Distinct code so agent knows to refresh creds vs retry |
| Destructive-confirmation-required | Distinct code so agent can re-invoke with confirmation |
| Version mismatch | Distinct code so agent knows to upgrade |
The documented contract lets the agent plan the recovery: - Retryable → back off + retry - Auth → refresh creds, retry once - Confirmation-required → prompt the human or apply policy - Version mismatch → abort the session with a clear message
Why the "documented" adjective matters¶
Undocumented exit codes are nearly as bad as no exit codes. The POSIX convention (0 = success, 1 = general error, 2 = misuse) is inadequate because nearly everything collapses to "1" and the agent has to string-parse stderr anyway. The Grafana commitment is to go beyond POSIX-baseline and publish the code table as part of the tool's contract — typically in the machine-readable catalog (concepts/machine-readable-command-catalog).
Contrast with the sibling structured-output contract¶
- concepts/json-output-stability — stable field names on the happy path.
- Exit code semantics — stable exit codes + error shapes on the failure path.
Both are needed. A CLI with stable JSON on success but exit 1 + ad-hoc stderr on failure is a half-contract — the agent's success-path parsing works, but its recovery logic stays LLM-mediated.
Related CLI-design traditions¶
- Git: documented exit codes with stable semantics
(
git merge: 0 clean, 1 conflict, 128 fatal). - kubectl: documented codes per subcommand.
- curl: famously 70+ documented exit codes, each with a specific failure category.
The agent-ergonomic-CLI generation (Cloudflare's cf,
Fly.io's flyctl, Grafana's gcx) extends this tradition
explicitly for agent use — the stability is the point.
Seen in¶
- sources/2026-04-29-grafana-get-observability-in-the-terminal-for-you-and-your-agents-with-the-gcx-cli-tool
— canonical statement of exit-code-semantics as an
agent-primary CLI commitment. Grafana's
gcx: "Exit codes and error shapes are documented and consistent, so an agent can branch on failure and recover on its own instead of guessing from astderrstring." First observability-vendor-shipped instance of the commitment.