Back to List

The Complete Guide to Claude Code CI/CD Integration: From Local Dev to Automated Pipelines

2026-03-17·8 min read·AITutorial

Introduction

Throughout this series, CI/CD has kept popping up — the testing guide touched on test automation, and the Git guide covered CI as part of the PR workflow. But no post has systematically addressed: how to embed Claude Code into your CI/CD pipeline so it works even when you're not around.

During local development, Claude Code is your pair programming partner. But its capabilities go far beyond that — through Headless mode and GitHub Actions integration, it becomes your team's 24/7 automated collaborator: auto-reviewing PRs, auto-fixing lint errors, even generating PRs directly from issues.

This post covers Claude Code's CI/CD capabilities thoroughly.


Why Use Claude Code in CI/CD

Manual Code Review vs Claude Code Automated Review

DimensionManual Code ReviewClaude Code Auto Review
Response timeWaiting for reviewer availability (hours to days)Minutes after PR creation
CoverageLimited by reviewer energy and expertiseSystematically checks all changed files
ConsistencyVaries by person, inconsistent standardsFollows unified rules in CLAUDE.md
AvailabilityWorking hours, timezone constraints24/7 around the clock
CostSenior engineer timeAPI call fees (usually lower)
DepthUnderstands business contextExcels at finding pattern issues and potential bugs

Note: Claude Code isn't meant to replace human code review — it's the first line of defense. It quickly catches obvious issues, letting human reviewers focus on architecture decisions and business logic.

Where Claude Code Fits in the Pipeline

Code push
  ↓
CI triggers (lint, tests, build)
  ↓
Claude Code auto review ← First line of defense
  ↓
Human code review ← Focus on architecture and business
  ↓
Merge
  ↓
CD deploy

Claude Code works best after CI checks but before human review. This way it reviews code that's already passed basic checks, resulting in higher quality reviews.


Headless Mode Basics

To use Claude Code in CI/CD, the core is Headless mode — no interactive terminal needed, everything runs through CLI arguments and pipes.

Core Parameters

ParameterDescriptionExample
-p, --printNon-interactive mode, outputs result directlyclaude -p "analyze this code"
--output-formatOutput format: text, json, stream-jsonclaude -p --output-format json "..."
--max-turnsLimit agent loop iterations, prevent runawayclaude -p --max-turns 10 "..."
--modelSpecify modelclaude -p --model claude-sonnet-4-6 "..."
--allowedToolsWhitelist: only allow specified toolsclaude -p --allowedTools "Read,Grep,Glob" "..."
--disallowedToolsBlacklist: block specified toolsclaude -p --disallowedTools "Bash,Write" "..."
--permission-modePermission modeclaude -p --permission-mode plan "..."

Basic Usage

Simple analysis:

# Analyze a file
claude -p "Analyze src/utils.ts for code quality issues"
 
# Pipe input
cat src/utils.ts | claude -p "Review this code"
 
# Analyze git diff
git diff main | claude -p "Review these changes, point out potential issues"

JSON output (for downstream processing):

claude -p --output-format json "Analyze src/utils.ts for code quality"

Response structure:

{
  "result": "Analysis result text...",
  "is_error": false,
  "total_cost_usd": 0.023,
  "session_id": "abc123"
}

Restricted tools (security review scenario):

# Read-only mode: only allow reading and searching, no file modifications
claude -p --allowedTools "Read,Grep,Glob" "Review all API endpoint security in src/"

Environment Variables

VariableDescription
ANTHROPIC_API_KEYAPI key (required in CI)
CLAUDE_MODELDefault model (overridden by --model)
CLAUDE_MAX_TURNSDefault max turns

In CI environments, ANTHROPIC_API_KEY must be injected via Secrets — never hardcode it in config files or source code.


GitHub Actions Integration

GitHub Actions is the most mature CI/CD integration for Claude Code. Anthropic provides an official Action that works out of the box.

The Official GitHub Action

# .github/workflows/claude-review.yml
name: Claude Code Review
 
