How to run Claude Code non-interactively: --print flag, piping input, CI/CD automation, scripting, and batch processing with Claude Code in headless mode.
Claude Code's headless mode lets you use Claude in scripts, CI pipelines, and automation workflows without the interactive REPL.
# --print runs Claude, outputs response to stdout, and exits:
claude --print "Summarize what src/auth.py does"
# Pipe input:
cat src/auth.py | claude --print "Review this file for security issues"
# Redirect file as input:
claude --print "What does this function do?" < src/utils.py
# Combine with shell tools:
git diff HEAD~1 | claude --print "Summarize these changes in one sentence"
# .github/workflows/pr-review.yml
name: Claude PR Review
on: [pull_request]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: Review PR
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
git diff origin/${{ github.base_ref }}...HEAD > pr.diff
REVIEW=$(claude --print --allowedTools "Read,Grep" "Review this PR diff for bugs and issues. Be concise." < pr.diff)
echo "$REVIEW"
# Optionally post as PR comment via gh CLI
# Get structured output for programmatic processing:
claude --print --output-format json "List all TODO comments in src/ as a JSON array with file and line fields"
# Parse with jq:
claude --print --output-format json "Extract function names from src/api.py" | jq '.[]'
# Streaming JSON (for long responses):
claude --print --output-format stream-json "Analyze all test files in tests/"
# Read-only mode (no writes, no shell):
claude --print --allowedTools "Read,Grep,Glob" "Find all database queries in src/"
# Allow read + specific shell commands only:
claude --print --allowedTools "Read,Grep,Bash(pytest:*)" "Run the test suite and summarize failures"
# Block all file writes in automation:
# Set in .claude/settings.json for project-wide enforcement:
# { "permissions": { "deny": ["Edit", "Write", "Bash"] } }
# Process multiple files:
for f in src/**/*.py; do
issues=$(claude --print --allowedTools "Read" "List any security issues in $f. Output: 'NONE' or a bulleted list." < "$f")
if [ "$issues" != "NONE" ]; then
echo "=== $f ===" >> security-report.txt
echo "$issues" >> security-report.txt
fi
done
# Generate changelog from git log:
git log --oneline v1.2.0..HEAD | claude --print "Turn this commit list into a user-facing changelog"
# Auto-generate docstrings for a module:
claude --print "Add Python docstrings to all public functions in src/utils.py.
Output the complete updated file." < src/utils.py > src/utils.py.new && mv src/utils.py.new src/utils.py
| Variable | Purpose |
|---|---|
| ANTHROPIC_API_KEY | API key for authentication (required) |
| ANTHROPIC_MODEL | Override default model (e.g., claude-haiku-4-5-20251001 for cost savings) |
| CLAUDE_CODE_MAX_OUTPUT_TOKENS | Cap response length |
| CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC | Disable telemetry in CI |
# Use Haiku for routine CI tasks (10x cheaper than Sonnet):
ANTHROPIC_MODEL=claude-haiku-4-5-20251001 claude --print "Check for obvious bugs in this diff" < pr.diff
# Use Sonnet for code review (better reasoning):
ANTHROPIC_MODEL=claude-sonnet-4-6 claude --print "Full security review of this PR" < pr.diff
# Estimate cost: 1K input tokens ≈ $0.0008 (Haiku) or $0.003 (Sonnet)
# Average PR diff: 2-4K tokens → $0.002-0.012 per review
For setting up Claude Code hooks that fire automatically (not requiring --print), see Claude Code hooks tutorial. For full GitHub Actions YAML examples, see Claude API in GitHub Actions.