Skip to main content

parse_jsonl_entries

Function parse_jsonl_entries 

Source
pub fn parse_jsonl_entries(path: &Path) -> Result<ParsedJsonl>
Expand description

Parse a single JSONL file into one UsageEntry per unique message.id.

Pure function: depends only on the file contents. Non-assistant entries, malformed lines, and missing IDs are skipped silently.

Dedup is split by field semantics, because Claude Code emits one JSONL row per assistant content block (thinking / text / each tool_use) all sharing the same message.id:

  • Billing fields (token counts, model, timestamp, session_id) come from the first row seen for each id — they repeat identically across rows.
  • Content fields (tool_uses, text_chars, and the bash commands fed to the activity classifier) are unioned across every row with that id, then activity is classified once at the end using the merged content.

Folding only by message.id (as this parser did before 2026-05-13) drops every tool_use after the first row, which made the Toolkit and Usage tool counters undercount by an order of magnitude. The chat parser already uses (message_id + content) for the same reason — see CLAUDE.md.

Runs a rolling last_user_text cursor during the stream: each genuine type: "user" row updates it; the snapshot taken at the first row of each assistant message is used for activity classification.