
PR の変更をグループ分けして要約する pulls.review を Claude Code で試してみた
はじめに
Anthony Fu が、GitHub の Pull Request をレビューするためのツール「pulls.review」を公開しました。
変更されたファイルを意図ごとにグループに分け、グループごとに要約を付けて、一つずつレビューできるようにするツールです。
Anthony Fu は Vue、Nuxt、Vite のコアチームのメンバーで、Vercel の Nuxt チームで働いています[1]。
Vitest、Slidev、VueUse、UnoCSS などの作者でもあり、Shiki や ESLint Stylistic のメンテナンスも担当しています。
GitHub の Files changed タブはファイルをパス順に並べます。
一つの機能が複数のディレクトリにまたがる PR では、関係するファイルが離れた位置に並ぶため、レビュアーは頭の中で変更を組み立て直すことになります。
pulls.review はこの組み立てを先にやってくれます。
この記事では、pulls.review の使い方を整理したうえで、ローカルの CLI から Claude Code を解析役にして PR を読んでみた結果を書きます。
pulls.review とは
pulls.review は「Pull request review made simple」をうたうツールで、MIT ライセンスで公開されています[2]。
README には Linear の PR review guides に強く影響を受けたと書かれています。
リポジトリの作成は 2026-09-16 で、最初のリリース v0.1.0 が 2026-10-05、この記事で使った v0.3.3 が 2026-10-13 です。
数日おきにリリースが出ていて、この記事を書いている間にも v0.3.0 から v0.3.3 まで 3 回更新されました。
README の冒頭に「Heavily work in progress」とあるとおり、まだ開発の初期段階です。

pulls.review のトップページ。PR の URL を貼り付けて開く
使い方の種類
pulls.review には次の使い方があります。
- Web サイト:pulls.review で GitHub アカウントを連携し、ブラウザで PR を開く
- userscript:GitHub の画面に pulls.review の機能を足す。サイトの GitHub の節からインストールする
- ローカル CLI:
npx pulls.reviewで手元の git の差分や GitHub の PR をブラウザで開く - GitHub Actions(experimental):PR ごとに CI で一度だけ解析し、結果を PR コメントとして残す
AI による解析には、モデルの API キーを設定画面で登録する方法と、手元にインストール済みのコーディングエージェントに任せる方法があります。
後者はローカル CLI だけの機能で、この記事で試したのもこちらです。
GitHub Actions の方式は、レビュアーそれぞれが自分のキーで同じ PR を解析する無駄を省くためのものです。
CI が PR コメントに残した解析結果は、pulls.review でその PR を開いた全員の画面に読み込まれます。
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 }}
pull_request_target を使っている理由は、README のコメントによると、解析が API 経由で差分を読むだけで PR のコードをチェックアウトしないためです。
ローカル CLI で PR を開く
ローカル CLI は git リポジトリの中で実行します。
引数で開くページを選び、それ以外の差分はブラウザ側で選び直せます。
npx pulls.review # 現在のブランチとデフォルトブランチの差分
npx pulls.review main...feat # feat が main から分岐して以降に足した変更
npx pulls.review HEAD # 1 コミット
npx pulls.review --worktree # 未コミットの変更(未追跡ファイルを含む)
npx pulls.review owner/repo#1 # GitHub の PR
GitHub の PR を開くときのトークンは、環境変数 GITHUB_TOKEN があればそれを、なければ gh auth token の結果を使います。
CLI は localhost でサーバーを立ち上げてブラウザでページを開きます。
README によると、ブラウザのタブはターミナルに表示されるワンタイムコードで信頼済みにします。
レビュー済みの印と AI の解析結果は、リポジトリの .git/pulls-review にキャッシュされます。
今回は、後の節で紹介する vuejs-translations/docs-ja の PR #1072 を開きました。
GitHub の PR は CLI を起動したリポジトリと無関係でも開けますが、キャッシュの置き場所として何らかの git リポジトリの中で実行する必要があります。
npx pulls.review@0.3.3 vuejs-translations/docs-ja#1072
実行すると、サーバーの URL が表示されてブラウザが開きます。
pulls.review is serving http://localhost:7390/gh/vuejs-translations/docs-ja/1072
解析役に Claude Code を選ぶ
設定画面の「AI 分析」タブでプロバイダーに Local agent を選ぶと、API キーの代わりに手元のコーディングエージェントが解析を担当します。
v0.3.3 時点で対応しているのは Claude Code、OpenCode、Pi、Codex の 4 つです(Pi は v0.3.1、Codex は v0.3.2 で追加)。
サインイン済みのエージェントをそのまま使うので、別途 API キーを用意する必要がありません。

