From fe289a9d7644e05121d89e95ff23c03ba09793c5 Mon Sep 17 00:00:00 2001 From: Mohammad Junaid Date: Sat, 4 Apr 2026 14:08:34 +0100 Subject: [PATCH 1/2] fix: Windows path handling and show project basenames in top projects - Always replace backslash, forward slash and colon when slugifying paths so Windows paths match session folder slugs regardless of separator style - Expand extractUsername regex to handle C:\Users\username\... paths - Show just the project folder basename instead of full path, all platforms Closes #9 --- __tests__/stats.test.ts | 4 ++-- src/lib/stats.ts | 28 +++++++++++++++++----------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/__tests__/stats.test.ts b/__tests__/stats.test.ts index 34599df..a9d22fc 100644 --- a/__tests__/stats.test.ts +++ b/__tests__/stats.test.ts @@ -157,9 +157,9 @@ describe("computeStats", () => { it("resolves session slug paths to real project paths", () => { const stats = computeStats(richData); - // -home-user-project-a should resolve to /home/user/project-a + // -home-user-project-a should resolve to /home/user/project-a, displayed as basename const projectNames = stats.topProjectStats.map((p) => p.name); - expect(projectNames).toContain("/home/user/project-a"); + expect(projectNames).toContain("project-a"); }); it("counts tool calls from session messages", () => { diff --git a/src/lib/stats.ts b/src/lib/stats.ts index d778c22..3be54e1 100644 --- a/src/lib/stats.ts +++ b/src/lib/stats.ts @@ -195,11 +195,13 @@ export function computeStats(data: ParsedData): ComputedStats { const projectSet = new Set(); const branchSet = new Set(); const projectActivity: Record = {}; - // Build slug→realPath from history so we can resolve session folder names + // Build slug→realPath from history so we can resolve session folder names. + // Always replace \, / and : so Windows drive letters (C:\ or C:/) slug correctly + // regardless of whether history.jsonl stores backslashes or forward slashes. + const pathToSlug = (p: string) => p.replaceAll("\\", "-").replaceAll("/", "-").replaceAll(":", "-"); for (const entry of history) { if (entry.project) { - const slug = entry.project.replaceAll("/", "-"); - slugToPath[slug] = entry.project; + slugToPath[pathToSlug(entry.project)] = entry.project; projectSet.add(entry.project); } } @@ -229,11 +231,15 @@ export function computeStats(data: ParsedData): ComputedStats { } } const topProjectStats = Array.from(projectSet) - .map((name) => ({ - name, - messages: projectActivity[name] || 0, - tokens: projectTokens[name] || 0, - sessions: projectSessions[name] || 0, + .map((fullPath) => ({ + name: + fullPath + .split(fullPath.includes("\\") ? "\\" : "/") + .filter(Boolean) + .at(-1) ?? fullPath, + messages: projectActivity[fullPath] || 0, + tokens: projectTokens[fullPath] || 0, + sessions: projectSessions[fullPath] || 0, })) .sort((a, b) => b.messages - a.messages) .slice(0, 5); @@ -434,15 +440,15 @@ function extractUsername(history: HistoryEntry[], sessions: { messages: { cwd?: for (const session of sessions) { for (const msg of session.messages) { if (msg.cwd) { - // /home/username/... or /Users/username/... - const match = msg.cwd.match(/^\/(?:home|Users)\/([^/]+)/); + // /home/username/... or /Users/username/... or C:\Users\username\... + const match = msg.cwd.match(/^(?:\/(?:home|Users)\/|[A-Za-z]:\\[Uu]sers\\)([^/\\]+)/); if (match) return match[1]; } } } for (const entry of history) { if (entry.project) { - const match = entry.project.match(/^\/(?:home|Users)\/([^/]+)/); + const match = entry.project.match(/^(?:\/(?:home|Users)\/|[A-Za-z]:\\[Uu]sers\\)([^/\\]+)/); if (match) return match[1]; } } From d4e0d187470252a80a248720436afb9fa6550382 Mon Sep 17 00:00:00 2001 From: Mohammad Junaid Date: Sun, 5 Apr 2026 23:02:31 +0100 Subject: [PATCH 2/2] docs: add hi to README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 41bcf1b..d2b170e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +hi + # Claude Code Rewind > There's no way to see your Claude Code usage. We changed that. Your developer archetype. Your token costs. Your Claude ELO. Nobody else has touched this data. Find out where you actually stand.