Tips & Tricks (更新: 2026/6/7)

コードレビュー チェックリスト+Claude Codeで一次レビューを回す方法

正しさ・可読性・セキュリティ・テスト・設計の観点別チェックリストと、CLAUDE.mdに観点を入れてClaude CodeにPRの一次レビューをさせる手順を、僕の失敗込みで紹介します。

コードレビュー チェックリスト+Claude Codeで一次レビューを回す方法

「このPR、レビューしといて」

そう頼まれた金曜の夕方、僕は差分を上から眺めて、変数名にいくつかコメントを付けて「LGTM」と返しました。月曜、本番でユーザーの課金状態が二重に更新される障害が出ました。原因は、僕がスルーしたWebhookの差分。署名検証も冪等性チェックも、きれいに抜け落ちていたんです。

レビューはちゃんとやったつもりでした。でも僕が見ていたのは「読みやすさ」だけで、「壊れたら何が起きるか」をまるで見ていなかった。

コードレビューで事故るのは、たいてい能力じゃなくて観点の抜けです。今日は、正しさ・可読性・セキュリティ・テスト・設計という観点別のチェックリストと、その観点をそのままClaude Codeに渡してPRの一次レビューを任せる手順を、僕の失敗込みで書きます。

この記事の要点

  • コードレビューの事故は「観点の抜け」で起きる。正しさ・可読性・セキュリティ・テスト・設計の5観点を、確認できる事実に落としたチェックリストを用意する。
  • すべてのPRを同じ重さで見ない。壊れたときの影響でLow / Medium / Highに分け、深さを変える。
  • Claude Codeは「レビュー担当者の代わり」ではなく「見落としを減らす一次レビュー」。リスクと触ったデータを伝えてから渡すと精度が上がる。
  • レビュー観点をCLAUDE.mdに書いておくと、毎回プロンプトを貼らなくてもClaude Codeが同じ基準で一次レビューしてくれる。
  • セキュリティの深掘りはレビューの片手間では足りない。観点だけ拾って、セキュリティ監査の記事に送る。

なぜ「全部見て」だと弱いのか

Claude Codeに「このPRをレビューして」とだけ頼むと、命名や軽い読みやすさの指摘は増えます。でもチームの事故は防ぎにくい。

理由はシンプルで、AIもレビュー担当者も、何を見るか決めずに差分を眺めると、目に入りやすいところ(命名、フォーマット、軽いスタイル)から拾うからです。本当に守るべきなのは、個人情報、課金、権限、Migration、テストの抜け、そしてAIが生成した差分の混入。このあたりは「気をつけて見る」では必ずすり抜けます。

だから僕は、レビューを5つの観点に分けて、それぞれを確認できる事実にしました。

観点何を見るか弱い言い方 → 確認できる言い方
正しさ仕様どおり動くか、境界値・異常系「ちゃんと動く」→「空配列・null・タイムアウト時の挙動がテストにある」
可読性名前・関数の長さ・意図の伝わりやすさ「読みやすい」→「関数名で何をするか分かる/50行超の関数に分割理由がある」
セキュリティ入力検証・権限・出力・ログ・外部通信「安全」→「ログにemail/token/paymentIdが出ていない」
テスト変更した挙動を証明するテストがあるか「テスト済み」→「修正前は落ち、修正後に通る回帰テストがある」
設計影響範囲・責務・後で戻せるか「きれい」→「この変更が触るモジュールが3つ以内/rollback手順がある」

前提として、Claude Codeはレビュー担当者の代わりではありません。Claude Codeは「見落としを減らす補助輪」で、最終判断はPRの責任者とレビュー担当者がやります。公式情報としては、Claude Codeのcode review setupGitHub Actions docs、GitHubのPRテンプレートprotected branchesを見ておくと安全です。セキュリティ観点はOWASP Secure Code Review Cheat Sheetを基準にしています。

リスク別に深さを変える

