Claude Code/Codexで大規模コードベースを迷わず読む実践ガイド
repo地図、rg検索、依存関係、入口追跡、リスク整理まで、大規模コードベースを安全に読む手順。
大規模コードベースを読むとき、最初にやるべきことは「全部を理解する」ではありません。最初の30分で作るべきものは、どこから入り、どこを触ってはいけないかが分かる地図です。
Claude CodeやCodexは、この地図作りに向いています。ただし、いきなり「このリポジトリを説明して」と投げるだけでは、会話に不要なファイル全文やログが混ざり、あとで重要な判断が埋もれます。ここでいうコンテキスト肥大化とは、AIとの会話に読解済みの断片を詰め込みすぎて、判断材料の密度が下がる状態です。
この記事では、Masaが既存案件の引き継ぎやClaudeCodeLabの記事改善で使っている読み方を、コピペしやすいコマンドとプロンプトに落とします。公式挙動は、Claude Codeのcommon workflows、CLI reference、memory、Codexのnon-interactive mode、AGENTS.mdを根拠にします。
最初にrepo地図を作る
初回は、AIに読ませる前にリポジトリの外形を自分で絞ります。rgはripgrepのコマンドで、Git管理外や除外対象を避けながら高速に検索できます。Claude CodeやCodexへ渡す前に、人間が「読む範囲」を作るのが安全です。
git status --short
git rev-parse --show-toplevel
git branch --show-current
rg --files \
-g '!*node_modules*' \
-g '!dist' \
-g '!build' \
-g '!coverage' \
-g '!*.lock' \
| sed 's#^[^/]*/##' \
| sort \
| uniq -c \
| sort -nr \
| head -40
find . -maxdepth 3 \( \
-name package.json -o \
-name pnpm-workspace.yaml -o \
-name pyproject.toml -o \
-name go.mod -o \
-name Cargo.toml -o \
-name Dockerfile -o \
-name docker-compose.yml -o \
-name AGENTS.md -o \
-name CLAUDE.md \
\) -print
この結果を見てから、次のように読解専用で依頼します。Claude Codeは公式ワークフローでも、広い質問から始めて特定領域へ絞る流れが紹介されています。Codexの場合も、非対話実行のcodex execは公式ドキュメント上でデフォルトがread-only sandboxなので、初回の棚卸しに向いています。
codex exec "Read only. Summarize the repository map: apps, packages, entrypoints, test commands, generated folders, and files that define project rules. Do not edit files."
Claude Codeで同じことをするなら、-pで非対話の出力にします。-pはCLI referenceで説明されているprint modeです。
claude -p "
読み取り専用で、このリポジトリのrepo地図を作ってください。
出力は次の順番にしてください。
1. アプリ/パッケージ/サービスの一覧
2. 起動入口、テスト入口、ビルド入口
3. 生成物や読まなくてよいフォルダ
4. AGENTS.md、CLAUDE.md、README、設計メモの要点
5. 次に読むべき10ファイルと、読む理由
編集やコマンド実行は提案だけにしてください。
"
検索戦略を段階化する
大規模コードベースで失敗しやすいのは、名前検索だけで「分かった気になる」ことです。検索は、構造、語彙、呼び出し、設定、履歴の5段階に分けます。
# 1. 入口候補
rg -n "createServer|listen\(|app\.use|router\.|main\(|bootstrap|hydrateRoot|createRoot" \
src apps packages server web
# 2. ドメイン語彙。例: 認証、課金、通知、検索
rg -n "Auth|Billing|Invoice|Notification|Search|FeatureFlag" \
src apps packages test tests
# 3. 変更予定のモジュールを参照している場所
rg -n "AuthService|useAuth|requireAuth|authMiddleware" \
src apps packages test tests
# 4. 設定と環境変数
rg -n "process\.env|import\.meta\.env|PUBLIC_|DATABASE_URL|JWT|STRIPE|OPENAI|ANTHROPIC" \
. -g '!node_modules' -g '!dist' -g '!build'
# 5. 履歴。なぜ今の設計になったかを見る
git log --oneline --decorate --date=short --max-count=30 -- src/auth packages/auth
AIに渡すときは、検索結果をそのまま大量投入しません。まずヒット件数を見て、上位のファイルだけを渡します。たとえば「50件ヒットしたので全部読んで」ではなく、「この15ファイルを候補として、どれが入口か分類して」と頼みます。
あなたはコードベース読解のレビュアーです。
以下のrg結果を、実装入口、呼び出し元、設定、テスト、ノイズに分類してください。
各分類で読むべきファイルを最大5件に絞り、理由を1行で書いてください。
不明なものは推測せず「追加検索が必要」と書いてください。
依存関係グラフを軽く作る
本格的な依存解析ツールを入れる前に、相対importだけを見る小さなNodeスクリプトでも役に立ちます。完璧な解析ではありませんが、「このファイルを触るとどこに波及するか」をAIと話す材料になります。
#!/usr/bin/env node
import { execFileSync } from "node:child_process";
import { readFileSync } from "node:fs";
import path from "node:path";
const target = process.argv[2]?.replace(/\\/g, "/");
if (!target) {
console.error("Usage: node scripts/dependency-map.mjs src/path/to/file.ts");
process.exit(1);
}
const tracked = execFileSync("git", ["ls-files"], { encoding: "utf8" })
.split(/\r?\n/)
.filter(Boolean)
.map((file) => file.replace(/\\/g, "/"));
const trackedSet = new Set(tracked);
const sourceFiles = tracked.filter((file) => /\.(mjs|cjs|js|jsx|ts|tsx)$/.test(file));
const importPattern =
/(?:from\s+["']([^"']+)["']|import\s*\(\s*["']([^"']+)["']\s*\)|require\s*\(\s*["']([^"']+)["']\s*\))/g;
function resolveLocalImport(specifier, fromFile) {
if (!specifier.startsWith(".")) return null;
const base = path.normalize(path.join(path.dirname(fromFile), specifier)).replace(/\\/g, "/");
const candidates = [
base,
`${base}.ts`,
`${base}.tsx`,
`${base}.js`,
`${base}.jsx`,
`${base}/index.ts`,
`${base}/index.tsx`,
`${base}/index.js`,
];
return candidates.find((candidate) => trackedSet.has(candidate)) ?? base;
}
const incoming = [];
for (const file of sourceFiles) {
const source = readFileSync(file, "utf8");
for (const match of source.matchAll(importPattern)) {
const resolved = resolveLocalImport(match[1] || match[2] || match[3], file);
if (resolved && (resolved === target || resolved.endsWith(`/${path.basename(target)}`))) {
incoming.push(file);
}
}
}
console.log(`Target: ${target}`);
console.log("Direct importers:");
for (const file of incoming.sort()) console.log(`- ${file}`);
保存して実行します。
mkdir -p scripts
$EDITOR scripts/dependency-map.mjs
node scripts/dependency-map.mjs src/services/AuthService.ts
出力をClaude CodeやCodexへ渡すときは、次のように「リスク評価」に変換します。
次のDirect importersを見て、AuthService.tsを変更する場合の影響範囲を評価してください。
分類は high / medium / low。
highは認証、課金、権限、永続化、公開APIに関係するもの。
各分類で追加で読むべきテストと設定ファイルも挙げてください。
エントリーポイントから実行経路を追う
ファイル一覧だけでは、実行時の流れは分かりません。Webアプリなら、リクエストがmiddleware、route、controller、service、repositoryへどう流れるかを追います。フロントエンドなら、route、loader、state、API client、componentの順番で追います。
rg -n "middleware|loader|action|controller|handler|route|repository|service" \
src apps packages \
-g '*.ts' -g '*.tsx' -g '*.js' -g '*.jsx'
rg -n "fetch\(|axios|graphql|trpc|prisma|drizzle|sequelize|typeorm" \
src apps packages \
-g '*.ts' -g '*.tsx' -g '*.js' -g '*.jsx'
ここでAIに頼むべき出力は、文章の感想ではなく、経路表です。
| 観点 | 良い出力 | 危ない出力 |
|---|---|---|
| 入口 | POST /login -> auth route -> AuthService.login | 「auth周辺が重要です」だけ |
| 状態 | Cookie、session、DB、cacheのどれが変わるか | 状態変更の説明がない |
| 例外 | 失敗時の戻り値、ログ、監査イベント | happy pathだけ |
| テスト | 既存テスト名と不足テスト | 「テストを追加しましょう」だけ |
プロンプトは次の形にします。
login処理の実行経路を、入口から永続化まで表にしてください。
列は「順番」「ファイル」「関数/クラス」「状態変更」「失敗時の動き」「読むべきテスト」。
不明な箇所は推測で埋めず、追加で読むべきファイル名を書いてください。
所有境界とリスク地図を作る
大規模コードベースでは「動くか」より前に「誰の境界か」を見ます。所有境界とは、チーム、責務、データ、リリース手順が変わる線です。ここを無視してAIに編集させると、動作は合っていてもレビューで止まります。
find . -maxdepth 4 \( \
-name CODEOWNERS -o \
-name OWNERS -o \
-name README.md -o \
-name AGENTS.md -o \
-name CLAUDE.md \
\) -print
rg -n "owner|maintainer|deprecated|legacy|do not edit|generated|migration|rollback|release" \
. -g '!node_modules' -g '!dist' -g '!build'
CodexはAGENTS.mdを読み込む公式仕様があるため、プロジェクト規約や所有境界をここへ置く価値があります。Claude CodeではCLAUDE.mdやメモリ機能を使って、次回の読解を短くできます。詳しくはCLAUDE.mdベストプラクティスも参考になります。
## Codebase map
### Entry points
- Web: apps/web/src/main.tsx
- API: services/api/src/server.ts
- Jobs: services/jobs/src/index.ts
### Ownership boundaries
- services/payments: owned by payments team; never change schema without migration review.
- packages/ui: shared design system; visual regression test required.
- legacy/: read-only unless the issue is production severity.
### High-risk files
- services/api/src/auth/AuthService.ts: login, session rotation, audit log.
- packages/db/schema.ts: migrations affect API and jobs.
- apps/web/src/routes/checkout.tsx: revenue path and analytics.
### Handoff notes
- Always start with rg search, then read top files.
- Prefer small diffs with tests.
- Do not paste large logs into the main conversation; summarize first.
読み取り専用の探索プロンプトを使う
初回探索では、編集権限を渡さない方が精度が上がります。AIが「直す」方向へ進む前に、地図、仮説、不明点を分けられるからです。
読み取り専用で調査してください。ファイル編集、依存追加、フォーマット変更、テスト実行はしないでください。
目的:
大規模コードベースのうち、[機能名]の実装範囲と変更リスクを把握する。
出力:
1. 入口ファイル
2. 主要なデータモデル
3. 直接依存と間接依存
4. 所有境界
5. high/medium/lowのリスク地図
6. 追加で読むべきファイル
7. まだ確証がない仮説
制約:
推測は「仮説」と明記する。
ファイル名と根拠を必ず書く。
大きなファイル全文を引用しない。
Claude Codeのsubagentsは、調査結果だけをメイン会話へ戻す用途に向いています。公式ドキュメントでも、サブエージェントは別のコンテキストで作業し、要約だけを返す説明があります。Codexのsubagentsも、コードベース探索のような並列タスクに使えると説明されています。ただし、サブエージェントはトークンを消費するので、境界が明確な調査に限定します。実践例はClaude Codeサブエージェント活用パターンにまとめています。
3つのサブエージェントで読み取り専用調査をしてください。
1. API入口と認証境界
2. DBスキーマとmigration境界
3. UIルートと収益導線
各エージェントは最大8ファイルまで読み、最終結果だけを返してください。
最後に親エージェントが重複、矛盾、不明点を統合してください。
コンテキスト肥大化を防ぐ
コンテキスト肥大化を防ぐコツは、会話に入れる情報を「証拠」と「判断」へ分けることです。ファイル全文、長いログ、検索結果100件は証拠として重すぎます。先にコマンドで絞り、AIには判断しやすい単位で渡します。
OpenAIのcompactionはAPI文脈の話ですが、実務の会話運用でも同じ発想が使えます。古い詳細を残し続けるのではなく、必要な要約を残して次へ進みます。
ここまでの調査を、次の作業者向けに300語以内で圧縮してください。
残すもの:
- 確認済みの入口
- high riskなファイル
- 変更禁止の境界
- 未確認の仮説
- 次に実行するコマンド
捨てるもの:
- すでに否定された仮説
- 長いログ
- 読む必要がない生成物
引き継ぎメモは、記事制作でも開発でも同じ価値があります。多言語記事なら「どのlocaleを触ったか」、アプリなら「どの入口まで追ったか」、バグ調査なら「どの仮説が外れたか」を残します。テスト観点はClaude Codeテスト戦略、権限まわりはapprovalとsandboxのガイドも合わせて確認してください。
3つの実例
1つ目は、新規参加したSaaSリポジトリです。初日に見るのは、ログイン、課金、管理画面、通知の4つです。repo地図を作り、AuthServiceとBillingServiceのimport元を調べ、checkout routeを入口からDBまで追います。ここで編集を始めないことが重要です。
2つ目は、レガシー移行です。legacy/やdeprecatedを検索し、所有境界を先に確認します。AIには「置き換え案」ではなく「互換性を壊す可能性」を出させます。特にDB migration、公開API、バッチ処理、cronは後戻りが難しい領域です。
3つ目は、ClaudeCodeLabのようなコンテンツサイトです。記事、CTA、内部リンク、商品導線、翻訳ファイルが分かれているため、slug単位で所有境界を作ります。AIには「このslugだけを読む」「他の記事はリンク確認だけ」と伝えます。これにより、並列作業でも他メンバーの編集を巻き込みにくくなります。
よくある落とし穴
- READMEだけを信じる。実際の入口は古いREADMEとずれていることがあります。
- 検索ヒット数を読解済みと勘違いする。ヒットは候補であり、実行経路ではありません。
- AIに最初から編集させる。所有境界を知らないまま変更するとレビューで止まります。
- 生成ファイル、lockfile、coverage、distを会話に入れる。重要な判断が薄まります。
- サブエージェントに広すぎる依頼を出す。戻ってくる要約が大きすぎると、結局メイン会話が重くなります。
- 「安全に直して」とだけ頼む。high/medium/lowのリスク基準を明示しないと、重要度の判断が揺れます。
収益導線とチーム導入
大規模コードベースの読解は、開発速度だけでなく収益にも直結します。課金導線、問い合わせフォーム、教材販売、広告計測を触る前に、入口、所有境界、リスク地図を作ると、修正の手戻りが減ります。
Claude CodeやCodexをチーム導入するなら、最初にrepo地図テンプレート、AGENTS.md/CLAUDE.md、レビュー観点、読み取り専用プロンプトを揃えるのが現実的です。個人で始めるなら無料チートシートで手順を固定し、チーム運用や研修が必要ならClaude Code研修・導入相談で実リポジトリ前提のルール作りに進めます。
この記事で紹介した内容を実際に試した結果
Masaがこの手順を使うと、最初の会話で巨大なファイルを読ませるより、後続の修正依頼が安定しました。特に「repo地図」「rg検索結果の分類」「依存関係の小さな表」「high/medium/lowのリスク地図」を先に作ると、Claude CodeやCodexが触るべきファイルを絞りやすくなります。逆に、最初から「この機能を直して」と頼むと、古いテスト、生成ファイル、別チーム領域まで話題に入り、コンテキストが膨らみました。公開前レビューでは、この記事のコマンド、プロンプト、Nodeスクリプトを読み直し、少なくとも構文としてコピペできる形になっていることを確認しました。
無料PDF: Claude Code はじめてのチートシート
まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。
スパムは送りません。登録情報は厳重に管理します。
Claude Codeを仕事で使える形にしませんか?
無料PDFで基礎を固めたあと、すぐ使えるテンプレート集で試し、必要なら業務自動化や導入相談まで進められます。
この記事を書いた人
Masa
Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
Claude Code権限セーフティラダー: 初心者がallowを広げる順番
Claude Codeの権限をread-onlyからbuild、限定編集、deploy確認まで段階的に広げる安全な運用手順。
Claude Code Small PR Proof Pack: 小さなPRをレビュー可能にする証拠セット
Claude Codeの小さなPRに、差分・検証・公開URL・CTA・rollbackを添える実務チェックリスト。
Claude Codeのコミット前レビューゲート: 差分、テスト、CTAをまとめて止める型
Claude Codeでcommit前に差分をレビューする実践手順。build、公開URL、CTA、Gumroadリンク、未翻訳本文を検知します。