anthropics / anthropics/claude-code
[FEATURE] /insights: weight the corpus by volume and recency instead of counting every session equally
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 147k
- Forks
- 24k
- PR merge metrics
- PR metrics pending
Description
Preflight Checklist
- I have searched existing requests and this feature hasn't been requested yet
- This is a single feature request (not multiple features)
Not a scoping request, and deliberately not filed on #95543. #95543 asks for a load-time filter — which sessions the report reads. This asks how the sessions it has already read should be weighted once it has them: a different code path, at a different stage, and useful even to someone who only ever works in one repository. I am keeping them apart rather than growing that issue, and nothing here asks for any change to it.
Problem Statement
/insights treats every session record as one equal unit of evidence, and treats a session from nine weeks ago exactly as it treats this morning's. Both are wrong, and they are wrong in different directions.
Measured on my machine (~/.claude/usage-data/session-meta/, 4,294 records, v2.1.278, 2026-09-19):
1. Most records are not sessions. 3,301 of the 4,294 — 76.9% — carry exactly 2 "messages", zero assistant turns, zero tool calls, zero tokens, zero duration, and first_prompt: "No prompt". Opening their transcripts shows what they are: a session that ran one local slash command and exited before any model turn ever happened.
7f020908-….jsonl 10 lines {'queue-operation': 2, 'attachment': 4, 'user': 2, 'system': 1, 'last-prompt': 1}
| <command-name>/usage</command-name>
Only 945 records (22.0%) contain any assistant turn or any tool call at all. A /usage invocation is counted as a session, sits in the report's denominator, and sits in the sampling pool beside a six-hour build session.
2. Among the real ones, volume is a spike, not a distribution. Across one project of mine — 53 records, 1,185 messages:
| median messages per session | 2 |
| sessions carrying ≤5 messages | 45 of 53 (85%), 90 messages between them — 7.6% of the project's volume |
| share carried by the single largest session | 37.3% |
| share carried by the top five | 80.3% |
Machine-wide the same shape: median 2 messages per session, and the top 10% of records carry 81.8% of all messages.
A uniform sample over records is therefore mostly a sample of stubs, and the handful of sessions where the design decisions were taken and the friction actually happened are precisely the ones it misses. My most recent report header reads 4,956 sessions total · 490 analyzed. If that sample is uniform over records, its expected substantive content is about 108 real sessions out of 490 — and the report says nothing about this, so a reader has no way to discount for it.
This is a plausible mechanic behind the standing "empty report" reports (#64275, #83849, #83695, #81679) and behind the coverage complaints (#23194, #54063, #26300, all three closed by the stale bot): thin narrative is the correct output for a corpus that thin, and analysing more records does not help if three quarters of the additional records are empty.
3. Old and new sessions answer different questions, and averaging them answers neither. The normal shape of real project work is a dense build phase — days long, where the architecture gets set and most of the volume lands — followed by weeks of short check-ins. Both matter:
- the build sessions carry the durable picture: how this thing is structured, what its recurring friction is, what was started and never finished
- the recent sessions carry the live picture: what is in front of me today
Flattened into one average, the durable findings get diluted by check-in noise, and the live findings get diluted by decisions taken two months ago. The "Suggested CLAUDE.md Additions" section is where this bites hardest, because it emits copy-pasteable rules: a rule derived from a build phase that ended six weeks ago is offered with the same confidence as one derived from this week.
Proposed Solution
One change with two dimensions of the same weight. No new data is needed — start_time, user_message_count, assistant_message_count, duration_minutes, tool_counts and lines_added/lines_removed are already top-level fields on every session-meta record.
Weight by volume, not by record count. Sample and weight on messages, tool calls or duration rather than on records, so the analysed corpus is proportional to where the work actually happened. The minimum viable version is a single substantive-session predicate applied before sampling:
const substantive = s => s.assistant_message_count > 0 || Object.keys(s.tool_counts ?? {}).length > 0
On my machine that removes 76.9% of the population and changes nothing else about how the report is produced.
Weight by recency, and show the two horizons separately rather than averaging them. Keep older sessions at full weight for the structural sections and weight them down for the current ones, then say which is which:
- Standing — patterns across the whole in-scope history: recurring friction, unfinished threads, things repeatedly started and never landed. Recency-flat.
- Live — the current window: what this project is doing now, what is going wrong now. Recency-weighted.
- Recommendations, split into now and later — the actions that follow from Live, and the actions that follow from Standing.
That split is the part I actually want. "Here is what you have never got round to, across everything" and "here is what is hitting you this week" are two different reports, and today they are averaged into one that is neither.
State the weighting in the header. Alongside the existing counts, print how many in-scope records were substantive and what share of in-scope messages the analysed sample covers. A reader can then see whether the narrative rests on anything, which today is not inspectable at all.
Alternative Solutions
- Date-range filtering (
--since/--until), requested repeatedly (#23323, #29539, both stale-closed). Blunter: it discards the older sessions rather than weighting them, so the standing picture is lost rather than separated out. It also does nothing about the 77% of records that are empty regardless of date. - Analysing more sessions (the ask in #23194, #54063 and #26300). Raising the sample size over an unweighted population raises the stub count proportionally. Coverage and weighting are different problems and the second one does not go away when the first is fixed.
- Reading the report and discounting mentally. Not possible — the report states neither the age distribution of its sample nor how much of it is zero-signal.
Priority
High - Significant impact on productivity
Feature Category
Other
Use Case Example
-
I open
/insightswanting two things: what I keep failing to finish on this codebase, and what I should do about this week. -
The corpus it draws on is 4,294 records, of which 945 contain anything at all. A uniform 490-record sample is mostly
/usagestubs. -
The one session in which I actually designed the thing — 442 messages, 37.3% of the project's entire volume — is a single record, no more likely to be sampled than a stub, and if sampled it is weighted the same as one.
-
The result is a narrative with no way to tell whether it rests on that session or on nothing, and a recommendations section that mixes "you never finished the migration you started in July" with "your tool errors spiked yesterday" at equal confidence and in no particular order.
-
With volume weighting, the design session dominates the corpus in proportion to the work in it. With the horizon split, "never finished the migration" appears under Standing and "tool errors spiked yesterday" under Live, and the recommendations say which of the two I should act on before Monday.
Additional Context
The figures above are reproducible from ~/.claude/usage-data/session-meta/*.json and the corresponding transcripts under ~/.claude/projects/; happy to attach the scripts. The zero-signal measurement also appears in #95543, where it bears on a different argument — that issue is about which records are read, this one is about what a record is worth once read. Neither depends on the other shipping first, though scoping first makes the weighting more visible.
Environment: Claude Code 2.1.278, Linux (Ubuntu LTS), 4,294 session-meta records of which 945 substantive.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating the /insights entry point and the code that reads ~/.claude/usage-data/session-meta/*.json and transcripts under ~/.claude/projects/. Trace how records are sampled and how the report is assembled. Done means the report distinguishes substantive records, volume and recency horizons, and states the relevant coverage and weighting in its header.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- analytics, cli
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100