Skip to content
Lesson 10 of 14

CLI Mastery and CI/CD Integration

8 min read

Two Modes of Operation

Up to this point in the course, you have used Claude Code interactively -- typing prompts, reviewing responses, approving actions. That interactive REPL is powerful for daily development work. But Claude Code has a second mode that unlocks an entirely different category of use cases: print mode.

When you run claude with no arguments, you enter the interactive REPL. When you run claude -p "your prompt", you enter print mode. In print mode, Claude processes your prompt, produces output to stdout, and exits. There is no ongoing conversation, no interactive approval, and no persistence. It behaves like any other Unix command-line tool.

This distinction matters because print mode makes Claude Code composable. You can pipe data into it, capture its output, chain it with other tools, and embed it in scripts and CI/CD workflows.

The basic syntax is straightforward:

# Single query, text output to stdout
claude -p "Explain the difference between map and flatMap in JavaScript"

# Provide a system prompt for context
claude -p "Review this code for security issues" --system-prompt "You are a security auditor. Focus on injection vulnerabilities and auth bypasses."

# Specify a model
claude -p "Summarize this file" --model claude-sonnet-4-20250514

Print mode accepts input from stdin, which means you can pipe content directly into Claude:

# Pipe a file for analysis
cat src/auth/login.ts | claude -p "Find potential security vulnerabilities in this code"

# Pipe error logs for explanation
tail -50 /var/log/app/error.log | claude -p "Explain these errors and suggest fixes"

# Pipe a diff for review
git diff HEAD~1 | claude -p "Review this diff. Flag any bugs, style issues, or missing tests"

Try this: run git log --oneline -20 | claude -p "Summarize the recent development activity based on these commit messages" in one of your projects.

Output Formats

By default, print mode outputs plain text. For automation, you often need structured data. Claude Code supports several output formats:

# JSON output — structured, parseable
claude -p "List all TODO comments in this project" --output-format json

# Streaming JSON — each event as a separate JSON object
claude -p "Analyze this codebase" --output-format stream-json

# Plain text (default)
claude -p "Explain this function" --output-format text

The JSON output format is particularly useful for pipelines because you can process it with jq:

# Extract just the response text from JSON output
claude -p "List the 5 most complex functions in src/" --output-format json | jq -r '.result'

# Get token usage information
claude -p "Summarize this file" --output-format json | jq '.usage'

The stream-json format emits one JSON object per line as Claude produces output, which is useful for real-time processing in longer tasks.

Essential CLI Flags

Here are the flags you will use most often in scripts and automation:

# Limit the number of agentic turns (critical for CI to prevent runaway sessions)
claude -p "Fix the failing tests" --max-turns 10

# Set permission mode for non-interactive use
claude -p "Refactor utils.ts" --permission-mode auto

# Restrict which tools Claude can use
claude -p "Review this PR" --allowedTools "read,grep,glob"

# Resume a named session
claude -r "my-session"

# Combine multiple flags
claude -p "Run tests and fix failures" \
  --max-turns 15 \
  --permission-mode auto \
  --output-format json \
  --model claude-sonnet-4-20250514

The --max-turns flag is essential for any automated usage. Without it, Claude could loop indefinitely trying to solve a problem, burning through tokens and time. Always set a reasonable limit.

The --allowedTools flag restricts what Claude can do. For a read-only review task, limit tools to read, grep, and glob. For a task that needs to edit files, add write and edit. This follows the principle of least privilege.

Batch Processing

Print mode shines when you need to process multiple files or items:

# Generate documentation for every TypeScript file in src/
for file in src/**/*.ts; do
  echo "Processing $file..."
  claude -p "Generate JSDoc documentation for all exported functions in this file. Output only the documented code." < "$file" > "${file}.documented"
done

