Skip to content

Claude Code subagent transcripts are never discovered (depth-2 cap) — ~54% of messages invisible on subagent-heavy workflows #207

Closed

Description

@lizhuojunx86

Context: surfaced while validating the #204 rewrite fix in #200 — the token-exact cross-check there covers main transcripts only; this is the orthogonal coverage gap mentioned in that thread, filed separately as requested.

Summary

The Claude Code analyzer discovers only ~/.claude/projects/<slug>/<session>.jsonl. Claude Code additionally writes per-subagent transcripts under ~/.claude/projects/<slug>/<sessionId>/subagents/**/agent-<agentId>.jsonl (Task tool: Explore / general-purpose / custom agents). Those files sit at depth ≥ 4, so their usage never enters splitrail's totals, uploads, or the leaderboard.

For anyone using subagents heavily, splitrail undercounts by a large factor. On my corpus (~50 days, mixed CLI + subagent workflows), live main transcripts hold 13,704 messages / 18.5M output tokens while live subagent transcripts hold 16,160 messages / 13.7M output tokens — 54% of live messages missing.

Where the cap lives (v3.6.0)

All three discovery paths hard-code depth 2 in src/analyzers/claude_code.rs:

  • discover_data_sources() — WalkDir::new(projects_dir).min_depth(2).max_depth(2)
  • is_valid_data_path() — relative.components().count() == 2
  • get_data_glob_patterns() — "{home}/.claude/projects/*/*.jsonl"

Observed layout (Claude Code 2.1.150–2.1.198, macOS)

~/.claude/projects/<project-slug>/
├── <sessionId>.jsonl                                  # main transcript (scanned)
└── <sessionId>/subagents/
    ├── agent-<agentId>.jsonl                          # NOT scanned
    └── agent-<agentId>.meta.json                      # agentType, e.g. "Explore"

Subagent lines carry the same schema as main-transcript assistant lines (message.id, model, usage, requestId), repeat the parent sessionId, and add agentId + isSidechain: true.

Repro

# any machine that has used the Task tool / subagents:
find ~/.claude/projects -mindepth 3 -name '*.jsonl' | wc -l    # files splitrail never sees
find ~/.claude/projects -mindepth 3 -name '*.jsonl' -exec grep -l '"type":"assistant"' {} + | head

Compare splitrail stats totals before/after copying one subagent file up to depth 2 (in a scratch $HOME): the totals jump by exactly that file's usage.

Numbers from my corpus (message.id-level dedup, append-only log as reference)

class files messages outputTokens
live main transcripts (scanned) 76 13,704 18,548,947
live subagents/** (not scanned) 1,423 16,160 13,738,324

Model mix makes the blind spot obvious: on my machine splitrail sees 22 of 5,059 sonnet messages and 0 of 1,566 haiku messages — those models run almost exclusively inside subagents.

Suggested fix

Lift the depth cap and include */*/subagents/**/*.jsonl (or simply walk without max_depth and filter on .jsonl):

  • The existing cross-file dedup already keys on local_hash = fast_hash(requestId_messageId), so any duplication between main and subagent records dedups correctly (I verified token-exact agreement between 3.6.0's main-transcript totals and an independent message.id-keyed ingest — the dedup semantics are sound).
  • is_valid_data_path and the watcher need the same relaxation, plus the 3.6.0 history store keys by conversation-path hash and should be unaffected (each subagent file becomes its own conversation).
  • Heads-up for Splitrail Cloud: totals for subagent-heavy users will jump on upgrade; may be worth a release-note line.

Happy to test a branch against my corpus (same fixture as in #200's validation) and report before/after.

Activity

  1. lizhuojunx86 commented on Jul 21, 2026

    @lizhuojunx86
    ContributorAuthor

    The rewrite-side regression fixture from the same validation run is now up as #208.

  2. mike1858 commented on Jul 22, 2026

    @mike1858
    Member

    Thank you. Closed via #208 and #209.

  3. lizhuojunx86 commented on Jul 25, 2026

    @lizhuojunx86
    ContributorAuthor

    Thanks for #209 — good to see it went through the same local_hash dedup path rather than just lifting the cap; that was the part I was least sure a quick fix would get right.

    I wrote up the whole arc (#200 → 3.6.0 → the A/B validation → #207/#208 → 3.6.1) here: https://dev.to/lizhuojunx86/an-append-only-audit-log-caught-two-accounting-bugs-in-a-216-star-usage-tracker-38co — it's mostly about append-only ingest as a prerequisite for trustworthy usage accounting, with splitrail as the worked example. Your turnaround on both is in the timeline as it happened.

    Next I'll re-run the frozen-snapshot protocol on 3.6.1 and post the before/after numbers for the subagent class here — 1,423 files / 16,160 messages / 13.7M output tokens that were previously invisible. Should be a reasonable independent check on #209 at a scale that's awkward to synthesize. And re: the audit part you mentioned earlier — happy to send a one-pager on the routing_audit module whenever it's useful, no rush.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions