I tried using pulls.review with Claude Code to group and summarize PR changes

I tried using pulls.review with Claude Code to group and summarize PR changes

Introducing the open-source code review tool "pulls.review": how to use it, and results from actually reading PRs using Claude Code as the analyzer from the local CLI.
2026.10.14

This page has been translated by machine translation. View original

Introduction

Anthony Fu has released a tool called "pulls.review" for reviewing GitHub Pull Requests.
It groups changed files by intent, attaches a summary to each group, and allows you to review them one by one.

Anthony Fu is a core team member of Vue, Nuxt, and Vite, and works on the Nuxt team at Vercel[1].
He is also the author of Vitest, Slidev, VueUse, UnoCSS, and maintains Shiki and ESLint Stylistic.

The Files changed tab on GitHub lists files in path order.
In PRs where a single feature spans multiple directories, related files end up scattered apart, forcing reviewers to mentally reassemble the changes.
pulls.review does this reassembly for you upfront.

This article summarizes how to use pulls.review, then shares the results of reading a PR using Claude Code as the analyzer from a local CLI.

https://x.com/antfu7/status/2107052841764569236

What is pulls.review?

pulls.review is a tool that bills itself as "Pull request review made simple," released under the MIT license[2].
The README states it was heavily inspired by Linear's PR review guides.
The repository was created on 2026-09-16, the first release v0.1.0 was on 2026-10-05, and v0.3.3 used in this article was on 2026-10-13.
Releases come out every few days, and even while writing this article, it was updated 3 times from v0.3.0 to v0.3.3.
As the README states at the top, "Heavily work in progress" — it is still in early development.

pulls.review top page. A field to enter the PR URL and an example of grouped changed files are shown
pulls.review top page. Paste a PR URL to open it

Types of Usage

pulls.review can be used in the following ways.

  • Website: Link your GitHub account at pulls.review and open PRs in the browser
  • Userscript: Adds pulls.review functionality to the GitHub interface. Install from the GitHub section of the site
  • Local CLI: Open diffs from your local git or GitHub PRs in the browser using npx pulls.review
  • GitHub Actions (experimental): Analyze once per PR in CI and leave the results as a PR comment

For AI analysis, you can either register a model API key in the settings screen or delegate to a locally installed coding agent.
The latter is a local CLI-only feature, and that is what this article tries.

The GitHub Actions approach is designed to eliminate the redundancy of each reviewer analyzing the same PR with their own key.
The analysis results that CI leaves as a PR comment are loaded on the screens of everyone who opens that PR in pulls.review.

.github/workflows/pulls-review.yml
name: pulls.review
on:
  pull_request_target:
    types: [opened, synchronize, reopened]

permissions:
  pull-requests: write

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: antfu/pulls.review@main
        with:
          api-key: ${{ secrets.VERCEL_AI_GATEWAY_API_KEY }}

The reason pull_request_target is used, according to a README comment, is that the analysis only reads the diff via API and does not check out the PR code.

Opening a PR with the Local CLI

The local CLI is run inside a git repository.
You specify the page to open with arguments, and you can reselect other diffs on the browser side.

npx pulls.review               # Diff between the current branch and the default branch
npx pulls.review main...feat   # Changes added to feat since it branched from main
npx pulls.review HEAD          # 1 commit
npx pulls.review --worktree    # Uncommitted changes (including untracked files)
npx pulls.review owner/repo#1  # GitHub PR

For the token when opening a GitHub PR, it uses the GITHUB_TOKEN environment variable if present, otherwise the result of gh auth token.
The CLI starts a server on localhost and opens the page in the browser.
According to the README, the browser tab is trusted with a one-time code displayed in the terminal.
Reviewed marks and AI analysis results are cached in the repository's .git/pulls-review.

For this article, I opened PR #1072 of vuejs-translations/docs-ja, introduced in a later section.
GitHub PRs can be opened regardless of the repository where the CLI is launched, but you need to run it inside some git repository as a place to store the cache.

npx pulls.review@0.3.3 vuejs-translations/docs-ja#1072

When run, the server URL is displayed and the browser opens.

pulls.review is serving http://localhost:7390/gh/vuejs-translations/docs-ja/1072

Selecting Claude Code as the Analyzer

In the settings screen's "AI Analysis" tab, selecting Local agent as the provider lets a locally installed coding agent handle the analysis instead of an API key.
As of v0.3.3, the four supported agents are Claude Code, OpenCode, Pi, and Codex (Pi was added in v0.3.1, Codex in v0.3.2).
Since it uses an already signed-in agent directly, you don't need to prepare a separate API key.

