Derive project/session stats from transcripts instead of history.jsonl - #2
Open
vvzvlad wants to merge 1 commit into
Open
Derive project/session stats from transcripts instead of history.jsonl#2vvzvlad wants to merge 1 commit into
vvzvlad wants to merge 1 commit into
Conversation
list_projects, find_patterns, get_project_context and get_session_summary read conversation stats from ~/.claude/history.jsonl, which is barely populated under VSCode-extension / Agent-SDK usage (only slash commands land there). They reported ~5 projects / 6 sessions while the real per-session transcripts in ~/.claude/projects hold hundreds of sessions across dozens of projects. Add src/parsers/transcript-history.ts: - parseSessionUserPrompts(): pure parser -> HistoryEntry[], one entry per genuine user prompt; skips meta turns, tool-result turns, empty turns and Claude Code injected non-prompt turns (<task-notification>, <ide_opened_file>, slash-command wrappers, ...). Project resolved from the in-transcript cwd (encoded dir fallback). - parseTranscriptHistory(): enumerates all session files with a per-file cache (mtime+size) so only changed files are re-read; prunes deleted files. Switch the four tools to parseTranscriptHistory(); HistoryEntry shape and all downstream helpers are unchanged. parseHistoryFile() is left intact. Add tests/parsers/transcript-history.test.ts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jhammant
approved these changes
Aug 10, 2026
jhammant
left a comment
Owner
There was a problem hiding this comment.
Apologies for the very slow response — two months is not the turnaround you deserved.
Reviewed and approving. Deriving from the session transcripts instead of history.jsonl is correct, and the undercount you describe is real: under the VSCode extension and Agent SDK that file barely gets written, so list_projects and find_patterns were reporting a fraction of actual usage.
Resolving the project from the first cwd in the file rather than decoding the dashed directory name is the better call too — it handles worktrees, which the encoded form can't do unambiguously. Nice touch keeping HistoryEntry[] as the boundary so the tool bodies didn't have to change.
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.
Problem
list_projects,find_patterns,get_project_contextand by-project lookup inget_session_summaryall read conversation statistics from~/.claude/history.jsonlthroughparseHistoryFile().I use Claude Code almost only through VS Code extension / Agent SDK, and in this setup
~/.claude/history.jsonlis almost never written — mine had captured only few slash commands — even there was hundreds of real session transcripts under~/.claude/projects/. Solist_projectsshowed 5 projects / 6 sessions, but actually i had 17 projects and 300+ sessions. Full-text search tools were fine, because they already index the transcripts; onlyhistory.jsonl-based tools undercount.Fix
I add
src/parsers/transcript-history.ts, which build the sameHistoryEntry[]shape from per-session transcripts instead ofhistory.jsonl, so all downstream helpers and tool bodies stay unchanged — only the data source swaps:parseSessionUserPrompts(content, sessionId, fallbackProject)— pure, IO-free, unit-testable. Turns one transcript into oneHistoryEntryper genuine user prompt. Skips meta turns (isMeta), tool-result turns (toolUseResult), empty turns, and Claude Code injected non-prompt user turns (<task-notification>,<ide_opened_file>,<ide_selection>, slash-command wrappers,<local-command-stdout>, ...). The project is resolved from in-transcriptcwd(with fallback to the encoded project dir, whichextractProjectNamealready handle).parseTranscriptHistory()— enumerates all session files (reuseenumerateSessionFiles) with per-file cache keyed onmtime+size, so on next calls only changed files are re-read; entries for deleted files are pruned.Then switch the four tools to
parseTranscriptHistory().parseHistoryFile()is left intact (still used by its test). Addedtests/parsers/transcript-history.test.ts.Result
list_projects: 5 → 17 projects, with correct session/message counts and realcwdpaths.find_patterns: now reports 325 sessions with meaningful topic / activity / issue breakdowns instead of almost empty sample.npx tsccompiles clean and full vitest suite passes (86 tests, including new parser tests). No behavior change for search/index/sync paths.