Claude Code のセッションを何本も並行して走らせていると、週の上限が思ったより早く減っていきます。どのセッションが食っているのか——それを知りたくて /usage を開いても、答えは出てきません。

結論から書くと、2026年9月時点で「どのセッションが何割使ったか」を表示する公式の画面はありません。/usage が出すのは、今のセッションの数字と、プラン全体の消費をスキル・サブエージェント・プラグイン・MCPサーバー別に分けた割合までです。セッション別に見たいなら、手元に残っている会話ログを自分で集計することになります。

ただし、ログは素直に足すと数え間違えます。筆者の環境で直近7日のログを実測したところ、行をそのまま足した合計は正しい値の2.06倍になりました。しかも誤差の倍率が、使用量の多い上位12セッションだけでも1.30倍から3.02倍までばらつくため、順位まで入れ替わります。この記事では、公式の画面で見られるものの整理から、正しい数え方、50行ほどの集計スクリプト、実測の結果までを扱います。

直近7日、どのセッションが使ったか

筆者の環境の29セッションを、API料金に換算した重みで集計。公式の画面にはこの内訳が出ない

セッションA
32.3%
セッションB
11.1%
セッションC
10.4%
セッションD
7.7%
セッションE
6.4%
残り24本
32.1%

出典: 筆者の環境で実測(2026年9月15日時点の直近7日。Windows のデスクトップアプリで動かしたセッションを、この記事の集計スクリプトで算出)

1. 公式の画面で見られるもの・見られないもの

使用量に関係する主な公式の表示を並べると、次のようになります(2026年9月時点)。どれも「セッション別の割合」は出しません。いちばん近いのは /usage のプラン内訳ですが、その軸は「どの機能に使ったか」で、「どのセッションが使ったか」ではありません。

見る場所見えるものセッション別の割合
/usage の Session 欄今のセッションのトークン数と費用の見積もり(モデル別)。/clear で0に戻る。公式は「API利用者向けで、Pro・Max では費用の数字は請求に関係しない」と注記している✕ 今のセッションだけ
/usage のプラン内訳(Pro・Max・Team・Enterprise)直近24時間または7日の使用量を、スキル・サブエージェント・プラグイン・MCPサーバー別の割合で。dw で切り替え。v2.1.242 以降は、重い定期タスク(/loop など)ごとのトークン数も出る✕ 機能別・定期タスク別で、セッション別ではない
デスクトップアプリの使用量リングそのセッションの文脈窓の使用量と、期間中のプラン使用量。公式は「プラン使用量はすべての Claude Code の画面で共通」と書いている✕ プラン全体の数字
claude.ai の「設定 → 使用量」5時間枠と週次上限に対する進捗バーと、リセットの時刻✕ プラン全体の数字
/insightsこの端末の最近のセッションを分析した HTML レポート(どのプロジェクトで何をしているか、どこでつまずいたか)。公式は「使ったトークン量ではなく、働き方のレポート」と説明している✕ トークン量を出さない
Team・Enterprise の分析画面、Claude Consoleユーザー別・モデル別の利用額✕ ユーザー単位
OpenTelemetry(監視データの書き出し)トークン数と費用の指標に、セッションIDが標準で付く○ ただし集計先を自分で用意する

出典: Claude Code 公式ドキュメント「Manage costs effectively」/usage/insights・組織向けの画面)、同「Desktop」(使用量リング)、Claude ヘルプセンター「Usage limit best practices」(設定の使用量ページ)、Claude Code 公式ドキュメント「Monitoring」(OpenTelemetry)

公式の「セッション上限」は、会話のセッションのことではない

claude.ai の使用量ページにある「セッション」は5時間の利用枠を指します。Claude Code で1本ずつ開いている会話のセッションとは別物です。この記事で「セッション」と書くときは、後者(サイドバーに並ぶ1本1本)を指します。

/usage のプラン内訳について、公式はもうひとつ大事なことを書いています。「値はおおよそで、この端末のセッション履歴から計算しているので、他の端末や claude.ai での使用は含まない」。つまり公式の内訳も、元をたどれば手元のログです。同じログを自分で読めば、公式が出していない「セッション」という軸でも集計できます。上限に達してしまったときの残量の見方は、Claude Code「usage limit reached」の対処で扱っています。

2. 答えは手元の会話ログにある

