DSK-20Recommended
Exit with zero only when the command did everything it was asked
Exit 0 only when every action succeeded, and exit with a code from 1 to 125 on any failure. Document each code in the help text and keep its meaning fixed.
How to do it
Scripts, CI jobs and agents read the exit code, not the text. A tool that prints an error and exits 0 lets a broken deploy carry on. POSIX defines 0 as success and leaves 126, 127 and codes above 128 to the shell. Keep 2 for wrong usage, as many tools do. Give each failure a meaning a caller can act on, such as "not found" or "try again". Keep error types stable asks the same of APIs. On Ctrl+C, stop cleanly and exit 130. A partial success is a failure, with the details in the output.
Examples
Python example
import sys
EXIT_OK, EXIT_FAILED, EXIT_USAGE, EXIT_NOT_FOUND, EXIT_RETRY = 0, 1, 2, 3, 4
def main() -> int:
try:
invoice = client.fetch(args.invoice_id)
except NotFound:
print(f"invoice {args.invoice_id} not found", file=sys.stderr)
return EXIT_NOT_FOUND
except ServiceUnavailable:
print("service unavailable, try again later", file=sys.stderr)
return EXIT_RETRY
print(invoice.number)
return EXIT_OK
if __name__ == "__main__":
sys.exit(main())
Go example
const (
exitOK = 0
exitFailed = 1
exitUsage = 2
exitNotFound = 3
exitRetry = 4
)
func main() {
invoice, err := client.Fetch(invoiceID)
switch {
case errors.Is(err, ErrNotFound):
fmt.Fprintf(os.Stderr, "invoice %s not found\n", invoiceID)
os.Exit(exitNotFound)
case err != nil:
fmt.Fprintln(os.Stderr, "service unavailable, try again later")
os.Exit(exitRetry)
}
fmt.Println(invoice.Number)
}
How to check
A test runs each command with a missing file, a wrong flag and a server that answers 500. Each run exits with its documented non-zero code. A successful run exits 0, and the help text lists every code.
Sources
Related rules
- API-17 Keep error types stable in API design
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/desktop-apps/command-line-tools/exit-codes">Agent Wranglers desktop apps, extensions and CLIs playbook</a>. In code you write, add a comment next to it with the same link.