Headless mode, scripts and CI automation
Run the agent non-interactively, parse its JSON output, gate a pipeline on exit codes, and keep CI permissions tighter than your laptop's.
Non-interactive runs
# one prompt, one answer, no session UI
claude -p "summarise what changed in this commit"
# machine-readable output
claude -p "list every TODO added in this branch" --output-format json
# streaming events, one JSON object per line
claude -p "review the diff" --output-format stream-json --verbose
# bound the run
claude -p "fix the lint errors" \
--max-turns 10 \
--allowedTools "Read,Edit,Bash(npm run lint:*)" \
--permission-mode acceptEdits| Flag | Purpose |
|---|---|
-p, --print | Run once and print the result, then exit |
--output-format json | Single JSON object with the result and metadata |
--output-format stream-json | Newline-delimited events as the run progresses |
--max-turns | Hard ceiling on agent turns; the main cost control |
--allowedTools | Pre-approve a specific list, avoiding interactive prompts |
--permission-mode | Set the default posture for the run |
--resume, -c | Continue an earlier session id |
⚠️
In CI, never use
--dangerously-skip-permissions. On a runner with a deploy token and network access, an unconstrained agent is a remote code execution primitive with your credentials attached. Constrain tools, run on a read-only checkout where possible, and let a separate job apply changes.Parsing output and gating on exit codes
#!/usr/bin/env bash
set -euo pipefail
out=$(claude -p "Review the staged diff. Reply with exactly PASS or FAIL then one sentence." \
--output-format json \
--max-turns 3 \
--allowedTools "Read,Grep,Bash(git diff:*)")
# json output carries the text, cost and turn count
echo "$out" | jq '{result, num_turns, total_cost_usd, is_error}'
if [ "$(echo "$out" | jq -r '.is_error')" = "true" ]; then
echo "agent run failed" >&2
exit 1
fi
case "$(echo "$out" | jq -r '.result')" in
PASS*) echo "review passed" ;;
*) echo "review requested changes" >&2; exit 1 ;;
esac- The JSON result includes the text, the number of turns, an error flag and a cost figure - log all four.
- Ask for a machine-checkable first token (PASS or FAIL) instead of parsing prose.
- Exit non-zero from your wrapper when the verdict is bad, so the pipeline and the reviewer both see it.
- Save the stream-json transcript as a build artefact; it is the only record of what the agent actually did.
A review job in a pipeline
name: agent-review
on: pull_request
jobs:
review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 22
- name: Review
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude -p "Review the diff against the base branch. Report only defects that would block a merge, with file:line." \
--output-format json \
--max-turns 8 \
--allowedTools "Read,Grep,Bash(git diff:*),Bash(git log:*)" \
> review.json || true
- uses: actions/upload-artifact@v4
if: always()
with:
name: agent-review
path: review.json- Give the job
contents: read; a reviewing agent needs no write scope. - Use a dedicated API key with a spend limit, and set a per-run turn ceiling so a loop cannot burn the budget.
- Run on pull requests rather than pushes to main - it keeps the cost proportional to review volume.
- Set an explicit job timeout as well; a hung run should fail fast rather than hold a runner.
FAQ
What is the difference between exit codes and the JSON error flag?
The process exit code tells the shell that the invocation itself failed;
is_error in the JSON tells you the agent run reported a problem. CI should check both, because a run can finish cleanly at the process level while reporting an in-band failure.How do I keep CI cost predictable?
Cap
--max-turns, restrict --allowedTools, choose a smaller model for review-style tasks, and only run on the events that need it. Log total_cost_usd per run so a regression is visible in the build history rather than on the invoice.Related
Hooks and deterministic automation Cost, model choice and troubleshooting
Last refreshed 2026-09-18.