on:
  pull_request:
    types: [opened, synchronize]
 
jobs:
  review:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
 
      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          prompt: |
            Review this PR's code changes. Focus on:
            1. Potential bugs and logic errors
            2. Security vulnerabilities
            3. Performance issues
            4. Code style consistency

This basic setup gets Claude Code to automatically review code on every PR creation or update, posting review results as PR comments.

Configuration Options

Key parameters for anthropics/claude-code-action@v1:

ParameterDescriptionDefault
anthropic_api_keyAPI keyRequired
promptCustom promptBuilt-in review prompt
modelModel selectionclaude-sonnet-4-6
max_turnsMax turns10
allowed_toolsAllowed tools listAll
disallowed_toolsBlocked tools listNone
timeout_minutesTimeout10

Automated Code Review

A more complete code review workflow:

name: Claude Code Review
 
on:
  pull_request:
    types: [opened, synchronize]
    paths:
      - 'src/**'
      - 'lib/**'
      - 'app/**'
 
jobs:
  review:
    runs-on: ubuntu-latest
    # Skip draft PRs and bot-created PRs
    if: |
      github.event.pull_request.draft == false &&
      github.event.pull_request.user.login != 'dependabot[bot]'
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
 
      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          model: claude-sonnet-4-6
          max_turns: 10
          prompt: |
            You are a strict but friendly code reviewer. Review all changes in this PR.
 
            Review focus:
            1. **Correctness**: Logic errors, edge cases, null handling
            2. **Security**: Injection vulnerabilities, sensitive data leaks, permission issues
            3. **Performance**: Unnecessary loops, memory leaks, N+1 queries
            4. **Maintainability**: Naming clarity, function complexity, code duplication
 
            Output format:
            - 🔴 Must fix: Blocking issues
            - 🟡 Suggestion: Improvement recommendations
            - 🟢 Well done: Things worth praising
 
            If no issues found, just say "LGTM" — don't manufacture problems.

Auto-Fix PRs

Claude Code can not only review but also fix issues directly:

name: Claude Auto Fix
 
on:
  issue_comment:
    types: [created]
 
jobs:
  auto-fix:
    # Only trigger on PR comments containing /claude-fix
    if: |
      github.event.issue.pull_request &&
      contains(github.event.comment.body, '/claude-fix')
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.issue.pull_request.head.ref }}
          fetch-depth: 0
 
      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          max_turns: 20
          allowed_tools: "Read,Grep,Glob,Edit,Write,Bash"
          prompt: |
            Read all review comments on this PR and fix the mentioned issues.
            After fixing, commit the changes.
            Commit message format: fix: <brief description of the fix>

Usage: type /claude-fix in a PR comment, and Claude Code will automatically read review feedback and fix the code.

Issue-Driven Development

The most powerful use case — generating PRs directly from issues:

name: Claude Issue to PR
 
on:
  issues:
    types: [labeled]
 
jobs:
  implement:
    # Only trigger when the "claude" label is added
    if: github.event.label.name == 'claude'
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
      issues: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
 
      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          max_turns: 30
          prompt: |
            Read Issue #${{ github.event.issue.number }}.
            Based on the issue description:
            1. Create a new branch: claude/issue-${{ github.event.issue.number }}
            2. Implement the feature or fix described in the issue
            3. Ensure code passes lint and tests
            4. Create a PR with the title referencing the issue number
            5. Explain the implementation approach in the PR description
 
            Follow the coding standards in the project's CLAUDE.md.

Workflow: Create issue → Describe requirements → Add claude label → Claude Code implements → Generates PR → Human review → Merge.


Other CI Platform Integration

Not using GitHub Actions? No problem. Claude Code's Headless mode works on any CI platform.

GitLab CI