Local agent で Claude Code を選ぶと、モデルはエージェントの既定か Sonnet、Opus、Haiku から選べる
Claude Code の場合、pulls.review は claude -p を次の引数で起動します(実装から抜粋)。
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())]
ツールは Read、Grep、Glob の読み取り系だけを許可し、Bash や Edit などの書き込み系は明示的に禁止しています。
解析結果は --json-schema でグルーピングのスキーマに沿った JSON として返させるので、pulls.review 側で出力をパースし直す必要がありません。
解析のあとのチャットは、同じセッションを --resume で続けます。
ローカルの差分を解析するときは、エージェントがリポジトリの中で動くため、hunk だけで意図が分からない変更は元のファイルを開いて確認できます。
API キー方式との違いはここにあります。
グルーピングの方針
AI にどう分けさせているかは、システムプロンプトに書かれています。
要点は次のとおりです。
- ディレクトリではなく意図でグループに分ける。一つの機能が複数のモジュールにまたがれば一つのグループにする
- グループは平らに保つ。子グループは 15 ファイルを超えて一度に読めない場合だけ使う
- 独立した意図を分けられる最小のグループ数にする。典型的な PR は 1 から 5 グループ
- テストやフィクスチャは、基本的に対象のコードとは別のグループにする
- レビューの優先順に並べる。中心となる変更を先に、ロックファイルや生成ファイルなど機械的な変更を最後に
- ファイルや行への注記と「critical」の印は、レビュアーの時間を節約する箇所だけに控えめに付ける
この方針は v0.3.1 で変わっています[3]。
v0.3.0 では 5 ファイルを超えたら子グループに分け、テストは対象の機能のグループに入れる方針でした。
コミット単位ではなく最終的な差分でまとめる点も明記されています。
fixup や WIP のコミットは関心事が混ざりがちだからです。
ロックファイルやビルド成果物は、プロンプトに差分本文を載せずファイル名と行数だけを渡します。
トークンを節約しつつ、そのファイルが変わったというレビュアーに必要な情報は残す作りです。
日本語 PR で試してみる
題材には、Vue 公式ドキュメントの日本語翻訳リポジトリ vuejs-translations/docs-ja でマージされた PR を選びました。
差分がコードではなく日本語の Markdown なので、日本語の文章の変更をどこまで意図ごとに分けられるかを確かめられます。
この PR は英語版の Vue ドキュメントで行われた変更(コンポーネントの v-model の説明を、コンポーネントのイベントのページから独立したページへ移す変更)を日本語版に反映したものです。
変更は 6 ファイル、+459/-438 で、コミットは 2 つです。
| ファイル | 変更 |
|---|---|
.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 |
GitHub の Files changed では、この表のとおりパス順に並びます。
400 行を超える削除と追加が 2 ファイルに分かれて並ぶので、一見すると大きな書き換えに見えます。

