← All Claude Code Skills

Claude Code in GitHub Actions

Run Claude Code headlessly in GitHub Actions to automate code review, generate PR descriptions, write tests, and build agentic CI/CD pipelines.

Basic Setup

Three things required: Node.js in your runner, ANTHROPIC_API_KEY as a secret, and --dangerously-skip-permissions to bypass interactive prompts.

name: Claude Code Review

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  review:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install Claude Code
        run: npm install -g @anthropic-ai/claude-code

      - name: Run Claude Code Review
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          DIFF=$(git diff origin/${{ github.base_ref }}...HEAD)
          REVIEW=$(echo "$DIFF" | claude --print --dangerously-skip-permissions \
            "Review this git diff for: bugs, security issues, performance problems, \
             and missing error handling. Be concise. Format as markdown." 2>&1)
          echo "$REVIEW" > /tmp/review.md

      - name: Post Review as PR Comment
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const review = fs.readFileSync('/tmp/review.md', 'utf8');
            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: '## Claude Code Review\n\n' + review
            });

Common Automation Patterns

1. Automated PR Description Generator

- name: Generate PR Description
  env:
    ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
    GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  run: |
    DIFF=$(git diff origin/${{ github.base_ref }}...HEAD --stat)
    FULL_DIFF=$(git diff origin/${{ github.base_ref }}...HEAD)
    DESC=$(echo "$FULL_DIFF" | claude --print --dangerously-skip-permissions \
      "Write a clear PR description for this diff. Include: Summary (2-3 sentences), \
       Changes (bullet list), and Testing (what to verify). Format as markdown.")
    gh pr edit ${{ github.event.number }} --body "$DESC"

2. Auto-Fix Lint Errors and Commit

- name: Fix Lint Errors
  env:
    ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
  run: |
    # Run linter and capture failures
    npm run lint 2>&1 > /tmp/lint-output.txt || true
    if [ -s /tmp/lint-output.txt ]; then
      cat /tmp/lint-output.txt | claude --dangerously-skip-permissions \
        "Fix all the ESLint errors shown. Only fix what's reported — no other changes."
    fi

- name: Commit fixes if any
  run: |
    git config user.email "ci@github-actions"
    git config user.name "Claude Code Bot"
    git diff --quiet || (git add -A && git commit -m "fix: auto-fix lint errors via Claude Code")
    git push

3. Test Generation for New Functions

- name: Generate Tests for New Code
  env:
    ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
  run: |
    # Find newly added functions in the diff
    NEW_FUNCTIONS=$(git diff origin/${{ github.base_ref }}...HEAD \
      --unified=0 | grep '^+.*function\|^+.*const.*=.*(' | head -20)
    if [ -n "$NEW_FUNCTIONS" ]; then
      echo "$NEW_FUNCTIONS" | claude --dangerously-skip-permissions \
        "Generate Jest unit tests for each new function shown. \
         Place tests in __tests__/ matching the source file structure. \
         Include edge cases and error paths."
    fi

Cost by Model

Model Input price Output price Cost per PR review (~5K in / ~500 out) Best for
Claude Haiku 4.5 $0.80/MTok $4/MTok ~$0.006 High-frequency, simple tasks (lint fix, commit msg)
Claude Sonnet 4.6 $3/MTok $15/MTok ~$0.022 Code review, test generation, complex refactors
Claude Opus 4.7 $15/MTok $75/MTok ~$0.113 Highest-stakes one-off tasks (architecture review)

Use Haiku for triggered-on-every-commit jobs; use Sonnet for PR-level quality gates; reserve Opus for scheduled deep reviews.

Security Best Practices

Never hardcode ANTHROPIC_API_KEY in YAML files. Always use ${{ secrets.ANTHROPIC_API_KEY }}. Leaked keys can be used by anyone — Anthropic cannot refund API costs from key leaks.

Frequently Asked Questions

Can Claude Code run in GitHub Actions without --dangerously-skip-permissions?
For read-only tasks (code analysis, generating output text), you can use the --print flag instead, which doesn't need permission bypassing because it doesn't write files. For tasks that write files (auto-fix, test generation, PR description updates), you need --dangerously-skip-permissions since there's no human to approve the tool calls. The flag is safe in CI because the runner environment is ephemeral and isolated.
How do I use Claude Code to review only the changed files?
Use git diff origin/$BASE_BRANCH...HEAD --name-only to get the list of changed files, then pass them directly: claude --print --dangerously-skip-permissions "Review these files: $(git diff --name-only origin/main...HEAD | tr '\n' ' ')". You can also pipe the full diff: git diff origin/main...HEAD | claude --print .... For very large diffs, filter to specific file types first: git diff origin/main...HEAD -- '*.ts' '*.tsx'.
Can Claude Code open GitHub Issues or close PRs?
Not directly — Claude Code doesn't have GitHub API tools built in. But you can use the GitHub CLI (gh) inside Claude Code's bash environment in CI. Claude can run gh commands to create issues, post comments, or update PR status. Alternatively, use github-script or other GitHub Actions after Claude Code finishes to act on its output.
How do I run Claude Code in a self-hosted runner or Docker?
In Docker: install Node.js (node:20-alpine works), run npm install -g @anthropic-ai/claude-code, set ANTHROPIC_API_KEY as an environment variable, and run claude commands normally. For self-hosted runners, install Node.js and the claude package on the runner machine, then reference ANTHROPIC_API_KEY from GitHub secrets the same way. No special Docker images are needed — it's just a Node.js CLI.

Related

More Claude Code Tools

⚡ Using Claude Code? 30 power prompts that 2× your output · £5 £3 first 10Get PDF £3 →