Claude Code compact nettop コンテキスト管理 トークン消費 ネットワーク

Claude Codeで作業していると回線全体が重くなる。以前から何度か起きていて、セッションをcompactしたら改善した経験はあったが、原因を特定しないままだった。今回、macOSのnettopでプロセス別の通信量を実測して原因を突き止めた。犯人は「画像で34MBに膨張したセッション」で、ターン実行中にリクエストごとコンテキスト全体を再アップロードしていた。この記事では、実測の手順と実際の数字、compactの効果測定、事前にできる対策までを書く。

まず疑ったのは「開きっぱなしの大量セッション」だった

私の環境ではClaude Codeのセッションを常時12個ほど起動している(PhpStormのターミナル内が大半、一部VS Code)。まずはこれを疑って、プロセス別の通信量を実測した。

nettop -P -x -d -L 7 | grep claude.exe | awk -F',' '{cnt[$2]++; if (cnt[$2]>1) {i[$2]+=$5; o[$2]+=$6}} END {for (p in i) printf "%-22s in: %8.1f KB/s  out: %8.1f KB/s\n", p, i[p]/6/1024, o[p]/6/1024}'

結果は意外で、アイドル状態のセッションは12個全部が通信量ほぼゼロだった。開いているだけのセッションは何個あっても帯域を食わない。

ひとつ注意点がある。nettopのデルタモード(-d)は、各プロセスの最初のサンプルだけ「プロセス起動以来の累積値」を返す。最初のサンプルを含めて集計すると、アイドルのセッションが通信中に見える。実際、最初の計測ではこの罠にはまって、無関係な4セッションを容疑者にしてしまった。上のコマンドで cnt[$2]>1 の条件を入れているのは、この初回サンプルを除外するためだ。

重かった時間帯に動いていたセッションは34MBに膨張していた

セッションの会話履歴は ~/.claude/projects/ 配下にJSONL形式で保存されている。サイズを比較すると一つだけ桁が違った。

ls -lhS ~/.claude/projects/*/*.jsonl | head

プロジェクトAのセッションが34MB(8,090行)。他のプロジェクトの最大が4.9MBなので約7倍だ。2週間前から使い続けているセッションで、ファイルの最終更新時刻は「ネットが重い」と感じた時間帯と一致していた。

膨張の中身は1枚1MB超のスクリーンショットだった

JSONLの各行のサイズと種類を集計すると、34MBのうち24.1MBがツール実行結果を含むエントリで、サイズ上位はすべてbase64エンコードされた画像だった。当日の作業でターミナルに渡したスクリーンショットで、19枚・合計約12MB。1枚で1.3MBのものもあった。スクリーンショットのファイルをターミナルにドラッグ&ドロップするとファイルパスが渡り、Claudeがそれを画像として読み込む。その画像がbase64のままコンテキストに残り続けていた。

画像がネットを重くする仕組み

Claude CodeはAPIリクエストのたびに、会話コンテキスト全体をアップロードする。ツールを1回実行するごとに1リクエスト発生するので、画像12MB分を抱えたセッションでターンを走らせると、ツール実行のたびに毎回その画像込みのコンテキストを送信し続けることになる。プロンプトキャッシュはサーバー側で処理を省く仕組みなので、料金は下がるがアップロード量は1バイトも減らない。

実測では、画像約1.9MBを抱えたcompactしていないセッションがターン実行中に25秒で1MB超を送信、ピークは592KB/s(約4.7Mbps)に達した。これが複数セッションで同時に走れば、ビデオ会議と重なった時に体感できるレベルで上りを圧迫する。

compactの効果を実測した

同じタイミングでターンを実行中の2セッションを25秒間計測して比較した。

セッション 送信量(25秒) 送信ピーク
compactなし(元5MB・画像約1.9MB) 1,059KB 592KB/s
compact直後(元34MB) 358KB 133KB/s

元が34MBだったセッションの方が、compact後は元5MBのセッションの3分の1の送信量になっている。compactで画像がテキストの要約に置き換わるためで、「compactしたら軽くなった」という過去の体感は正しかった。compact済みセッションは3分間フルに動かしても送信合計773KBだった。

トークン消費も同じ構造で増える

再送されるのはネットワークだけでなく入力トークンも同じだ。大きな画像は縮小された上で1枚あたり最大およそ1,600トークンを消費する。19枚なら画像だけで約3万トークンが、ツール実行のたびに入力として再カウントされる。費用面はプロンプトキャッシュで大幅に緩和されるが、入力が大きいほど1リクエストの処理は確実に遅くなる。膨張したセッションが「もっさりする」のはネットワークとこの両方が効いている。

対策1: 画像の確認をサブエージェントに任せる

CLAUDE.mdに次の1行を入れた。

- スクリーンショットや画像の確認・検証はサブエージェント(Task)に任せること。画像を親セッションのコンテキストに直接読み込むと膨張して毎リクエストの再アップロードでネットワークを圧迫するため。サブエージェントに画像パスを渡して確認させ、結果は文字の要約で受け取る。

画像はサブエージェント側のコンテキストで消費され、親セッションには文字の要約だけが返る。画像を見て判断する能力を失わずに膨張だけ防げる。ファイルパスで渡した画像(今回の主犯)にはこれが効く。クリップボードから直接貼り付けた画像はユーザーメッセージの一部として親に入るため、この指示では防げない。

対策2: スクリーンショットをJPEGで保存する

macOSのスクリーンショットは標準でPNGで、Retina環境の全画面だと1枚1MBを超える。JPEGに変えるとファイルサイズはおおむね5分の1以下になる。

defaults write com.apple.screencapture type jpg

戻す場合は type png を指定する。直接貼り付ける場合にも効く対策はこれだ。

対策3: タスクの区切りで/clearする

今回の34MBセッションは2週間同じセッションを使い続けた結果だった。別のタスクに移る時は/clearで仕切り直せば送信量はゼロベースに戻る。auto-compactはコンテキスト上限の近くまで発動しないので、ネットワーク対策としては当てにならない。

「Claude Codeを使っているとネットが重い」と感じたら、まずnettopで測って、~/.claude/projects/のJSONLサイズを見る。アイドルのセッションは無罪で、犯人は画像を抱えて動いているセッションだ。