Skip to main content

Code review (GitHub Actions)

subak init scaffolds an automated code-review workflow into your repo that runs Claude on every pull request. A fleet of agents reviews the diff in the context of your codebase and posts findings as inline comments on the exact lines. It runs in your own GitHub Actions and bills per token against your Anthropic API key — no Claude subscription or managed plan required.

Two files are written (skip-if-exists, so re-running init never clobbers your edits):

FilePurpose
.github/workflows/code-review.ymlThe workflow: triggers, permissions, and the review prompt.
REVIEW.mdReview-only instructions injected as the highest-priority guidance every run. Tune what gets flagged here.

Setup

The workflow needs one secret. Until it's set, the workflow no-ops with a warning rather than failing, so it's safe to commit immediately.

  1. Create an API key at console.anthropic.com.
  2. In your repo, go to Settings → Secrets and variables → Actions → New repository secret.
  3. Name it ANTHROPIC_API_KEY and paste the key.

Open a pull request. Within a minute or two a Claude code review check run appears; findings land as inline comments on the diff.

note

Reviews run only on branches in the same repository — GitHub does not expose Actions secrets to pull requests from forks, so fork PRs are skipped.

What it does

  • Reviews the current diff. Each push re-runs the review against the changes the PR introduces, not the whole repo.
  • Posts inline comments, tagged by severity: 🔴 Important (a bug to fix before merge) and 🟡 Nit (minor). Findings include a ```suggestion block when a concrete fix fits, so you can commit it from the GitHub UI.
  • Converges across pushes. It reads its own prior comments and won't re-post a finding that's still valid. When you fix a finding, GitHub automatically marks that thread Outdated and collapses it on the next run.
  • Never blocks merges. Findings are advisory comments; the check run always completes neutrally.

Reviews complete in a couple of minutes for a small PR and cost roughly a few cents to a few dollars depending on PR size and codebase complexity. Because the workflow re-runs on every push, a concurrency group cancels an in-flight review when you push again, and timeout-minutes bounds worst-case cost.

Tuning with REVIEW.md

REVIEW.md is plain markdown injected verbatim as the top-priority instruction for every review. Common tunings:

  • Recalibrate severity — state exactly what 🔴 Important means for your repo.
  • Cap nit volume — e.g. "report at most 5 nits; summarize the rest as a count."
  • Skip paths — generated code, lockfiles, vendored dependencies, or anything CI already enforces (lint, formatting, type errors).
  • Repo-specific checks — e.g. "new API routes must have an integration test."
  • Verification bar — require a file:line citation before a finding is posted.

Your repo's CLAUDE.md files are also read as project context; newly introduced violations are flagged as nits. Keep REVIEW.md short — length dilutes the rules that matter most.

Reviewer identity and thread resolution

By default the workflow authenticates with the built-in GITHUB_TOKEN, so findings post as github-actions[bot]. Fixed findings auto-collapse as Outdated on the next push, which — combined with the reviewer not re-posting still-valid findings — keeps a re-reviewed PR focused on what's current. This is enough for most teams and needs no extra setup.

Two independent upgrades are possible:

Post under your own identity (GitHub App)

Run the review under a GitHub App token so comments post under your App's name (e.g. your-app[bot]) instead of github-actions[bot]. Install a GitHub App with pull-requests: write on the repo, add its APP_ID and private key (APP_PRIVATE_KEY) as secrets, and mint a token per run:

- name: Mint app token
id: app-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}

- name: Review
if: steps.guard.outputs.skip != 'true'
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ steps.app-token.outputs.token }}
# …track_progress, prompt, claude_args as scaffolded…
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}

Mark threads Resolved (requires a user token)

caution

The green Resolved badge needs a user-flavored token — a fine-grained or classic Personal Access Token with pull-requests: write. Neither the built-in GITHUB_TOKEN nor a GitHub App installation token can run the resolveReviewThread GraphQL mutation: GitHub rejects it as "Resource not accessible by integration" for any App identity, regardless of granted scopes.

If you want fixed findings marked Resolved (not just Outdated), store a PAT as a secret, expose it to the agent's gh calls (GH_TOKEN), and add a line to the prompt telling the reviewer to resolve threads whose finding is gone via resolveReviewThread (gh api graphql). Most teams skip this and rely on the automatic Outdated collapse instead.

Triggering and re-running

The workflow triggers on opened, synchronize (each push), reopened, and ready_for_review. To re-run without pushing, use the Re-run jobs button on the workflow run, or push an empty commit.

To review a diff locally before opening a PR, run /code-review in a Claude Code session — no workflow required.