Dataset: ~/.claude history of one developer, 88 Claude Code threads, 262 session files, ~6 months. Verified 2026-04-19 on warehouse-full.sqlite.
If you count Claude Code .jsonl session files per thread, you get a number that looks like “retry count” — but 100% of it is subagent spawning, not the user retrying. On this dataset, zero threads have more than one main session.
Most AI-usage dashboards (including an early version of this one) compute something like:
attempt_count = count of session files per thread
retry_count = attempt_count - 1
Intuition: if a thread has 3 session files, the user probably restarted twice. This intuition is wrong for Claude Code.
Claude Code stores each subagent invocation as a separate .jsonl file, named agent-<uuid>.jsonl (or subagents/agent-acompact-<uuid>.jsonl for compact subagents). These files are siblings of the main thread’s <uuid>.jsonl file and share the same parent thread_id. A naive “file-per-attempt” counter treats every Agent tool_use — every time Claude internally delegates work to a subagent — as if the user had retried.
On this dataset:
| Dimension | Count |
|---|---|
| Claude sessions total | 262 |
| ↳ main sessions (UUID-named files) | 88 |
↳ subagent sessions (agent-*.jsonl) |
156 |
↳ compact subagent sessions (subagents/agent-acompact-*) |
18 |
Claude threads with main_sessions > 1 |
0 / 88 |
Codex threads with sessions > 1 (no subagent mechanism exists in Codex) |
0 / 72 |
Warehouse-wide threads with main_attempt_count > 1 |
0 / 160 |
Thread distribution by subagent count: 51 threads have 0 subagents, 15 have 1, rest trail off to a single outlier with 17 subagents.
The rule that distinguishes main from subagent is purely filename-based and 100% deterministic on this dataset:
def session_kind(session_path: str) -> str:
base = os.path.basename(session_path)
if base.startswith('agent-') or '/subagents/' in session_path:
return 'subagent'
return 'main'
No regex over payload, no LLM, no heuristics. Also cross-verified: on one sampled thread, every Agent tool_use event in the main session has a matching agent-<uuid>.jsonl file with timestamp within 3ms of the tool_use event.
--continue usage after crashes).unknown if filenames stop matching the known patterns.rollout-<timestamp>-<uuid>.jsonl); other tools may differ.