Claude Codeのsubagentでコードレビューを自動化する最小構成は?
プロジェクト直下に .claude/agents/code-reviewer.md(役割・読み取り専用ツール・出力形式を定義)を1ファイル置き、claude -p でレビューを依頼するだけです。本記事の構成は2026年8月6日にWindows 11で実行検証済みで、仕込んだ脆弱性3件をすべて[高]で検出しました。
この記事でできること
プロジェクトに定義ファイルを1枚置き、コマンド1行でコードレビューが返ってくる最小構成を作ります。本記事の手順と実行結果は、2026年8月6日にWindows 11のサンドボックス環境(Claude Code 2.1.161)ですべて実際に実行したものです。わざと脆弱性を仕込んだサンプルコードに対し、SQLインジェクション2箇所とパスワードのハードコードをすべて重要度[高]で検出できました。
なぜsubagentを使うのか
メインの会話とは独立したコンテキストで動く「役割固定の担当者」を作れるからです。素のプロンプトで毎回レビューを頼む方式と比べ、観点と出力形式が定義ファイルに固定されるため結果が安定します。使えるツールを制限できる点も実務では重要です。
- レビュー観点・重要度基準・出力形式を定義ファイルで固定できる
- ツールを読み取り専用(Read / Grep / Glob)に絞れるため、レビュー中にコードを書き換えられる事故を防げる
- 非対話モード(
claude -p)から呼べるので、自動化フローに組み込みやすい
前提環境
Claude Codeが動く環境であれば追加インストールは不要です。動作確認は次の環境で行いました。
- Claude Code 2.1.161(
claude --versionの出力:2.1.161 (Claude Code)) - Windows 11(コマンド実行はGit Bash)
手順1: レビュー対象のサンプルコードを用意する
検出精度を確かめるため、問題を3種類(SQLインジェクション・秘密情報のハードコード・雑な例外処理)仕込んだ app.py を用意します。
"""問い合わせフォームの送信内容をDBに保存する簡易API(レビュー対象のサンプル)"""
import sqlite3
DB_PATH = "contacts.db"
ADMIN_PASSWORD = "admin1234" # 管理画面の簡易認証
def save_contact(name, email, message):
conn = sqlite3.connect(DB_PATH)
cur = conn.cursor()
# 受け取った値をそのままSQLに埋め込んで保存する
cur.execute(
f"INSERT INTO contacts (name, email, message) VALUES ('{name}', '{email}', '{message}')"
)
conn.commit()
conn.close()
def find_contact(email):
try:
conn = sqlite3.connect(DB_PATH)
cur = conn.cursor()
cur.execute(f"SELECT * FROM contacts WHERE email = '{email}'")
return cur.fetchall()
except:
return []
手順2: subagent定義ファイルを作る
プロジェクト直下に .claude/agents/code-reviewer.md を作成します。ここが本構成の心臓部で、frontmatterの tools で読み取り専用ツールだけを許可し、本文でレビュー手順と出力形式を固定します。
---
name: code-reviewer
description: コードの品質・セキュリティレビュー担当。レビュー依頼を受けたら対象ファイルを読み、重要度つきで指摘を返す。
tools: Read, Grep, Glob
---
あなたはセキュリティ重視のコードレビュアーです。
レビュー手順:
1. 指定されたファイルをReadで読む
2. セキュリティ(インジェクション・秘密情報のハードコード)、エラーハンドリング、リソース管理の順で確認する
出力形式(この形式以外で返さない):
- [高] ファイル名:行番号 指摘内容と修正方針(1行)
- [中] 同上
- [低] 同上
最後に「指摘: 高X件 / 中Y件 / 低Z件」の集計行を付ける。
ポイントは3つあります。description はメインエージェントが「いつこのsubagentに任せるか」を判断する材料になるため、役割とトリガーを具体的に書きます。tools にWriteやEditを含めないことで、レビューが勝手に修正へ進む事故を構造的に防ぎます。出力形式を「この形式以外で返さない」と固定すると、後工程でのパースもしやすくなります。
手順3: 非対話モードで実行する
プロジェクトのディレクトリで次のコマンドを実行します。
claude -p "code-reviewer サブエージェントを使って app.py をコードレビューしてください。サブエージェントの結果をそのまま出力してください。"
実行結果(実出力)
下記は上記コマンドで実際に得られた標準出力の全文です。手直しはしていません。
code-reviewer の結果をそのまま出力します。
---
- [高] app.py:13 `save_contact` で f-string によるSQL文字列連結を行っておりSQLインジェクション脆弱性がある。プレースホルダに変更する(`cur.execute("INSERT INTO contacts (name, email, message) VALUES (?, ?, ?)", (name, email, message))`)
- [高] app.py:23 `find_contact` も同様にf-stringでSQLを組み立てておりインジェクション可能。`cur.execute("SELECT * FROM contacts WHERE email = ?", (email,))` に変更する
- [高] app.py:5 管理パスワード `admin1234` がソースにハードコードされている。環境変数(`os.environ["ADMIN_PASSWORD"]`)やシークレット管理へ移し、リポジトリ履歴からも除去する
- [中] app.py:25-26 裸の `except:` が全例外(KeyboardInterrupt含む)を握りつぶし空リストを返すため障害検知不能。`except sqlite3.Error as e:` に限定しログ出力するか、例外を呼び出し元へ伝播させる
- [中] app.py:21-26 `find_contact` は例外発生時・正常時ともに `conn.close()` を呼ばず接続がリークする。`with sqlite3.connect(DB_PATH) as conn:` + `finally` で確実にクローズする
- [中] app.py:9-16 `save_contact` も `execute`/`commit` で例外が出ると `close()` に到達せずリークする。コンテキストマネージャ(`with contextlib.closing(sqlite3.connect(DB_PATH)) as conn:`)に置き換える
- [低] app.py:8 入力値のバリデーションが皆無(email形式・文字数上限なし)。保存前に形式チェックと長さ制限を追加する
- [低] app.py:4 `DB_PATH` が相対パスのため実行ディレクトリ依存で意図しない場所にDBが作られうる。絶対パス化または設定値から解決する
指摘: 高3件 / 中3件 / 低2件
---
修正まで進める場合は指示ください(高3件だけ先に潰すのが推しです)。
仕込んだ3つの問題(SQLインジェクション2箇所・パスワードのハードコード)はすべて[高]で検出され、指摘の行番号も実ファイルの行位置と一致していました。定義ファイルで固定した出力形式(重要度タグ+集計行)どおりに返ってきている点も確認できます。
つまずきポイント
最小構成でも運用上の注意点があります。特にツール制限と形式固定は、省くと自動化の信頼性が下がります。
toolsにWrite/Editを含めると、レビューを越えて修正まで進むことがある。レビューと修正は別のステップに分離する- 出力の前後にメインエージェントの文(上記実出力の1行目と最終行)が付くことがある。機械処理する場合は
---区切りなど、切り出せる形式を定義側で決めておく - 生成AIのレビューには見落としの可能性が残る。マージ判断は人の確認とセットで運用する
まとめ
定義ファイル1枚とコマンド1行という最小構成でも、重要度つきの実用的なレビューが返ることを実出力つきで確認しました。まずは自分のプロジェクトに code-reviewer を1体置き、プルリクエスト前のセルフチェックとして使い始めるのが導入しやすい形です。
FAQFrequently Asked
まずは無料体験セッションで、AI導入・実装支援の中身を確かめてください
AIディアが実践している「AI導入・実装支援」の考え方を、60分の無料体験セッションで具体的にご案内します。
無料体験セッション60分を申し込む