Model selection dialog when Claude Code is selected as the agent
When selecting Claude Code as a Local agent, the model can be chosen from the agent's default, Sonnet, Opus, or Haiku

For Claude Code, pulls.review launches claude -p with the following arguments (excerpt from the implementation).

packages/cli/src/agents/claude.ts
const READ_ONLY_TOOLS = ['Read', 'Grep', 'Glob']
const WRITE_TOOLS = ['Bash', 'Edit', 'Write', 'MultiEdit', 'NotebookEdit', 'WebFetch', 'WebSearch', 'Task']

const list = ['-p', '--output-format', 'stream-json', '--verbose',
  '--system-prompt', system,
  '--permission-mode', 'dontAsk',
  '--allowedTools', ...READ_ONLY_TOOLS,
  '--disallowedTools', ...WRITE_TOOLS,
  '--json-schema', JSON.stringify(analysisJsonSchema())]

Only read-oriented tools — Read, Grep, and Glob — are allowed, while write-oriented tools like Bash and Edit are explicitly prohibited.
Analysis results are returned as JSON conforming to the grouping schema via --json-schema, so pulls.review doesn't need to re-parse the output.
The chat after analysis continues the same session using --resume.

When analyzing local diffs, the agent runs inside the repository, so for changes where the intent isn't clear from the hunk alone, it can open the original file to check.
This is where it differs from the API key approach.

Grouping Policy

How the AI is instructed to divide things is written in the system prompt.
The key points are as follows.

  • Group by intent, not by directory. If a single feature spans multiple modules, put it in one group
  • Keep groups flat. Use child groups only when there are more than 15 files that can't be read at once
  • Use the minimum number of groups that separates independent intents. A typical PR has 1 to 5 groups
  • Tests and fixtures should basically be in a separate group from the code they target
  • Order by review priority. Core changes first, mechanical changes like lock files and generated files last
  • Use file and line annotations and "critical" marks sparingly — only where they save the reviewer time

This policy changed in v0.3.1[3].
In v0.3.0, child groups were used when there were more than 5 files, and tests were included in the group of the feature they target.

It is also explicitly noted that grouping is done on the final diff rather than per commit.
This is because fixup and WIP commits tend to mix concerns.

For lock files and build artifacts, only the filename and line count are passed without including the diff body in the prompt.
This saves tokens while preserving the information a reviewer needs — that the file changed.

Trying It with a Japanese PR

For the subject, I chose a merged PR from vuejs-translations/docs-ja, the Japanese translation repository of the official Vue documentation.
Since the diff is Japanese Markdown rather than code, it lets us verify how well intent-based grouping works for changes to Japanese text.

https://github.com/vuejs-translations/docs-ja/pull/1072

This PR reflects changes made in the English Vue documentation (moving the v-model explanation for components from the component events page to a standalone page) into the Japanese version.
The changes span 6 files, +459/-438, with 2 commits.

File Changes
.vitepress/config.ts +1/-0
src/api/built-in-directives.md +1/-1
src/api/reactivity-utilities.md +1/-1
src/guide/components/events.md +19/-435
src/guide/components/v-model.md +436/-0
src/guide/essentials/forms.md +1/-1

In GitHub's Files changed, these appear in path order as shown in the table.
More than 400 lines of deletions and additions are split across 2 files, making it look like a large rewrite at first glance.

GitHub Files changed screen showing the large number of deletions in events.md
GitHub Files changed. Files are listed in path order, with a long run of deletions in events.md