Claude Code は会話の全記録を、1セッション1ファイルの JSONL(1行に1つの JSON)で保存しています。置き場所は公式ドキュメントに書かれています。

会話の本体
~/.claude/projects/<プロジェクト>/<セッション>.jsonl

メッセージ、ツール呼び出し、ツールの結果まですべて入る。Windows では C:\Users\<ユーザー名>\.claude\projects

サブエージェント
~/.claude/projects/<プロジェクト>/<セッション>/subagents/

サブエージェントの会話は本体とは別のファイル。親のログが古くなって消えるときに一緒に消える

保存期間
ターミナルは既定30日

ターミナルで使ったセッションは cleanupPeriodDays(既定30日)を過ぎると消える。デスクトップアプリ(または Cowork)で始めた・最後に続けたセッションは、v2.1.248 以降は期間に関係なく残る

出典: Claude Code 公式ドキュメント「Explore the .claude directory」

<プロジェクト> のフォルダ名は、筆者の環境では作業フォルダの絶対パスの記号を - に置き換えた名前でした(D:\work\site-a なら D--work-site-a)。デスクトップアプリの Code タブで動かしたセッションも同じ場所に書かれており、各行に "entrypoint":"claude-desktop" と記録されていました。

集計に使うのは、Claude の応答を記録した行("type":"assistant")に付いている usage です。実物の1行から、集計に使う項目だけを抜き出すとこうなっています(IDは伏せています)。

{"type":"assistant","requestId":"req_…","timestamp":"2026-07-25T00:16:37.822Z",
 "message":{"id":"msg_…","model":"claude-opus-5",
  "content":[{"type":"text","text":"…"}],
  "usage":{"input_tokens":2,"output_tokens":255,
           "cache_read_input_tokens":33775,"cache_creation_input_tokens":17265,
           "cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":17265}}}}

usage の4つの数字(入力・出力・キャッシュ読み込み・キャッシュ書き込み)は、Claude API の応答に含まれる公式の項目です。一方、ログファイルの形——1行に何を書くか——は公式に説明されていません。この記事の数え方は、筆者の手元にある v2.1.197〜v2.1.260 のログで確かめたもので、今後の版で変わる可能性があります。

もうひとつ、公式が明記している注意があります。ログは暗号化されておらず、守っているのは OS のファイル権限だけです。ツールが .env を読めば、その中身もログに残ります。集計の結果を人に見せるのは問題ありませんが、ログそのものを渡したり、よく知らないツールに読ませたりするときは気を付けてください

3. そのまま足すと約2倍になる——4つの落とし穴

usage の行を見つけて全部足す——いちばん素直な方法ですが、筆者のログでは合計が正しい値の約2倍になりました。原因は4つあります。

① 1回の応答が何行にも書かれる

Claude の応答1回(APIへの要求1回)は、ログの1行とは限りません。筆者の環境では、思考・本文・ツール呼び出しといった中身のかたまり1つにつき1行ずつ書かれ(99.9%以上の行が1行1かたまり)、そのすべての行に usage が付いていました。応答を見分ける鍵は message.idrequestId の組です。

1行だけ
33.5%

71,865件。足しても正しい

2行
32.6%

69,810件。足すと2倍

3行
24.8%

53,060件。足すと3倍

4行以上
9.1%

19,475件。足すと4倍以上

出典: 筆者の環境で実測(2026年3月30日〜9月15日のログ。usage の付いた476,404行が、応答としては214,210件だった)

2行以上ある応答142,345件のうち、76%は全部の行で usage がまったく同じでした。残りの24%は、出力トークンの値が行によって違っていました。そこで、応答ごとに出力トークンがいちばん大きい行を1つだけ採ります。なお、同じ応答が別のファイルにも入っていることが1,903件ありました(トークン全体の0.95%)。原因までは確かめていませんが、同じ鍵で1件にまとめれば、これも二重には数えません。

② サブエージェントの記録は別のファイルにある

本体の .jsonl だけを読むと、サブエージェントの分がまるごと抜けます。筆者のログで、正しい合計のうちサブエージェントが占めた割合はこうでした。

  • 入力(キャッシュ外): 42.9%
  • 出力: 23.2%
  • キャッシュ書き込み: 10.8%
  • キャッシュ読み込み: 6.9%

セッション単位で見ると差はもっと大きく、直近7日を料金換算で見ると0%のセッションから54%のセッションまでありました。サブエージェントに作業を配る使い方をしているセッションほど、本体だけの集計では小さく見えます。