冒頭の僕の失敗は、CSSの余白修正もWebhookの署名検証も、同じ軽さで眺めたことが原因でした。前者には重すぎ、後者には軽すぎたんです。

そこで、すべてのPRを同じ重さで見るのをやめて、壊れたときの影響で3段階に分けました。

リスク必須レビュー
Low文言修正、軽いスタイル、ログ文言、ドキュメント1人レビュー、スクショか差分説明
MediumUI状態、APIレスポンス、フォーム、検索、権限に触れないDB読み取り1人レビュー、テスト証跡、Claude Code一次レビュー
High認証、認可、課金、個人情報、Migration、削除処理、外部Webhook2人レビュー、rollback手順、CI必須、セキュリティ観点

ここでいう「Migration」は、データベースの表や列を変える作業です。コードは戻せても、削除した列や上書きしたデータは簡単には戻りません。だからMigrationは、実装のきれいさより先に「失敗時に戻せるか」を見ます。

Claude Codeにも、このリスクを先に伝えます。リスクを言わずに渡すと、AIは一般論の指摘に寄ります。逆に「High risk: 課金Webhookと顧客メールを変更」と伝えると、署名検証、冪等性、ログ、個人情報、テストの不足を見つけやすくなる。僕が一番やらかしたのは、観点を「品質」「可読性」「セキュリティ」みたいな抽象語で置いたことでした。抽象語だけだと、忙しい日に必ず抜けます。

そのまま使えるレビュー チェックリスト

以下は.github/review-checklist.mdやチームWikiに置けるMarkdownです。Claude Codeに渡す前提で、質問が具体的になるようにしています。

# Code Review Checklist

## 0. PR scope
- [ ] This PR has one clear purpose.
- [ ] Changed files match the stated purpose.
- [ ] Generated or AI-written files are marked in the PR description.
- [ ] No unrelated formatting, dependency, or config changes are mixed in.

## 1. Correctness and design
- [ ] Edge cases (empty, null, timeout, large input) are handled.
- [ ] The change touches a small, clear set of modules.
- [ ] Public behavior change is intentional and documented.
- [ ] Risk level is marked as low, medium, or high.

## 2. Readability
- [ ] Names describe intent, not implementation detail.
- [ ] Long functions are split or have a reason to stay long.
- [ ] No dead code, leftover debug logs, or commented-out blocks.

## 3. Security and privacy
- [ ] User input is validated on the server side.
- [ ] Authorization is checked near the data access point.
- [ ] Secrets are not printed, committed, or sent to Claude prompts.
- [ ] Logs do not include email, tokens, addresses, payment IDs, or private content.
- [ ] Injection, XSS, broken access control, and SSRF were considered.

## 4. Tests
- [ ] Unit or integration tests cover the changed behavior.
- [ ] A regression test covers the bug that motivated the PR.
- [ ] Manual steps are written with actual result, not "works locally".

## 5. Migration and data risk
- [ ] Migration is backward compatible during rollout.
- [ ] Destructive changes have backup or recovery steps.
- [ ] Old and new app versions can run during deployment.

## 6. AI-generated diff hygiene
- [ ] AI-generated code was read by a human before approval.
- [ ] The diff does not remove tests, monitoring, analytics, or CTA links.
- [ ] New dependencies are justified.

コツは、項目を「気をつける」ではなく確認できる事実にすることです。「セキュリティを確認した」では弱く、「ログにemail/token/paymentIdが出ていない」なら確認できる。「設計がきれい」では弱く、「触るモジュールが3つ以内」なら確認できる。チェックボックスは、埋めた人が嘘をつけない形にして初めて意味を持ちます。

レビュー観点をCLAUDE.mdに入れて一次レビューさせる

ここが今日の本題です。毎回プロンプトを貼るのは続きません。だから僕は、レビュー観点をCLAUDE.mdに書いて、Claude Codeに「PRを見て」と言うだけで同じ基準で一次レビューが返ってくるようにしました。