# .gitlab-ci.yml
claude-review:
  stage: review
  image: node:20
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  before_script:
    - npm install -g @anthropic-ai/claude-code
  script:
    - |
      git diff origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME...HEAD > /tmp/diff.txt
      REVIEW=$(claude -p --output-format text --max-turns 10 \
        --allowedTools "Read,Grep,Glob" \
        "Review the following code changes, point out potential issues: $(cat /tmp/diff.txt)")
      echo "$REVIEW"
      # Post review as MR comment
      curl --request POST \
        --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
        --header "Content-Type: application/json" \
        --data "{\"body\": \"## Claude Code Review\n\n${REVIEW}\"}" \
        "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/notes"
  variables:
    ANTHROPIC_API_KEY: $ANTHROPIC_API_KEY

Generic CI Pattern

Regardless of CI platform, the core pattern is the same:

#!/bin/bash
# scripts/claude-review.sh
 
set -euo pipefail
 
# 1. Get changes
DIFF=$(git diff origin/main...HEAD)
 
if [ -z "$DIFF" ]; then
  echo "No code changes, skipping review"
  exit 0
fi
 
# 2. Claude Code review
REVIEW=$(echo "$DIFF" | claude -p \
  --output-format text \
  --max-turns 10 \
  --allowedTools "Read,Grep,Glob" \
  "Review these code changes. Focus on bugs, security vulnerabilities, and performance issues. If no issues found, reply LGTM.")
 
# 3. Output result
echo "$REVIEW"
 
# 4. Check for blocking issues (optional)
if echo "$REVIEW" | grep -q "🔴"; then
  echo "::error::Claude Code found blocking issues"
  exit 1
fi

Call this script from any CI platform:

# Jenkins, CircleCI, Azure DevOps, etc.
- run: bash scripts/claude-review.sh
  env:
    ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

Docker Approach

If your CI environment can't easily install Node.js:

# .claude/Dockerfile
FROM node:20-slim
RUN npm install -g @anthropic-ai/claude-code
ENTRYPOINT ["claude"]
# Use in CI
steps:
  - run: |
      docker build -t claude-code -f .claude/Dockerfile .
      git diff main | docker run -i \
        -e ANTHROPIC_API_KEY=${{ secrets.ANTHROPIC_API_KEY }} \
        claude-code -p --max-turns 10 "Review these changes"

Security Best Practices

Running an AI agent in CI/CD means security is the top priority.

API Key Management

✅ Do:
- Use your CI platform's Secrets management (GitHub Secrets, GitLab Variables, etc.)
- Rotate API keys regularly
- Use different keys for different environments

❌ Don't:
- Hardcode in YAML files
- Commit to Git repositories
- Print keys in logs

Tool Permission Control

In CI environments, Claude Code's permissions should be as tight as possible:

# Read-only review (safest)
- uses: anthropics/claude-code-action@v1
  with:
    allowed_tools: "Read,Grep,Glob"
    prompt: "Review code changes"
 
# Can fix (needs write permissions)
- uses: anthropics/claude-code-action@v1
  with:
    allowed_tools: "Read,Grep,Glob,Edit,Write"
    disallowed_tools: "Bash"
    prompt: "Fix lint errors"
 
# Full permissions (use with caution)
- uses: anthropics/claude-code-action@v1
  with:
    disallowed_tools: "WebFetch,WebSearch"
    prompt: "Implement this feature"

Rule of thumb: Read-only for reviews, add write for fixes, only grant Bash for feature implementation. Always disable network tools unless you specifically need them.

Preventing Prompt Injection

Claude Code in CI reads PR titles, descriptions, and comments — all user input. Malicious users might attempt instruction injection:

# Don't concatenate user input directly into prompts
# ❌ Dangerous
prompt: "Review this PR: ${{ github.event.pull_request.title }}"
 
# ✅ Safe: let Claude Code read PR info itself
prompt: "Review the current PR's code changes, focus on security and correctness"

Security Checklist

CheckDescription
API key in SecretsNot in code or config files
Minimal tool permissionsOnly grant necessary tools
max_turns is limitedPrevent infinite loops burning tokens
Network tools disabledPrevent data exfiltration
User input not concatenatedPrevent prompt injection
Output contains no secretsReview results don't leak sensitive data

