---
title: "CI/CD and Headless Mode with Claude Code"
description: "Integrate Claude Code into your CI/CD pipelines: headless mode, GitHub Actions, automatic code generation, and production best practices."
url: "https://angelo-lima.fr/en/claude-code-cicd-headless-en/"
lang: "en"
author: "Angelo Lima"
datePublished: "2025-12-25T12:00:00.000Z"
tags: ["IA","Développement"]
translation: "https://angelo-lima.fr/fr/claude-code-cicd-headless/"
---

# CI/CD and Headless Mode with Claude Code

*Day 15 - Automate your pipelines with AI*

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:

```bash
claude -p "Explain what this code does" < file.js
```

Claude reads the prompt, executes the task, and returns the result to stdout.

### Basic Syntax

```bash
# 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

```yaml
# .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: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          claude -p "Review these modified files and identify potential issues: ${{ steps.changed.outputs.files }}" \
            --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

```yaml
# .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: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          claude -p "Generate comprehensive tests for @${{ github.event.inputs.file }}" \
            --allowedTools Read,Write

      - name: Create PR
        uses: peter-evans/create-pull-request@v6
        with:
          title: "test: add tests for ${{ github.event.inputs.file }}"
          body: "Tests automatically generated by Claude Code"
          branch: claude/tests-${{ github.run_id }}
```

## GitLab CI Integration

```yaml
# .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

```bash
#!/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

```bash
#!/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

```bash
#!/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

```yaml
# .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: ${{ secrets.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

```bash
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

```bash
# 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

```bash
# 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

```yaml
# Example: limit runs per day
jobs:
  review:
    if: github.event.pull_request.draft == false
    # Avoid reviewing drafts
```

## JSON Output Format

### Response Structure

```bash
claude -p "Analyze this code" --output-format json
```

```json
{
  "result": "Code analysis...",
  "cost": {
    "input_tokens": 1234,
    "output_tokens": 567,
    "total_cost": 0.01
  },
  "session_id": "abc123",
  "duration_ms": 5432
}
```

### Parsing in Scripts

```bash
#!/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

```yaml
- name: Cache Claude artifacts
  uses: actions/cache@v4
  with:
    path: ~/.claude
    key: claude-${{ runner.os }}-${{ hashFiles('**/CLAUDE.md') }}
```

### 2. Reproducible Environment

```yaml
- name: Setup Claude environment
  run: |
    npm install -g @anthropic-ai/claude-code@latest
    echo "CLAUDE_CODE_USE_BEDROCK=0" >> $GITHUB_ENV
```

### 3. Error Handling

```bash
#!/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

```yaml
- 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](https://angelo-lima.fr/en/claude-code-vscode-jetbrains/)*
