Skip to content

feat(exitcode): add semantic exit codes for AI-native CLIs#63

Merged
leodido merged 2 commits into
mainfrom
feat/exitcode
Mar 27, 2026
Merged

feat(exitcode): add semantic exit codes for AI-native CLIs#63
leodido merged 2 commits into
mainfrom
feat/exitcode

Conversation

@leodido
Copy link
Copy Markdown
Owner

@leodido leodido commented Mar 27, 2026

Summary

  • Adds structcli/exitcode subpackage with fine-grained exit code constants for AI-native CLIs
  • Exit codes are grouped into ranges that form a decision tree for agents
  • Includes Category() and IsRetryable() helpers

Exit code ranges

Range Category Agent strategy
0 ok Success — proceed
1–9 runtime Not the agent's fault — report to human
10–19 input Bad input — self-correct from error JSON, retry
20–29 config Environment problem — fix config/env vars, retry

Input errors (10–19):

Code Constant Meaning
10 MissingRequiredFlag Required flag not provided
11 InvalidFlagValue Wrong type or format
12 UnknownFlag Flag doesn't exist
13 ValidationFailed Custom validation rule failed
14 UnknownCommand Subcommand doesn't exist
15 InvalidFlagEnum Value not in allowed enum set

Config/environment errors (20–29):

Code Constant Meaning
20 ConfigParseError Config file is malformed
21 ConfigUnknownKey Unrecognized config key
22 ConfigInvalidValue Config key has wrong type
23 ConfigNotFound --config path doesn't exist
25 EnvInvalidValue Env var set but wrong format
26 EnvMissingRequired Required flag not on CLI, env var not set

Runtime errors (1–9):

Code Constant Meaning
0 OK Success
1 Error Unclassified runtime error
2 PermissionDenied Filesystem/network permission
3 Timeout Operation timed out
4 Interrupted SIGINT/SIGTERM

Why

This is the foundation for Phase 2a (structured error output). HandleError will return these codes and include them in JSON error output, enabling agents to branch on exit codes without parsing text.

Test plan

  • go test ./exitcode/... -cover — 100% coverage
  • All constants map to correct category
  • Full range boundary tests (every code 1–29)
  • Edge cases (negative, >29 fall back to runtime)
  • IsRetryable correct for all codes
  • go vet ./exitcode/... — clean
  • go test ./... — no regressions (pre-existing flaky TestMemoryCleanup unrelated)
leodido added 2 commits March 27, 2026 13:28
Define fine-grained exit code constants grouped by category:
- 0: success
- 1–9: runtime errors (report to human)
- 10–19: input errors (agent can self-correct and retry)
- 20–29: config/env errors (fix environment, then retry)

Include Category() and IsRetryable() helpers for agent decision
trees.
Cover all constants, full range boundaries, edge cases (negative,
out-of-range codes), and IsRetryable. 100% coverage.
@leodido leodido self-assigned this Mar 27, 2026
@leodido leodido merged commit 19a3491 into main Mar 27, 2026
4 checks passed
@ccoVeille
Copy link
Copy Markdown

hi @leodido

While I understand the need, I'm a bit surprised by the error code you chose.

Do you know exit code are somehow normalized and only some ranges are available ?

I would like to suggest you to take a look at this project that tried to define something close to what you did, but took into account the existing exit code ranges

https://github.com/square/exit?tab=readme-ov-file#reserved-codes-and-prior-art

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants