-
-
Notifications
You must be signed in to change notification settings - Fork 407
Description
While building a Claude Code energy monitor, I discovered that the JSONL session logs that ccusage reads contain placeholder/incomplete token values. This is an upstream Claude Code bug (not a ccusage bug), but it means ccusage's reported totals are significantly undercounted.
What's wrong upstream
Claude Code's JSONL logs write usage values from early streaming events and never update them to final values:
input_tokens: ~75% of entries have a value of 0 or 1 (streaming placeholder, never finalized). Undercount: 100-174x.output_tokens: Excludes thinking tokens (which Anthropic classifies as output tokens). Undercount: 10-17x on Opus.cache_read_input_tokensandcache_creation_input_tokens: Accurate (~1x vs ground truth).
Evidence
Comparing JSONL sums (deduplicated by requestId) against Claude Code's statusbar cumulative totals for the same day:
| Metric | JSONL (dedup) | Statusbar | Ratio |
|---|---|---|---|
| Input tokens | 41,444 | 7,199,162 | 174x |
| Output tokens | 183,829 | 3,208,365 | 17x |
| Cache read | 104,353,324 | 114,798,863 | 1.1x |
| Cache creation | 3,170,696 | 2,717,775 | 0.9x |
Cache metrics matching at ~1x confirms both sources track the same API calls — the discrepancy is in the recorded values, not missing entries.
Impact on ccusage
Cost and token reports from ccusage will be significantly lower than actual usage. For a heavy Opus day, ccusage reported ~$50 where statusbar-derived estimates put the equivalent API cost at ~$446.
Upstream issues
- anthropics/claude-code#28197 — our report (input + output)
- anthropics/claude-code#25941 — output placeholder (closed)
- anthropics/claude-code#21971 — output streaming incomplete
- anthropics/claude-code#27361 — missing
message_stopevent
Suggestion
Until this is fixed upstream, it might be worth adding a note/warning to ccusage output that input and output token counts may be understated due to known JSONL data quality issues. Full investigation: FINDINGS.md.