③ 2つの誤りは打ち消し合うが、打ち消し方がセッションごとに違う

本体のファイルの行をそのまま足すと、①で増えて②で減ります。直近7日の合計は正しい値の2.06倍でした。もしどのセッションも同じ2倍なら、割合は正しいままです。ところが実際はそうなりませんでした。

セッション正しい割合(順位)そのまま足した割合(順位)そのまま÷正しいサブエージェントの比率
A31.7%(1位)27.4%(1位)1.79倍21%
C12.7%(2位)12.0%(3位)1.96倍2%
B11.4%(3位)15.0%(2位)2.71倍9%
D8.6%(4位)5.4%(5位)1.30倍39%
E5.4%(5位)6.8%(4位)2.60倍39%
F4.6%(6位)4.1%(8位)1.85倍0%
G3.2%(9位)4.7%(6位)3.02倍5%

出典: 筆者の環境で実測(2026年9月15日時点の直近7日。この表だけは比べやすいよう、サブエージェントの比率も含めて重みを付けないトークン数で並べた。セッション名は冒頭の図と共通)

2位と3位、4位と5位が入れ替わり、9位のGは6位まで浮き上がりました。サブエージェントの多いDが小さく出るのは②のとおりですが、サブエージェントの比率がDと同じ39%のEは、逆に2.60倍です。1回の応答が何行に分かれるか(思考やツール呼び出しの多さ)も効くので、倍率は前もって読めません。「ざっくり半分にすればいい」は通用しない、ということです。

④ トークン数の97%はキャッシュの読み込み

正しく数えても、トークン数をそのまま比べると重さを見誤ります。直近7日の中身はこうでした。

トークン数の内訳(直近7日・全セッション合計)

キャッシュ読み込み 96.9%
キャッシュ書き込み 2.6%
出力 0.43%
入力(キャッシュ外) 0.01%未満

出典: 筆者の環境で実測(2026年9月15日時点の直近7日)

ところが単価はまったく違います。Anthropic の公式料金表では、キャッシュ読み込みは入力単価の0.1倍(Claude Fable 5.1 と Mythos 5.1 は0.025倍)、5分キャッシュの書き込みは1.25倍、1時間キャッシュは2倍、そして出力は現行モデルでいずれも入力の5倍です。トークン数で12.7%を占めていたセッションCは、この単価で重みを付けると10.4%になりました。

数字の大きさ自体にも意味があります。上位12本のうちDとEを除く10本は、1回の応答あたり平均で約41万〜48万トークンの文脈を読み込んでいました(サブエージェントの多いDとEは約24万と31万)。Claude Code は毎回の要求で会話全体を送るので、長く開いているセッションほど1回が重くなります。この仕組みはClaude Codeのコンテキストは何に食われているのかで詳しく扱っています。

4. 集計スクリプト

①〜④をすべて反映した集計スクリプトです。Python 3 の標準ライブラリだけで動きます(筆者は 3.11 で確認)。ログを読むだけで、書き換えも送信もしません。環境変数 CLAUDE_CONFIG_DIR で設定の置き場所を変えている場合は、そちらを読みます。

import json, os, sys
from collections import defaultdict
from datetime import datetime, timedelta, timezone
from pathlib import Path

DAYS = float(sys.argv[1]) if len(sys.argv) > 1 else 7
ROOT = Path(os.environ.get("CLAUDE_CONFIG_DIR") or Path.home() / ".claude") / "projects"
SINCE = datetime.now(timezone.utc) - timedelta(days=DAYS)
# USD per 1M input tokens (output = 5x). First match wins.
PRICES = [("sonnet-5", 2), ("sonnet", 3), ("haiku", 1), ("opus-4-1", 15),
          ("opus-4-2025", 15), ("opus", 5), ("fable", 10), ("mythos", 10)]

best = {}  # one API response = one (message.id, requestId)
for path in ROOT.rglob("*.jsonl"):  # also reads <session>/subagents/*.jsonl
    project = path.relative_to(ROOT).parts[0]
    with path.open(encoding="utf-8", errors="replace") as f:
        for line in f:
            if '"usage"' not in line:
                continue
            try:
                row = json.loads(line)
            except ValueError:
                continue
            msg = row.get("message") or {}
            usage = msg.get("usage")
            ts = row.get("timestamp")
            if row.get("type") != "assistant" or not usage or not ts:
                continue
            if datetime.fromisoformat(ts.replace("Z", "+00:00")) < SINCE:
                continue
            key = (msg.get("id"), row.get("requestId"))
            old = best.get(key)
            if old is None or usage.get("output_tokens", 0) >= old[2].get("output_tokens", 0):
                best[key] = (project, msg.get("model") or "", usage)

