Skip to content
LinkedInX

Level 6: Systems Builder — Headless Automation and Pipelines

5 min read + 40 min hands-on

Target audience: Readers who use Claude Code for multi-step work and want to integrate it into automation pipelines
Prerequisites: Read Level 5

Claude Code can run not just interactively in the terminal, but in a “headless mode” using the --print flag — where it receives output and exits. This makes it possible to embed it in shell scripts and CI/CD pipelines like GitHub Actions.


Normal Claude Code runs interactively. The --print flag switches it to headless mode, where it accepts a prompt, returns output, and then exits.

# Normal mode (interactive)
claude

# Headless mode (pass a prompt, receive output, exit)
claude --print "Please review the code in src/api/main.py"

Headless mode is suitable for calling from scripts or CI, and for piping output to other commands.

You can use cat and pipes to pass file contents to Claude.

# Pass a diff via standard input
git diff main...HEAD | claude --print "Please review this diff"

# Pass the contents of multiple files
cat src/api/routes.py | claude --print "Please list the problems in this code"

This approach lets you build pipelines that pass dynamically generated data directly to Claude.

Using --output-format json makes Claude return output in JSON format. Combined with the jq command, you can handle the response as structured data in subsequent processing.

# Receive output in JSON format
RESULT=$(claude --print --output-format json "
Please analyze the following error log and return the cause and solution in JSON format.
{\"error\": \"cause\", \"solution\": \"solution\"}

$(cat logs/app.log | tail -50)
")

# Extract a specific field with jq
echo "$RESULT" | jq -r '.solution'

Here’s a general-purpose PR review script. It’s designed to accept the target file extensions as an argument so it can be used in any project.

#!/bin/bash
# scripts/review_pr.sh
# A general-purpose script that has Claude review a PR diff
# Usage: ./scripts/review_pr.sh "*.py *.ts"

set -e

# Target extensions (default: Python and TypeScript)
FILE_PATTERNS=${1:-"*.py *.ts *.tsx"}

# Get the diff against main
DIFF=$(git diff main...HEAD -- $FILE_PATTERNS)

if [ -z "$DIFF" ]; then
  echo "No changes to review"
  exit 0
fi

echo "=== AI Code Review ==="

REVIEW=$(echo "$DIFF" | claude --print "
The following is a code diff. Please review it from these perspectives:

1. Potential bugs or logic errors
2. Security issues (unsanitized values, hardcoded secrets)
3. Performance issues
4. Readability and maintainability issues

If there are issues, list them in the format \"[Severity: High/Medium/Low] filename:line: description.\"
If there are none, just respond with \"LGTM\".
")

echo "$REVIEW"

# Return exit code 1 if a high-priority issue is detected
if echo "$REVIEW" | grep -q "\[Severity: High\]"; then
  echo ""
  echo "High-priority issues detected. Please fix them and re-review."
  exit 1
fi

Grant the script execution permission and test it.

chmod +x scripts/review_pr.sh
./scripts/review_pr.sh "*.py"

Create .github/workflows/ai-review.yml to automatically run a review every time a PR is created or updated.

name: AI 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

      - 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: Run AI Review
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          DIFF=$(git diff origin/main...HEAD)

          if [ -z "$DIFF" ]; then
            echo "No review targets"
            exit 0
          fi

          echo "$DIFF" | claude --print \
            --dangerously-skip-permissions \
            "Please review this diff.
            Check from the perspectives of bugs, security, and performance.
            If there are issues, list them with severity. If not, respond with LGTM." \
            > review_result.txt

          cat review_result.txt

      - name: Post Review Comment
        if: github.event_name == 'pull_request'
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs')
            const review = fs.readFileSync('review_result.txt', 'utf8')
            await github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `## AI Code Review\n\n${review}\n\n---\n*Automated review by Claude Code*`
            })

In automated execution environments like CI where user confirmation is not possible, the --dangerously-skip-permissions flag skips confirmation dialogs.

claude --print --dangerously-skip-permissions "..."

This flag grants Claude all operation permissions including file changes and deletions. Use it only in trusted CI environments or other controlled settings where operations are limited and managed. I recommend avoiding routine use in local development environments.


Q. When should I use headless mode vs. normal mode?

Use headless mode for automation scripts, CI/CD, and piping with other commands. Normal mode is better suited for complex interactive tasks or interactive debugging.

Q. What changes when I use —output-format json?

Claude’s response is returned in JSON format including metadata. You can extract specific fields with jq, making it easier to process in subsequent scripts.


Hands-on tutorial for this level →

I’ve understood how to automate PR reviews in headless mode. Next, I’ll learn how to control a browser using MCP.

Next: Level 7: Browser Automator — Browser Control, Scraping, and PDFs.

See the references for the external specifications and background sources used on this page.[1][2]

  1. Anthropic, Claude Code documentation
  2. Anthropic, Claude API documentation