Automation & CI/CD
Master Claude Code headless mode — full flag reference, five CI/CD recipes, Docker isolation, session resumption and a Codex comparison
Need an API key? Sign up →Endpoints & base URLs →
On This Page
Claude Code supports a headless mode you can use in scripts, CI/CD pipelines and automated workflows with no human interaction. This article covers the complete flag reference and several real scenarios.
1. Basic Usage¶
One-shot execution (-p mode)¶
# Basic run
claude -p "Analyse this project's architecture"
# JSON output
claude -p "List every TODO comment" --output-format json
# Cap the number of turns
claude -p "Write unit tests for UserService" --max-turns 5
# Pick a model (claude-sonnet-5 for everyday work; 4.x is still on sale)
claude -p "Review the code for security issues" --model claude-opus-5
Restricting the available tools¶
# Read-only analysis (no writes, no command execution)
claude -p "Analyse code quality" --permission-mode dontAsk --allowedTools Read,Glob,Grep
# Read and write (no command execution)
claude -p "Refactor this file" --permission-mode dontAsk --allowedTools Read,Write,Edit,Glob,Grep
# All tools (controlled environment)
claude -p "Fix the lint errors" --permission-mode dontAsk --allowedTools Read,Write,Edit,Bash,Glob,Grep
--allowedToolsmeans "these tools run without asking"; on its own it does not restrict any other tool. The examples above only expose the listed tools because they pair it with--permission-mode dontAsk, which denies everything not listed. To hide the other built-in tools from Claude entirely, use--tools, for example--tools "Read,Edit,Bash"(only these three built-in tools are offered).
Set the permission mode explicitly (don't rely on the default)¶
Since Claude Code 2.1.285, claude -p and the Agent SDK start in auto when no permission mode is set in sessions
that can't fetch feature flags: a classifier reviews actions that need approval, and classifier requests (model
claude-sonnet-5) count toward your usage. Connecting to QCode with ANTHROPIC_AUTH_TOKEN gives Claude Code no
credential to fetch them (the same holds for CI containers that start fresh every run), so this is your CI's default.
For fixed, reproducible CI behavior, set the mode explicitly:
# only allow-listed tools run; everything else is denied without asking
claude -p "Fix the lint errors" --permission-mode dontAsk --allowedTools "Read,Edit,Bash(npm run lint:*)"
See Feature Availability for how auto mode behaves through QCode.
Skipping permission prompts¶
# Only in a safe, isolated environment!
claude -p "Fix every lint error and commit" --dangerously-skip-permissions
Security warning:
--dangerously-skip-permissionsskips every permission confirmation. Use it only inside a Docker container or an isolated CI environment.
2. Complete Flag Reference¶
Execution control¶
| Flag | What it does | Example |
|---|---|---|
-p "prompt" |
Headless mode, run a single task | claude -p "analyse the architecture" |
--bare |
Minimal mode, skips hooks/LSP/plugins | claude --bare -p "..." |
--max-turns N |
Cap the number of interaction turns | --max-turns 5 |
--model MODEL |
Choose a model | --model claude-opus-5 |
--permission-mode MODE |
Set the permission mode (default / acceptEdits / plan / auto / dontAsk / bypassPermissions) |
--permission-mode dontAsk |
--dangerously-skip-permissions |
Skip every permission confirmation | Isolated environments only |
Output formats¶
| Flag | What it does | When to use |
|---|---|---|
--output-format text |
Plain text (default) | For humans |
--output-format json |
Structured JSON | For scripts |
--output-format stream-json |
Streaming JSON | Real-time processing |
Tool restrictions¶
| Flag | What it does |
|---|---|
--allowedTools Tool1,Tool2 |
Pre-approve: the listed tools run without asking (other tools are not restricted) |
--permission-mode dontAsk |
Deny anything not pre-approved, without asking; paired with --allowedTools it acts as an allow list |
--tools Tool1,Tool2 |
Offer Claude only the listed built-in tools (an actual restriction) |
--disallowedTools Tool1 |
Remove the listed tools from those available |
Available tool names: Read, Write, Edit, Bash, Glob, Grep, WebFetch, WebSearch, Agent, NotebookEdit
Session management¶
| Flag | What it does |
|---|---|
--session-id ID |
Set the session id |
--resume |
Resume a previous session |
Environment variables¶
| Variable | What it does |
|---|---|
ANTHROPIC_BASE_URL |
API endpoint (QCode.cc: https://api.qcode.cc/api) |
ANTHROPIC_AUTH_TOKEN |
API key (starts with cr_) |
CLAUDE_CODE_MAX_TURNS |
Default maximum turns |
CLAUDE_CODE_OUTPUT_FORMAT |
Default output format |
CLAUDE_MODEL |
Default model |
3. CI/CD Recipes¶
Recipe 1: GitHub Actions — AI code review¶
name: AI Code Review
on: [pull_request]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history, needed for the diff
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: AI Code Review
env:
ANTHROPIC_BASE_URL: "https://api.qcode.cc/api"
ANTHROPIC_AUTH_TOKEN: ${{ secrets.QCODE_API_KEY }}
run: |
# Collect the files changed in this PR
FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
claude -p "Review the code changes in the following files, focusing on:
1. Security vulnerabilities (SQL injection, XSS, leaked secrets)
2. Performance problems (N+1 queries, memory leaks)
3. Logic errors
4. Code style issues
Changed files:
$FILES" \
--output-format json \
--max-turns 3 \
--model claude-sonnet-5 \
--permission-mode dontAsk \
--allowedTools Read,Glob,Grep \
> review.json
echo "Review completed"
cat review.json | jq -r '.result' || cat review.json
Recipe 2: generate tests automatically¶
name: Auto Generate Tests
on:
push:
paths: ['src/**/*.ts', '!src/**/*.test.ts']
jobs:
generate-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install dependencies
run: |
npm ci
npm install -g @anthropic-ai/claude-code
- name: Generate missing tests
env:
ANTHROPIC_BASE_URL: "https://api.qcode.cc/api"
ANTHROPIC_AUTH_TOKEN: ${{ secrets.QCODE_API_KEY }}
run: |
claude -p "Look at the .ts files under src/ and write unit tests for the ones that have none.
Use Vitest + Testing Library.
Name test files xxx.test.ts and put them next to the source file.
Target 80%+ coverage." \
--max-turns 10 \
--permission-mode dontAsk \
--allowedTools Read,Write,Glob,Grep,Bash
- name: Run tests
run: npx vitest --run
- name: Create PR with tests
if: success()
run: |
git config user.name "claude-bot"
git config user.email "bot@qcode.cc"
git checkout -b auto-tests-$(date +%s)
git add '*.test.ts'
git commit -m "test: auto-generated unit tests" || exit 0
git push origin HEAD
Recipe 3: a code quality gate¶
name: Code Quality Gate
on: [pull_request]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: npm install -g @anthropic-ai/claude-code
- name: Quality Analysis
env:
ANTHROPIC_BASE_URL: "https://api.qcode.cc/api"
ANTHROPIC_AUTH_TOKEN: ${{ secrets.QCODE_API_KEY }}
run: |
claude -p "Analyse code quality and output JSON:
{
\"score\": 0-100,
\"issues\": [{\"severity\": \"high|medium|low\", \"file\": \"...\", \"description\": \"...\"}],
\"summary\": \"one-line summary\"
}
Scoring:
- Type safety (20 points)
- Error handling (20 points)
- Test coverage (20 points)
- Readability (20 points)
- Security (20 points)" \
--output-format json \
--max-turns 3 \
--model claude-sonnet-5 \
--permission-mode dontAsk \
--allowedTools Read,Glob,Grep \
> quality.json
- name: Check score
run: |
SCORE=$(cat quality.json | jq -r '.result' | jq -r '.score // 0')
echo "Quality score: $SCORE"
if [ "$SCORE" -lt 60 ]; then
echo "Quality gate failed: score $SCORE < 60"
exit 1
fi
Recipe 4: generate a changelog¶
#!/bin/bash
# generate-changelog.sh — build a changelog from git commits
export ANTHROPIC_BASE_URL="https://api.qcode.cc/api"
export ANTHROPIC_AUTH_TOKEN="cr_your_api_key"
# Commits since the last tag
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$LAST_TAG" ]; then
COMMITS=$(git log --oneline -20)
else
COMMITS=$(git log --oneline ${LAST_TAG}..HEAD)
fi
claude -p "Produce a structured changelog from these git commits:
$COMMITS
Format:
## [version] - $(date +%Y-%m-%d)
### Added
### Fixed
### Changed
### Breaking changes (if any)
Write in English, concise and professional." \
--output-format text \
--max-turns 2 \
--model claude-sonnet-5 \
--permission-mode dontAsk \
--allowedTools Read,Glob,Grep
Recipe 5: keep the docs up to date¶
#!/bin/bash
# update-docs.sh — refresh the API docs after code changes
export ANTHROPIC_BASE_URL="https://api.qcode.cc/api"
export ANTHROPIC_AUTH_TOKEN="cr_your_api_key"
claude -p "Look at the route files under src/api/ and compare them with the documentation in docs/api.md.
Find API descriptions that are missing or out of date and update docs/api.md.
Keep the existing document format and style." \
--max-turns 8 \
--permission-mode dontAsk \
--allowedTools Read,Write,Edit,Glob,Grep
4. Docker Isolation¶
When you use --dangerously-skip-permissions in CI/CD, we strongly recommend running inside a Docker container:
FROM node:22-slim
# Install Claude Code
RUN npm install -g @anthropic-ai/claude-code
# Install project dependencies
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
# QCode.cc environment
ENV ANTHROPIC_BASE_URL=https://api.qcode.cc/api
# ANTHROPIC_AUTH_TOKEN is injected at runtime
# Run as a non-root user
RUN useradd -m claude
USER claude
CMD ["claude", "-p", "Run a code review", "--dangerously-skip-permissions", "--max-turns", "5"]
Run it:
docker build -t claude-ci .
docker run --rm -e ANTHROPIC_AUTH_TOKEN=cr_your_key claude-ci
5. Session Resumption and Multi-step Pipelines¶
Multi-step tasks¶
# Step 1: analyse
claude -p "Analyse the project architecture" \
--session-id "pipeline-42" \
--output-format json \
--max-turns 3 \
--permission-mode dontAsk \
--allowedTools Read,Glob,Grep
# Step 2: build a plan from that analysis
claude -p "Based on the previous analysis, draft a refactoring plan" \
--resume --session-id "pipeline-42" \
--max-turns 3
# Step 3: execute the plan
claude -p "Carry out the first step of the refactoring plan" \
--resume --session-id "pipeline-42" \
--max-turns 10 \
--permission-mode dontAsk \
--allowedTools Read,Write,Edit,Bash,Glob,Grep
6. Controlling Cost¶
Strategy 1: cap the turns¶
# Three turns is enough for a simple task
claude -p "Quick analysis" --max-turns 3
# Ten at most for a complex one
claude -p "Full refactor" --max-turns 10
Strategy 2: pick the right model¶
| Scenario | Recommended | Why |
|---|---|---|
| Code review | Sonnet | Good enough and cheap |
| Security scanning | Opus | Needs deep analysis |
| Bulk formatting | Haiku | Cheapest |
| Test generation | Sonnet | Best value |
claude -p "Format the code" --model claude-haiku-5-5 --max-turns 3
Strategy 3: restrict tools to cut token usage¶
# Read-only analysis → no repeated write/test cycles to pay for
claude -p "Analyse the code" --permission-mode dontAsk --allowedTools Read,Glob,Grep --max-turns 3
7. Compared with Codex Headless¶
| Claude Code -p | Codex headless | |
|---|---|---|
| Flag | -p "prompt" |
codex -q "prompt" |
| Sandbox | Needs Docker isolation | Built-in kernel-level sandbox |
| Output formats | text/json/stream-json | text/json |
| Session resumption | --resume --session-id |
Not supported |
| Tool restriction | --tools / --permission-mode dontAsk + --allowedTools |
--approval-mode |
| Parallel execution | Not supported | codex cloud exec |
Use them together: Claude Code for analysis and planning (read-only), Codex for execution (fully automatic).
A QCode.cc plan shares its quota, so switching between the two tools in CI costs nothing.
8. Best Practice Checklist¶
- Always cap the turns: use
--max-turnsin CI to prevent runaway execution - Restrict the tools: allow only what the task needs with
--permission-mode dontAsk+--allowedTools(or limit the available tools with--tools) - Isolate with Docker:
--dangerously-skip-permissionsmust run in a container - JSON output: prefer
--output-format jsonin automation so results are easy to parse - Control cost: Sonnet for analysis, Haiku for simple tasks
- Idempotency: make sure repeated runs have no side effects
- Timeouts: set a job timeout in the pipeline (10 minutes, say)
- Secret management: keep the API key in CI secrets, never hard-code it
Next Steps¶
- Hooks System — trigger actions automatically
- CLI Tips — more command-line usage
- Cost Optimization — techniques for controlling spend
- Complete Claude Code Tutorial — from zero to fluent
Get started with QCode
One API key for Claude Code, Codex and more — billed per token, per-model prices on qcode.cc/models