GitHub の Files changed。ファイルはパス順に並び、events.md の削除が続く
差分を中身で分けると、この PR には次の 4 種類の変更が入っています。
- 内容の移動:
events.mdのv-modelの節(約 435 行)を、新しいv-model.mdへ移す - 古いリンクの転送:
events.mdに、移動前のアンカー(#usage-with-v-modelなど 4 つ)で開かれたらv-model.htmlの同じアンカーへ転送するスクリプトを足す - リンク先の更新:
built-in-directives.md、reactivity-utilities.md、forms.mdの 3 ファイルで、events.html#usage-with-v-modelへのリンクをv-model.htmlに書き換える - サイドバーの項目追加:
.vitepress/config.tsに「コンポーネントの v-model」を足す
レビューで読むべき箇所は多くありません。
移動した約 435 行のうち、移動前後で変わったのは見出しと序文と 3 つの見出しレベル(H3 から H2)だけです。
残りは転送スクリプトの 19 行と、リンクとサイドバーの 4 行です。
Files changed でこれを確かめるには、レビュアーが 2 ファイルを行き来して「移動しただけか」を自分で照合する必要があります。
pulls.review がこの照合をどこまで肩代わりできるかを見ていきます。
pulls.review で解析した結果
解析の結果、6 ファイルは 2 つのグループに分かれました。
画面上部にグループがタブとして並び、左側にグループの要約とファイルの一覧、右側に差分が表示されます。

解析後の画面。6 ファイルが 2 つのグループにまとまり、それぞれに要約が付く
| グループ | ファイル | 要約(原文のまま) |
|---|---|---|
| v-model ページの分離(+456/-435) | v-model.md、events.md、.vitepress/config.ts |
v-model の節を独立したページに移し、サイドバーに追加します。古いアンカー付きリンクで events.md に来た読者は、クライアント側のスクリプトで新ページに転送されます。 |
| 参照リンクの更新(+3/-3) | built-in-directives.md、reactivity-utilities.md、forms.md |
events.html#usage-with-v-model を指していた他のページのリンクを、新しい v-model.html に書き換えます。 |
前の節で挙げた 4 種類の変更と照らすと、移動、転送スクリプト、サイドバーの追加が 1 つ目のグループに、リンク先の更新が 2 つ目のグループに入っています。
移動に付随する変更をひとまとめにし、他のページへの波及を分けた形で、筆者が差分を読んで分けた結果と一致しました。
要約も自然な日本語でした。
要約が転送スクリプトに触れている点も役に立ちました。
転送スクリプトの 19 行は、435 行の削除と同じ events.md の中にあり、Files changed では読み飛ばしやすい位置にあります。
要約を先に読めば、このファイルには削除だけでなくスクリプトの追加もあると分かった状態で差分を開けます。
グループ内のファイルは、新しい v-model.md、移動元の events.md、サイドバーの config.ts の順に並んでいて、移動を追う順番になっています。
パス順の Files changed では config.ts が先頭に来るので、ここも読みやすさが違います。
一方で、移動した行そのものは、Files changed と同じく削除と追加として全行が表示されます。
移動前と移動後が同じ内容かどうかは、差分の表示だけでは確かめられません。
チャットで移動の中身を確かめる
そこで、画面右下のチャットで「events.md から v-model.md へ移した内容のうち、移動以外で変わった箇所を挙げて」と聞いてみました。

チャットで移動以外の変更を聞いた回答。見出しと序文の変更を旧と新で並べて示す
回答は、移動以外の変更は PR の本文に書かれている 3 種類(見出し、序文、見出しレベル)だけで、本文、コードブロック、Playground の URL は移動前と同じ、というものでした。
筆者が移動前の削除行と移動後の追加行を突き合わせた結果とも一致します。
回答には「行番号は説明文の値をそのまま使っていて、自分では数え直していない」という断りも付いていて、どこを自分で確かめればよいかが分かります。
回答には、PR の本文に書かれていない指摘も一つありました。
移動前の見出しにあった {#usage-with-v-model} というアンカーが新しいページの見出しには付いていないため、転送スクリプトで v-model.html#usage-with-v-model に飛んでもページの先頭に着地する、という指摘です。
マージ時点の v-model.md を確認したところ、このアンカーは確かにありませんでした。
英語版の原文も同じなので、翻訳の不備ではありません。
転送先のページ自体が v-model の説明で、先頭に着地しても読者が困ることはなさそうです。
それでも、転送スクリプトのアンカー一覧と新しいページの見出しという離れた 2 か所を結び付けないと気付けない指摘で、Files changed を目で追うだけでは見落としやすい種類のものでした。
Files changed と比べて
Files changed で同じ PR をレビューする場合、900 行近い差分を前に、まずどれが本質的な変更かを自分で切り分けることになります。
pulls.review では、この切り分けがグループと要約として最初から示されていて、2 つのグループを順に読むだけで PR の全体像をつかめました。
移動の検証そのものは、差分の表示だけでは楽になりません。
ただ、チャットに聞けば移動以外の変更を挙げてくれ、本文に書かれていない点まで拾ってくれました。
グループと要約で全体をつかみ、細かい確認はチャットに聞く、という使い方が合っていると感じました。
気になったこと
pulls.review は開発の初期段階で、数日おきに挙動が変わる可能性が高いです。
この記事を書いている間にも、グループの分け方の方針が v0.3.1 で変わりました(前述)。
記事の内容は v0.3.3 時点のものです。
また、エージェントから pulls.review を呼ぶための MCP サーバーや skill は、v0.3.3 時点では用意されていません。
ローカル CLI はブラウザでページを開く前提で、解析結果を標準出力に返すモードもありません。
連携の向きは、エージェントが pulls.review を呼ぶのではなく、pulls.review が Local agent としてエージェントを呼ぶ流れです。
おわりに
pulls.review は、PR の変更をファイル単位ではなく意図の単位で並べ直し、要約と注記を付けてくれるツールです。
ローカル CLI なら、手元の Claude Code などの使い慣れたコーディングエージェントをそのまま解析役にでき、API キーを用意せずに試せます。
pulls.review の UI 上で要約やチャットなどの機能が使えるので、既に実用的なツールだと感じました。
まだ開発の初期段階で更新も速いので、気になった方はリリースを追いながら試してみてください。