Breaking down the diff by content, this PR contains the following 4 types of changes.

  1. Content move: Move the v-model section (~435 lines) from events.md to the new v-model.md
  2. Old link forwarding: Add a script to events.md that redirects visitors arriving via old anchors (#usage-with-v-model etc., 4 in total) to the same anchors in v-model.html
  3. Link target updates: Rewrite links pointing to events.html#usage-with-v-model in 3 files — built-in-directives.md, reactivity-utilities.md, and forms.md — to v-model.html
  4. Sidebar entry addition: Add "Component v-model" to .vitepress/config.ts

There is not much to read in the review.
Of the ~435 moved lines, the only things that changed between source and destination are the heading, the introduction, and three heading levels (H3 to H2).
The rest consists of the 19 lines of the forwarding script and 4 lines of links and the sidebar.

To verify this in Files changed, a reviewer would need to go back and forth between 2 files to manually confirm "was this just moved?"
Let's see how much of this verification pulls.review can handle.

Analysis Results from pulls.review

After analysis, the 6 files were divided into 2 groups.
The groups appear as tabs at the top of the screen, with a summary and file list for each group on the left and the diff on the right.

pulls.review screen after analysis. Two tabs — "v-model page separation" and "Reference link updates" — appear at the top, with a summary and file list for each group on the left
Screen after analysis. The 6 files are organized into 2 groups, each with a summary

Group Files Summary (as-is)
v-model page separation (+456/-435) v-model.md, events.md, .vitepress/config.ts Moves the v-model section to a standalone page and adds it to the sidebar. Visitors arriving at events.md via old anchor links are forwarded to the new page by a client-side script.
Reference link updates (+3/-3) built-in-directives.md, reactivity-utilities.md, forms.md Rewrites links in other pages that pointed to events.html#usage-with-v-model to the new v-model.html.

Comparing against the 4 types of changes identified in the previous section, the move, forwarding script, and sidebar addition are in the first group, and the link target updates are in the second group.
Changes accompanying the move were bundled together, and the ripple effects to other pages were separated — matching the result of the author's own reading of the diff.
The summaries were also in natural Japanese.

The fact that the summary mentions the forwarding script was also helpful.
The 19 lines of the forwarding script are inside events.md along with the 435 deleted lines, and they are easy to skim past in Files changed.
Reading the summary first means you can open the diff already knowing that this file contains not just deletions but also a script addition.

The files within the group are ordered as: the new v-model.md, the source events.md, and the sidebar config.ts — in the order you'd follow to trace the move.
In Files changed with path ordering, config.ts comes first, so the readability differs here too.

On the other hand, the actual moved lines are still displayed as full deletions and additions, just as in Files changed.
Whether the content before and after the move is identical cannot be confirmed from the diff display alone.

Verifying the Move Contents via Chat

So I used the chat in the bottom right of the screen to ask: "List any changes in the content moved from events.md to v-model.md, other than the move itself."

pulls.review chat. Changes other than the move are listed — heading and introduction changes shown side by side, old vs. new
Chat response when asking about changes beyond the move. Heading and introduction changes shown with old and new side by side

The response was that the only changes beyond the move were the 3 types mentioned in the PR description (heading, introduction, heading levels), that the body text, code blocks, and Playground URLs were identical to before the move.
This matched the result of the author's own comparison of deleted and added lines.
The response also included a note that "line numbers are taken as-is from the description and I haven't re-counted them myself," making it clear what to verify independently.

The response also included one point not mentioned in the PR description.
The anchor {#usage-with-v-model} present on the heading in the source was not attached to the heading in the new page, meaning that following the forwarding script to v-model.html#usage-with-v-model would land at the top of the page.
Checking the merged v-model.md confirmed that this anchor was indeed absent.
The English original is the same, so it is not a translation error.
Since the destination page itself explains v-model, landing at the top shouldn't cause any problem for readers.
Still, it is the kind of observation that requires connecting two distant places — the anchor list in the forwarding script and the headings in the new page — and is easy to miss when just scanning Files changed.

Compared to Files Changed

When reviewing the same PR in Files changed, you face nearly 900 lines of diff and first have to cut out what is essential yourself.
In pulls.review, this sorting was presented upfront as groups and summaries, and reading through 2 groups in order was enough to grasp the full picture of the PR.

Verifying the move itself doesn't get easier from the diff display alone.
However, asking the chat let you identify changes beyond the move, picking up even points not mentioned in the PR description.
The approach of grasping the big picture through groups and summaries, then asking the chat for detailed confirmation, felt like a good fit.

Things to Note

pulls.review is in early development, and behavior is likely to change every few days.
Even while writing this article, the grouping policy changed in v0.3.1 (as mentioned above).
The content of this article reflects v0.3.3.

Also, as of v0.3.3, there is no MCP server or skill for calling pulls.review from an agent.
The local CLI is designed to open a page in the browser, and there is no mode to return analysis results to standard output.
The direction of integration is not agents calling pulls.review, but pulls.review calling agents as a Local agent.

Conclusion

pulls.review is a tool that reorganizes PR changes by intent rather than by file, and attaches summaries and annotations.
With the local CLI, you can use a familiar coding agent like Claude Code as the analyzer without needing to prepare an API key.
Since features like summaries and chat are available within the pulls.review UI, I found it to already be a practical tool.

It is still in early development with fast-moving updates, so if you are interested, try it out while following the releases.

References

脚注
  1. https://antfu.me/ ↩︎

  2. https://github.com/antfu/pulls.review ↩︎

  3. https://github.com/antfu/pulls.review/pull/78 ↩︎


Claudeならクラスメソッドにお任せください

クラスメソッドは、Anthropic社とリセラー契約を締結しています。各種製品ガイドから、業種別の活用法、フェーズごとのお悩み解決などサービス支援ページにまとめております。まずはご覧いただき、お気軽にご相談ください。

サービス詳細を見る

Share this article

AI白書