Skip to content

Backend

AI Code Review in CI — Claude Sub-Agents on Every GitHub PR

GitHub Copilot review is fine. Claude in CI is stronger — every PR opens → GitHub Action triggers → Claude reads the full diff alongside codebase context → posts inline comments about bugs, security patterns, style drift. What humans miss, Claude catches. Free. Shipping since 2024.

🤖 📝

Code review is a tax. Every merge request sits on human review queue. A senior dev reads the diff, spots 3 security issues, 2 style inconsistencies, 1 architectural concern, writes comments, waits for rebuttal. 30 minutes per PR. 10 PRs a day. Five hours of senior time. At scale, that's a salary.

Copilot review exists. VS Code extension. Reviews your code before you push. It's okay. Mostly surface-level. Aidxn went harder: Claude sub-agents in GitHub Actions. PR opens → webhook fires → Claude reads the diff *and* the codebase context (folder structure, dependencies, existing patterns) → posts detailed inline comments for security, architecture, style. No manual trigger. No side tool. Baked into the CI loop.

The Setup

GitHub Action on every push to a PR. Thirty-second bootstrap, Claude reads the diff, parses the changes, flags issues. Two patterns: lightweight (just the diff) and heavy (diff + codebase context).

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: Get PR diff
        id: diff
        run: |
          git fetch origin ${{ github.base_ref }}
          git diff origin/${{ github.base_ref }}..HEAD > /tmp/diff.txt
          cat /tmp/diff.txt

      - name: Run Claude review
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: node scripts/review-pr.js

The action checks out the branch, fetches the base branch, generates a unified diff, passes it to a Node script that calls Claude. Claude returns structured comments: line number, issue type (security/style/arch), explanation, suggestion. The script parses the response and posts it back to the PR.

The Claude Call

const anthropic = new Anthropic();

const review = async (diff, codebaseContext) => {
  const response = await anthropic.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 2048,
    system: `You are a senior code reviewer. Analyze diffs for:
1. Security (SQL injection, XSS, hardcoded secrets, missing validation)
2. Performance (N+1 queries, inefficient loops, unnecessary re-renders)
3. Consistency (naming conventions, architecture drift, style mismatches)
4. Testing (missing edge cases, incomplete coverage)

Format each issue as JSON: { line, type, severity, message, suggestion }`,
    messages: [{
      role: 'user',
      content: `Codebase patterns:\n${codebaseContext}\n\nDiff:\n${diff}`
    }]
  });

  return JSON.parse(response.content[0].text);
};

const issues = await review(diffText, codebaseContext);
for (const issue of issues) {
  await github.rest.pulls.createReview({
    owner, repo, pull_number: prNumber,
    body: `**${issue.type}**: ${issue.message}\n\nSuggestion: ${issue.suggestion}`,
    event: 'COMMENT',
    comments: [{
      path: issue.file,
      position: issue.line,
      body: issue.message
    }]
  });
}

One API call per PR. Costs ~$0.01–0.03 depending on diff size. Takes 5–8 seconds. Posts comments inline on the exact lines that triggered flags.

What Gets Caught

Security: "Line 42: Query uses string interpolation instead of parameterized statements. SQL injection risk." Performance: "Line 88: Inside a loop. This fires N requests for N items. Batch or memoize." Style: "Line 15: Inconsistent naming — rest of the file uses camelCase, you're using snake_case." Architecture: "This adds a Supabase query inside a React component — should move to a server action or hook." Testing: "Line 120: Removed the error case test. Every success path needs a failure case."

Claude doesn't auto-fix or merge. It surfaces. You decide. The human review loop stays intact — Claude is the first pass.

Three Implementation Patterns

Pattern 1: Lightweight (Diff Only)

Just send the diff. Fast (~3 sec), cheap (~$0.005). Catches obvious bugs, style drift. Misses context-dependent issues ("is this pattern used elsewhere in the repo?").

Pattern 2: Codebase Context

Send diff + folder structure + summary of existing patterns (extract 5–10 key files that match the diff's domain). Slower (~7 sec), slightly more expensive (~$0.02). Claude understands your conventions and flags architecture drift. Recommended.

Pattern 3: Tool Use

Give Claude access to GitHub API inside the action. It can fetch the full modified files, run git blame on changed lines, query the repo for similar patterns. Slowest (~15 sec), most expensive (~$0.05 per PR), most accurate. Overkill for most teams. Use if you're paranoid about security or have strict style rules.

Five FAQs

Will this reject my PRs?

No. Claude posts comments. It never blocks merge. It's advisory. You read the feedback, push back if it's wrong, or iterate. A senior dev's job isn't eliminated — it's shifted from "catch the obvious stuff" to "decide if Claude's feedback is valid and why."

What if Claude's review is wrong?

It will be, sometimes. "This is SQL injection risk" when it's not. Respond in the comment thread. Over time, tune your system prompt to match your team's rules. If a false positive recurs, log it and adjust the prompt. Human judgment still wins.

How much does this cost?

For a 20-PR-per-day team: ~$0.30–0.60 per day, or ~$9–18 per month. One junior dev's GitHub subscription. Competitive vs. adding a linter rule or running a separate code-review SaaS.

Can I integrate it with other CI checks?

Yes. Run Claude review in parallel with unit tests, linting, type checking. They're independent. If you want Claude review to block merge on critical severity issues, you can set that — but it's not the default and requires discipline.

Does it work for all languages?

Claude handles TypeScript, Python, Go, Rust, SQL, frontend, backend. Give it a system prompt tuned to the language. Performance review for Python is different than for JavaScript. One prompt per language-domain, swap them based on diff content-type.

The Verdict

Code review is still human. But the boring first pass — "here are the obvious issues" — is now a 30-line GitHub Action and a Claude API call. Copilot review is convenient. Claude in CI is continuous. Ship once, review every PR forever. Ready to wire it up? Let's ship your first agent or read about autonomous workflows with Claude SDK.

Let us make some quick suggestions?
Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.