Blog
Stable CLI Exit Codes Scripts Can Branch On
Document a small set of CLI exit codes and never reuse them. Reserve 0 for success, 1 for unexpected failure, and specific codes for auth, usage, and unavailable dependencies.
2026-10-14 · 7 min read · AethelLayer
The exit code is the contract that survives a discarded stderr
CI, Makefiles, and agents often throw stderr away. The status byte is what remains. If every failure returns 1, nobody can branch. If codes change between minor versions, every script you inspired is now wrong.
Use 0 for success. Use 1 for an unexpected failure you have not classified. Give auth, usage, network, and missing-config their own codes, document them in --help, and treat a rename as a breaking change.
Stay out of the shell's reserved range
Statuses above 125 already mean something. 126 and 127 are exec failures. 128 plus a signal is how the shell reports SIGINT, so 130 usually means the user hit Ctrl-C. Do not invent a product meaning for those numbers.
BSD sysexits (64 through 78) is a fine vocabulary if you want usage, data, and no-input to mean the same thing across tools. Pick that set or a smaller private set. Do not mix them casually.
A non-zero status is not always an error
grep exits 1 when there is no match. diff exits 1 when files differ. If your CLI has a similar 'this is the answer' status, document it as an outcome, not a failure, and do not attach an error message to it.
Container runtimes add another layer. Exit 137 is 128 plus SIGKILL, which on Docker often means the OOM killer. Surface that as a named code in your own CLI so the developer is not left decoding the kernel.
Store the status with the story
An exit code without the command is a metric. The command plus 'I was trying to refresh a staging token' is a ticket. Capture both at the moment of failure.
When you draft the GitHub issue, put the exit status in the title area and the developer's sentence in the body. Reviewers should not have to re-run the command to learn which one it was.
Keep reading
Capture the failure before they leave
Capture the failure before they leave. Book early access or talk to sales, then install @aethellayer/sdk when you are onboarded.