CLAUDE.mdはプロジェクト直下に置くと、Claude Codeが起動時に自動で読みます。そこにレビュー方針を書いておくわけです。観点をリポジトリに固定するやり方はCLAUDE.mdの書き方で詳しく整理しています。

# CLAUDE.md

## コードレビューの方針

PRレビューを頼まれたら、次の手順で「一次レビュー」を返す。

1. まずPRの目的と変更ファイルを読む。コードはまだ書き換えない。
2. リスクを low / medium / high で自分で判定し、理由を1行で書く。
3. 次の5観点で、深刻度順に findings を出す:
   - 正しさ(境界値・null・異常系・仕様逸脱)
   - 可読性(命名・関数の長さ・デッドコード)
   - セキュリティ(入力検証・権限・出力・ログ・外部通信)
   - テスト(変更挙動を証明するテストの有無)
   - 設計(影響範囲・責務・rollback可否)
4. 各 finding に「ファイル/関数」「なぜ問題か」「最小の修正案」を付ける。
5. "must fix before merge" と "follow-up" を分ける。
6. 最後に block / approve with fixes / approve のどれかを1行で出す。

禁止事項:
- レビュー中に勝手にコードを書き換えない。findings を先に出す。
- 根拠のない断定をしない。差分・テスト・公式ドキュメントと照合する。
- セキュリティは観点の指摘までにとどめ、深掘りは security-audit の手順に回す。

これを置いておくと、ターミナルで差分を見せて「このPRをレビューして」と頼むだけで、リスク判定→観点別findings→マージ判断、の順で返ってきます。僕は手元のステージング前PRに対して、こんな流れで使っています。

# 変更点をClaude Codeに渡して一次レビューを頼む
git fetch origin
git diff origin/main...HEAD > /tmp/pr.diff

# Claude Codeを起動して、差分とリスクを伝える
claude "このPRを一次レビューして。High risk(課金Webhook変更)。
触ったデータ: 顧客メールと決済ID。
/tmp/pr.diff の findings をCLAUDE.mdの手順どおりに出して。"

一次レビューが返ってきたら、僕がやるのは「正しいか照合する」ことだけ。AIが挙げた指摘を、差分・テスト・公式ドキュメント・実行結果と突き合わせます。ここを飛ばすと、もっともらしいだけの嘘の指摘を信じて、別の事故を起こします。CLAUDE.mdの運用はコードベース把握テスト戦略と組み合わせると、表面的な命名指摘で終わりにくくなります。

なお、git diffをそのまま渡すときは、差分の中に本物のAPIキーや顧客メール、決済IDが混ざっていないか先に確認してください。Claude Codeに渡す内容も「外に出していい情報か」を毎回見ます。

Claude Codeに直接貼る一次レビュープロンプト

CLAUDE.mdを置けない場面(他人のリポジトリ、一回きりのレビュー)では、同じ観点をプロンプトで直接渡します。特に禁止事項が大事で、レビュー中に勝手に大きな修正を始めると、レビューと実装が混ざってPRの責任範囲が曖昧になります。

You are doing a first-pass review of a pull request for a production team.

Goal:
- Find concrete risks before merge.
- Prioritize correctness, readability, security/privacy, tests, and design/migration risk.
- Do not rewrite code yet. Produce review findings first.

Context:
- Risk level: <low | medium | high>
- Business area: <auth | billing | content | search | admin | other>
- Sensitive data touched: <none | email | payment | address | private content>
- Rollout plan: <flag | migration | immediate deploy | other>

Review method:
1. Read the PR summary and changed files.
2. List the top risks by severity.
3. For each finding, include file, line or function, why it matters, and a minimal fix.
4. Separate "must fix before merge" from "follow-up".
5. Check whether tests prove the changed behavior.
6. Flag any AI-generated code, dependency, config, or formatting change unrelated to the PR goal.

