Exit codes are part of the CLI's contract with agents and CI. Branch on them instead of matching on error strings.
0success. The command did what it said.1generic error: bad usage, a network failure, or a job that failed server-side. Something is actually broken.2not authenticated. No key, or the key was rejected. Fix the credential, then retry.3forbidden. The key is valid but lacks the required scope. Widening the key is a decision for a human, not a retry.4rate limit or daily quota reached. Back off and resume later.5plan upgrade or payment required. The message carries the upgrade URL.
Code 5 is deliberately distinct from 1. An agent can tell this account needs a paid plan apart from something broke, and respond by surfacing a link to the human instead of retrying in a loop.
A shell pattern that works
npx argorant export --keywords fintech --country Germany -n 500 -o leads.csv --yes
case $? in
0) echo "done" ;;
2|3) echo "credential problem, stopping"; exit 1 ;;
4) echo "rate limited, retry later" ;;
5) echo "needs credits, notify the human" ;;
*) echo "failed" ;;
esac
Codes map directly to HTTP status codes on the REST API: 401 becomes 2, 403 becomes 3, 429 becomes 4 and 402 becomes 5. Agents that use both surfaces can share one error-handling path.