Durable stats ledger independent of session jsonl files

Open 💬 2 comments Opened May 26, 2026 by karlkfi

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

/stats (sessions, messages, tokens) is computed by scanning
~/.claude/projects/*/*.jsonl. Any operation that removes those files
silently erases the corresponding history from stats. There are at least
three paths that hit this today:

  1. Default cleanupPeriodDays: 30 auto-deletes old session jsonls

(root-cause analysis in #22123 — now closed/locked).

  1. Auto-updates have been observed to delete jsonls (#41591).
  2. User housekeeping. In my case: I work in a repo with many

short-lived git worktrees, each producing a session jsonl under
~/.claude/projects/-…-claude-worktrees-<name>/<uuid>.jsonl. After a
few weeks I have 50+ project dirs for worktrees that no longer exist
on disk. Cleaning them up — the obvious thing to do — silently nukes
those sessions, messages, and tokens from /stats.

The cleanupPeriodDays: 3650 workaround stops the bleeding from path
(1) but doesn't address (2) or (3). It also turns ~/.claude/projects/
into an append-only graveyard the user can't safely curate.

Proposed Solution

Persist aggregate stats in a ledger that is independent of session-jsonl
presence. Concretely: as each session ends (or incrementally during the
session), roll up its key metrics — id, project, model, input/output/
cache tokens, message count, started_at, ended_at — and append to e.g.
~/.claude/usage.jsonl (or whatever store fits best).

/stats and any future claude usage command (see #33978) read from
the ledger, not by re-scanning jsonls. The jsonls remain authoritative
for resuming a session, but their presence is no longer required for
stats to be accurate.

Benefit

  • Users can archive or delete old session jsonls (defunct worktrees,

stale projects) without destroying their lifetime totals.

  • Auto-cleanup (#22123) and auto-update deletion (#41591) stop being

data-loss events for stats.

  • Provides a stable foundation for richer analytics (#33978) without

re-parsing 100MB+ jsonl files on every /stats invocation.

Related

  • #22123 — closed/locked; root-cause analysis and suggested fix

("Separate stats storage from transient session files") that this
request formalizes.

  • #41591 — same data-loss class, different trigger.
  • #33978 — would build cleanly on top of a durable ledger.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