Follow-up from PR #222.
PR #222 introduced gh-style process exit codes: 0 success, 1 error, 2 cancelled, 4 auth required. The initial mapping is intentionally coarse — this issue is to step back and review the taxonomy as a whole now that the mechanism is in place.
Current behavior
0 success
1 generic error (everything not classified below)
2 cancelled (defined, not yet produced — reserved for future long-running/polling commands)
4 auth required — set for missing credentials, the OAuth-only-write block, and API 401/403
Classification lives in CloudError (kind: CloudErrorKind) via convert_error in cloud/client.rs, mapped to the top-level Error in main.rs.
Questions to settle
403 granularity. A 403 with a valid API key means insufficient permissions, where re-authenticating will not help — yet it currently maps to 4 (auth required) the same as 401. Should permission-403 be generic (or its own code), with 4 reserved for 401 + the bearer/OAuth-write case?
5xx server errors. Currently generic (1). Should server-side failures be distinguishable from client-side mistakes (e.g. a dedicated code), since they are transient/retryable and not the caller’s fault?
- Rate limiting /
429. No dedicated signal today. Agents and scripts would benefit from a distinct code (and/or surfacing Retry-After) so they can back off rather than treating it as a hard error.
- Not found /
404. Should "resource does not exist" be distinguishable from a generic error?
- Validation / bad input. User input errors (bad flags, unparseable IDs) are
1 today — worth a distinct code (cf. gh reserving codes per category)?
- Network/transport failures. Connection refused, DNS, timeouts — currently generic; candidate for a transient/retryable code.
Goal
Agree on a small, documented, stable exit-code taxonomy (what each code means, which HTTP statuses and failure classes map to it) before downstream agents/scripts start depending on the current values. Update convert_error, the Error::exit_code() mapping, the README exit-code table, and cli.rs after_help to match, with unit-test coverage per category.
Related: #233 (make the routing structurally correct rather than downcast-dependent).
Follow-up from PR #222.
PR #222 introduced
gh-style process exit codes:0success,1error,2cancelled,4auth required. The initial mapping is intentionally coarse — this issue is to step back and review the taxonomy as a whole now that the mechanism is in place.Current behavior
0success1generic error (everything not classified below)2cancelled (defined, not yet produced — reserved for future long-running/polling commands)4auth required — set for missing credentials, the OAuth-only-write block, and API401/403Classification lives in
CloudError(kind: CloudErrorKind) viaconvert_errorincloud/client.rs, mapped to the top-levelErrorinmain.rs.Questions to settle
403granularity. A403with a valid API key means insufficient permissions, where re-authenticating will not help — yet it currently maps to4(auth required) the same as401. Should permission-403be generic (or its own code), with4reserved for401+ the bearer/OAuth-write case?5xxserver errors. Currently generic (1). Should server-side failures be distinguishable from client-side mistakes (e.g. a dedicated code), since they are transient/retryable and not the caller’s fault?429. No dedicated signal today. Agents and scripts would benefit from a distinct code (and/or surfacingRetry-After) so they can back off rather than treating it as a hard error.404. Should "resource does not exist" be distinguishable from a generic error?1today — worth a distinct code (cf.ghreserving codes per category)?Goal
Agree on a small, documented, stable exit-code taxonomy (what each code means, which HTTP statuses and failure classes map to it) before downstream agents/scripts start depending on the current values. Update
convert_error, theError::exit_code()mapping, the README exit-code table, andcli.rsafter_helpto match, with unit-test coverage per category.Related: #233 (make the routing structurally correct rather than downcast-dependent).