Use Claude Code Exit Codes to Handle Failures in Shell Scripts
Claude Code behaves like a proper UNIX tool: it exits with code 0 on success and a non-zero code when something goes wrong. This means you can integrate it into shell scripts using the same patterns you use for any other command.
# Only commit if Claude's review passes
claude -p "Review src/auth.ts for security issues" \
&& git commit -am "feat: add auth module"
# Try a complex task, fall back to a simpler one if it fails
claude -p --max-turns 20 "Full migration with tests" \
|| claude -p --max-turns 5 "Apply migration only, skip tests"
# Check exit code explicitly
claude -p "Run the test suite and report any failures"
if [ $? -ne 0 ]; then
echo "Claude Code encountered an error — check the output above"
exit 1
fi
Non-zero exits happen when:
- Claude hits the
--max-turnslimit before completing the task - A tool call fails and Claude cannot recover
- The prompt is refused or a permission is denied mid-run
In CI pipelines, Claude Code steps fail the job automatically on a non-zero exit — exactly the same as any other command:
# GitHub Actions — job fails if Claude exits non-zero
- name: Security review
run: claude -p "Audit this diff for vulnerabilities" --max-turns 10
Pair exit codes with --max-turns and --max-budget-usd to make every automated run predictable and safely bounded. A turn-limit exit is a signal to investigate — something took longer than expected.
Claude Code plays by UNIX rules — build on the exit code and your scripts become as reliable as any other tool in the pipeline.
Log in to leave a comment.
The /security-review command scans your uncommitted changes for injection vectors, auth gaps, hardcoded secrets, and other common vulnerabilities.
The SessionStart hook fires when any session begins or resumes, making it ideal for loading environment variables and running one-time setup scripts.
Ask Claude to write property-based tests for your functions using fast-check — it identifies the mathematical invariants in your code and generates tests that cover inputs you'd never enumerate by hand.