Repository navigation
Conversation
When neither session duration nor speed metrics are requested, the
transcript scan only reads usage records, compact boundaries, effort
stdout, and custom-title records. Each of these carries a fixed
printable-ASCII marker ("usage", "compact_boundary",
"<local-command-stdout>Set ", "custom-title"). JSON can only spell those
characters differently with a -~ escape. A line with neither
a marker nor such an escape therefore cannot change any enabled
collector, and it is skipped before JSON.parse. The recursive agentId
walk (speed widgets only) gets the same guard with the "agentId" marker.
ANSI \u001b escapes in tool output do not trigger the guard.
A differential test builds seeded corpora with escaped keys and values,
odd whitespace, malformed lines, CRLF, BOM, nested and escaped agentIds,
and subagent files. It compares each against a copy that forces the full
parse on every line, over every option set. Dropping any marker or the
escape guard makes it fail.
Measured (node dist, 20 interleaved passes, load1 ~17 on 6 cores), CPU
median per render on a real 60 MB Claude Code transcript: token widgets
3389 -> 2758 ms (-19%), all widgets 4996 -> 4513 ms (-10%). On the
synthetic 50 MB corpus: -5%. Analysis output is identical on 160 real
transcript x option runs, and stdout is byte-identical on 99
config/payload pairs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
BLUF
JSON.parseon every line (tool results and attachments are most of the bytes).JSON.parse. The recursiveagentIdwalk (speed widgets only) gets the same guard.Details
With neither session duration nor speed metrics requested, each collector reads only these records:
message.usage, compact boundary"usage","compact_boundary"subtype: "compact_boundary""compact_boundary"<local-command-stdout>Set(shared start of both prefixes, now exported fromjsonl-metadata.ts)type: "custom-title""custom-title"agentIdstring"agentId"Soundness:
–~escape. Any line matching/\\u00[2-7]/is always parsed.\u001bfrom ANSI-colored tool output, which accounts for about 30% of the bytes in the real transcript measured here.agentIdwalk stays guarded in that case.Tests (
jsonl-metrics-prefilter.test.ts):stop_reason, sidechain, and API-error recordsagentIdnested in arrays, empty, and spelledagentIdusage,compact_boundary,custom-titleA. That copy forces the unfiltered path on every line. The comparison covers all 16 option sets: speed, compaction, effort, name.Overlap: #591 (ours) and #622 change token counting in
src/utils/jsonl-metrics.ts. #634 (ours) addsincludeTokenMetricsthere. This PR only touches the scan loop and adds the marker helpers, so conflicts would be mechanical. The two perf PRs are independent: #634 skips the scan when nothing reads it, and this PR makes the scans that remain cheaper.Measurements
node dist/ccstatusline.js. Base and patched arms were interleaved round-robin in one run with 20 passes plus anode -e 0control. CPU is user+sys including children, in ms. Settings usegitCacheTtlSeconds: 0. "Token widgets" means the default widgets plustokens-total,tokens-input,compaction-counter, andsession-name. "All widgets" is every widget, including speed and session clock.node -e 0Load1 during the run was min 10.7, median 17.1, max 20.2 on 6 cores. The host was loaded, so compare ratios. The saving depends on how many bytes sit in marker-free lines. The synthetic corpus has short tool results and no escapes, so it gains less than a real session.
Equivalence:
getTranscriptAnalysisonmainand on this branch matched on 160 runs: 10 real transcripts, some with subagents, times 16 option sets.Checks
bun run lint: clean.bun run build: OK.bun teston the jsonl, metrics, compaction, speed, and prefilter suites: 74 pass. The full suite has the same host-load flakes as unmodifiedmainon this machine:fetchUsageData error handling,custom command capture, and TUI menu timeouts. None of them touch this code.🤖 Generated with Claude Code