はじめに
LLM エージェント(Claude Code, OpenCode など)を使い込むと、すぐにコンテキスト問題に直面する。ファイル読み込み、ツール出力、ログ検索、git diff — 全部が context window を圧迫し、30 分も作業すると 4 割前後がツール出力で埋まる。
この問題に対して、レイヤーの異なる 2つのアプローチがある:
- Headroom — LLM に送る情報(会話履歴・tool 出力・RAG)を送信直前に圧縮(API トランスポート層)
- Context Mode — ツール出力をローカル処理して、そもそもトランスクリプトに入れない(エージェント/hook 層)
この記事では、2つのツールの設計思想の違い、実装レベルでの違い、そして組み合わせるときの実践的な手順を整理する。
まず:Claude Code のようなエージェントはどう動くのか
後で出てくる図を読むには、Claude Code のような「LLM エージェント」がどう動くかを先に押さえる必要がある。ここだけは前提知識として、できるだけかみ砕いて説明する。
ポイントは1つ。LLM(AI の本体)は、前の会話を覚えていない。だから毎回、「これまでの会話ぜんぶ」をもう一度まとめて渡してあげないと話が通じない。
たとえるなら、LLM は記憶力がゼロの天才だ。とても賢いが、1回答えるたびに記憶がリセットされる。だから話しかけるたびに、これまでのやりとりを書いたノートを丸ごと最初から読ませるしかない。エージェント(Claude Code)は、その「ノートを毎回渡す」係だと思えばいい。
動きを番号付きで追うとこうなる。
① あなたが指示する(例:「このログのエラー原因を調べて」)
↓
② これまでの会話を“ぜんぶ”まとめて LLM に送る ← 「送信」の瞬間
↓
③ LLM が答えを返す or「道具を使いたい」と言う
↓
④ 道具(ツール)を実行する
(ファイルを読む / コマンドを走らせる / 検索する)
↓
⑤ 道具の出力が“ノート(会話)”に追記される ← ここがどんどん膨らむ
↓
(②に戻ってくり返す)
ここで2つの言葉を覚えておく。
- コンテキスト(ノート):②で毎回送る「これまでの会話ぜんぶ」。LLM の作業机のようなもの。
- コンテキストウィンドウ:その机の広さ(=1回に送れる上限)。無限ではない。
問題は ⑤ だ。kubectl logs やコード検索のように、道具の出力が巨大だと、それがそのままノートに貼り付けられて机を埋めていく。机が埋まれば、本来の作業に使えるスペースが減る。「30 分で 4 割がツール出力」というのは、この⑤がたまり続けた結果だ。
ここまで分かると、この記事の2ツールはこの図のどこに割り込むかの違いだと一言で言える。
- Context Mode … ④〜⑤に割り込む。道具の出力が巨大なら、そもそもノートに貼らずに要約だけ残す。
- Headroom … ②の直前に割り込む。送る瞬間に、ノート全体をぎゅっと圧縮してから渡す。
以降の各ツールの「タイミング」は、この①〜⑤の番号を指していると思って読んでほしい。
1. ツール概要と比較テーブル
Headroom(chopratejas/headroom)
何か:LLM エージェント向けのコンテキスト圧縮エンジン
動作原理:
messages → ContentRouter →
├─ JSON → SmartCrusher (50-90% reduction)
├─ Code → CodeCompressor (AST解析, 40-70%)
└─ Text → Kompress-base (ML model, 30-80%)
↓
CacheAligner (prefix stabilization)
↓
CCR reversible layer (originals in SQLite)
↓
LLM
主な特徴:
- タイミング:②の直前(LLM送信直前 / post-execution)
- 圧縮単位:メッセージシーケンス全体
- デプロイ方法:Proxy, Library, MCP, CLI wrap
- 復元性:CCR で完全復元可能(SQLite TTL 付き)
- 可用性:言語・プラットフォーム非依存
CCR / SQLite TTL とは:Headroom の圧縮は原文を「捨てる」のではなく「畳んで隠す」方式だ。削った原文はローカルの SQLite に退避し、本文側にはプレースホルダだけを残す。この原文を退避して後から巻き戻せる可逆レイヤーが CCR(図の "CCR reversible layer")で、必要になればプレースホルダから原文をそのまま復元できる(lossless)。退避した原文には **TTL(Time To Live=保持期限)**が付いていて、一定時間で自動的に消える。これにより「あとから完全復元できる」一方で、SQLite が無限に肥大化しないようにしている。
(注:本記事では "CCR" を可逆レイヤーの呼称として扱う。正式な略称の展開は未確認なので、公開前に Headroom の README で確認のこと。)
実績:
| 場面 | 圧縮率 |
| Code search (100結果) | 92% |
| SRE incident debugging | 92% |
| GitHub issue triage | 73% |
| Codebase exploration | 47% |
Context Mode(mksglu/context-mode)
何か:Claude Code プラグイン + MCP サーバ。ツール出力の自動ルーティングと session tracking
動作原理:
tool call
↓
[PreToolUse hook]
↓
raw output ← tool execution
↓
[PostToolUse hook] 判定:
├─ small → context に
├─ large → ctx_execute で処理
│ ↓
│ script 実行
│ ↓
│ ctx_index (FTS5)
│ ↓
│ summary だけ context に
│
└─ compacting → FTS5 search で復元
主な特徴:
- タイミング:④〜⑤(ツール呼び出しの前後。hook で routing を強制 + イベント記録)
- 処理単位:ツール単位のローカルスクリプト実行("think in code")
- デプロイ方法:Claude Code plugin / OpenCode plugin など hook 対応エージェント + MCP
- 復元性:FTS5 BM25 検索で復元(キーワードベース)
- 可用性:16 プラットフォーム対応(Claude Code, OpenCode, Gemini CLI, Cursor など)
注意:Context Mode は Headroom のように「出力されたバイト列を透過的に圧縮する」のではない。hook が raw な Bash/Read/WebFetch を抑制してモデルに ctx_execute(スクリプト実行)を 書かせる よう仕向け、結果のサマリーだけを context に入れる。つまり「モデルの振る舞いを変える」アプローチである。
実績(README より):
| 場面 | 削減 |
| Playwright snapshot | 56 KB を context に入れない |
| GitHub Issues 20件 | 59 KB → 集計サマリーのみ |
| session 全体 | 315 KB → 5.4 KB(98%) |
| "think in code" 例 | 47×Read (700 KB) → 1×ctx_execute (3.6 KB) |
| OpenCode セッション | ~98% saved(README 計測値) |
比較テーブル
| 項目 | Headroom | Context Mode |
| 圧縮対象 | 既にcontextにある情報全体 | tool出力(contextに入る前) |
| 圧縮アルゴリズム | ML model (Kompress-v2) + AST | 決定的なスクリプト実行 |
| 復元方法 | CCR tool で完全復元 | FTS5 search でキーワード検索 |
| 依存性 | MCP 不要(Proxy/Library で可) | hooks が必要(自動化のため) |
| 使用対象 | 全LLM API (Anthropic/OpenAI/Bedrock) | hook 対応エージェント 16種 (Claude Code / OpenCode 等) |
| output削減 | Verbosity steering + Effort routing | — (prose-style は強制しない方針) |
| Session memory | Cross-agent memory | SQLite + hooks tracking |
| 設定難易度 | 低(headroom wrap 一発 or Proxy起動) | 低(plugin install) |
| 圧縮率 | 47-92% (場面依存) | ~98% (raw tool出力が大きい場合) |
圧縮率は測定対象が異なるため直接比較できない。Headroom は「送信リクエスト全体のトークン削減率」、Context Mode は「raw tool 出力を context に入れないことによる削減率」を指す。レイヤーが違うので、後述の通り組み合わせると相補的に効く。
どちらをいつ使うか
Headroom が向いている場面:
- 複数ツール間で context を共有する必要がある
- API response が JSON で深い(SmartCrusher 向き)
- Code review や long diff を読ませたい
- 複数のLLM provider を使い分けたい
Context Mode が向いている場面:
rg --json, kubectl logs, git log など raw 出力が巨大
- 同じ調査・デバッグを何度も繰り返したくない
- session 中に「最後の編集ファイル」を自動検索したい
- Claude Code での日常作業
両方組み合わせるべき場面:
- 長期 debugging session(Context Mode で即座に削減 + session 記憶)
- Conversation compacting 後の resume(Context Mode で FTS5 検索 + Headroom で再圧縮)
- multi-agent 運用(Headroom で cross-agent memory + Context Mode で Claude Code local routing)
2. 実践的な実装手順
2.1 Claude Code での Context Mode セットアップ
前提条件:Claude Code v1.0.33+
手順:
# 1. Plugin install
/plugin marketplace add mksglu/context-mode
/plugin install context-mode@context-mode
# 2. Reload
/reload-plugins
# 3. Verify
/context-mode:ctx-doctor
# ✅ RuntimeCheck, HooksCheck, FTS5Check all pass
自動的に有効になること(plugin が 4 hook を登録):
SessionStart hook:routing 指示を runtime で注入(プロジェクトにファイルは書かない)
PreToolUse hook:raw な tool 呼び出しを routing(ctx_* へ誘導)
PostToolUse hook:実行結果(編集・git・error・決定)を session DB に記録
PreCompact hook:Compacting 直前に FTS5 へ index 化して resume 用 snapshot を準備
- 11 個の MCP tools:6 sandbox(
ctx_execute, ctx_search, ctx_index など)+ 5 meta(ctx_stats, ctx_doctor など)
設定ファイル(optional):
{
"statusLine": {
"type": "command",
"command": "context-mode statusline"
}
}
2.2 OpenCode での Context Mode セットアップ
OpenCode は TypeScript プラグイン方式に対応している。Claude Code のような /plugin マーケットプレイスではなく、opencode.json に plugin を登録する。
前提条件:Node.js >= 22.5(または Bun), OpenCode installed
手順:
# 1. opencode.json に追記
# (プロジェクト直下、またはグローバルは ~/.config/opencode/opencode.json)
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["context-mode"]
}
この plugin エントリだけで、11 個の ctx_* tool が in-process で登録され、hook が有効になる(OpenCode が context-mode の TS プラグインを直接呼ぶので、stdio MCP の子プロセスは立たない)。
# 2. (任意) routing rules ファイルをコピー
# モデルがどの tool を使うべきか・どのコマンドがブロックされるかを認識する
cp node_modules/context-mode/configs/opencode/AGENTS.md AGENTS.md
# 3. OpenCode を再起動
# 4. Verify — セッション内で `ctx stats` と入力
注意点:
- OpenCode には本物の
SessionStart hook が無い(sst/opencode#14808)。プラグインは experimental.chat.system.transform を代替として使い、routing block と前回セッションの snapshot を system prompt に注入する。
- routing 強制は
tool.execute.before / tool.execute.after で行われる。
- 既存 config に
plugin: ["context-mode"] と mcp.context-mode の両方があると ctx_* tool が 0 個になる。context-mode upgrade で legacy MCP エントリを削除する。
2.3 Headroom の設定
Headroom は API のリクエストを透過的に圧縮するプロキシとして動く。ルーティングは HTTP プロキシ(http_proxy)ではなく、ANTHROPIC_BASE_URL / OPENAI_BASE_URL をローカルプロキシに向ける方式である点に注意。
前提条件:uv。以下のいずれの方法でも、まず Headroom 本体を入れておく。
uv tool install "headroom-ai[all]"
# → headroom コマンドが PATH に入る
# インストール確認: headroom --version
方法D(Library)でプロジェクトに直接組み込む場合は、ツールではなく依存として uv add "headroom-ai[all]" を使う。
以降の方法A〜Dは、この headroom が入っている前提で進める。
方法A:Claude Code を wrap(最も簡単)
# wrap で起動(proxy 起動 + ANTHROPIC_BASE_URL 設定を自動でやる)
headroom wrap claude
# → 内部で `ANTHROPIC_BASE_URL=http://127.0.0.1:8787` 相当を設定し Claude Code を起動
headroom wrap の対応エージェント:claude, codex, cursor, aider, copilot, gemini。
方法B:Proxy を手動起動して任意のエージェントを向ける
# 1. Proxy 起動
headroom proxy --port 8787
# 2. エージェント側で provider の base URL をプロキシに向ける
# Claude Code を手動で向ける場合:
export ANTHROPIC_BASE_URL=http://127.0.0.1:8787
OpenCode は headroom wrap の対応リストに無い。OpenCode は OpenAI 互換クライアントなので、headroom proxy を立てて OpenCode の provider 設定(opencode.json の provider baseURL)をプロキシに向ける方式になる。この経路は本記事の検証対象(シナリオ参照)— 正確な設定は検証後に追記する。
方法C:MCP(Claude Code 向け)
headroom mcp install
# → Claude Code 再起動で headroom_compress / headroom_retrieve / headroom_stats が使える
方法D:Library(Python/TypeScript apps に直接組み込み)
from headroom import compress
messages = [...]
compressed = compress(messages, model="claude-sonnet-4-6")
# → 圧縮後のメッセージを Anthropic SDK に送信
2.4 組み合わせ運用(Context Mode + Headroom)
シナリオ:大規模コードベース調査
┌─ Codebase scanning task
│
├─ [Claude Code / OpenCode]
│ └─ User: "Find all uses of API X in the codebase"
│
├─ [Context Mode PreToolUse hook]
│ └─ Detects: rg --json output (5MB)
│ └─ Routes: ctx_execute で filter script に
│ ↓
│ (JavaScript)
│ const results = JSON.parse(input)
│ .filter(r => r.path.includes('src'))
│ .slice(0, 50) // Top 50 only
│ console.log(`${results.length} matches found`)
│ results.forEach(r => console.log(`${r.path}:${r.line}`))
│ ↓
│ Output: 2.4 KB
│
├─ [ctx_index hook]
│ └─ FTS5に索引化(full results も保存)
│
├─ [次ターン送信前: Headroom proxy が request を圧縮]
│ └─ 圧縮対象は「送信リクエスト=これまでの会話履歴+残った tool 出力」
│ └─ SmartCrusher: JSON を 50-90% / CodeCompressor: AST を 40-70%
│ └─ CacheAligner: provider KV cache のヒット率向上
│
└─ [Output token reduction (optional, HEADROOM_OUTPUT_SHAPER=1)]
└─ Verbosity steering / Effort routing でモデルの「書き戻し」を削減
結果(2つは別レイヤーなので相補的):
- context に入る raw 量: Context Mode が削減(2.4 KB に)
- 送信リクエストのトークン: Headroom がさらに圧縮
- 出力トークン: Headroom output shaper が削減
- Session DB: full results は FTS5 に indexed(ctx_search で後から復元)
ポイント:Context Mode はトランスクリプトに入る情報を減らし、Headroom は API へ送る/返るバイト列を圧縮する。動作レイヤーが違うため二重圧縮にならず、片方が削り残した分をもう片方が拾う。ただし両者とも "think in code" 的な思想を持ち、Headroom は内部で RTK(shell 出力書き換え)を同梱するため、シェル出力まわりは役割が一部重なる。
実装手順:
-
Context Mode 起動(Claude Code plugin)
/context-mode:ctx-stats # 確認
-
Task 実行
User: "Find all imports of ./utils in this repo"
Claude Code (自動的に):
→ $ rg --json "import.*utils" src/
Context Mode (自動):
→ PreToolUse: 出力サイズ > threshold → ctx_execute へ
→ ctx_execute で集計スクリプト実行
→ 結果 (2.3 KB) + indexed summary
-
Compaction 後の resume
Context Mode (自動):
→ PreCompact hook: FTS5 index を最新化
User: "中断した調査を続けて"
Claude Code:
→ ctx_search("utils imports") で過去の結果を検索
→ Session DB から前回の編集ファイル等を復元
-
Headroom での最終圧縮(optional)
# Context Mode plugin を有効にしたまま、Claude Code を Headroom 経由で起動
headroom wrap claude
# → ANTHROPIC_BASE_URL がプロキシに向き、送信リクエストが圧縮される
# Context Mode の hook/MCP はそのまま動く(レイヤーが違うため共存可能)
共存時の注意:両方とも RTK/shell 出力の取り扱いに触れるため、headroom wrap 側の HEADROOM_CONTEXT_TOOL と Context Mode の routing が二重に効いていないか、/context-mode:ctx-stats と headroom perf の両方で実測して確認すること(検証シナリオ参照)。
まとめ(現時点)
ここまでを整理すると、2つのツールは競合ではなく別レイヤーで効く補完関係だ。
- Context Mode は「そもそも context に入れない」。tool 出力が巨大なとき(
rg --json, kubectl logs, CI ログなど)に直撃で効く。plugin を入れるだけで動き、Claude Code の日常作業で一番手軽。
- Headroom は「送信直前に圧縮する」。会話履歴も残った tool 出力もまとめて削るので、Context Mode が削り残した分を拾える。
headroom wrap claude で両立する。
- 迷ったら まず Context Mode、効果が頭打ちになったら Headroom を被せる、という順番が分かりやすい。
一方で、本文中の数値(圧縮率・対応プラットフォーム数・ツール数・バージョン要件など)は、どちらのツールも更新が速く変わりやすい。公開前に各 README で最新の値を確認してほしい。
次章には、これらを実際に自分の環境で測るための検証シナリオを置いておく。数値は追って追記する。
3. 動作検証シナリオ(後で試験・更新用)
以下のシナリオで、実際の context 削減量を測定する。結果は追って本記事に追記する。
シナリオ 1:Kubernetes ログ調査(Context Mode メイン)
目的:kubectl logs が大きい場合、Context Mode がどこまで削減できるか
検証環境:
cluster: 任意の Kubernetes 環境(local k3d でも OK)
pod: エラーが頻出している pod(CrashLoopBackOff 推奨)
テスト手順:
-
Raw log サイズを記録
kubectl logs pod-name > /tmp/raw.log
wc -c /tmp/raw.log # Size in bytes
-
Claude Code で Context Mode 経由で分析
User: "このpodのログを分析して、エラーパターンを教えて"
Claude Code (自動):
→ $ kubectl logs pod-name
# Context Mode が自動 intercept
-
削減前後を比較
/context-mode:ctx-stats
# per-tool breakdown, tokens consumed, savings ratio を記録
期待される結果:
- Raw log:5-50 MB
- Context に入る情報:< 5 KB
- 削減率:96-98%
- Session DB に indexed
記録すべき数値:
シナリオ 2:Codebase 検索 (Context Mode + Headroom)
目的:大型 codebase を検索するときに、Context Mode と Headroom が組み合わさるとどこまで削減できるか
検証環境:
repo: 自分のプロジェクト(50+ files, 10k+ lines)
search: 特定の API / function の全呼び出し箇所
テスト手順:
-
検索を実行(両方 OFF / ベースライン)
# Context Mode plugin を外し、Headroom も経由しない素の Claude Code
/plugin disable context-mode
# ANTHROPIC_BASE_URL を設定せず、`headroom wrap` も使わずに起動
User: "FunctionX を使っているすべてのファイルを見つけて"
記録:
-
Context Mode のみ ON
# Context Mode plugin は有効のまま
# 同じ質問を繰り返す(session を reset)
User: "[別の会話で] FunctionY を使っているすべてのファイルを見つけて"
記録:
-
Context Mode + Headroom proxy ON
# Context Mode plugin を再有効化した上で、Headroom 経由で起動
/plugin enable context-mode
headroom wrap claude # ANTHROPIC_BASE_URL がプロキシに向く
User: "[別の会話で] FunctionZ を使っているすべてのファイルを見つけて"
記録:
期待される結果:
| 項目 | OFF | Context Mode | + Headroom |
| Tool calls | N | N (削減) | N (削減) |
| Input tokens | X | 0.3X | 0.15X |
| Output tokens | Y | Y | 0.7Y |
| Session DB | ❌ | ✅ | ✅ |
記録すべき数値:
シナリオ 3:CI ログ(複数 job)の原因抽出
目的:複雑な CI ログセットを、Context Mode で効率化できるか
検証環境:
CI: GitHub Actions / GitLab CI
build: 失敗している複数 job のログセット(30-300MB 総量)
テスト手順:
-
全 job log を fetch
# GitHub Actions なら
gh run download <run-id> --dir /tmp/logs
du -sh /tmp/logs # Total size
-
Claude Code で分析(Context Mode OFF)
# Context Mode を一時的に無効化(plugin を外す or 別プロファイルで起動)
# ※ HEADROOM_CONTEXT_TOOL は Headroom 側の CLI ツール選択変数であり
# Context Mode の ON/OFF とは無関係なので使わないこと
/plugin disable context-mode # ベースライン計測用
User: "このCI runの失敗原因を分析して"
# Claude Code が各ログを生で read(ベースライン)
記録:
-
Context Mode ON で再実行
# session reset
User: "このCI runの失敗原因を分析して"
# Context Mode が自動 filtering
記録:
期待される結果:
- Raw logs:30-300 MB
- Context に入る summary:< 10 KB
- Tool calls:10+ → 2-3 に削減
- Analysis 時間:短縮(ctx_search が高速)
- 精度:変わらない(summary に問題の root cause は含まれているはず)
記録すべき数値:
検証後の更新ポイント
試験後、以下を記事に追記してください: