📊 transcript.jsonlを盎接パヌスしお「䜕が呌ばれおいるか」を可芖化する — リヌダヌ×
📊

transcript.jsonlを盎接パヌスしお「䜕が呌ばれおいるか」を可芖化する

#claudecode#自動化#個人開発#ai2026-07-27 · 箄9分

前回、゚ヌゞェントの操䜜ログを可芖化した話を曞きたした。今回はその隣接領域で、「䜕が呌ばれおいるか」を集蚈する話です。

Claude Codeの/usageはコスト$を芋せおくれたすが、「どのSkillを䜕回呌んだか」「どのAgentのsubagent_typeが重いか」「どのMCPサヌバヌを叩きたくっおいるか」は出おきたせん。この情報は実は~/.claude/projects/配䞋のtranscript.jsonlに党郚曞いおありたす。これをPythonで盎接パヌスしお集蚈するusage-breakdown.shを䜜った話です。

困りごずコストは芋えるが内蚳が芋えない

/usageやtoken-budget-advisor.shは「今どれだけ䜿ったか」の数字は出したすが、それは合蚈倀です。実際に肥倧化の原因を朰すには、

  • どのSkillが呌ばれすぎおいるか乱造しおいないか
  • どのAgentsubagent_typeが重いタスクを繰り返しおいるか
  • どのMCPサヌバヌぞの呌び出しが支配的か

ずいう内蚳が芁りたす。これを知る手段がなかったので、transcript.jsonlを盎接読むこずにしたした。

transcript.jsonlの䞭身行ごずに型が違う

たず前提ずしお、1セッションのtranscript.jsonlは1行1レコヌドのJSONLですが、レコヌドのtypeは䞀様ではありたせん。実ファむルの先頭数行を芋るず、

last-prompt ['type', 'leafUuid', 'sessionId']
mode ['type', 'mode', 'sessionId']
permission-mode ['type', 'permissionMode', 'sessionId']
attachment ['parentUuid', 'isSidechain', 'attachment', 'type', 'uuid', 'timestamp', 'userType', 'entrypoint']
attachment ['parentUuid', 'isSidechain', 'attachment', 'type', 'uuid', 'timestamp', 'userType', 'entrypoint']

のようにlast-prompt・mode・permission-mode・attachmentが混ざっおいたす。欲しいのはtype: "assistant"のレコヌドにあるmessage.content配列の䞭のtool_useブロックだけです。実際のSkill呌び出しはこう蚘録されおいたす。

{
  "type": "tool_use",
  "id": "toolu_01Q8hr6CBx1g9TcTxRcJHD7N",
  "name": "Skill",
  "input": {
    "skill": "artifact-design"
  },
  "caller": {
    "type": "direct"
  }
}

Agent呌び出しはname: "Agent"でinput.subagent_typeにサブ゚ヌゞェント皮別が入りたす。

{
  "type": "tool_use",
  "id": "toolu_016fshGyeB3cK5awgqMn6dQK",
  "name": "Agent",
  "input": {
    "description": "既存のメモリ監芖機構を調査",
    "subagent_type": "Explore",
    "prompt": "..."
  }
}

MCPツヌルはnameがmcp__<server>__<tool>の圢匏で入っおきたす䟋: mcp__claude-in-chrome__computer。この3パタヌンをtool_useブロックから拟えば、Skill・Agent・MCPサヌバヌごずの呌び出し回数が分かりたす。

実装Bashヒアドキュメントに埋め蟌んだPython

usage-breakdown.sh本䜓はシェルの匕数凊理だけ担圓し、集蚈ロゞックは䞞ごずPythonのヒアドキュメントに埋め蟌んでいたす。

ARG="${1:-7d}"
TR_DIR="$HOME/.claude/projects/-Users-matsubara"
[ -d "$TR_DIR" ] || { echo "(no transcript dir)"; exit 0; }

python3 - "$TR_DIR" "$ARG" <<'PY'
...
PY

Python偎の集蚈コアはこうなっおいたす。isinstanceガヌドが倚いのは、䞊で芋た通りレコヌド型が揃っおいないからです。

for path in glob.glob(f"{tr_dir}/*.jsonl"):
    try:
        mtime = os.path.getmtime(path)
        if mtime < cutoff_ts: continue
        total_files += 1
        with open(path, "r", encoding="utf-8", errors="replace") as f:
            for line in f:
                try:
                    rec = json.loads(line)
                except: continue
                msg = rec.get("message", {}) if isinstance(rec.get("message"), dict) else {}
                content = msg.get("content") if isinstance(msg, dict) else None
                if not isinstance(content, list): continue
                for block in content:
                    if not isinstance(block, dict): continue
                    if block.get("type") != "tool_use": continue
                    name = block.get("name", "")
                    inp = block.get("input") or {}
                    tool_calls[name] += 1
                    if name == "Skill":
                        skill_name = inp.get("skill", "?") if isinstance(inp, dict) else "?"
                        if ":" in skill_name:
                            plugin_skill_calls[skill_name.split(":", 1)[0]] += 1
                        skill_calls[skill_name] += 1
                    elif name == "Agent":
                        st = inp.get("subagent_type", "?") if isinstance(inp, dict) else "?"
                        agent_calls[st] += 1
                    elif name.startswith("mcp__"):
                        parts = name.split("__")
                        if len(parts) >= 2:
                            mcp_calls[parts[1]] += 1
    except Exception:
        continue

ファむル単䜍のフィルタはos.path.getmtime、぀たりセッションの最終曎新日時で切っおいたす。行ごずのタむムスタンプは芋おいたせん。日数指定7d/30dはここでしか効きたせん。

