1セッション1タスク — Claude Codeのコンテキスト管理で学んだ原則
このトピックを深掘りする
Claude Code活用
Claude Codeを使った大規模リファクタリング・CLAUDE.md設計・セッション管理の実践知
全4本中 3 本目。
次に読む記事
AIが量産するコードの品質をどう担保するか — 200コンポーネントで運用する4層の品質ゲート
約200個のインタラクティブコンポーネントをAI駆動で量産・運用しているサイトの品質担保の実構成。pre-commitフック4本・データ不変条件テスト・ブラウザ実機スモーク・品質スコア+PR提案の4層を、構成ファイル名のレベルで公開する。
Claude Codeで200コンポーネントを一括修正した実録 — バグ分類・修正・検証の全工程
203個のインタラクティブコンポーネントに潜むバグを、Claude Codeで6コミット・100+ファイル一括修正した実践記録。分類・テンプレート化・検証の全工程を公開。
CLAUDE.mdを育てる — AIコラボレーション設定ファイルの3ヶ月の変遷
323コミットのプロジェクトでCLAUDE.mdを3ヶ月間更新し続けた記録。効いたルール、効かなかったルール、そして「助言的」設定の限界。
シリーズ全体の流れを見ながら、次に読む記事へ進めます。 初めての方はホームへ →
はじめに
Claude Code で211個のインタラクティブコンポーネントを開発してきた。流体シミュレーション、ピアノ、ピンボール、迷路生成——ブラウザ上で動く小さなデモを次々と作り、バグを直し、リファクタし、アクセシビリティを改善してきた。
その過程で、ワークフローについて膨大な試行錯誤をした。プロンプトの書き方、CLAUDE.md の構成、タスクの分割方法。何十ものルールを試して、効いたものを残し、効かなかったものを捨てた。
その結果、CLAUDE.md にこう書くようになった。
1セッション1タスク。コンテキストは最も希少なリソース。
この一行に至るまでの経緯を書く。なぜこれが最も効く原則なのか、どんな失敗を経てたどり着いたのかを共有したい。
コンテキスト枯渇とは何か
まず前提を整理する。LLM にはコンテキストウィンドウという制約がある。セッション中のすべてのやり取り——プロンプト、ツール呼び出し、ファイルの読み書き結果——がこのウィンドウに積み上がっていく。
ウィンドウが埋まるとどうなるか。古い情報から順に圧縮される。圧縮といえば聞こえはいいが、実態は「忘れる」に近い。さっき読んだファイルの内容、さっき議論した設計方針、さっき修正したバグのパターン——これらが曖昧になっていく。
自分がこの現象に気づいたのは、211コンポーネントを横断する一括修正のときだった。setTimeout のリークを全ファイルから探して修正するというタスクで、最初の30ファイルは完璧だった。パターンを正確に認識し、cleanup 関数を適切に追加していた。
ところが50ファイルを超えたあたりから、明らかに精度が落ちた。同じパターンのバグを見逃す。修正済みのファイルと同じ修正を「新しい発見」として報告する。ひどいときには、直したはずのコードを元に戻してしまう。
これがコンテキスト枯渇だ。ウィンドウの容量は有限で、タスクが大きくなるほどコンテキストの「鮮度」が下がる。人間の集中力と同じで、使えば使うほど消耗する。
4つの失敗パターン
コンテキスト枯渇に気づくまでに、いくつかの典型的な失敗を繰り返した。
1. 「ついでにこれも」症候群
最も陥りやすいパターンだ。AudioContext のエラーハンドリングを修正するセッションで、ふと目に入った mountedRef の欠如も一緒に直そうとする。
一見効率的に見える。同じファイルを開いているのだから、ついでに直せばいいじゃないか。
実際にはこうなる。AudioContext の修正パターンをコンテキストに積んだ状態で、突然 mountedRef のパターンを処理し始める。2つのパターンが混在し、どちらのルールを適用しているのか曖昧になる。結果、AudioContext の修正は8割の精度、mountedRef の修正は6割の精度。両方とも中途半端になる。
分けてやれば、どちらも95%以上の精度で完了する。実際にそうした。コミット 04163d8e は「AudioContext エラーハンドリング、mountedRef ガード、clipboard 安全性」を18ファイルで修正しているが、これは3つの小セッションに分けて実行し、最後にまとめてコミットした結果だ。
2. 長時間セッションの精度低下
3時間のセッションを続けたことがある。最初の1時間は快調だった。パターンを説明し、ファイルを読ませ、修正を確認する。精度は95%以上。
2時間目、やや怪しくなる。「さっき話したパターンと同じです」と言っても、微妙にずれた修正を提案してくる。確認回数が増える。
3時間目、もはや新しいセッションを始めたほうが早い状態になる。同じ説明を繰り返し、同じ修正を再確認する。体感で精度は50%以下だ。
長時間セッションの問題は、生産性の低下が緩やかで気づきにくいことだ。突然壊れるのではなく、じわじわと精度が落ちる。気づいたときには、後半の修正を全部やり直す羽目になっている。
3. コンテキストの汚染
前のタスクの残留情報が、新しいタスクの判断を歪めるパターンだ。
例えば、Canvas 系コンポーネントのパフォーマンス最適化をやった直後に、DOM 系コンポーネントのアクセシビリティ改善に取り掛かる。すると、DOM コンポーネントに対して Canvas 的な最適化を提案してきたりする。requestAnimationFrame のバッチ処理を DOM 要素に適用しようとする、みたいなことが起きる。
このプロジェクトでは Canvas と DOM を明確に使い分けている。BubbleWrap や ParticleField は Canvas(パフォーマンス重視)、GravityBadges や FidgetZone は DOM + CSS Transform(アクセシビリティ重視)。この判断基準はアーキテクチャとして確立しているのに、コンテキストが汚染されるとその境界が曖昧になる。
4. 「全部直して」丸投げ
初期の頃、こんなプロンプトを投げていた。
「src/components/interactions/ 以下の全コンポーネントを点検して、バグがあれば修正して」
結果は悲惨だった。211ファイルに対してスコープが無限に広い。何をバグと見なすかの基準がない。修正の優先順位もない。AI は真面目に全ファイルを読もうとするが、コンテキストが枯渇して途中からまともに機能しなくなる。
この失敗から学んだのは、スコープの明確さがコンテキスト効率に直結するということだ。「setTimeout のリークを修正して」と言えば、AI は setTimeout と clearTimeout のパターンだけをコンテキストに保持すればいい。余計な情報でウィンドウを消費しない。
原則の確立
これらの失敗を経て、いくつかの明確なルールを CLAUDE.md に書いた。
「同じ問題で2回失敗したら /clear」。2回失敗するということは、コンテキストに必要な情報がないか、汚染されている証拠だ。リトライするより、きれいな状態からやり直したほうが早い。
「無関係なタスク間でも /clear」。タスクAが終わってタスクBに移るとき、たとえタスクAが成功していても /clear する。タスクAの情報はタスクBには不要なのに、コンテキストを圧迫し続ける。
タスクの粒度は「1コミットに収まるサイズ」。これが最も実用的な基準だった。1コミットで説明できないほど大きなタスクは、分割すべきだというシグナルだ。
実際のコミットログがこの原則を裏付けている。
04163d8e: AudioContext エラーハンドリング — 18ファイル、1セッションf51f0c83: モジュールレベル可変状態の排除 — 15ファイル、1セッション1fc14711: 数値安全性ガード — 8ファイル、1セッション7723cfaf: Pointer Events 統一 — 16コンポーネント、1セッション
各コミットは1つのバグカテゴリに絞っている。これがコンテキストを温存し、精度を保つための最も重要な判断だった。
takt ワークフローとの統合
1セッション1タスクの原則を体系化するために、takt というワークフローを作った。タスクの規模に応じてセッションの分け方を変える仕組みだ。
quick-fix: バグ修正や小さなリファクタ。スコープが明確で3ファイル以下なら、1セッションで完結させる。計画→実装→確認をすべて1セッション内で行う。ほとんどのタスクはこれで済む。
plan-implement-review: 新機能の追加。計画・実装・レビューの3セッションに分ける。最初のセッションで何をするか決め、2番目のセッションで実装し、3番目のセッションで品質を確認する。各セッションは独立しており、前のセッションの結論だけを引き継ぐ。
spec-then-build: 大きな機能やアーキテクチャ変更。SPEC の策定・計画・実装・レビューの4セッションに分ける。SPEC を先に書くことで、実装セッションではコードに集中できる。
重要なのは、セッションを分けること自体が品質を上げるという発見だ。計画セッションでは計画だけに集中するから、より良い計画ができる。実装セッションでは実装だけに集中するから、より正確なコードが書ける。
これは人間のワークフローでも同じだ。設計書を書きながらコードを書く人は、どちらも中途半端になりがちだ。フェーズを分けることで、各フェーズの品質が上がる。AI も同じだった。
実践テクニック
1セッション1タスクの原則を最大限に活かすために、いくつかのテクニックを併用している。
バリデーション先行
セッションの最初に「何をもって完了とするか」を明示する。テストがあればテストを渡す。なければ期待する出力を具体的に示す。
これだけで品質が2-3倍になる。なぜか。AI がゴールを知っていれば、コンテキストの使い方が変わるからだ。「すべてのファイルを隅々まで調べる」のではなく、「ゴールに関係する情報を優先的に保持する」ようになる。コンテキストウィンドウの有効活用だ。
例えば「useEffect の cleanup で clearTimeout を呼んでいないファイルを全部修正して」と言うより、「以下のパターンを探して修正して。修正前: useEffect(() => { const id = setTimeout(...); }, []) → 修正後: useEffect(() => { const id = setTimeout(...); return () => clearTimeout(id); }, [])」と言うほうが圧倒的に精度が高い。
パターンの名指し
「このファイルを参照して同じパターンで」という指示が非常に効く。抽象的なルールを説明するよりも、具体的な実装例を1つ見せるほうが、AI は正確にパターンを再現する。
実際にやったのは、211コンポーネントのうち1つを手動で完璧に修正し、それを「お手本」としてセッションに渡す方法だ。「Match3.tsx の修正パターンを参照して、残りのファイルも同じように修正して」と言えば、AI はそのパターンをコンテキストに保持して横展開してくれる。
お手本が具体的であればあるほど、コンテキストの消費が少なくて済む。抽象的なルールは解釈の余地があり、その解釈にコンテキストを消費する。具体例はそのまま適用できるので、消費が最小限になる。
Worktree 分離
独立したタスクは cc <name> コマンドで別の worktree に分離して並列実行する。これは Git の worktree 機能を使ったもので、物理的にディレクトリを分けることでセッション間の干渉を完全に排除する。
例えば、Canvas 系コンポーネントの修正と DOM 系コンポーネントの修正は完全に独立している。これらを同じセッションで順番にやると、前述の「コンテキスト汚染」が起きる。別 worktree で並列実行すれば、各セッションは自分のタスクだけに集中できる。
終了時に staging ブランチへ自動マージするので、統合のオーバーヘッドもほぼない。
レビュー視点の分離
コードレビューと仕様レビューは別セッションで行う。
コードレビュー(微視的)は、変数名、エラーハンドリング、パフォーマンス、型安全性といった実装の詳細を見る。仕様レビュー(巨視的)は、要件との整合性、アーキテクチャとの一貫性、ユーザー体験への影響を見る。
同じセッションで両方やると、どちらかに偏る。コードの詳細に入り込むと仕様の俯瞰を忘れ、仕様を考えているとコードの細部を見落とす。分ければ、各レビューが徹底的になる。
定量的な効果
原則の導入前後で、明確な差が出た。
セッション分割前(初期の試行錯誤期):
- 1セッションあたりの修正ファイル数: 平均5ファイル
- 修正精度(手動確認での合格率): 約70%
- 手戻り率: 30%以上
- 1タスクの総所要時間: 長い(手戻り込み)
セッション分割後(原則確立後):
- 1セッションあたりの修正ファイル数: 平均15ファイル
- 修正精度: 約95%
- 手戻り率: 5%以下
- 1タスクの総所要時間: 短い(手戻りがほぼない)
修正ファイル数が3倍になって精度も上がった、というのは矛盾に聞こえるかもしれない。秘訣はスコープを絞ってコンテキストを温存することだ。
1つのバグパターンに集中すれば、AI はそのパターンの認識と修正にコンテキストを集中投下できる。15ファイルに同じパターンの修正を適用するのは、5ファイルに異なるパターンの修正を適用するより、コンテキスト効率がはるかに高い。
CLAUDE.md の進化
1セッション1タスクの原則にたどり着く過程で、CLAUDE.md 自体も大きく変わった。
初期: React のルールを長々と書いていた。「useEffect の依存配列を正しく設定すること」「コンポーネントは副作用を持たないこと」。こういう当たり前のことを書いても、ほとんど効果がない。AI はすでに知っている。書くだけコンテキストの無駄だ。
中期: ワークフローのルールを書くようになった。「ファイルを修正する前にテストを実行すること」「修正後は bun run check で lint を通すこと」。これはやや効いた。手順が明確になり、抜け漏れが減った。
現在: 判断基準とフォールバックを書いている。「迷ったら quick-fix を選ぶ」「同じ問題で2回失敗したら /clear」。これが最も効く。AI に「何をすべきか」ではなく「迷ったときにどうすべきか」を教える。
この進化の過程で得た重要な気づきがある。
「hooks は決定論的、CLAUDE.md は助言的」。
Biome の pre-commit hook でフォーマットを強制するのは決定論的だ。ルールに違反したらコミットが失敗する。これは確実に効く。一方、CLAUDE.md に「フォーマットを整えてください」と書くのは助言的だ。AI が従うかどうかは確率的で、コンテキストの状態に依存する。
だから、確実に守らせたいルールは hook にする。CLAUDE.md には、hook では表現できない判断基準——タスクの粒度、セッションの分け方、迷ったときのフォールバック——を書く。
もう1つ、効かないルールは定期的に削除する。CLAUDE.md が長くなるほど、各ルールが受け取るコンテキストの「注意力」が薄まる。10個のルールより5個のルールのほうが、各ルールの遵守率が高い。これもコンテキスト管理の一環だ。
まとめ: コンテキストは注意力に似ている
1セッション1タスクの原則は、突き詰めると「コンテキストウィンドウは注意力に似ている」という洞察に基づいている。
人間も、長時間集中すると精度が下がる。複数のタスクを同時にやると、どちらも中途半端になる。前の仕事の疲れが次の仕事に影響する。休憩を挟むと回復する。
AI のコンテキストウィンドウも同じだ。長いセッションは精度を下げる。複数タスクの混在はコンテキストを汚染する。前のタスクの情報が新しいタスクを歪める。/clear でリセットすると回復する。
この類似性に気づいたとき、AI との協働の仕方が根本的に変わった。AI を「疲れ知らずの万能ツール」として扱うのをやめて、「集中力に限りがある優秀な協力者」として扱うようになった。
優秀な協力者に仕事を頼むなら、タスクを明確にし、スコープを絞り、必要な情報だけを渡す。「全部やって」ではなく「これだけやって」と言う。1つ終わったら次を頼む。
この原則は、AI に限った話ではない。人間のチーム開発でも、1つのプルリクエストに複数の関心事を混ぜないのは基本だ。コードレビューの精度が落ちるからだ。AI との協働も同じ原則に従う。
211コンポーネントを開発してきた経験から言えるのは、生産性のボトルネックはコンテキストの管理にあるということだ。プロンプトの巧みさでも、モデルの性能でもない。有限のコンテキストウィンドウをいかに効率的に使うか。それが、AI を使った開発の最も実践的な課題であり、1セッション1タスクはその最もシンプルな答えだ。