Open sourceReleased

claude-pr-review-bot

A pull request reviewer for GitHub Actions that asks Claude for one document of findings, and can only ever comment.

C# on .NET 10. Structured output against a JSON Schema, a single read_file tool, findings filtered against the lines GitHub accepts, and one review per run. It never approves, requests changes or blocks a merge.

Role:
Design and development
Year:
2026
bugs flagged in a real demo pull request
3/3
measured cost of that review on Claude Haiku 5.5
$0.0009
permissions to approve, block or merge
0
tool: read_file, fetched by SHA from the API
1

The problem

The obvious AI reviewer gives the model a post-comment tool and executes each call as it arrives. That costs a round trip per finding, can leave half a review behind when a call times out, and never gives the code a moment to see the whole set and decide it is noise. An early version left 47 comments on one pull request, most of them on generated files.

Constraints

  • It must review pull requests from forks, which needs secrets under pull_request_target
  • Contributor code must never run next to the API key
  • A prompt injection inside a diff must not be able to approve or block anything
  • A predictable, visible cost per pull request

How it works

  1. The bot fetches the changed files and their patches from the GitHub API and parses the hunks into the set of lines GitHub will accept a comment on.
  2. Claude receives the diff as untrusted content and returns its findings as one document that conforms to a JSON Schema. When a hunk is a keyhole, it can call read_file, which fetches the file at the head SHA through a path check.
  3. A filter drops findings outside the diff, keeps the most severe one per line and caps the total. Then a single COMMENT review is posted, and every dropped finding is logged.

Key decisions

Findings as data, not actions

Structured output returns the whole set at once, so the code can filter, deduplicate and cap it before anything reaches GitHub, and a failure posts nothing instead of half a review.

Trade-off: The review appears all at once at the end of the run instead of comment by comment.

Comment-only by construction

The GitHub client has five methods, and none of them can approve, request changes or merge. The worst a prompt injection can do is make the bot go quiet.

Trade-off: It cannot enforce anything; a team that wants a blocking gate keeps it in its own CI.

Built from source on every run

The composite action compiles the bot at the pinned ref, so the code reviewing your pull request is exactly the code in the repository.

Trade-off: About a minute per run; a Docker action would be faster but less transparent.

Results

  • On a real demo pull request, Claude Haiku 5.5 flagged all three bugs it introduced (a non-thread-safe cache, a catch-all that turns timeouts into declines, an API key written to stdout) in one call, for USD 0.0009.
  • About USD 0.12 per 400-line pull request on Claude Opus 5 and about USD 0.05 on Sonnet 5, with input, output and cache-read tokens logged per turn.
  • A cached system prompt, plus a built-in ignore list for lockfiles and generated code that more than halved the average diff sent to the model.
  • A dry-run mode with fixture findings exercises the whole pipeline in CI on every push, with no API key.
  • The design is explained in a DEV.to article, in English and in Spanish.

Stack

  • .NET 10
  • C# 14
  • Claude API
  • Structured outputs
  • GitHub Actions
  • xUnit