Output format:
- Findings first, ordered by severity.
- Then missing evidence.
- Then questions for the author.
- Then a short merge recommendation: block, approve with fixes, or approve.

レビューの前に「このPRが触るドメインを3分で説明して」と頼むと、ドメインを理解した上で見るので、命名指摘だけで終わりにくくなります。

PRレビューの回し方とCIガード

観点が決まったら、次はチームで回す仕組みです。GitHubでは.github/pull_request_template.mdを置くと、PR作成画面にテンプレートが自動で入ります。狙いは長文の作文ではなく、Claude Codeと人間が同じ前提で読める「レビュー材料」を集めることです。

## Summary
- TODO

## Risk
Risk level: low | medium | high
Risk reasons:
- Data touched:
- Users affected:
- Rollout:

## Review focus
- [ ] Correctness
- [ ] Readability
- [ ] Security/privacy
- [ ] Tests
- [ ] Design / migration risk
- [ ] AI-generated diff hygiene

## Test evidence
- Automated:
- Manual:
- Not tested because:

## Migration / rollback
- Migration included: no | yes
- Backward compatible: no | yes | not applicable
- Rollback plan:

避けたいのは、チェックボックスだけを増やすことです。多すぎると全員が機械的に埋めて終わる。上のテンプレートはRisk reasonsRollback planのように、証拠を書かないと埋まらない欄を入れています。

そして、テンプレートの空欄をCIで弾きます。次はPR本文と差分を見て、レビュー材料の欠落をチェックするNode.jsスクリプトです。DangerJSを入れてもいいですが、最初は依存を増やさないこれで十分でした。

.github/workflows/pr-review-guard.yml:

name: PR review guard

on:
  pull_request:
    types: [opened, edited, synchronize, reopened, ready_for_review]

permissions:
  contents: read
  pull-requests: read

jobs:
  review-guard:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: "20"
      - name: Check PR review evidence
        run: node scripts/pr-review-guard.mjs
        env:
          BASE_SHA: ${{ github.event.pull_request.base.sha }}
          HEAD_SHA: ${{ github.event.pull_request.head.sha }}

scripts/pr-review-guard.mjs:

import { execSync } from "node:child_process";
import { readFileSync } from "node:fs";

const eventPath = process.env.GITHUB_EVENT_PATH;
if (!eventPath) {
  throw new Error("GITHUB_EVENT_PATH is missing. Run this in GitHub Actions.");
}

const event = JSON.parse(readFileSync(eventPath, "utf8"));
const pr = event.pull_request;
const body = pr?.body ?? "";
const base = process.env.BASE_SHA ?? pr?.base?.sha;
const head = process.env.HEAD_SHA ?? pr?.head?.sha;

// SHAの形を検証してからgitに渡す(任意文字列をそのまま渡さない)
function safeRef(value, name) {
  if (!value || !/^[a-f0-9]{40}$/i.test(value)) {
    throw new Error(`${name} must be a full git SHA.`);
  }
  return value;
}

const baseSha = safeRef(base, "BASE_SHA");
const headSha = safeRef(head, "HEAD_SHA");
const changedFiles = execSync(`git diff --name-only ${baseSha} ${headSha}`, {
  encoding: "utf8",
})
  .split(/\r?\n/)
  .filter(Boolean);

function includesFile(pattern) {
  return changedFiles.some((file) => pattern.test(file));
}

const failures = [];
const hasRisk = /Risk level:\s*(low|medium|high)/i.test(body);
const hasTests =
  /## Test evidence[\s\S]*Automated:\s*\S/i.test(body) ||
  /## Test evidence[\s\S]*Manual:\s*\S/i.test(body);
const hasRollback = /Rollback plan:\s*\S/i.test(body);
const highRisk = /Risk level:\s*high/i.test(body);
const migrationChanged = includesFile(/migrations?|schema|prisma|drizzle/i);
const authOrBillingChanged = includesFile(
  /auth|session|permission|billing|payment|webhook/i,
);

