Problem: Manual Code Review Slows Every PR
Claude Code GitHub Actions automated PR review means every pull request gets consistent AI feedback before a human sees it — catching bugs, style drift, and missing tests in seconds. Without it, reviewers burn time on mechanical checks instead of architecture decisions.
You'll learn:
- Wire
claude-code-actioninto a GitHub Actions workflow that triggers on every PR - Configure Claude to post inline comments and a summary review
- Restrict which files Claude reviews so costs stay predictable
Time: 20 min | Difficulty: Intermediate
Why Manual-Only Reviews Break at Scale
Code review is a bottleneck in every team above three engineers. A reviewer opens a 400-line diff, checks formatting, spots a missing null check, flags a hardcoded URL — work that takes 15 minutes and adds zero architectural insight. That's the exact problem Claude Code solves at the PR layer.
GitHub Actions runs Claude as a workflow step. It reads the diff, posts inline comments via the GitHub Review API, and leaves a summary. The human reviewer inherits a pre-triaged PR.
End-to-end flow: a pushed commit triggers Actions, Claude Code reads the diff and posts inline comments, the human reviewer gets a pre-triaged PR.
Set Up the Repository Secret
Store the Anthropic API key as a GitHub Actions secret so it never appears in logs.
Open your repo → Settings → Secrets and variables → Actions → New repository secret.
| Field | Value |
|---|---|
| Name | ANTHROPIC_API_KEY |
| Value | your key from console.anthropic.com |
Claude Sonnet 4 costs $3/MTok input and $15/MTok output. A 400-line diff typically runs under $0.05 per review. On the Pro plan ($20/month) you get API credits separate from the chat interface — use a dedicated API key here, not your personal one.
Create the GitHub Actions Workflow
Step 1: Add the workflow file
Create .github/workflows/claude-review.yml in your repo root. This file defines when Claude runs and what permissions it needs.
# Runs on every PR open, reopen, or new commit push — not on draft PRs
name: Claude Code PR Review
on:
pull_request:
types: [opened, synchronize, reopened]
# Only review non-draft PRs to avoid noise on WIP branches
branches-ignore: []
permissions:
# Required: Claude posts comments via the GitHub Review API
pull-requests: write
# Required: checkout action needs read access
contents: read
jobs:
review:
runs-on: ubuntu-22.04
# Skip draft PRs — Claude runs only when the author marks PR ready
if: github.event.pull_request.draft == false
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
# Fetch full history so Claude can compare base and head
fetch-depth: 0
- name: Run Claude Code PR Review
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
# claude-sonnet-4 balances cost and review quality
model: "claude-sonnet-4-20250514"
review_type: "pull_request"
# Post a blocking REVIEW (not just a comment) so it appears in PR timeline
post_as_review: "true"
Expected output: On the next PR open, you'll see a "Claude Code PR Review" check appear under the PR's Checks tab within 30 seconds.
If it fails:
Error: Resource not accessible by integration→ thepull-requests: writepermission is missing from thepermissionsblock.anthropic_api_key is required→ the secret name in Settings doesn't matchANTHROPIC_API_KEYexactly — it's case-sensitive.
Step 2: Scope which files Claude reviews
Without path filtering, Claude reads every file in every PR — including lock files, auto-generated code, and vendored dependencies. That's wasted tokens and noisy comments.
Add a paths trigger and a review_ignore input:
on:
pull_request:
types: [opened, synchronize, reopened]
paths:
# Only trigger when source files change — not docs or config
- "src/**"
- "lib/**"
- "app/**"
- "*.ts"
- "*.py"
Then extend the claude-code-action step:
- name: Run Claude Code PR Review
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
model: "claude-sonnet-4-20250514"
review_type: "pull_request"
post_as_review: "true"
# Comma-separated globs — Claude skips these entirely
review_ignore: "package-lock.json,*.lock,dist/**,*.generated.ts"
# Give Claude context about your standards
system_prompt: |
You are a senior engineer reviewing a pull request.
Focus on: correctness, missing error handling, security issues.
Skip: formatting, naming conventions (handled by linter).
Be concise. One comment per distinct issue. No praise.
Step 3: Add a summary comment to the PR description
The inline comments cover line-level issues. A summary gives reviewers a 3-sentence overview before they open the diff. Add summary: "true" to the action inputs:
summary: "true"
summary_template: |
## Claude Code Review Summary
**Risk level:** {risk_level}
**Issues found:** {issue_count}
{summary_text}
Claude posts this as an edit to the PR description (not a separate comment), so it stays at the top of the PR page.
Verification
Open a test PR with a deliberate bug — a missing await on an async call works well.
# Create a test branch with a known bug
git checkout -b test/missing-await
echo "async function fetchUser(id) { return db.find(id); }" >> src/users.ts
git add . && git commit -m "test: missing await for claude review"
git push origin test/missing-await
# Open a PR via GitHub UI or gh CLI
gh pr create --title "Test Claude review" --body "Testing automated review"
You should see:
- The
claude-reviewcheck appear within 30 seconds under Checks - An inline comment on the
db.find(id)line: "Missingawait—db.findreturns a Promise; withoutawaitthis returnsPromise<User>, notUser." - A PR summary at the top: "Risk level: low. Issues found: 1."
What You Learned
claude-code-action@v1uses the GitHub Review API — it posts a formal review, not a bot comment, so it appears in the PR approval flow.pathsfiltering at the workflow trigger level is more efficient thanreview_ignore— Actions skips the job entirely instead of spinning up a runner then ignoring files.- Claude Sonnet 4 (
claude-sonnet-4-20250514) is the right model here. Opus is overkill for diff review and costs 5× more. Haiku misses subtle logic bugs. - The
system_promptis the highest-leverage config option. Describe your team's standards once and every PR inherits them.
Tested on claude-code-action v1.0, GitHub Actions ubuntu-22.04, Node 22
FAQ
Q: Does Claude Code PR review work on private repositories?
A: Yes. The ANTHROPIC_API_KEY secret and pull-requests: write permission work identically on private repos. No additional GitHub App installation is needed.
Q: What is the difference between post_as_review: true and leaving it false?
A: With true, Claude submits a formal GitHub Pull Request Review — it appears in the approvals section and can be required by branch protection rules. With false, it posts a regular PR comment, which is easier to ignore.
Q: How much does this cost for a team of 10 engineers merging 20 PRs/day? A: At an average of $0.04 per review (400-line diff, Sonnet 4 pricing), 20 PRs/day runs about $0.80/day — roughly $24/month. Add path filtering and that drops by 30–50% for repos with large lock files.
Q: Can Claude approve or request changes, not just comment?
A: Yes. Set review_event: "REQUEST_CHANGES" or "APPROVE" in the action inputs. Most teams leave this as "COMMENT" and let humans make the final approval call.
Q: Does this work with self-hosted runners on AWS us-east-1?
A: Yes. The action calls api.anthropic.com outbound over HTTPS port 443. Allow that domain in your runner's egress rules. No inbound ports needed.