# Analyze multiple log files
for log in logs/*.log; do
  echo "=== $log ===" >> analysis.txt
  claude -p "Summarize errors and warnings in this log file" < "$log" >> analysis.txt
done

For larger batch jobs, you can parallelize with xargs:

# Process 4 files in parallel
find src/ -name "*.ts" | xargs -P 4 -I {} bash -c \
  'claude -p "Check for unused imports in this file" < "{}" > "/tmp/review-$(basename {}).txt"'

GitHub Actions Integration

One of the most powerful applications of print mode is integrating Claude Code into CI/CD pipelines. Here is a GitHub Actions workflow that uses Claude to review pull requests automatically:

name: AI Code Review
on:
  pull_request:
    types: [opened, synchronize]

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 Changes
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          git diff origin/main...HEAD | claude -p \
            "Review this pull request diff. Check for:
            1. Bugs or logic errors
            2. Security vulnerabilities
            3. Performance issues
            4. Missing error handling
            Output a structured review with severity levels." \
            --output-format json \
            --max-turns 5 > review.json

      - name: Post Review Comment
        uses: actions/github-script@v7
        with:
          script: |
            const review = require('./review.json');
            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: review.result
            });

Automated Test Analysis

Another practical pipeline analyzes test failures and suggests fixes:

- name: Run Tests
  id: tests
  run: npm test 2>&1 | tee test-output.txt
  continue-on-error: true

- name: Analyze Failures
  if: steps.tests.outcome == 'failure'
  env:
    ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
  run: |
    cat test-output.txt | claude -p \
      "Analyze these test failures. For each failure:
      1. Identify the root cause
      2. Suggest a specific fix
      3. Rate confidence (high/medium/low)
      Format as markdown." \
      --max-turns 3 > failure-analysis.md

Batch Documentation Generation

Generate documentation for an entire codebase in one pipeline run:

#!/bin/bash
# generate-docs.sh — Batch documentation generation

OUTPUT_DIR="docs/api"
mkdir -p "$OUTPUT_DIR"

find src/ -name "*.ts" -not -path "*/node_modules/*" | while read file; do
  filename=$(basename "$file" .ts)
  echo "Documenting $file..."

  claude -p "Generate API documentation for this TypeScript file. \
    Include: function signatures, parameter descriptions, return types, \
    and usage examples. Output as markdown." \
    --max-turns 3 \
    < "$file" > "$OUTPUT_DIR/${filename}.md"
done

echo "Documentation generated in $OUTPUT_DIR"

Scheduled Tasks

Claude Code supports scheduled recurring automation with the /schedule command:

# Schedule a daily codebase health check
/schedule daily "Run the linter, check for outdated dependencies with npm outdated, and report any security vulnerabilities with npm audit. Summarize findings."

# Schedule weekly documentation freshness review
/schedule weekly "Compare source code changes from the last 7 days against the documentation. List any docs that may be outdated."

Scheduled tasks run in print mode automatically and can deliver results through hooks or notifications.

Cost Management and Rate Limiting

When running Claude Code in automated pipelines, cost control is critical:

# Always set max-turns in CI to prevent runaway sessions
claude -p "Fix this bug" --max-turns 10

# Check costs after a run
/cost

# View usage statistics
/stats

For CI pipelines, establish a token budget by combining --max-turns with focused prompts. A well-scoped prompt with --max-turns 5 will cost a fraction of an open-ended prompt with no turn limit.

Best Practices for Automation

Always use --max-turns in CI. This is non-negotiable. An uncapped session in a CI pipeline can run for hours and consume thousands of dollars in API costs.

Use --output-format json when parsing results. JSON output is deterministic in structure, making it reliable for downstream processing. Plain text output can vary in format.

Restrict tools with --allowedTools. If a CI step only needs to read and analyze code, do not give it write permissions. This prevents accidental modifications.

Keep prompts specific. In automation, vague prompts lead to unpredictable results. Instead of "review this code," specify exactly what to look for and what format to use for the output.

Store API keys as secrets. Never hardcode your ANTHROPIC_API_KEY in workflow files. Use your CI platform's secrets management.

Test locally first. Before adding a Claude Code step to your CI pipeline, test the exact command locally with claude -p to verify it produces the output you expect.

Print mode transforms Claude Code from an interactive assistant into a programmable component that fits anywhere in your development infrastructure.