if (!hasRisk) failures.push("Add `Risk level: low | medium | high` to the PR body.");
if (!hasTests) failures.push("Add automated or manual test evidence.");
if ((highRisk || migrationChanged) && !hasRollback) {
  failures.push("High-risk or migration PRs need a rollback plan.");
}
if (authOrBillingChanged && !/Rollback plan:\s*\S/i.test(body)) {
  failures.push("Auth, billing, or webhook changes need a rollback plan.");
}
if (changedFiles.length > 40 && !/AI-generated diff hygiene/i.test(body)) {
  failures.push("Large diffs need an AI-generated diff hygiene note.");
}

if (failures.length > 0) {
  console.error("PR review guard failed:");
  for (const failure of failures) console.error(`- ${failure}`);
  process.exit(1);
}

console.log("PR review guard passed.");

このガードは「レビューの質」を完全に保証はしません。でも、レビュー材料の欠落はかなり減ります。protected branchesでこのworkflowを必須にすると、PR本文が空のままマージされる事故が消えます。注意は、厳しくしすぎると小さな修正まで止まること。最初はHigh riskとMigrationだけ厳格にして、Low riskは軽く通すのが現実的です。

観点別の実務ユースケース

1. 認証・管理画面のPR 管理者だけが見られるユーザー一覧や権限変更を、UIのif文だけで守ると危険です。見るのはAPI側のauthorization、ログの個人情報、権限変更の監査証跡、テストデータの分離。可読性より先に正しさとセキュリティを見ます。

2. 課金・WebhookのPR 冒頭で僕が事故ったやつです。StripeなどのWebhookでは、署名検証、冪等性、二重処理、失敗時再試行、返金やキャンセル状態が要点。Claude Codeには「同じeventが2回来ても課金状態が壊れないか」を重点的に見てもらいます。

3. DB Migrationを含むPR 列追加だけなら軽く見えますが、not null制約、default、index、削除、renameは本番データで失敗しやすい。古いアプリと新しいアプリが同時に動く時間を考え、expand and contract方式で段階的に変えます。設計観点の「戻せるか」が主役です。

4. AIが大量生成したUI差分 Claude Codeに一覧画面やフォームをまとめて作らせると差分が膨らみます。見るのは、意図しないCTA削除、分析イベント名の変更、既存CSSの破壊、snapshot更新の意味。AI生成diff hygieneの観点が効きます。

セキュリティ観点は拾って深掘りは別記事へ

レビューの片手間で本格的なセキュリティ監査はできません。だから一次レビューでは「観点として拾う」ところまでにします。

僕が使っているのは、OWASPを丸暗記する代わりに入力・権限・出力・ログ・外部通信の5つに分ける見方です。入力はサーバー側で検証されているか。権限は画面ではなくデータ取得の近くで確認されているか。出力はXSSにつながらないか。ログに個人情報やtokenが出ていないか。外部通信はSSRFや署名検証漏れにつながらないか。この順でClaude Codeに見せると、指摘の粒度が安定します。

プライバシーは「秘密情報」だけではありません。メール、住所、購入履歴、問い合わせ本文、分析用IDも、扱いを間違えると信用を失う。Claude Codeに渡す前に、本物のAPIキーや顧客メール、決済IDを貼らないこと。必要なら値をマスクし、構造だけ渡します。

そして、ここで見つかった懸念は「follow-up」に積んで、ちゃんとした監査に回します。脅威モデル、範囲定義、証跡、CIゲートまでの手順はClaude Codeでセキュリティ監査を実務化する方法にまとめたので、High riskのPRはそちらへ送ってください。レビューと監査は、別の仕事として分けるのが安全です。

僕がやらかしたレビューの落とし穴

