buildpartner 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/dist/bin/cli.d.ts +2 -0
  2. package/dist/bin/cli.js +44 -0
  3. package/dist/bin/cli.js.map +1 -0
  4. package/dist/src/api-client.d.ts +18 -0
  5. package/dist/src/api-client.js +74 -0
  6. package/dist/src/api-client.js.map +1 -0
  7. package/dist/src/classifiers/activity-classifier.d.ts +12 -0
  8. package/dist/src/classifiers/activity-classifier.js +300 -0
  9. package/dist/src/classifiers/activity-classifier.js.map +1 -0
  10. package/dist/src/classifiers/path-detector.d.ts +33 -0
  11. package/dist/src/classifiers/path-detector.js +98 -0
  12. package/dist/src/classifiers/path-detector.js.map +1 -0
  13. package/dist/src/commands/log-session.d.ts +10 -0
  14. package/dist/src/commands/log-session.js +162 -0
  15. package/dist/src/commands/log-session.js.map +1 -0
  16. package/dist/src/commands/serve.d.ts +1 -0
  17. package/dist/src/commands/serve.js +5 -0
  18. package/dist/src/commands/serve.js.map +1 -0
  19. package/dist/src/commands/setup.d.ts +1 -0
  20. package/dist/src/commands/setup.js +578 -0
  21. package/dist/src/commands/setup.js.map +1 -0
  22. package/dist/src/constants.d.ts +9 -0
  23. package/dist/src/constants.js +12 -0
  24. package/dist/src/constants.js.map +1 -0
  25. package/dist/src/installer/hook-installer.d.ts +19 -0
  26. package/dist/src/installer/hook-installer.js +114 -0
  27. package/dist/src/installer/hook-installer.js.map +1 -0
  28. package/dist/src/installer/mcp-installer.d.ts +9 -0
  29. package/dist/src/installer/mcp-installer.js +80 -0
  30. package/dist/src/installer/mcp-installer.js.map +1 -0
  31. package/dist/src/installer/skill-installer.d.ts +5 -0
  32. package/dist/src/installer/skill-installer.js +55 -0
  33. package/dist/src/installer/skill-installer.js.map +1 -0
  34. package/dist/src/installer/skill-sync.d.ts +10 -0
  35. package/dist/src/installer/skill-sync.js +76 -0
  36. package/dist/src/installer/skill-sync.js.map +1 -0
  37. package/dist/src/mcp/server.d.ts +3 -0
  38. package/dist/src/mcp/server.js +106 -0
  39. package/dist/src/mcp/server.js.map +1 -0
  40. package/dist/src/mcp/subscription-gate.d.ts +19 -0
  41. package/dist/src/mcp/subscription-gate.js +74 -0
  42. package/dist/src/mcp/subscription-gate.js.map +1 -0
  43. package/dist/src/mcp/tools/ai-profile.d.ts +88 -0
  44. package/dist/src/mcp/tools/ai-profile.js +123 -0
  45. package/dist/src/mcp/tools/ai-profile.js.map +1 -0
  46. package/dist/src/mcp/tools/classify-session.d.ts +31 -0
  47. package/dist/src/mcp/tools/classify-session.js +34 -0
  48. package/dist/src/mcp/tools/classify-session.js.map +1 -0
  49. package/dist/src/mcp/tools/get-knowledge.d.ts +25 -0
  50. package/dist/src/mcp/tools/get-knowledge.js +31 -0
  51. package/dist/src/mcp/tools/get-knowledge.js.map +1 -0
  52. package/dist/src/mcp/tools/get-profile.d.ts +1 -0
  53. package/dist/src/mcp/tools/get-profile.js +77 -0
  54. package/dist/src/mcp/tools/get-profile.js.map +1 -0
  55. package/dist/src/mcp/tools/get-stats.d.ts +58 -0
  56. package/dist/src/mcp/tools/get-stats.js +135 -0
  57. package/dist/src/mcp/tools/get-stats.js.map +1 -0
  58. package/dist/src/mcp/tools/get-suggestions.d.ts +7 -0
  59. package/dist/src/mcp/tools/get-suggestions.js +176 -0
  60. package/dist/src/mcp/tools/get-suggestions.js.map +1 -0
  61. package/dist/src/mcp/tools/get-training.d.ts +48 -0
  62. package/dist/src/mcp/tools/get-training.js +102 -0
  63. package/dist/src/mcp/tools/get-training.js.map +1 -0
  64. package/dist/src/mcp/tools/log-highlight.d.ts +32 -0
  65. package/dist/src/mcp/tools/log-highlight.js +39 -0
  66. package/dist/src/mcp/tools/log-highlight.js.map +1 -0
  67. package/dist/src/mcp/tools/quest.d.ts +78 -0
  68. package/dist/src/mcp/tools/quest.js +72 -0
  69. package/dist/src/mcp/tools/quest.js.map +1 -0
  70. package/dist/src/mcp/tools/web-search.d.ts +15 -0
  71. package/dist/src/mcp/tools/web-search.js +17 -0
  72. package/dist/src/mcp/tools/web-search.js.map +1 -0
  73. package/dist/src/readers/history-reader.d.ts +28 -0
  74. package/dist/src/readers/history-reader.js +83 -0
  75. package/dist/src/readers/history-reader.js.map +1 -0
  76. package/dist/src/readers/session-reader.d.ts +89 -0
  77. package/dist/src/readers/session-reader.js +310 -0
  78. package/dist/src/readers/session-reader.js.map +1 -0
  79. package/dist/src/readers/stats-reader.d.ts +38 -0
  80. package/dist/src/readers/stats-reader.js +125 -0
  81. package/dist/src/readers/stats-reader.js.map +1 -0
  82. package/dist/src/store/local-store.d.ts +72 -0
  83. package/dist/src/store/local-store.js +145 -0
  84. package/dist/src/store/local-store.js.map +1 -0
  85. package/dist/src/store/quest-store.d.ts +77 -0
  86. package/dist/src/store/quest-store.js +309 -0
  87. package/dist/src/store/quest-store.js.map +1 -0
  88. package/dist/src/store/status-store.d.ts +73 -0
  89. package/dist/src/store/status-store.js +372 -0
  90. package/dist/src/store/status-store.js.map +1 -0
  91. package/dist/src/suggestions/rules.d.ts +1 -0
  92. package/dist/src/suggestions/rules.js +2 -0
  93. package/dist/src/suggestions/rules.js.map +1 -0
  94. package/dist/src/suggestions/video-links.d.ts +1 -0
  95. package/dist/src/suggestions/video-links.js +2 -0
  96. package/dist/src/suggestions/video-links.js.map +1 -0
  97. package/package.json +35 -0
  98. package/skills/he-coach/SKILL.md +56 -0
  99. package/skills/he-consult/SKILL.md +43 -0
  100. package/skills/he-enhance-claude-md/SKILL.md +58 -0
  101. package/skills/he-flex-socials/SKILL.md +50 -0
  102. package/skills/he-full-audit/SKILL.md +119 -0
  103. package/skills/he-improve-skill/SKILL.md +111 -0
  104. package/skills/he-interview/SKILL.md +54 -0
  105. package/skills/he-life-story/SKILL.md +64 -0
  106. package/skills/he-log-experience/SKILL.md +68 -0
  107. package/skills/he-open-dashboard/SKILL.md +27 -0
  108. package/skills/he-quest-status/SKILL.md +48 -0
  109. package/skills/he-recap-week/SKILL.md +49 -0
@@ -0,0 +1,83 @@
1
+ import { readFileSync } from "fs";
2
+ import { join } from "path";
3
+ import { homedir } from "os";
4
+ const HISTORY_PATH = join(homedir(), ".claude", "history.jsonl");
5
+ /**
6
+ * Parse ~/.claude/history.jsonl — the prompt history log.
7
+ * Each line is a JSON object representing a user prompt submission.
8
+ */
9
+ export function readHistory() {
10
+ let raw;
11
+ try {
12
+ raw = readFileSync(HISTORY_PATH, "utf-8");
13
+ }
14
+ catch {
15
+ return [];
16
+ }
17
+ const entries = [];
18
+ for (const line of raw.split("\n")) {
19
+ const trimmed = line.trim();
20
+ if (!trimmed)
21
+ continue;
22
+ try {
23
+ const obj = JSON.parse(trimmed);
24
+ if (obj.sessionId && obj.timestamp) {
25
+ entries.push(obj);
26
+ }
27
+ }
28
+ catch {
29
+ // Skip malformed lines
30
+ }
31
+ }
32
+ return entries;
33
+ }
34
+ /**
35
+ * Get a summary of history data: session counts, project list, date range.
36
+ */
37
+ export function getHistorySummary() {
38
+ const entries = readHistory();
39
+ const sessions = new Set();
40
+ const sessionsByProject = {};
41
+ let firstTimestamp = null;
42
+ let lastTimestamp = null;
43
+ for (const entry of entries) {
44
+ sessions.add(entry.sessionId);
45
+ if (!sessionsByProject[entry.project]) {
46
+ sessionsByProject[entry.project] = new Set();
47
+ }
48
+ sessionsByProject[entry.project].add(entry.sessionId);
49
+ if (firstTimestamp === null || entry.timestamp < firstTimestamp) {
50
+ firstTimestamp = entry.timestamp;
51
+ }
52
+ if (lastTimestamp === null || entry.timestamp > lastTimestamp) {
53
+ lastTimestamp = entry.timestamp;
54
+ }
55
+ }
56
+ return {
57
+ totalEntries: entries.length,
58
+ uniqueSessions: sessions.size,
59
+ uniqueProjects: Object.keys(sessionsByProject).sort(),
60
+ firstTimestamp,
61
+ lastTimestamp,
62
+ sessionsByProject,
63
+ };
64
+ }
65
+ /**
66
+ * Get all unique session IDs grouped by project path.
67
+ */
68
+ export function getSessionsByProject() {
69
+ const entries = readHistory();
70
+ const map = {};
71
+ for (const entry of entries) {
72
+ if (!map[entry.project]) {
73
+ map[entry.project] = new Set();
74
+ }
75
+ map[entry.project].add(entry.sessionId);
76
+ }
77
+ const result = {};
78
+ for (const [project, sessions] of Object.entries(map)) {
79
+ result[project] = [...sessions];
80
+ }
81
+ return result;
82
+ }
83
+ //# sourceMappingURL=history-reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-reader.js","sourceRoot":"","sources":["../../../src/readers/history-reader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ /** A single message in a session JSONL file. */
2
+ export interface SessionMessage {
3
+ type: "user" | "assistant" | "summary" | "system" | "progress" | "file-history-snapshot";
4
+ userType?: "external" | "internal";
5
+ message?: {
6
+ role: string;
7
+ content: string | ContentBlock[];
8
+ model?: string;
9
+ };
10
+ uuid?: string;
11
+ parentUuid?: string | null;
12
+ timestamp?: string;
13
+ sessionId?: string;
14
+ cwd?: string;
15
+ version?: string;
16
+ gitBranch?: string;
17
+ permissionMode?: string;
18
+ summary?: string;
19
+ slug?: string;
20
+ }
21
+ export interface ContentBlock {
22
+ type: "text" | "tool_use" | "tool_result" | "thinking";
23
+ text?: string;
24
+ thinking?: string;
25
+ name?: string;
26
+ input?: Record<string, unknown>;
27
+ id?: string;
28
+ }
29
+ /** Parsed session with extracted metadata. */
30
+ export interface ParsedSession {
31
+ sessionId: string;
32
+ projectPath: string;
33
+ projectDirName: string;
34
+ startTime: string | null;
35
+ endTime: string | null;
36
+ userPromptCount: number;
37
+ toolCalls: ToolCall[];
38
+ filesTouched: string[];
39
+ summary: string | null;
40
+ gitBranch: string | null;
41
+ slug: string | null;
42
+ permissionMode: string | null;
43
+ }
44
+ export interface ToolCall {
45
+ name: string;
46
+ input: Record<string, unknown>;
47
+ }
48
+ /**
49
+ * Convert a project working directory to the Claude projects folder name.
50
+ * e.g. "/Users/austinmarchese/code/incubator-website" -> "-Users-austinmarchese-code-incubator-website"
51
+ */
52
+ export declare function projectPathToDirName(projectPath: string): string;
53
+ /**
54
+ * List all project directories in ~/.claude/projects/
55
+ */
56
+ export declare function listProjects(): string[];
57
+ /**
58
+ * List all session JSONL files for a given project directory name.
59
+ */
60
+ export declare function listSessionFiles(projectDirName: string): string[];
61
+ /**
62
+ * List ALL session JSONL files across all projects.
63
+ */
64
+ export declare function listAllSessionFiles(): {
65
+ projectDirName: string;
66
+ filePath: string;
67
+ }[];
68
+ /**
69
+ * Parse a single session JSONL file into structured data.
70
+ */
71
+ export declare function parseSession(filePath: string): ParsedSession | null;
72
+ /**
73
+ * Parse all sessions across all projects.
74
+ */
75
+ export declare function parseAllSessions(): ParsedSession[];
76
+ /** Workspace and tooling data extracted from a session. */
77
+ export interface SessionTooling {
78
+ mcpServersUsed: string[];
79
+ mcpToolCounts: Record<string, number>;
80
+ skillsInvoked: string[];
81
+ toolCounts: Record<string, number>;
82
+ appsDetected: string[];
83
+ editorsDetected: string[];
84
+ techStack: string[];
85
+ }
86
+ /**
87
+ * Extract MCP servers, skills, tool counts, and workspace apps from a parsed session.
88
+ */
89
+ export declare function extractTooling(session: ParsedSession): SessionTooling;
@@ -0,0 +1,310 @@
1
+ import { readFileSync, readdirSync, statSync } from "fs";
2
+ import { join, basename } from "path";
3
+ import { homedir } from "os";
4
+ const PROJECTS_DIR = join(homedir(), ".claude", "projects");
5
+ /**
6
+ * Convert a project working directory to the Claude projects folder name.
7
+ * e.g. "/Users/austinmarchese/code/incubator-website" -> "-Users-austinmarchese-code-incubator-website"
8
+ */
9
+ export function projectPathToDirName(projectPath) {
10
+ return projectPath.replace(/\//g, "-");
11
+ }
12
+ /**
13
+ * List all project directories in ~/.claude/projects/
14
+ */
15
+ export function listProjects() {
16
+ try {
17
+ return readdirSync(PROJECTS_DIR).filter((name) => {
18
+ const full = join(PROJECTS_DIR, name);
19
+ return statSync(full).isDirectory();
20
+ });
21
+ }
22
+ catch {
23
+ return [];
24
+ }
25
+ }
26
+ /**
27
+ * List all session JSONL files for a given project directory name.
28
+ */
29
+ export function listSessionFiles(projectDirName) {
30
+ const dir = join(PROJECTS_DIR, projectDirName);
31
+ try {
32
+ return readdirSync(dir)
33
+ .filter((f) => f.endsWith(".jsonl"))
34
+ .map((f) => join(dir, f));
35
+ }
36
+ catch {
37
+ return [];
38
+ }
39
+ }
40
+ /**
41
+ * List ALL session JSONL files across all projects.
42
+ */
43
+ export function listAllSessionFiles() {
44
+ const results = [];
45
+ for (const projectDir of listProjects()) {
46
+ for (const filePath of listSessionFiles(projectDir)) {
47
+ results.push({ projectDirName: projectDir, filePath });
48
+ }
49
+ }
50
+ return results;
51
+ }
52
+ /**
53
+ * Parse a single session JSONL file into structured data.
54
+ */
55
+ export function parseSession(filePath) {
56
+ let raw;
57
+ try {
58
+ raw = readFileSync(filePath, "utf-8");
59
+ }
60
+ catch {
61
+ return null;
62
+ }
63
+ const messages = [];
64
+ for (const line of raw.split("\n")) {
65
+ const trimmed = line.trim();
66
+ if (!trimmed)
67
+ continue;
68
+ try {
69
+ messages.push(JSON.parse(trimmed));
70
+ }
71
+ catch {
72
+ // Skip malformed lines
73
+ }
74
+ }
75
+ if (messages.length === 0)
76
+ return null;
77
+ let sessionId = "";
78
+ let projectPath = "";
79
+ let startTime = null;
80
+ let endTime = null;
81
+ let userPromptCount = 0;
82
+ let summary = null;
83
+ let gitBranch = null;
84
+ let slug = null;
85
+ let permissionMode = null;
86
+ const toolCalls = [];
87
+ const filesSet = new Set();
88
+ for (const msg of messages) {
89
+ // Extract session metadata from any message that has it
90
+ if (msg.sessionId && !sessionId)
91
+ sessionId = msg.sessionId;
92
+ if (msg.cwd && !projectPath)
93
+ projectPath = msg.cwd;
94
+ if (msg.gitBranch && !gitBranch)
95
+ gitBranch = msg.gitBranch;
96
+ if (msg.slug && !slug)
97
+ slug = msg.slug;
98
+ if (msg.permissionMode && !permissionMode)
99
+ permissionMode = msg.permissionMode;
100
+ // Track timestamps
101
+ if (msg.timestamp) {
102
+ if (!startTime || msg.timestamp < startTime)
103
+ startTime = msg.timestamp;
104
+ if (!endTime || msg.timestamp > endTime)
105
+ endTime = msg.timestamp;
106
+ }
107
+ // Count user prompts (external only, not subagent messages)
108
+ if (msg.type === "user" && msg.userType === "external") {
109
+ userPromptCount++;
110
+ }
111
+ // Extract summary
112
+ if (msg.type === "summary" && msg.summary) {
113
+ summary = msg.summary;
114
+ }
115
+ // Extract tool calls from assistant messages
116
+ if (msg.type === "assistant" && msg.message?.content) {
117
+ const content = msg.message.content;
118
+ if (Array.isArray(content)) {
119
+ for (const block of content) {
120
+ if (block.type === "tool_use" && block.name) {
121
+ const input = block.input || {};
122
+ toolCalls.push({ name: block.name, input });
123
+ // Extract file paths from tool inputs
124
+ const filePath = input.file_path ||
125
+ input.path ||
126
+ "";
127
+ if (filePath && filePath.startsWith("/")) {
128
+ filesSet.add(filePath);
129
+ }
130
+ // Extract file paths from Bash commands
131
+ if (block.name === "Bash" && typeof input.command === "string") {
132
+ extractFilePathsFromCommand(input.command, filesSet);
133
+ }
134
+ }
135
+ }
136
+ }
137
+ }
138
+ }
139
+ // Fall back to deriving sessionId from filename
140
+ if (!sessionId) {
141
+ sessionId = basename(filePath, ".jsonl");
142
+ }
143
+ // Derive project dir name from file path
144
+ const parts = filePath.split("/");
145
+ const projectsIdx = parts.indexOf("projects");
146
+ const projectDirName = projectsIdx >= 0 ? parts[projectsIdx + 1] || "" : "";
147
+ return {
148
+ sessionId,
149
+ projectPath,
150
+ projectDirName,
151
+ startTime,
152
+ endTime,
153
+ userPromptCount,
154
+ toolCalls,
155
+ filesTouched: [...filesSet].sort(),
156
+ summary,
157
+ gitBranch,
158
+ slug,
159
+ permissionMode,
160
+ };
161
+ }
162
+ /**
163
+ * Parse all sessions across all projects.
164
+ */
165
+ export function parseAllSessions() {
166
+ const sessions = [];
167
+ for (const { filePath } of listAllSessionFiles()) {
168
+ const parsed = parseSession(filePath);
169
+ if (parsed && parsed.userPromptCount > 0) {
170
+ sessions.push(parsed);
171
+ }
172
+ }
173
+ return sessions.sort((a, b) => {
174
+ if (!a.startTime || !b.startTime)
175
+ return 0;
176
+ return a.startTime.localeCompare(b.startTime);
177
+ });
178
+ }
179
+ /** Best-effort extraction of file paths from shell commands. */
180
+ function extractFilePathsFromCommand(command, filesSet) {
181
+ const pathRegex = /\/[\w./-]+\.\w+/g;
182
+ const matches = command.match(pathRegex);
183
+ if (matches) {
184
+ for (const m of matches) {
185
+ if (!m.includes("node_modules") && !m.startsWith("/dev/") && !m.startsWith("/tmp/")) {
186
+ filesSet.add(m);
187
+ }
188
+ }
189
+ }
190
+ }
191
+ const MCP_SERVER_LABELS = {
192
+ "claude_ai_Notion": "Notion", "notion": "Notion",
193
+ "claude_ai_Canva": "Canva", "canva": "Canva",
194
+ "supabase-prod": "Supabase", "supabase-dev": "Supabase", "supabase": "Supabase",
195
+ "posthog": "PostHog",
196
+ "excalidraw": "Excalidraw",
197
+ "gemini": "Google Gemini",
198
+ "slack": "Slack",
199
+ "linear": "Linear",
200
+ "github": "GitHub",
201
+ };
202
+ /**
203
+ * Extract MCP servers, skills, tool counts, and workspace apps from a parsed session.
204
+ */
205
+ export function extractTooling(session) {
206
+ const mcpServers = new Set();
207
+ const mcpToolCounts = {};
208
+ const skills = [];
209
+ const toolCounts = {};
210
+ const apps = new Set();
211
+ const editors = new Set();
212
+ const tech = new Set();
213
+ for (const tc of session.toolCalls) {
214
+ // Tool counts
215
+ toolCounts[tc.name] = (toolCounts[tc.name] || 0) + 1;
216
+ // MCP detection
217
+ if (tc.name.startsWith("mcp__")) {
218
+ const parts = tc.name.split("__");
219
+ const server = parts[1] || "";
220
+ const tool = parts.slice(2).join("__");
221
+ mcpServers.add(server);
222
+ if (tool)
223
+ mcpToolCounts[tool] = (mcpToolCounts[tool] || 0) + 1;
224
+ // Map to app labels
225
+ const label = MCP_SERVER_LABELS[server];
226
+ if (label)
227
+ apps.add(label);
228
+ }
229
+ // Skill detection
230
+ if (tc.name === "Skill") {
231
+ const skillName = tc.input?.skill || "";
232
+ if (skillName)
233
+ skills.push(skillName);
234
+ }
235
+ // Bash command analysis
236
+ if (tc.name === "Bash") {
237
+ const cmd = tc.input?.command || "";
238
+ // Editor detection
239
+ if (cmd.includes("cursor ") || cmd.includes("cursor."))
240
+ editors.add("Cursor");
241
+ if (cmd.match(/\bcode\b/) && (cmd.includes("code .") || cmd.includes("code -")))
242
+ editors.add("VS Code");
243
+ if (cmd.match(/\bvim\b|\bnvim\b/))
244
+ editors.add("Vim/Neovim");
245
+ // App detection
246
+ if (cmd.includes("open -a")) {
247
+ const match = cmd.match(/open -a ["']?([^"'\s]+)/);
248
+ if (match)
249
+ apps.add(match[1]);
250
+ }
251
+ if (cmd.includes("docker"))
252
+ apps.add("Docker");
253
+ if (cmd.includes("vercel"))
254
+ apps.add("Vercel");
255
+ if (cmd.includes("netlify"))
256
+ apps.add("Netlify");
257
+ if (cmd.includes("gh "))
258
+ apps.add("GitHub CLI");
259
+ if (cmd.includes("supabase "))
260
+ apps.add("Supabase CLI");
261
+ if (cmd.includes("firebase"))
262
+ apps.add("Firebase");
263
+ if (cmd.includes("obsidian"))
264
+ apps.add("Obsidian");
265
+ // Tech stack
266
+ if (cmd.match(/\bnpm\b|\bnpx\b|\bpnpm\b|\byarn\b|\bbun\b/))
267
+ tech.add("Node.js");
268
+ if (cmd.match(/\bpython\b|\bpip\b/))
269
+ tech.add("Python");
270
+ if (cmd.match(/\bgo\b/) && cmd.includes("go "))
271
+ tech.add("Go");
272
+ if (cmd.match(/\bcargo\b|\brustc\b/))
273
+ tech.add("Rust");
274
+ if (cmd.includes("next "))
275
+ tech.add("Next.js");
276
+ if (cmd.includes("vite"))
277
+ tech.add("Vite");
278
+ if (cmd.includes("tailwind"))
279
+ tech.add("Tailwind");
280
+ if (cmd.includes("prisma"))
281
+ tech.add("Prisma");
282
+ if (cmd.match(/\bjest\b|\bvitest\b/))
283
+ tech.add("Testing");
284
+ }
285
+ // File path analysis for editors/apps
286
+ if (tc.name === "Read" || tc.name === "Edit" || tc.name === "Write") {
287
+ const fp = tc.input?.file_path || "";
288
+ if (fp.includes(".obsidian/"))
289
+ apps.add("Obsidian");
290
+ if (fp.includes(".vscode/"))
291
+ editors.add("VS Code");
292
+ if (fp.includes(".cursor/"))
293
+ editors.add("Cursor");
294
+ if (fp.includes(".github/workflows"))
295
+ apps.add("GitHub Actions");
296
+ if (fp.includes("Dockerfile") || fp.includes("docker-compose"))
297
+ apps.add("Docker");
298
+ }
299
+ }
300
+ return {
301
+ mcpServersUsed: [...mcpServers],
302
+ mcpToolCounts,
303
+ skillsInvoked: skills,
304
+ toolCounts,
305
+ appsDetected: [...apps],
306
+ editorsDetected: [...editors],
307
+ techStack: [...tech],
308
+ };
309
+ }
310
+ //# sourceMappingURL=session-reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-reader.js","sourceRoot":"","sources":["../../../src/readers/session-reader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ export interface DailyActivity {
2
+ date: string;
3
+ messageCount: number;
4
+ sessionCount: number;
5
+ toolCallCount: number;
6
+ }
7
+ export interface StatsCache {
8
+ version: number;
9
+ lastComputedDate: string;
10
+ dailyActivity: DailyActivity[];
11
+ }
12
+ export interface StatsSummary {
13
+ totalDays: number;
14
+ totalMessages: number;
15
+ totalSessions: number;
16
+ totalToolCalls: number;
17
+ firstDate: string | null;
18
+ lastDate: string | null;
19
+ currentStreak: number;
20
+ bestStreak: number;
21
+ dailyActivity: DailyActivity[];
22
+ }
23
+ /**
24
+ * Read and parse ~/.claude/stats-cache.json
25
+ */
26
+ export declare function readStatsCache(): StatsCache | null;
27
+ /**
28
+ * Compute a full stats summary from the cache.
29
+ */
30
+ export declare function getStatsSummary(): StatsSummary | null;
31
+ /**
32
+ * Get activity for a specific date range.
33
+ */
34
+ export declare function getActivityInRange(startDate: string, endDate: string): DailyActivity[];
35
+ /**
36
+ * Get activity for the current week (Mon–Sun).
37
+ */
38
+ export declare function getThisWeekActivity(): DailyActivity[];
@@ -0,0 +1,125 @@
1
+ import { readFileSync } from "fs";
2
+ import { join } from "path";
3
+ import { homedir } from "os";
4
+ const STATS_CACHE_PATH = join(homedir(), ".claude", "stats-cache.json");
5
+ /**
6
+ * Read and parse ~/.claude/stats-cache.json
7
+ */
8
+ export function readStatsCache() {
9
+ try {
10
+ const raw = readFileSync(STATS_CACHE_PATH, "utf-8");
11
+ return JSON.parse(raw);
12
+ }
13
+ catch {
14
+ return null;
15
+ }
16
+ }
17
+ /**
18
+ * Compute a full stats summary from the cache.
19
+ */
20
+ export function getStatsSummary() {
21
+ const cache = readStatsCache();
22
+ if (!cache || !cache.dailyActivity.length)
23
+ return null;
24
+ const days = cache.dailyActivity;
25
+ const sorted = [...days].sort((a, b) => a.date.localeCompare(b.date));
26
+ let totalMessages = 0;
27
+ let totalSessions = 0;
28
+ let totalToolCalls = 0;
29
+ for (const day of sorted) {
30
+ totalMessages += day.messageCount;
31
+ totalSessions += day.sessionCount;
32
+ totalToolCalls += day.toolCallCount;
33
+ }
34
+ // Compute streaks from the sorted daily activity
35
+ const activeDates = new Set(sorted.map((d) => d.date));
36
+ const { currentStreak, bestStreak } = computeStreaks(activeDates);
37
+ return {
38
+ totalDays: sorted.length,
39
+ totalMessages,
40
+ totalSessions,
41
+ totalToolCalls,
42
+ firstDate: sorted[0].date,
43
+ lastDate: sorted[sorted.length - 1].date,
44
+ currentStreak,
45
+ bestStreak,
46
+ dailyActivity: sorted,
47
+ };
48
+ }
49
+ /**
50
+ * Get activity for a specific date range.
51
+ */
52
+ export function getActivityInRange(startDate, endDate) {
53
+ const cache = readStatsCache();
54
+ if (!cache)
55
+ return [];
56
+ return cache.dailyActivity
57
+ .filter((d) => d.date >= startDate && d.date <= endDate)
58
+ .sort((a, b) => a.date.localeCompare(b.date));
59
+ }
60
+ /**
61
+ * Get activity for the current week (Mon–Sun).
62
+ */
63
+ export function getThisWeekActivity() {
64
+ const now = new Date();
65
+ const dayOfWeek = now.getDay(); // 0=Sun, 1=Mon, ...
66
+ const mondayOffset = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
67
+ const monday = new Date(now);
68
+ monday.setDate(now.getDate() + mondayOffset);
69
+ const sunday = new Date(monday);
70
+ sunday.setDate(monday.getDate() + 6);
71
+ const startDate = formatDate(monday);
72
+ const endDate = formatDate(sunday);
73
+ return getActivityInRange(startDate, endDate);
74
+ }
75
+ /**
76
+ * Compute current and best streak from a set of active dates.
77
+ * A streak is consecutive calendar days with activity.
78
+ */
79
+ function computeStreaks(activeDates) {
80
+ if (activeDates.size === 0)
81
+ return { currentStreak: 0, bestStreak: 0 };
82
+ const sorted = [...activeDates].sort();
83
+ // Current streak: count backwards from today
84
+ const today = formatDate(new Date());
85
+ let currentStreak = 0;
86
+ let checkDate = new Date(today + "T00:00:00");
87
+ // Allow today or yesterday as the starting point
88
+ if (!activeDates.has(formatDate(checkDate))) {
89
+ checkDate.setDate(checkDate.getDate() - 1);
90
+ if (!activeDates.has(formatDate(checkDate))) {
91
+ currentStreak = 0;
92
+ }
93
+ }
94
+ if (currentStreak === 0 && activeDates.has(formatDate(checkDate))) {
95
+ while (activeDates.has(formatDate(checkDate))) {
96
+ currentStreak++;
97
+ checkDate.setDate(checkDate.getDate() - 1);
98
+ }
99
+ }
100
+ // Best streak: scan all dates
101
+ let bestStreak = 0;
102
+ let streak = 1;
103
+ for (let i = 1; i < sorted.length; i++) {
104
+ const prev = new Date(sorted[i - 1] + "T00:00:00");
105
+ const curr = new Date(sorted[i] + "T00:00:00");
106
+ const diffDays = (curr.getTime() - prev.getTime()) / (1000 * 60 * 60 * 24);
107
+ if (diffDays === 1) {
108
+ streak++;
109
+ }
110
+ else {
111
+ bestStreak = Math.max(bestStreak, streak);
112
+ streak = 1;
113
+ }
114
+ }
115
+ bestStreak = Math.max(bestStreak, streak);
116
+ return { currentStreak, bestStreak };
117
+ }
118
+ /** Format a Date as YYYY-MM-DD in local time (not UTC). */
119
+ function formatDate(date) {
120
+ const year = date.getFullYear();
121
+ const month = String(date.getMonth() + 1).padStart(2, "0");
122
+ const day = String(date.getDate()).padStart(2, "0");
123
+ return `${year}-${month}-${day}`;
124
+ }
125
+ //# sourceMappingURL=stats-reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats-reader.js","sourceRoot":"","sources":["../../../src/readers/stats-reader.ts"],"names":[],"mappings":"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"}