Claude Code isn’t limited to interactive use. With headless mode, you can integrate it into your CI/CD pipelines. Let’s see how to automate intelligently.
Headless Mode: -p
The -p (or --print) flag allows running Claude Code without interaction:
claude -p "Explain what this code does" < file.js
Claude reads the prompt, executes the task, and returns the result to stdout.
Basic Syntax
# Simple prompt
claude -p "Generate a .gitignore file for Node.js"
# With stdin input
cat src/utils.ts | claude -p "Find potential bugs"
# With files in context
claude -p "Refactor @src/api/auth.ts to use async/await"
Headless Mode Options
| Option | Description |
|---|---|
-p "prompt" |
Execute with this prompt |
--output-format json |
Structured JSON output |
--output-format text |
Text output (default) |
--max-turns N |
Limit iterations |
--allowedTools |
Restrict tools |
GitHub Actions Integration
Automatic Code Review Workflow
# .github/workflows/claude-review.yml
name: Claude Code Review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: Get changed files
id: changed
run: |
echo "files=$(git diff --name-only origin/main...HEAD | tr '\n' ' ')" >> $GITHUB_OUTPUT
- name: Claude Review
env:
ANTHROPIC_API_KEY: $
run: |
claude -p "Review these modified files and identify potential issues: $" \
--output-format json > review.json
- name: Post Review Comment
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const review = JSON.parse(fs.readFileSync('review.json', 'utf8'));
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 🤖 Claude Code Review\n\n${review.result}`
});
Test Generation Workflow
# .github/workflows/claude-tests.yml
name: Generate Missing Tests
on:
workflow_dispatch:
inputs:
file:
description: 'File to generate tests for'
required: true
jobs:
generate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: Generate Tests
env:
ANTHROPIC_API_KEY: $
run: |
claude -p "Generate comprehensive tests for @$" \
--allowedTools Read,Write
- name: Create PR
uses: peter-evans/create-pull-request@v6
with:
title: "test: add tests for $"
body: "Tests automatically generated by Claude Code"
branch: claude/tests-$
GitLab CI Integration
# .gitlab-ci.yml
stages:
- review
- generate
claude-review:
stage: review
image: node:20
before_script:
- npm install -g @anthropic-ai/claude-code
script:
- |
claude -p "Review the code in this MR and list issues" \
--output-format json > review.json
- cat review.json
artifacts:
paths:
- review.json
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
generate-docs:
stage: generate
image: node:20
before_script:
- npm install -g @anthropic-ai/claude-code
script:
- claude -p "Generate JSDoc documentation for all src/**/*.ts files without documentation"
when: manual
Production Use Cases
1. Automatic Code Review
#!/bin/bash
# scripts/review-pr.sh
PR_FILES=$(git diff --name-only origin/main...HEAD)
claude -p "
You are a senior reviewer. Analyze these modified files:
$PR_FILES
Look for:
1. Potential bugs
2. Performance issues
3. Security vulnerabilities
4. Convention violations
Format: JSON with severity (high/medium/low)
" --output-format json
2. Changelog Generation
#!/bin/bash
# scripts/generate-changelog.sh
LAST_TAG=$(git describe --tags --abbrev=0)
COMMITS=$(git log $LAST_TAG..HEAD --pretty=format:"%s")
claude -p "
Generate a changelog from these commits:
$COMMITS
Keep a Changelog format with sections:
- Added
- Changed
- Fixed
- Removed
"
3. Automatic Code Migration
#!/bin/bash
# scripts/migrate-to-ts.sh
for file in src/**/*.js; do
claude -p "Convert this JavaScript file to TypeScript with strict types: @$file" \
--allowedTools Read,Write
done
4. Security Audit
# .github/workflows/security-audit.yml
name: Security Audit
on:
schedule:
- cron: '0 2 * * 1' # Every Monday at 2am
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: Security Audit
env:
ANTHROPIC_API_KEY: $
run: |
claude -p "
Perform a comprehensive security audit:
1. Scan dependencies for known vulnerabilities
2. Check for dangerous code patterns
3. Identify potentially exposed secrets
Generate a report with priorities.
" --output-format json > security-report.json
- name: Upload Report
uses: actions/upload-artifact@v4
with:
name: security-report
path: security-report.json
Permission Control in CI
Recommended Strict Mode
claude -p "Generate tests" \
--allowedTools Read,Grep,Glob \
--dangerously-skip-permissions
⚠️ --dangerously-skip-permissions should only be used in isolated environments (CI containers).
Tool Restriction
# Read-only
claude -p "Analyze this code" --allowedTools Read,Grep,Glob
# With limited write access
claude -p "Fix the bugs" --allowedTools Read,Write,Edit
# Full access (dangerous)
claude -p "Setup the project" --allowedTools "*"
Cost Management in CI
Limit Tokens
# Limit execution turns
claude -p "Quick review" --max-turns 3
# For simple tasks
claude -p "Explain this function" --max-turns 1
Cost Estimation
| Task | Estimated tokens | Approximate cost |
|---|---|---|
| Simple code review | ~5,000 | ~$0.02 |
| Test generation | ~15,000 | ~$0.05 |
| Complete refactoring | ~50,000 | ~$0.15 |
| Security audit | ~30,000 | ~$0.10 |
Daily Budget
# Example: limit runs per day
jobs:
review:
if: github.event.pull_request.draft == false
# Avoid reviewing drafts
JSON Output Format
Response Structure
claude -p "Analyze this code" --output-format json
{
"result": "Code analysis...",
"cost": {
"input_tokens": 1234,
"output_tokens": 567,
"total_cost": 0.01
},
"session_id": "abc123",
"duration_ms": 5432
}
Parsing in Scripts
#!/bin/bash
RESULT=$(claude -p "Check for bugs" --output-format json)
BUGS=$(echo $RESULT | jq '.result')
COST=$(echo $RESULT | jq '.cost.total_cost')
echo "Bugs found: $BUGS"
echo "Cost: $COST"
CI/CD Best Practices
1. Cache Claude Artifacts
- name: Cache Claude artifacts
uses: actions/cache@v4
with:
path: ~/.claude
key: claude-$-$
2. Reproducible Environment
- name: Setup Claude environment
run: |
npm install -g @anthropic-ai/claude-code@latest
echo "CLAUDE_CODE_USE_BEDROCK=0" >> $GITHUB_ENV
3. Error Handling
#!/bin/bash
set -e
if ! claude -p "Task" --output-format json > result.json; then
echo "Claude failed, falling back to manual review"
exit 0 # Don't block the pipeline
fi
4. Detailed Logging
- name: Claude with logging
run: |
claude -p "Task" 2>&1 | tee claude-output.log
env:
CLAUDE_CODE_DEBUG: "1"
What’s Coming Tomorrow
In Day 16, we’ll talk about billing and cost optimization - understanding and mastering your Claude Code consumption.
This article is part of the “Master Claude Code in 20 Days” series. Day 14: VS Code and JetBrains