Cost Control

Claude Code call volume in CI/CD can add up fast. Cost control matters.

Model Selection Strategy

ScenarioRecommended ModelReason
Simple lint fixesHaikuFast, cheap, sufficient for formatting
Code reviewSonnetBest cost-performance ratio, good review quality
Complex feature implementationOpusNeeds deep understanding and multi-step reasoning
PR description generationHaikuTemplate-like task, no heavy reasoning needed
# Choose model based on task
- uses: anthropics/claude-code-action@v1
  with:
    model: claude-sonnet-4-6  # Sonnet for code review
    max_turns: 10
 
# Haiku for simple tasks
- uses: anthropics/claude-code-action@v1
  with:
    model: claude-haiku-4-5
    max_turns: 5

Trigger Condition Optimization

Not every PR needs Claude Code review:

on:
  pull_request:
    types: [opened, synchronize]
    paths:
      # Only review source code changes, ignore docs and config
      - 'src/**'
      - 'lib/**'
      - 'app/**'
      - '!**/*.md'
      - '!**/*.mdx'
 
jobs:
  review:
    # Skip draft PRs
    if: github.event.pull_request.draft == false
    # Skip bot PRs
    if: github.event.pull_request.user.login != 'dependabot[bot]'

max_turns Strategy

Task TypeRecommended max_turnsRationale
Code review (read-only)5-10Read diff + analyze
Lint fixes10-15Read + modify + verify
Feature implementation20-30Multi-file read/write + tests
Bug fixes15-20Investigate + fix + verify

max_turns is the most effective cost control lever. Too low and tasks will not complete; too high and you waste tokens. Adjust based on task complexity.

Cost Monitoring

# Use JSON output to get cost info
- name: Claude Review
  id: review
  run: |
    RESULT=$(claude -p --output-format json --max-turns 10 "Review code changes")
    COST=$(echo "$RESULT" | jq -r '.total_cost_usd')
    echo "cost=$COST" >> $GITHUB_OUTPUT
    echo "Claude Code review cost: \$$COST"
 
# Set up cost alerts
- name: Cost Alert
  if: steps.review.outputs.cost > 1.0
  run: echo "::warning::Claude Code single review cost exceeded $1.0"

CLAUDE.md for CI

Claude Code reads the project CLAUDE.md in CI just like it does locally. You can add CI-specific rules.

CI-Specific Rules Example

# CLAUDE.md
 
## CI/CD Rules
 
When running in CI (CI=true environment variable detected):
 
### Code Review
- Only focus on files changed in this PR, do not review unmodified code
- Categorize findings: 🔴 Must fix, 🟡 Suggestion, 🟢 Well done
- If no issues found, just reply "LGTM" — do not manufacture problems
- Do not suggest refactoring unmodified code
 
### Auto-Fix
- Only fix clear issues (lint errors, type errors), do not refactor opportunistically
- Run relevant tests after each fix to confirm nothing breaks
- Commit message format: fix: <brief description>
 
### Security
- Never include environment variable values in output
- Do not read .env files
- Do not make network requests

Project Context

Claude Code in CI reads the full project context, same as locally:

CLAUDE.md             → Project standards and CI rules
.claude/settings.json → Hooks and permission config
package.json          → Dependencies and scripts
tsconfig.json         → TypeScript config
.eslintrc             → Lint rules

This means standards you have configured locally are automatically followed in CI. No need to duplicate them in CI config.


Practical Example: Complete PR Automation Pipeline

Let us tie everything together into a complete PR automation pipeline.

Pipeline Design

Developer opens PR
    ↓
CI basic checks (lint, tests, build)
    ↓
Claude Code auto review
    ↓
Review passes → Await human review
Review fails → Developer fixes OR comment /claude-fix for auto-fix
    ↓
Human review approved
    ↓
Merge

Complete Workflow Configuration

# .github/workflows/claude-pr-pipeline.yml
name: Claude PR Pipeline
 
