Claude Codeを既存システムに導入すると詰まる「コンテキスト問題」とハーネスエンジニアリングの話

このブログ(dev-octane)を作るとき、ひとつ賭けをした。「デザインの検討からコード生成まで、ほぼClaudeだけでやってみる」という賭けだ。
結果は想定を超えた。普通に組んだら2週間はかかるような作業が、2〜3日で形になった。Next.jsのコンポーネント設計・Tailwindのカラーシステム・MDXの記事パイプライン・アフィリエイトリンクの管理機構。これらを一気に作れたのは、完全にClaude Codeのおかげだった。
「この感覚を、本業の大規模システムにも持ち込めないか」と思った。
それが甘かった。
一つ前置きをしておくと、Claude Codeのベストプラクティスはまだ誰も確立していない。ツール自体が比較的新しく、各社・各個人がいまもリアルタイムで実験している状態だ。GitFlowのように「これが定番の使い方」と言えるものはまだない。この記事も「自分が今の時点で考えていること」であって、6ヶ月後に答え合わせしたら半分は覆っているかもしれない。そういう段階の話として読んでほしい。
個人開発でClaudeが「神」に見えた理由
まず正直に言うと、個人開発でのClaude体験は異常に良すぎる。
何が良いかというと、プロジェクト全体の文脈を渡せる規模感だ。個人開発のWebアプリなら、ディレクトリ構成・技術スタック・設計方針・命名規則を CLAUDE.md という1ファイルにまとめて冒頭に食わせれば、「このプロジェクトの文脈を理解したエンジニア」として振る舞ってくれる。
「Tailwindのカラートークンは navy ink sub accent で統一している」「ユーティリティは lib/ ではなく util/ に置く」「アフィリエイトURLは記事内に直書きしない」。こういうプロジェクト固有のルールをCLAUDE.mdに書いておくと、それ以降の会話でいちいち説明しなくていい。
デザインから実装まで一気通貫でこなせたのは、この「文脈の共有」がうまく機能したからだ。Claudeが「このプロジェクトで何が正解か」を理解した状態で提案してくれるから、自分がゼロから考える量が激減する。
個人開発の規模であれば、全仕様をClaude に食わせてもトークン的にも現実的な範囲に収まる。だから「全渡し」が成立する。
問題は、既存の大規模システムに持ち込もうとしたときに始まる。
大規模システムで詰まった話
本業の開発環境にClaude Codeを持ち込んでみた。数十万行規模のコードベース、複数チームが並行開発しているシステムだ。
「よし、このマイクロサービス全体の設計を食わせてClaude に把握させよう」——最初はそう考えた。しかし現実はそう単純ではなかった。
問題1: 仕様が多すぎてトークンが消し飛ぶ
大規模システムの全体像をClaude に渡そうとすると、関連ファイルだけで数百KB〜数MB規模になる。コンテキストウィンドウに全部収めようとすると、1回の会話のトークンコストが跳ね上がる。しかも「大量に渡したから理解が深まる」かというとそうでもない。無関係な情報が多いと、Claude は重要な情報と非重要な情報を混同しやすくなる。
問題2: 何も渡さないと的外れな回答になる
じゃあ何も渡さずに聞けばいいかというと、今度は逆の問題が起きる。「このサービスの○○という処理にバグがある」と言っても、Claudeはシステムの前提知識がないからトンチンカンな回答をしてくる。一般論としては正しくても、「このコードベースでの正解」ではない、というやつだ。
この2つの問題の間に挟まれる感覚が、大規模システムへのClaude Code導入における「コンテキストジレンマ」だ。
現実解:スポット活用に割り切る
結論から言うと、今のところ大規模システムに対してClaude を使う現実的な方法は「スポット活用」だ。
ユニットテストの生成が最も費用対効果が高い。「このクラス・この関数のテストを書いて」というスコープが明確なタスクは、渡すコンテキストが少なく済む。既存の実装コードをそのまま貼り付けるだけで、Claude はそのコードを理解してテストを生成できる。大量の仕様を食わせる必要がない。
ピンポイントのバグ修正も効果的だ。「このエラーログとその周辺コードを見てほしい」という形で、問題が起きているファイル数ファイルだけを渡す。Claude が全体を知らなくても、局所的な問題は局所的なコンテキストで解ける。
コードの解析・レビュー補助も使いやすい。「このPRの変更差分を渡すから、気になる点を指摘してほしい」という使い方は、渡す量が自然に絞られるので機能しやすい。
これらに共通するのは、タスクのスコープと渡すコンテキストのスコープが一致しているという点だ。「全体を理解させてから質問する」ではなく、「この質問に答えるために必要な情報だけを渡す」という発想の転換が大事だった。
正直に言うと、最初は「スポット活用に割り切る」のがもったいない気がしていた。個人開発での全能感みたいなものを大規模でも再現したかった。でもそれは現時点では難しい。現実的な使い方に落とし込んだほうが、チーム全体の生産性は上がる。
個人開発では「CLAUDE.md で全仕様渡し」が正解
逆に個人開発・小規模プロジェクトでは、全仕様渡しを徹底するほうがいい。そのための仕組みがCLAUDE.mdだ。
CLAUDE.md はプロジェクトルートに置く設定ファイルで、Claude Code がセッション開始時に自動で読み込む。ここにプロジェクトの「説明書」を書いておくことで、毎回コンテキストを説明し直す手間がなくなる。
このブログのCLAUDE.mdには以下の情報が入っている。
# DevOctane — CLAUDE.md
## プロジェクト概要
- サイト名: DevOctane
- URL: https://www.dev-octane.site
- ニッチ: SES脱出・転職・副業・クラウドスキル・FinOps
- ターゲット: 25〜35歳の現役バックエンド/インフラ/DevOpsエンジニア
- マネタイズ: アフィリエイト (転職エージェント・VPS・スクール等)
## Tech Stack
- Framework: Next.js 15 (App Router)
- Styling: Tailwind CSS v3
- Content: MDX
- Hosting: Vercel
- Package Manager: pnpm
## やってはいけないこと
- lib/ ディレクトリにファイルを作る(global gitignoreのため)
- any 型を使う
- draft: true の記事をビルドに含めるこれがあることで、「このプロジェクトでの常識」をClaude が知っている状態になる。「lib/ じゃなくて util/ に置いてくれ」と毎回言わなくていいし、「アフィリエイトリンクは /go/[slug] 経由にしてくれ」と都度説明しなくていい。
CLAUDE.mdを書くときのコツは「やってはいけないこと」を必ず入れることだ。「やること」だけ書いても、Claudeはデフォルト設定でコードを生成することがある。禁止事項として明示することで、プロジェクト固有のルールを確実に守らせられる。
もうひとつのコツは「なぜそうするか」の背景も1行添えること。
## 重要
lib/ ディレクトリは使わない → util/ を使う
(理由: lib は global gitignore に含まれているため)理由が書いてあると、Claude が例外ケースを判断するときに「この理由があるから例外もNG」と判断できる。ただ「禁止」とだけ書いてあるより、判断の精度が上がる実感がある。
MDファイルを散在させる罠
CLAUDE.md(Markdown)は引き続き推奨されている。ただし「Claudeにコンテキストを渡すためのMarkdownファイル」をプロジェクト内に散在させるのは別の話で、こちらは非推奨だ。
たとえば docs/api-spec.md docs/architecture.md docs/conventions.md のようなファイルを大量に作り、「Claudeはこれを読んで理解してほしい」という設計にすると問題が起きる。複数のMDファイルを読む場合、「どのファイルに何が書かれているか」を把握しながら推論する必要があり、CLAUDE.md 1本にまとまっているより精度が落ちる。また散在したドキュメントは更新されないまま古くなる。古い仕様書と新しいコードの間で矛盾した情報を読む状態になる。
推奨パターンはシンプルだ。
- CLAUDE.md 1本に集約する:設計思想・ルール・禁止事項はCLAUDE.mdに書く
- コードはコードで語る:ディレクトリ構造・命名・型定義が自明であれば、ドキュメントに頼らなくていい
- メモリファイルは
.claude/以下に置く:Claude Code が管理するメモリは専用ディレクトリに分離し、ソースコードと混在させない
Claudeに渡すべき情報は「ルール・禁止事項・固有の文脈」であって、「一般的な技術ドキュメント」ではない。後者はClaude が学習データから知っている。
余談だが。SNSで「MarkdownをやめてHTMLに変えろ」という情報が一時期流れた。Anthropicのエンジニアが「個人的にHTMLが好み」と述べたことが「Markdownは非推奨」として拡散したものだ。実際は逆で、出力フォーマットをHTMLにするとトークン消費が増え、生成時間は2〜4倍遅くなる上に、git diffがノイズだらけになる。HTMLが有効なのはデザインプロトタイプなど「視覚的な出力が必要なケース」に限られる。CLAUDE.md本体はMarkdownのままで問題ない。
理想の開発フロー:要件定義から段階的PRへ
スポット活用が現実解だとしても、「もっとうまくClaudeを使えないか」という欲は消えない。
理想として考えているのは、要件定義を渡して、段階的なPR単位で実装を進めるフローだ。
今のClaude Codeで「この機能を作って」と頼むと、一気に大量のコードが生成される。100ファイル差分のPRを出されても、人間はレビューできない。しかし10ファイル程度の差分なら、エンジニアは内容を把握してレビューできる。
つまり理想の使い方はこうだ。
1. 要件定義を渡す(機能の目的・制約・インターフェース)
2. Claudeに実装を小タスクに分解させる
3. 小タスク単位(10ファイル前後)でPRを作ってもらう
4. 人間がレビューして承認・差し戻し
5. 次のタスクへ人間とClaude がペアプロをしているイメージに近い。Claudeが実装を進め、人間がレビューで品質をコントロールする。
これが現時点での理想論であって、完全に実現できているかというとまだそこまでいっていない。大規模システムに対してこのフローを回すには、「要件定義をClaudeが理解できる粒度で書く」スキルが人間側に求められる。Claudeが判断できるほど具体的に書かないと、実装計画の段階でズレが生じる。
とはいえ個人開発の規模であれば、今すぐこのフローを試せる。「CLAUDE.mdで全仕様渡し + タスクを段階的に渡す」だけで、かなりコントロールしながら開発が進む。
ハーネスエンジニアリング:Claudeの出力を自動検証する
「Claudeが生成したコードを信頼していいか」という問いへの答えとして、ハーネスエンジニアリングという考え方がある。Claude に自由に実装させながら、自動チェックのしくみを組み込んでClaudeの出力を検証するアプローチだ。
Claude Code にはHooks機能がある。PreToolUse(ツール実行前)と PostToolUse(ツール実行後)にシェルコマンドを自動実行できる仕組みだ。.claude/settings.json に設定を書くだけで動く。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "pnpm lint --fix"
}
]
}
]
}
}この設定を入れると、Claude がファイルを書くたびに自動でlintが走る。Claude が生成したコードの品質問題を、人間が目視チェックする前に機械的に潰せる。
Hooksを活用したハーネスの例:
| Hook タイミング | 使い方 | 効果 |
|---|---|---|
| PostToolUse (Write/Edit) | pnpm lint --fix | 生成コードを即座にフォーマット |
| PostToolUse (Write/Edit) | pnpm type-check | 型エラーをその場で検出 |
| PostToolUse (Bash) | pnpm test --changed | 変更ファイルに関連するテストを自動実行 |
| PreToolUse (Bash) | 危険なコマンドのブロック | rm -rf などの実行を防止 |
重要なのは、このハーネスが「Claude を信頼しながら安全に使う」ためのものだという点だ。Claude の出力を逐一手動チェックするのは現実的ではない。自動検証のしくみを先に組んでおくことで、人間はロジックのレビューに集中できる。
大規模システムに導入するときこそ、このハーネスが重要になる。テストカバレッジが高いシステムなら、Claude がコードを変更するたびにテストを自動実行できる。テストが落ちたらClaude 自身がエラーを受け取って修正するループも作れる。
Sub Agent パターン:タスクをスコープ限定で委譲する
Hooksと組み合わせて使えるのがSub Agentパターンだ。大きなタスクを複数のサブエージェントに分割し、それぞれ「このファイルだけ・この責務だけ」という制限されたスコープで動かす。
一般的な会話の中でClaude を使うと、セッションが長くなるほどコンテキストが肥大化して精度が落ちる。Sub Agent は独立したセッションで動くため、コンテキストが汚染されにくい。たとえば「APIのスキーマ変更」「既存テストの修正」「ドキュメントの更新」を3つの別エージェントに分けて並列処理させると、1セッションで全部やらせるより品質が安定する。
「AIに自由度を与えて何でもやらせる」より「仕組みで制約して確実に動かす」という発想の転換が、大規模システムでClaude を使いこなすときの軸になる。Hooks + Sub Agent + 要件起点の小タスク分割、この3つを組み合わせるのが現時点で考えられる現実的なハーネスの形だ。
ハーネスエンジニアリングはまだ実験中の領域だ。「どこまで自動化するか」「人間がどの段階でレビューするか」のバランスは、チームの規模・コードベースの品質・テストカバレッジによって全然違う。ただ、「とりあえずHooksでlintとtype-checkを自動実行する」くらいのハーネスは今すぐ組める。まずそこから始めてみる価値はある。
コンテキスト設計のチェックリスト
まとめとして、プロジェクト規模別のコンテキスト設計をまとめておく。
個人開発・小規模プロジェクト(〜数万行)
- CLAUDE.mdにプロジェクト概要・技術スタック・ディレクトリ構成を書く
- 「やってはいけないこと」を明示する(理由も1行添える)
- 命名規則・コーディング規約を書く
- アフィリエイト・外部サービス連携などの固有ルールを書く
- ビルドコマンド・デプロイ方法を書く(Claude がCI/CDを把握できるように)
大規模システム・チーム開発(数十万行〜)
- タスクのスコープと渡すコンテキストのスコープを一致させる
- 関係するファイルのみを選んで渡す(全体ではなく局所)
- システム全体のルールは要約版として渡す(長大な仕様書をそのまま渡さない)
- ユニットテスト・コードレビュー補助・ピンポイントのバグ修正から始める
- 大きな機能開発はタスク分解から始め、PR単位でレビューする
余談だが。「AIに全部任せれば開発者が不要になる」という話を時々聞く。個人的にはそれは当面ないと思っている。少なくとも今のClaude の使い方で実感するのは、「人間が要件とコンテキストを正確に定義できるほど、Claudeの出力が良くなる」ということだ。AIを使いこなすには、エンジニアとしての理解力が依然として必要になる。道具が変わったのであって、思考が不要になったわけではない。
Claude Codeを使う前に知っておきたかったこと
最後に、使い始める前に知っておきたかった3つのことをまとめておく。
1. 最初の投資はCLAUDE.mdの設計に使う
Claude Codeを導入したらまずCLAUDE.mdを作り込む。「とりあえず使い始める」より「最初の30分でCLAUDE.mdを書く」ほうが、その後の会話の品質が全然違う。最初にサボると、ずっと毎回同じことを説明し続けることになる。
2. 大規模システムには「スポット活用」から入る
いきなり全体を把握させようとしない。ユニットテスト・コードレビュー補助・局所的なバグ修正という小さい成功体験を積み上げてから、徐々に活用範囲を広げる。
3. 要件の言語化がClaudeの出力を決める
「なんかいい感じに作って」という指示に対する回答は、いい感じではないことが多い。Claudeへの指示は、後輩エンジニアへの指示と同じクオリティで書く必要がある。機能の目的・制約・既存コードとのつながり・完了条件。これを言語化できるかどうかが、Claude活用の実質的な壁になる。
→ Claude Code vs GitHub Copilot|使い分け完全ガイド → GitHub Actions 実践ガイド|CI/CDをゼロから構築する学習ステップ → 【2026年版】クラウドエンジニアへの最短学習ロードマップ