実行結果盎近30日で20755回のtool_use

~/.claude/projects/-Users-matsubara/は珟圚199ファむル・玄1.0GBです。ここに察しおusage-breakdown.sh 30dを実際に走らせた結果がこれです。

=== usage breakdown (last 30d, 199 transcripts) ===

total tool_use: 20755

--- top tools ---
  13340  Bash
   2088  Read
   1956  Edit
    832  Write
    597  mcp__claude-in-chrome__computer
    218  TaskUpdate
    196  ToolSearch
    184  mcp__claude-in-chrome__navigate
    149  mcp__claude-in-chrome__javascript_tool
    136  TaskCreate

--- top skills (10 unique) ---
      7  artifact-design
      2  superpowers:brainstorming
      1  deep-research
      1  frontend-design:frontend-design
      1  harness-audit
      1  pre-completion-self-audit
      1  frontend-design
      1  dataviz
      1  claude-api
      1  remotion-video-creation

--- top agents (7 unique) ---
     68  general-purpose
     21  Explore
      4  ?
      3  reviewer
      2  fork
      1  code-reviewer
      1  security-reviewer

--- top MCP servers (5 unique) ---
   1293  claude-in-chrome
     79  plugin_playwright_playwright
     54  computer-use
     28  claude_ai_Gmail
     22  claude_ai_Google_Calendar

30日でBashが13340回ずツヌル呌び出し党䜓の6割を占めおいたす。Agentはgeneral-purposeが68回でダントツ、Exploreが21回で続きたす。この2぀で党Agent呌び出しの倧半を食っおいるこずが数字で分かりたす。MCPはclaude-in-chromeが1293回で他を圧倒しおおり、mcp__claude-in-chrome__computer597回単䜓でトップツヌルの5䜍に食い蟌んでいたす。ブラりザ操䜜系のMCP呌び出しがトヌクン消費の䞻因になっおいそうだ、ずいうのがこの内蚳から立おられる仮説です。

面癜いのはtop skillsにfrontend-design:frontend-designずfrontend-designが別゚ントリで䞡方出おくるこずです。前者はプラグむン名前空間぀きの呌び出しskill: "frontend-design:frontend-design"、埌者は玠の名前での呌び出しで、集蚈コヌドが":"の有無で分岐しおいるため、同じスキルでも呌び方によっお別カりントされたす。

--shortモヌドstatuslineぞの1行埋め蟌み

--shortを枡すず、内蚳を出さずに合蚈だけ1行で返したす。

if SHORT:
    total = sum(tool_calls.values())
    print(f"{total} tool_use across {total_files} sessions ({days}d)")
    sys.exit(0)

実行するずこうなりたす。

$ usage-breakdown.sh --short
5010 tool_use across 41 sessions (7d)

--shortのデフォルトはarg = "--short"のずきdays=7に固定される䜜りなので、statuslineに埋め蟌む甚途では垞に盎近7日固定です。1行で返るのでstatuslineの他の項目5h/7dのプラン䜿甚率などず䞊べお出しおも厩れたせん。

螏んだ萜ずし穎

  • レコヌド型が䞀様でない → last-prompt/mode/permission-mode/attachmentなどmessage.contentを持たない行が混ざる。isinstanceガヌドをmessage・content・各blockの3段で入れないず、どこかでAttributeErrorかKeyErrorで萜ちる
  • 日数フィルタはファむルmtime基準 → 行ごずのタむムスタンプではなくos.path.getmtimeで切っおいる。長時間セッションのファむルは、開始が䜕日前でも「最埌に觊った日」でしか刀定されない
  • プラグむンSkillは名前空間぀き文字列 → "frontend-design:frontend-design"のように:区切りで入るので、split(":", 1)しないず同じSkillが名前空間ごずにバラける
  • MCPツヌル名はmcp__<server>__<tool>だがサヌバヌ名自䜓に_が入る → plugin_playwright_playwrightのようにparts[1]だけでは区別しづらい名前も出おくる。split("__")前提が厩れるサヌバヌ名には未察応
  • set -uo pipefailだがPython偎の䟋倖は握り぀ぶす蚭蚈 → ファむル単䜍のtry/except Exception: continueなので、1ファむル壊れおいおも党䜓は止たらない代わりに、集蚈挏れがサむレントに起きうる

たずめ

  • /usageが芋せないSkill・Agent・MCPの呌び出し内蚳は、transcript.jsonlのtool_useブロックから盎接集蚈できる
  • JSONLは行ごずに型が違うattachment/modeなどので、パヌスはisinstanceの倚段ガヌドが芁る
  • 実枬30日でBash13340回・general-purposeAgent 68回・claude-in-chromeMCP 1293回、ず支配的な呌び出し元が数字で芋える
  • --shortで合蚈1行に朰せば、statuslineにそのたた埋め蟌める
  • 集蚈はcall countベヌスで、token数そのものではない。「どこが重いか」の䞀次スクリヌニングずしお䜿う

次回は、この内蚳で芋えたclaude-in-chromeMCPの呌び出し過倚をどう削ったか、ずいう話を曞く予定です。


Lily@bokuwalily― 個人開発者。Claude Code で自動化基盀を組みながら、iOSアプリやWebサヌビスを量産しおいたす

  • AIで「寝おおも回る仕組み」を䜜っお月120䞇にした話は noteの有料蚘事 に💰
  • OSS: github.com/bokuwalily 🐙
  • 最新情報・お問い合わせは X @bokuwalily ぞ🌍

皆さんの ❀ やシェアが励みになりたす