on:
  pull_request:
    types: [opened, synchronize]
    paths:
      - 'src/**'
      - 'lib/**'
      - 'app/**'
  issue_comment:
    types: [created]
 
jobs:
  # Job 1: Auto review
  review:
    if: |
      github.event_name == 'pull_request' &&
      github.event.pull_request.draft == false
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
 
      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          model: claude-sonnet-4-6
          max_turns: 10
          allowed_tools: "Read,Grep,Glob"
          timeout_minutes: 10
          prompt: |
            Review this PR's code changes.
 
            Review focus:
            1. Correctness: Logic errors, edge cases, null handling
            2. Security: Injection vulnerabilities, sensitive data leaks
            3. Performance: Unnecessary loops, memory leaks
            4. Maintainability: Naming, complexity, duplication
 
            Output format:
            - 🔴 Must fix (with specific file and line number)
            - 🟡 Suggestion
            - 🟢 Well done
 
            No issues? Just say LGTM.
 
  # Job 2: Auto fix (comment-triggered)
  auto-fix:
    if: |
      github.event_name == 'issue_comment' &&
      github.event.issue.pull_request &&
      contains(github.event.comment.body, '/claude-fix')
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.issue.pull_request.head.ref }}
          fetch-depth: 0
 
      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          model: claude-sonnet-4-6
          max_turns: 20
          allowed_tools: "Read,Grep,Glob,Edit,Write,Bash"
          disallowed_tools: "WebFetch,WebSearch"
          prompt: |
            Read all review comments on this PR and fix the mentioned issues.
            After fixing:
            1. Run lint to confirm it passes
            2. Run tests to confirm nothing is broken
            3. Commit changes with format: fix: <description>

Usage Flow

  1. Developer opens a PR
  2. CI runs lint and tests
  3. Claude Code auto-reviews and posts comments
  4. If issues found:
    • Developer fixes manually, or
    • Types /claude-fix in a PR comment for Claude Code to auto-fix
  5. After review passes, human reviewer does final confirmation
  6. Merge

FAQ

Q: How is Claude Code in CI different from local? A: Functionally identical — it just runs in non-interactive mode via the -p flag. It still reads CLAUDE.md, settings.json, and other project config. The main difference is that CI typically restricts tool permissions (e.g., disabling network access).

Q: Are Claude Code review results reliable? A: Very reliable for pattern-based issues (null handling, type safety, common security vulnerabilities). For business logic correctness, it may lack context. That is why it is recommended as a first line of defense, not a replacement for human review.

Q: How much does it cost? A: Depends on PR size and model choice. A medium PR (200-500 lines changed) costs roughly $0.02-0.05 with Sonnet. Haiku is cheaper for simple tasks. For a moderately active team (5-10 PRs/day), expect around $30-50/month.

Q: Can Claude Code merge PRs automatically? A: Technically yes, but strongly discouraged. Claude Code should be an assistive tool — the final merge decision should be made by humans. The risk of auto-merging is too high.

Q: Will multiple Claude Code workflows conflict? A: No. Each workflow runs in an isolated environment with its own checkout and session. But watch out for auto-fix workflows pushing commits that trigger new CI runs, potentially causing loops. Use conditional checks (like checking commit author) to prevent this.

Q: Does it work with private repositories? A: Yes. Claude Code runs in CI after the code is checked out locally, so no additional repo access is needed. You just need ANTHROPIC_API_KEY and a GitHub token (automatically provided by Actions).


Conclusion

Claude Code CI/CD integration boils down to two things:

  1. Headless mode lets Claude Code run in any automated environment — the -p flag + tool permission control + cost limits, three levers that cover everything
  2. The official GitHub Actions integration makes PR automation plug-and-play — auto review, auto fix, issue-driven development, pick the combination you need

Start with the simplest auto code review, get it running smoothly, then gradually add auto-fix and issue-driven development. Do not try to build the full automation suite from day one — let your team get comfortable with AI reviews first, then expand from there.


Further Reading