10万行を超えるモノレポで Claude Code を使い始めて3週間、私が一番時間を奪われたのはバグでも仕様変更でもなく「セッションが重たくなる現象」でした。最初の1〜2タスクは快調なのに、機能横断のリファクタリングを始めた途端にレスポンスが遅くなり、ある段階で /compact を促す警告が出てそれまでの推論コンテキストが圧縮される。圧縮後はファイルパスを覚え直すために何度も Glob と Read を発火させて、結果として課金もレイテンシも倍増する、という流れです。
公式ドキュメントには「200K トークンまで使えます」と書かれていますが、現場の体感では 80〜100K あたりから挙動が変わり始めます。本記事は、そうした「公式の数字と実運用のギャップ」を埋めるために、私が複数プロジェクトで試行錯誤してたどり着いた7つのパターンをまとめたものです。理論よりも、明日からそのまま使える運用ルールとスクリプトを優先しました。
なぜ Context Window は「広く取れば良い」だけではないのか
Anthropic の Claude Sonnet 4.6 は 200K トークン、同時期にリリースされた Opus 系統では 500K トークンの拡張版が用意されています。数字だけ見ると余裕がありそうですが、実運用では次の3つが同時に効いてきます。
ひとつ目は Attention のコスト 。同じプロンプトでも、入力トークンが増えるほど内部での参照処理が重くなり、応答時間とコストの双方が伸びます。私の手元計測では、入力 60K のときに比べて 150K では平均応答時間が 1.7 倍、課金額は 2.5 倍になりました。
ふたつ目は キャッシュ境界の崩壊 。Claude のプロンプトキャッシュ(5分/1時間)はプレフィックス一致が崩れた瞬間に無効化されます。ファイルの読み直しが頻発すると、同じ会話の中でもキャッシュヒット率が大きく低下し、コスト効率が崩れます。
みっつ目は 思考の濁り 。これは数字に出にくい部分ですが、関連性の薄いコンテキストが大量に積まれると、生成される修正パッチの方針がぶれることが増えます。「該当箇所だけ直してほしい」と頼んでも、無関係なファイルにまで波及する修正が返ってくる経験は、誰しもあるのではないでしょうか。
つまり Context Window の運用は 「上限まで使い切る」ゲームではなく「いま必要な分だけ載せる」ゲーム なのです。これを徹底するための7つのパターンを順に紹介します。
パターン1: セッション開始時に「タスクスコープ」を明示する
最初の発話で扱う範囲を限定するだけで、Claude Code が自動的に読み込むファイル数が大きく減ります。私が定型化しているのは、次の4行のテンプレートです。
このセッションのスコープ:
- 対象ディレクトリ: src/payments/ のみ
- 触らないファイル: src/auth/, tests/legacy/
- 完了条件: stripe webhook の冪等性テストが緑になること
- 想定セッション長: 30分以内
スコープを言語化しておくと、Claude Code 側の自動探索が「想定セッション長」と「完了条件」を意識した動きに切り替わります。特に Glob と Grep の発火回数が体感で 3 割ほど減り、初動の Context 膨張を防げます。
ここで効くのは、禁止リストを必ず添える ことです。「触らないファイル」を明示すると、依存解析中に意図せず関連ファイルを開く挙動が抑えられます。「あのモジュールも見てくれて気が利く」と思える挙動が、長い目で見ると Context を破壊する主犯であることは多いです。
パターン2: 計測スクリプトでトークン消費を可視化する
体感に頼ると、対策の優先順位を見誤ります。私はセッション中、別ターミナルで以下のスクリプトを走らせて、~/.claude/sessions/ 配下の最新ファイルからトークン消費を5秒ごとに表示しています。
#!/usr/bin/env bash
# claude-context-watch.sh — 現在のセッションの累計トークンを監視
set -euo pipefail
SESSION_DIR = "${ HOME }/.claude/sessions"
THRESHOLD_WARN = "${ THRESHOLD_WARN :- 120000 }"
THRESHOLD_DANGER = "${ THRESHOLD_DANGER :- 160000 }"
while true ; do
latest = $( ls -t "${ SESSION_DIR }"/ * .jsonl 2> /dev/null | head -1 )
if [[ -z "${ latest }" ]]; then
echo "$( date +%H:%M:%S) セッションファイルが見つかりません" >&2
sleep 5
continue
fi
# 最後の usage レコードから input/output を抽出
read -r in_tok out_tok < <(
tac "${ latest }" \
| grep -m1 '"usage"' \
| python3 -c '
import json, sys
line = sys.stdin.read()
try:
data = json.loads(line)
usage = data.get("usage", {})
print(usage.get("input_tokens", 0), usage.get("output_tokens", 0))
except Exception:
print(0, 0)
'
)
total = $(( in_tok + out_tok ))
ts = $( date +%H:%M:%S )
if (( total >= THRESHOLD_DANGER )); then
printf "\033[31m[%s] 危険: %d tok (in=%d out=%d) — /compact 推奨\033[0m\n" \
"${ ts }" "${ total }" "${ in_tok }" "${ out_tok }"
elif (( total >= THRESHOLD_WARN )); then
printf "\033[33m[%s] 警告: %d tok (in=%d out=%d)\033[0m\n" \
"${ ts }" "${ total }" "${ in_tok }" "${ out_tok }"
else
printf "[%s] OK: %d tok (in=%d out=%d)\n" \
"${ ts }" "${ total }" "${ in_tok }" "${ out_tok }"
fi
sleep 5
done
このスクリプトを動かしておくと、「気がついたら 180K に到達していた」という事故が起きなくなります。閾値はプロジェクトに合わせて調整してください。私の場合は警告 120K、危険 160K で、危険値に達したら無条件に /compact を打つルールにしています。
ポイントは、自動 /compact ではなく自分の意思で打つ ことです。自動圧縮は推論の途中で発動すると、文脈の重要部分が削れてしまうことがあります。閾値を可視化しておけば、キリのよいタスク区切りで意図的に圧縮できます。
パターン3: /compact の前に「要約サマリ」を自分で渡す
/compact だけに任せると、Claude Code は会話履歴を独自の判断で要約します。便利ではあるのですが、開発の文脈では「次に何をやるか」が落ちやすい傾向があります。私は圧縮の直前に、次のような要約を自分で投げてから /compact を呼びます。
ここまでのまとめ:
- 完了: stripe webhook の署名検証, 冪等性テスト3件
- 未完了: dispute イベントのハンドラ実装, retry ロジック
- 重要な決定: 冪等キーは event.id をそのまま使う方針
- 触ったファイル: src/payments/webhook.ts, src/payments/idempotency.ts
次のアクション: dispute ハンドラの雛形作成 → 単体テスト追加
このサマリ自体が Context として残るため、圧縮後にも「何をやっていたか」が確実に維持されます。経験的に、この一手間があるかないかで圧縮後の生産性は3割ほど変わります。
長期セッションでの文脈維持については、過去にまとめたClaude Code 長時間セッションのコンテキスト維持術 も参考になります。
パターン4: サブエージェントで「読むファイル」を物理的に隔離する
Claude Code のカスタムサブエージェント機能を使うと、特定タスクの実行を別の Context Window に隔離できます。これは Context 管理の決定打のひとつです。
例えばテスト実行とログ解析だけを担当させるエージェントを ~/.claude/agents/test-runner.md に定義します。
---
name : test-runner
description : 単体テストの実行とログ解析だけを行う。実装には触らない。
allowed-tools : Bash, Read, Grep
---
あなたはテスト実行係です。次のルールを厳守してください。
1. ユーザーから渡されたコマンドのみを実行する
2. 失敗ログは「失敗テスト名・エラー要約・該当行番号」の3点だけを報告する
3. 修正提案やコード生成は一切行わない(メインエージェントの仕事です)
4. 1メッセージあたり最大 200 文字で回答する
メインエージェント側で @test-runner npm test を実行してログを要約 のように呼ぶと、テスト出力という巨大なテキストブロックがメインの Context に流入しなくなります。失敗時の要約だけが返ってくるため、メイン Context は10倍くらい長持ちします。
ここで気をつけたいのは 権限の最小化 。allowed-tools を絞らないと、サブエージェントが勝手に実装まで始めて Context を巻き戻すことがあります。サブエージェント設計のより詳しい話はClaude Code サブエージェント・オーケストレーション実践 にまとめています。
パターン5: MCP サーバーの「常時接続を疑う」
MCP は便利ですが、接続するだけで起動時のシステムプロンプトに各サーバーの説明が積まれます。私の手元の計測では、MCP サーバーを5つ常時接続している状態で、初期 Context が 12K トークン増えていました。これは無視できない数字です。
MCP の選択的接続は ~/.claude/mcp.json で設定できますが、現実的な運用としては プロジェクトごとに必要なものだけを enabled にし、残りは disabled にしておくのが効きます。具体的には次のような分類が有効でした。
全プロジェクト常時オン: ファイルシステム、git
リサーチタスクのみ: web検索、ブラウザ自動化
データ系タスクのみ: 各種 DB、Notion、Slack
私は週初めに「今週の主タスク」を決めて MCP の enabled フラグを更新する運用にしています。たかが 12K と思いがちですが、200K の Context Window で 12K は 6% に相当し、これがすべてのターンで足し算される影響は思ったより大きいです。
パターン6: ファイル読み込みは「分割 + 部分指定」を徹底する
Read ツールは行範囲を指定できます。しかし習慣として全体を読み込みがちで、これが Context 膨張の温床になります。次のような明示的な指示を出すクセをつけると効きます。
src/payments/webhook.ts は 100 行目から 180 行目だけを読んでください。
全体構造を把握する必要があれば、最初に grep で関数定義一覧だけ取ってから判断してください。
特に1ファイルが2,000 行を超える場合、フル読み込みはほぼ常に過剰です。次のような Bash ワンライナーをセッション初期に走らせて、対象ファイルの「見出し」だけを Claude に渡す手もあります。
# ファイルの関数定義一覧だけを抽出(TypeScript 想定)
rg -n '^(export\s+)?(async\s+)?(function|const|class)\s+\w+' \
src/payments/webhook.ts \
--max-columns 200
その出力を貼り付けて「この中でどの関数を読むべきか提案して」と聞けば、Claude は自律的に読む範囲を絞ってくれます。「全体を読まなくても判断できる材料を先に渡す」のが Context 節約の本質です。
パターン7: セッションを「短く・濃く」回す
最後のパターンは技術というより運用文化の話です。1セッションでやることを意図的に小さくし、終わったら速やかに新しいセッションを立ち上げる。これが結局のところ実用的の Context 管理術でした。
私の現在のルールは次のとおりです。
1セッション = 1つの PR を生むまで
1セッションの上限時間 = 90分
終了時に必ず「セッションサマリ」を docs/sessions/YYYY-MM-DD-HHMM.md に保存
セッションサマリは次のテンプレートを使っています。
# Session: 2026-04-27 10:30 — Stripe Webhook Idempotency
## 達成
- 冪等性テスト 3件 緑化
- event.id を冪等キーに採用
## 未達
- dispute ハンドラの実装
## 次セッションの開始プロンプト
「stripe webhook の dispute ハンドラを src/payments/dispute.ts に実装してください。
冪等性は既存の idempotency.ts を使ってください。テストは tests/payments/dispute.test.ts に追加してください。」
サマリを保存しておくと、次のセッションは「このサマリを読んでから始めて」と渡すだけで、最小コンテキストでフルスピードに復帰できます。長く繋いで使うより、短く切って繋ぎ直すほうが、結果としてトータルコストは下がります。
よくある間違いと回避策
実プロジェクトで何度も見てきた失敗パターンを3つ挙げます。
間違い1: 「とりあえず関連ファイルを全部開いて」と頼む
これは初動でやりがちな最悪パターンです。Claude Code はディレクトリ構造から関連を推測して、本来不要なファイルまで Read します。20ファイル × 平均 300 行 ≈ 6,000 行 ≈ 30K トークンが一瞬で消費される計算です。代わりに「この PR の差分から、修正が必要な3ファイルを特定してください」のように、まず候補を絞らせる依頼にしましょう。
間違い2: /clear ではなく /compact を多用する
/clear は会話履歴を完全に消し、/compact は要約を残します。新しいタスクに移るときは /clear のほうが Context は綺麗になりますが、「前のタスクの教訓を引き継ぎたい」という心理から /compact を選びがちです。結果として、もう不要な情報がじわじわ残り続けて、長時間セッションが Context 圧迫の温床になります。タスクが完全に切り替わるなら /clear を選ぶ勇気を持ちましょう。
間違い3: 大きな出力をそのまま会話に貼る
ログファイル、SQL の結果、JSON のレスポンス。これらをそのままチャットに貼ると、5,000〜20,000 トークンが一瞬で消費されます。代わりに head -100、tail -100、jq '.[] | select(.status=="error")' などで切り出してから渡すのが鉄則です。Auto Compaction が暴発する原因のほとんどは、巨大ペーストです。Auto Compaction の挙動についてはClaude Code の /clear と /compact 使い分け もあわせてどうぞ。
週単位での Context 監査ルーチン
個人開発でもチーム開発でも、週初めに 15 分だけ「Context 監査」の時間を取ると効きます。私が運用しているチェック項目を共有します。
先週の長時間セッションのトップ3をレビュー(どこで膨張したかを特定)
不要になった MCP を disabled に戻す
スコープテンプレートの「禁止リスト」を更新
セッションサマリのテンプレートに不足項目がないか確認
~/.claude/sessions/ 配下の古いセッションログをアーカイブ
このルーチンを1ヶ月続けると、平均セッション長は確実に短くなり、応答速度も改善します。チームで運用する場合は、サマリのフォーマットを共通化しておくと、別の開発者がそのまま続きを引き継げるという副次効果もあります。
Claude Code を本番ワークフローに組み込む話は、私のClaude Code 失敗ファースト運用パターン でもまとめていますので、本記事と組み合わせて読んでいただくと運用の輪郭が掴みやすいかと思います。
仕上げに — 今週から始める一歩
ここまで7つのパターンを紹介しましたが、全部を一度に取り入れる必要はありません。今日この瞬間から始めるなら、パターン2の計測スクリプトを動かす のが最も投資対効果が高いです。可視化してしまえば「次に何を直すべきか」が自然に見えてきます。
数字で振り返ると、この7パターンを言語化してから3ヶ月で、私の平均セッション長は73分から38分へ、1セッションあたりの平均トークン消費は145Kから71Kまで下がりました。週あたりに出すPRの本数は変わっていません。作業量を減らしたのではなく、同じ仕事をより少ないコンテキストでこなせるようになっただけです。数週間にまたがる長期プロジェクトが、3週目あたりで「エージェントのお守りをしながら祈る」状態へ崩れていた以前と違い、いまは現実的に走り切れる。静かにそう実感しています。 Dolice Labs として複数のサイトとアプリを個人開発で並行運用している私自身、このルーチンがなければ数週間級のプロジェクトは支えきれなかったと感じています。
このサイトは個人で運営しており、サーバー費用と検証用 API 費用を読者の皆さまの応援で賄っています。広告は一切置いていません。本記事が Claude Code セッションを快適にする助けになりましたら、記事末尾のチップやメンバーシップでご支援いただけると次の検証記事の燃料になります。最後までお読みいただき、ありがとうございました。