Max や Pro の契約で Claude Code を使っていて、こんな経験はないだろうか。
- たいしてコードも書いていないのに、週次の利用枠が1日で100%に達する
- 「軽い作業しかしていない」のに、午後には枠が尽きて締め出される
- サポートに問い合わせても「上限はリセットできません」と自動の返信が返るだけ
- 高い料金を払っているのに、肝心なときに使えない
これは実際に複数の利用者が報告している事象で、「拡張機能が背景でワークスペースを常に読み直しているのでは」「トークンの計算が間違っているのでは」とバグを疑う声が多い。
ただ、バグなのか、それとも自分の使い方で説明がつくのかは、自分のローカルのログを読めば切り分けられる。そして多くの場合、原因は意外なところにある。コードの量ではなく、文脈の再読み込みだ。
この記事では、消費の内訳を自分で測る方法と、「バグか期待どおりか」を反証可能な形で切り分ける手順を示す。
消費の記録は全部ローカルにある
Claude Code は、各リクエストのトークンの使用量を ~/.claude/projects/**/*.jsonl に全部書き出している。各行の message.usage に、次の4つの数が入っている。
-
input_tokens: 新しく送った入力 -
cache_creation_input_tokens: キャッシュへの書き込み -
cache_read_input_tokens: キャッシュからの読み込み -
output_tokens: モデルが生成した出力
ここを日ごと、セッションごとに足し上げれば、何が枠を食っているかが見える。次のスクリプトは読み取りだけで、何も書き換えない。
import json, os, glob, collections, sys
root = os.path.expanduser(sys.argv[1] if len(sys.argv) > 1 else "~/.claude/projects")
day, sess, msgs = collections.defaultdict(collections.Counter), collections.defaultdict(collections.Counter), collections.Counter()
for fp in glob.glob(f"{root}/**/*.jsonl", recursive=True):
sid = os.path.basename(fp)[:8]
for line in open(fp, encoding="utf-8", errors="replace"):
try:
o = json.loads(line); u = o.get("message", {}).get("usage")
except Exception:
continue
if not u:
continue
d = o.get("timestamp", "")[:10]
for k, f in (("in", "input_tokens"), ("cache_write", "cache_creation_input_tokens"),
("cache_read", "cache_read_input_tokens"), ("out", "output_tokens")):
day[d][k] += u.get(f, 0); sess[sid][k] += u.get(f, 0)
msgs[sid] += 1
print("=== 日ごと ===")
for d in sorted(day)[-7:]:
c = day[d]; print(d, dict(c))
print("=== 重いセッションの順 ===")
for sid, c in sorted(sess.items(), key=lambda kv: sum(kv[1].values()), reverse=True)[:8]:
print(sid, "msgs", msgs[sid], "cache_read", c["cache_read"], "out", c["out"])
実行すると、こういう形の出力が出る。これは実際に1週間ぶん集計した結果だ。
2026-06-06 in=788,643 cache_write=18,908,737 cache_read=1,235,216,305 out=7,461,998
重いセッション msgs=927 cache_read=496,248,446 out=1,242,439
スクリプトを動かさずブラウザで済ませたい人向けに、同じ集計をその場でやる Token Drain Analyzer を用意した。ログはブラウザの中だけで解析し、どこにも送らない。
消費の99%は cache_read だった
数字を見ると一目でわかる。1日あたり cache_read が12億トークン規模に対し、output_tokens は700万、cache_creation(書き込み)は1,900万にすぎない。トークンの量のおよそ99%が cache_read、つまりキャッシュからの読み込みだ。
なぜこうなるのか。Claude Code は会話の各ターンで、それまでに積み上がった文脈の全体を毎回もう一度モデルに送る。システムの指示、読み込んだファイル、これまでのやり取りの履歴——その全部が、新しいメッセージごとに cache_read として再送される。
ここが肝心なところだ。消費は「文脈の大きさ × ターン数」で決まる。書いたコードの行数では決まらない。
だから「軽い作業しかしていないのに枠が枯れる」は、矛盾でも何でもない。大きなワークスペースを抱えた長いセッションでは、こちらが一行の指示を打つたびに、数百万トークンの文脈が読み直される。コードを1行も書かなくても、ターンを重ねるほど消費は膨らむ。「背景で常に読み直している」という体感は正しく、そしてそれは多くの場合バグではなく、文脈の窓がそういう仕組みだという話だ。
バグか、文脈駆動か——反証可能な切り分け
ここまでで「設計どおりの消費」の可能性が見えたが、本物の異常を否定したわけではない。上のスクリプトの出力で、次の2点を確かめれば切り分けられる。
- 重いセッションや日は、自分が実際に使った時間と一致するか。一致するなら、文脈駆動の消費だ。あなたの使い方で説明がつく(対処は後述)。一方、自分がまったく使っていない時間帯やセッションに大きな消費が出ているなら、それは本物の異常だ。日ごとの表を証拠にしてサポートへ報告する価値がある。「なんとなくおかしい」より、具体的な表のほうがはるかに通りやすい。
-
output_tokens(実際の生成)が小さいのにcache_readが巨大か。そうなら、コストはモデルが勝手に大量生成したのではなく、文脈の再読み込みだと確定できる。
文脈駆動だった場合に効くレバー
仕組みがわかれば、効く対処も決まる。
- タスクの区切りで
/clearを使う。これが一番効く。/clearは積み上がった文脈を捨てるので、毎ターン再送される量がリセットされる。一つの巨大なセッションを延々と続けるのが、最も枠を溶かす使い方だ。 - 作業するフォルダを絞って開く。巨大なモノレポの根ではなく、いま触る部分のディレクトリで開けば、文脈に取り込まれる量が減る。
- 早い段で読み込んだ巨大ファイルに注意する。一度文脈に入った大きなファイルは、その後の毎ターンで読み直される。生成物やログの巨大ファイルが紛れていないか確認する。
正直な注記
ひとつ誤解しないでほしい。生の cache_read の数は「量」であって、ドルや枠の費用そのものではない。キャッシュからの読み込みは、出力に比べてトークンあたりの重み付けがずっと軽い。だから「12億」という数字をそのまま料金として読まないこと。この診断の値打ちは、絶対値ではなく帰属にある。どのセッションが消費したのか、それが自分の実利用と一致するのか——そこを見るための道具だ。
そのうえで、利用していない時間に消費が出ているなら、それは堂々と異常として報告していい。
安全な運用の確認の型(破壊的なコマンドの防止、設定のレビュー、月次のチェックリストなど)は、無料の cc-safe-setup にまとめて置いている。費用の事故も、データの消失も、まず「自分のログで事実を確かめる」ところから始めるのが、いちばん遠回りに見えて近い。