totals = defaultdict(lambda: [0, 0.0])  # [tokens, weight]
for project, model, u in best.values():
    p = next((v for name, v in PRICES if name in model), 5)
    read_rate = 0.025 if "5-1" in model and ("fable" in model or "mythos" in model) else 0.1
    inp, out = u.get("input_tokens", 0), u.get("output_tokens", 0)
    read, write = u.get("cache_read_input_tokens", 0), u.get("cache_creation_input_tokens", 0)
    write_1h = (u.get("cache_creation") or {}).get("ephemeral_1h_input_tokens", 0)
    totals[project][0] += inp + out + read + write
    totals[project][1] += p * (inp + out * 5 + read * read_rate
                               + (write - write_1h) * 1.25 + write_1h * 2)

all_tokens = sum(t for t, _ in totals.values()) or 1
all_weight = sum(w for _, w in totals.values()) or 1
print(f"last {DAYS:g} days: {len(best):,} responses")
print(f"{'weight':>7} {'tokens':>7}  project")
for project, (t, w) in sorted(totals.items(), key=lambda kv: -kv[1][1]):
    print(f"{w / all_weight:7.1%} {t / all_tokens:7.1%}  {project}")

usage_by_session.py などの名前で保存し、引数に日数を渡します。省略すると直近7日です。

python usage_by_session.py        # 直近7日
python usage_by_session.py 1      # 直近24時間
python usage_by_session.py 30     # 直近30日

出力はこうなります(フォルダ名は伏せてあります)。weight が料金換算の重み、tokens がトークン数そのままの割合です。

last 7 days: 19,991 responses
 weight  tokens  project
  32.3%   31.7%  D--work-project-a
  11.1%   11.4%  D--work-project-b
  10.4%   12.7%  D--work-project-c
   7.7%    8.6%  D--work-project-d
   6.4%    5.4%  D--work-project-e

スクリプトの要点

  • rglob で下の階層まで読む——subagents/ のファイルも拾い、親と同じプロジェクトに合算する(落とし穴②)
  • message.idrequestId の組で1件にまとめ、出力トークンが最大の行を残す(落とし穴①)
  • 単価で重みを付ける——モデルの入力単価に、出力5倍・キャッシュ読み込み0.1倍・書き込み1.25倍か2倍を掛ける(落とし穴④)。単価は2026年9月の公式料金表に合わせてあるので、料金が変わったら PRICES を直す
  • まとめる単位はプロジェクトのフォルダ——同じフォルダで複数のセッションを開いているなら、project の代わりにファイル名(サブエージェントは subagents フォルダの1つ上にある、セッションのフォルダ名)で集計すればセッションIDごとに分かれる

5. 実測:29セッションのうち1つが3割を使っていた

筆者の環境で直近7日に動いていたのは29セッションでした。冒頭の図のとおり、使用量はごく一部に集中していました

最も使ったセッション
32.3%

1本で全体の約3分の1

上位3セッション
53.8%

3本で半分を超える

上位5セッション
67.9%

残り24本で約3分の1

1%未満のセッション
15本

29本のうち半分以上

出典: 筆者の環境で実測(2026年9月15日時点の直近7日。API料金に換算した重みで集計)

数字を並べて見えたことが3つあります。

ひとつ目は、上位のセッションほど「1回あたりが重い」こと。上位3本は、応答1回あたり平均で約41万〜48万トークンを読み込んでいました。回数が多いだけでなく、1日じゅう開いたまま文脈が育っていることが効いています。公式も、長く開いたセッションでは一行の質問でも会話全体ぶんの使用量が発生すると書いています。

ふたつ目は、サブエージェントを多用するセッションは本体からは小さく見えること。DとEは、料金換算の使用量のそれぞれ44%と54%をサブエージェントが占めていました。サイドバーで本体の会話を眺めていても、この分は目に入りません。