ひとつ目は、冒頭のとおり読みやすさだけ見たこと。命名にコメントを付けて満足して、署名検証の欠落を見逃しました。観点を5つに分けてから、この種の見逃しは減りました。

ふたつ目は、Claude Codeの指摘をそのまま信じたこと。AIはもっともらしい嘘の指摘を作ります。差分・テスト・公式ドキュメント・実行結果と照合してから採用する、を徹底したら、無駄な手戻りが消えました。

みっつ目は、レビューと修正を同時に進めたこと。レビュー中にClaude Codeへ「直して」と言い始めたら、PRの差分がさらに膨らんで、何をレビューしていたのか分からなくなった。今はfindingsを出し切ってから、must fixだけ別コミットで直します。

よっつ目は、Migrationのrollbackをコードのrevertと同じだと思ったこと。DB変更はrevertしてもデータが戻らない場合がある。backup、復旧SQL、feature flag、二段階Migrationをやっと先に書くようになりました。

よくある質問

Q. コードレビューの観点は結局いくつ覚えればいい? 正しさ・可読性・セキュリティ・テスト・設計の5つで十分です。多すぎると機械的に埋めるだけになります。各観点を「確認できる事実」に落とすほうが、数を増やすより効きます。

Q. Claude Codeのレビューだけでマージしていい? やめたほうがいいです。Claude Codeは一次レビュー(見落とし減らし)止まりで、最終判断は人間がします。特にHigh riskは2人レビューを残してください。

Q. PRレビューの観点はどこに置くのが正解? チーム共有なら.github/review-checklist.md、Claude Codeに一次レビューさせるならCLAUDE.mdの両方です。CLAUDE.mdに置くと、毎回プロンプトを貼らずに同じ基準でレビューが返ります。

Q. AIコードレビューの精度を上げるコツは? リスク(low/medium/high)と触ったデータ種別を先に伝えることです。「レビューして」だけより、findingsの粒度が明確に上がります。

Q. セキュリティはこのチェックリストで足りる? 一次レビューの観点としては足ります。ただし本格的な監査は別物です。懸念はfollow-upに積んで、セキュリティ監査の記事の手順に回してください。

実際に試した結果

このチェックリストとCLAUDE.md運用を、小さなNext.js想定PR、DB Migration想定PR、AI生成UI差分想定PRに当てて回しました。一番効いたのは、Risk levelRollback planをPR本文に強制したこと。これだけで、冒頭の僕みたいな「読みやすさだけ見て事故る」が止まりました。

Claude Codeの一次レビューも、抽象的な「レビューして」より、リスクとデータ種別を渡したほうが明らかに当たります。逆に、チェック項目をただ増やしても品質は上がりませんでした。観点を5つに絞り、リスクで深さを変え、CLAUDE.mdに固定して、CIで材料の欠落を弾く。この4点を短く保つのが、チームで続く一番のコツでした。

次はClaude Codeペアプログラミングと組み合わせて、レビューで見つけたmust fixをその場で安全に直す流れを作ると速いです。チームでテンプレート・プロンプト・CLAUDE.md・CIガードまで一気に整えたいなら教材・テンプレート一覧、実リポジトリ前提で一緒に設計したいならClaude Code研修・導入相談も使ってください。レビューは、速くするだけでは足りません。危険な差分を、マージ前に確実に止める仕組みにしてください。

#Claude Code #コードレビュー #PRレビュー #AIコードレビュー #チェックリスト
無料

無料PDF: Claude Code はじめてのチートシート

まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。

スパムは送りません。登録情報は厳重に管理します。

Claude Codeを仕事で使える形にしませんか?

まず無料PDFで基本を固め、繰り返し使う作業はGumroad教材へ、チーム導入や権限設計は導入相談へ進めます。

Masa

この記事を書いた人

Masa

Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。

PR

関連書籍・参考図書

この記事のテーマに関連する書籍を楽天ブックスで探せます。

※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。