This page documents the analyze-token-usage.py script: its purpose, how it locates and parses Claude Code session transcripts, how it attributes token consumption to individual agents, and how it computes cost estimates.
This script is a diagnostic utility used within the integration test suite. For information about the integration tests that invoke it, see Integration Test Cases. For the broader test infrastructure it belongs to, see Claude Code Test Suite.
After an integration test run, analyze-token-usage.py reads the .jsonl session file written by Claude Code and produces a per-agent breakdown of:
This lets developers understand how expensive a multi-agent workflow actually is, identify which subagents consume the most tokens, and detect regressions in context size.
Sources: tests/claude-code/analyze-token-usage.py1-10
The script is called at the end of the integration test for subagent-driven-development. After Claude finishes executing the plan, the test shell script locates the most recent .jsonl session file and passes it to analyze-token-usage.py.
Call site in the integration test:
tests/claude-code/test-subagent-driven-development-integration.sh285-286
python3 "$SCRIPT_DIR/analyze-token-usage.py" "$SESSION_FILE"
The session file is discovered by scanning ~/.claude/projects/<escaped-working-dir>/ for .jsonl files modified within the last 60 minutes.
tests/claude-code/test-subagent-driven-development-integration.sh166-170
Flow from integration test to analysis:
Sources: tests/claude-code/test-subagent-driven-development-integration.sh164-286
Claude Code writes one JSON object per line to a .jsonl file as the session proceeds. The script reads two record types:
| Record type | data["type"] | Contains |
|---|---|---|
| Main session turn | "assistant" | data["message"]["usage"] |
| Subagent result | "user" | data["toolUseResult"]["usage"], data["toolUseResult"]["agentId"] |
A record with type == "assistant" and a top-level "message" key contains a usage object:
{
"type": "assistant",
"message": {
"usage": {
"input_tokens": ...,
"output_tokens": ...,
"cache_creation_input_tokens": ...,
"cache_read_input_tokens": ...
}
}
}
A record with type == "user" and a "toolUseResult" key that contains both "usage" and "agentId" represents a completed subagent invocation:
{
"type": "user",
"toolUseResult": {
"agentId": "...",
"prompt": "You are ...",
"usage": {
"input_tokens": ...,
"output_tokens": ...,
"cache_creation_input_tokens": ...,
"cache_read_input_tokens": ...
}
}
}
Sources: tests/claude-code/analyze-token-usage.py32-68
Data flow inside analyze-token-usage.py:
Sources: tests/claude-code/analyze-token-usage.py12-168
| Function | Signature | Purpose |
|---|---|---|
analyze_main_session | (filepath) -> (dict, dict) | Parses the entire .jsonl file; returns main_usage and subagent_usage dicts |
format_tokens | (n) -> str | Formats an integer with thousands separators |
calculate_cost | (usage, input_cost_per_m, output_cost_per_m) -> float | Computes dollar cost from token counts |
main | () -> None | CLI entry point; validates arguments, calls analysis, prints report |
Sources: tests/claude-code/analyze-token-usage.py12-168
calculate_cost uses hardcoded rates that correspond to Claude API pricing at the time the script was written:
| Token type | Rate |
|---|---|
| Input (incl. cache creation and cache read) | $3.00 per million |
| Output | $15.00 per million |
tests/claude-code/analyze-token-usage.py76-81
The formula:
total_input = input_tokens + cache_creation + cache_read
input_cost = total_input * 3.0 / 1_000_000
output_cost = output_tokens * 15.0 / 1_000_000
total_cost = input_cost + output_cost
These rates are passed as default parameters to calculate_cost, so they can be overridden if called from Python but not from the CLI.
Sources: tests/claude-code/analyze-token-usage.py76-81
The script prints a fixed-width table to stdout, one row per agent, followed by aggregate totals.
Sample column layout:
Agent Description Msgs Input Output Cache Cost
----------------------------------------------------------------------------------- --------
main Main session (coordinator) 4 12,000 3,500 8,200 $0.08
agent-abc123 an implementer subagent for Task 1 12 45,000 9,000 22,000 $0.28
...
Columns:
| Column | Source field |
|---|---|
| Agent | "main" literal, or agent_id from toolUseResult.agentId |
| Description | "Main session (coordinator)" for the main agent; first 60 chars of first line of subagent prompt, with "You are " prefix stripped |
| Msgs | count of records accumulated for this agent |
| Input | input_tokens |
| Output | output_tokens |
| Cache | cache_read_input_tokens |
| Cost | result of calculate_cost() |
After the table, the script prints total message count, each token category sum, a combined input total (raw + cache), an overall token total, and the estimated total cost.
Sources: tests/claude-code/analyze-token-usage.py96-165
When first encountering a new agentId, the script reads the "prompt" field from toolUseResult, takes the first newline-delimited line, and strips the prefix "You are " if present. The result is truncated to 60 characters and stored as the description for all subsequent messages from that agent.
tests/claude-code/analyze-token-usage.py53-60
This heuristic works because Claude Code subagent prompts typically begin with a role statement such as "You are an implementer subagent...".
python3 tests/claude-code/analyze-token-usage.py <path-to-session.jsonl>
The script exits with code 1 if fewer than one argument is provided or if the file does not exist.
tests/claude-code/analyze-token-usage.py83-93
Session files are stored by Claude Code under:
~/.claude/projects/<escaped-working-dir>/<session-id>.jsonl
where the working directory path has slashes replaced with hyphens.
tests/claude-code/test-subagent-driven-development-integration.sh165-170
Sources: tests/claude-code/analyze-token-usage.py83-168 tests/claude-code/test-subagent-driven-development-integration.sh164-171
Refresh this wiki
This wiki was recently refreshed. Please wait 3 days to refresh again.