みっつ目は、半分以上のセッションはほとんど使っていないこと。「開いているセッションが多いから上限が早く減る」のではなく、少数の重いセッションが減らしている。対策を打つなら、その少数から手を付ければ十分です。何から削るかはClaude Codeのトークン節約術と上限到達時の追加料金にまとめています。

6. 数字の読み方と限界

この集計で分かること・分からないこと

  • 🟡 重みはAPI料金に換算した目安です。Pro・Max の上限がこの比率どおりに減るとは公表されていません。セッション同士を比べる物差しとしては使えますが、「残り何%」の計算には使えません
  • この端末の分だけです。別の端末、claude.ai のチャット、クラウドで動かしたセッションは入りません。公式の /usage の内訳も同じ制約を持っています
  • ターミナルで使ったセッションは、30日より前を出せません。ログが cleanupPeriodDays(既定30日)で消えるためです。デスクトップアプリ(または Cowork)で始めた・最後に続けたセッションは、v2.1.248 以降は期間に関係なく残ります
  • 🟡 ログの形は公式の仕様ではありません。1回の応答が何行に分かれるか、といった書き方は版で変わる可能性があります。数字がおかしいと感じたら、まず重複をまとめる前後の件数を比べてください
  • 料金は変わります。Claude Sonnet 5 は導入価格だった $2/$10 がそのまま正式な価格になり(予定されていた9月1日の値上げは取りやめ)、Fable 5.1 はキャッシュ読み込みが入力単価の0.025倍です。PRICES は公式料金表と合わせて更新してください

7. これから先を続けて見るなら OpenTelemetry

ログの集計は過去30日をすぐに見られるのが強みです。一方、これから先を継続して見たいなら、公式の監視機能である OpenTelemetry のほうが向いています。

有効にすると、Claude Code はトークン数の指標 claude_code.token.usage(種類は inputoutputcacheReadcacheCreation)と、費用の指標 claude_code.cost.usage を書き出します。どちらにも session.id が標準で付きますOTEL_METRICS_INCLUDE_SESSION_ID、既定は true)。ログファイルを読むわけではないので、落とし穴①の重複行とは無関係で、サブエージェントの分も query_sourcemainsubagentauxiliary)で区別して記録されます。

まず手元で試すなら、公式ドキュメントにあるとおり、結果を画面に出す設定で起動します。

export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=console
export OTEL_METRIC_EXPORT_INTERVAL=1000
claude

継続して集計するには、OTEL_METRICS_EXPORTER=otlp にして、自分で用意した集計先(OTLP を受け取れる監視基盤)へ送ります。送り先を用意する手間がかかることと、有効にする前の分は記録されないことが、ログ集計との違いです。

出典: Claude Code 公式ドキュメント「Monitoring」(指標名、属性、環境変数)

FAQ

Q1. /usage のプラン内訳では足りませんか。
軸が違います。プラン内訳は「スキル・サブエージェント・プラグイン・MCPサーバーのどれに使ったか」を割合で出すもので、どのセッションが使ったかは出しません。上限が減る原因を機能の側から探すなら /usage、セッションの側から探すならこの記事の集計、と使い分けてください。

Q2. 既製の集計ツールは使えますか。
使えます。たとえば非公式のツール ccusage は、同じログからセッション別のレポートを出せます。使う前に2つ確かめてください。ひとつは処理が手元で完結するか——ログにはツールの結果が暗号化されずに入っています。もうひとつは数え方——重複行とサブエージェントの扱いが揃っているか、この記事のスクリプトの結果と一度突き合わせると安心です。

Q3. 別の端末や claude.ai で使った分も合わせて見たいです。
ログは端末ごとにしか残らないので、端末ごとに集計して足すことになります。claude.ai のチャットは Claude Code のログに記録されません。プラン全体の残りは、claude.ai の「設定 → 使用量」の進捗バーで見るのが確実です。

Q4. 古い分も集計できるよう、ログを残しておきたいです。
ターミナルで使ったセッションは、settings.jsoncleanupPeriodDays を大きくすれば長く残せます。デスクトップアプリ(または Cowork)で始めた・最後に続けたセッションは、v2.1.248 以降もともと期間に関係なく残ります(期限を付けたいときは desktopSessionCleanupPeriodDays)。ただし公式は、ログの露出を減らす手段としてこれらの値を小さくすることを挙げています。長く残すほど、暗号化されていない記録が長く手元に置かれる点は意識してください。

出典