@viren/claude-code-dashboard 0.0.1 → 0.0.3

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.
package/src/demo.mjs ADDED
@@ -0,0 +1,490 @@
1
+ /**
2
+ * Generate realistic fake data for --demo flag.
3
+ * Produces a complete data object ready for generateDashboardHtml().
4
+ */
5
+
6
+ function daysAgo(n) {
7
+ return Math.floor(Date.now() / 1000) - n * 86400;
8
+ }
9
+
10
+ const DEMO_CONFIGURED = [
11
+ {
12
+ key: "acme-web",
13
+ name: "acme-web",
14
+ path: "~/work/acme-web",
15
+ shortPath: "~/work/acme-web",
16
+ commands: [
17
+ { name: "dev", desc: "Start dev server with hot reload", filepath: "" },
18
+ { name: "test", desc: "Run vitest suite with coverage", filepath: "" },
19
+ { name: "deploy", desc: "Deploy to staging via Vercel", filepath: "" },
20
+ { name: "lint", desc: "Run ESLint + Prettier check", filepath: "" },
21
+ ],
22
+ rules: [
23
+ { name: "architecture", desc: "App router conventions and component patterns", filepath: "" },
24
+ {
25
+ name: "testing",
26
+ desc: "Test behavior not implementation, use MSW for mocks",
27
+ filepath: "",
28
+ },
29
+ { name: "styling", desc: "Tailwind utility-first, no inline styles", filepath: "" },
30
+ ],
31
+ desc: [
32
+ "Customer-facing web application built with Next.js 15 and React Server Components.",
33
+ "Uses Supabase for auth and database, deployed on Vercel.",
34
+ ],
35
+ sections: [
36
+ {
37
+ name: "Architecture",
38
+ preview: [
39
+ "App router with RSC",
40
+ "Shared components in /ui",
41
+ "Feature modules in /features",
42
+ ],
43
+ },
44
+ {
45
+ name: "Testing",
46
+ preview: ["Vitest for unit tests", "Playwright for E2E", "MSW for API mocking"],
47
+ },
48
+ {
49
+ name: "Deployment",
50
+ preview: ["Preview deploys on PRs", "Staging auto-deploy from main"],
51
+ },
52
+ ],
53
+ freshness: daysAgo(3),
54
+ freshnessText: "3 days ago",
55
+ freshnessClass: "fresh",
56
+ techStack: ["next", "react"],
57
+ healthScore: 95,
58
+ healthReasons: ["Has CLAUDE.md", "Has commands", "Has rules", "Recently updated"],
59
+ hasAgentsFile: true,
60
+ configPattern: "modular",
61
+ drift: { level: "synced", commitsSince: 0 },
62
+ similarRepos: [{ name: "marketing-site", similarity: 72 }],
63
+ matchedSkills: [{ name: "e2e-test" }, { name: "react-doctor" }],
64
+ mcpServers: [
65
+ { name: "playwright", type: "stdio", scope: "project", source: "~/work/acme-web" },
66
+ ],
67
+ },
68
+ {
69
+ key: "payments-api",
70
+ name: "payments-api",
71
+ path: "~/work/payments-api",
72
+ shortPath: "~/work/payments-api",
73
+ commands: [
74
+ { name: "test", desc: "Run pytest with coverage", filepath: "" },
75
+ { name: "migrate", desc: "Run alembic migrations", filepath: "" },
76
+ { name: "serve", desc: "Start FastAPI dev server", filepath: "" },
77
+ ],
78
+ rules: [
79
+ { name: "security", desc: "Input validation on all endpoints, no raw SQL", filepath: "" },
80
+ {
81
+ name: "error-handling",
82
+ desc: "Structured errors with codes, never expose internals",
83
+ filepath: "",
84
+ },
85
+ ],
86
+ desc: ["Payment processing API handling Stripe integration and subscription management."],
87
+ sections: [
88
+ {
89
+ name: "Security",
90
+ preview: ["Validate all inputs with Pydantic", "Rate limiting on sensitive endpoints"],
91
+ },
92
+ {
93
+ name: "Database",
94
+ preview: ["PostgreSQL via SQLAlchemy", "Alembic for migrations"],
95
+ },
96
+ ],
97
+ freshness: daysAgo(12),
98
+ freshnessText: "12 days ago",
99
+ freshnessClass: "fresh",
100
+ techStack: ["python"],
101
+ healthScore: 80,
102
+ healthReasons: ["Has CLAUDE.md", "Has commands", "Has rules"],
103
+ hasAgentsFile: true,
104
+ configPattern: "modular",
105
+ drift: { level: "low", commitsSince: 4 },
106
+ similarRepos: [],
107
+ matchedSkills: [{ name: "systematic-debugging" }],
108
+ mcpServers: [],
109
+ },
110
+ {
111
+ key: "mobile-app",
112
+ name: "mobile-app",
113
+ path: "~/work/mobile-app",
114
+ shortPath: "~/work/mobile-app",
115
+ commands: [
116
+ { name: "ios", desc: "Run on iOS simulator", filepath: "" },
117
+ { name: "android", desc: "Run on Android emulator", filepath: "" },
118
+ { name: "test", desc: "Run Jest test suite", filepath: "" },
119
+ ],
120
+ rules: [
121
+ { name: "navigation", desc: "React Navigation v7 patterns and deep linking", filepath: "" },
122
+ ],
123
+ desc: ["Cross-platform mobile app built with Expo and React Native."],
124
+ sections: [
125
+ {
126
+ name: "Navigation",
127
+ preview: ["File-based routing via expo-router", "Deep link config in app.json"],
128
+ },
129
+ ],
130
+ freshness: daysAgo(45),
131
+ freshnessText: "1 month ago",
132
+ freshnessClass: "aging",
133
+ techStack: ["expo", "react"],
134
+ healthScore: 60,
135
+ healthReasons: ["Has CLAUDE.md", "Has commands"],
136
+ hasAgentsFile: true,
137
+ configPattern: "monolithic",
138
+ drift: { level: "medium", commitsSince: 18 },
139
+ similarRepos: [{ name: "acme-web", similarity: 45 }],
140
+ matchedSkills: [{ name: "react-doctor" }],
141
+ mcpServers: [],
142
+ },
143
+ {
144
+ key: "infra-tools",
145
+ name: "infra-tools",
146
+ path: "~/work/infra-tools",
147
+ shortPath: "~/work/infra-tools",
148
+ commands: [
149
+ { name: "build", desc: "Build all Go binaries", filepath: "" },
150
+ { name: "test", desc: "Run go test ./...", filepath: "" },
151
+ ],
152
+ rules: [],
153
+ desc: ["Internal CLI tools for infrastructure automation."],
154
+ sections: [{ name: "Build", preview: ["Go 1.22", "Multi-binary workspace layout"] }],
155
+ freshness: daysAgo(90),
156
+ freshnessText: "3 months ago",
157
+ freshnessClass: "stale",
158
+ techStack: ["go"],
159
+ healthScore: 40,
160
+ healthReasons: ["Has CLAUDE.md", "Has commands"],
161
+ hasAgentsFile: true,
162
+ configPattern: "minimal",
163
+ drift: { level: "high", commitsSince: 34 },
164
+ similarRepos: [],
165
+ matchedSkills: [],
166
+ mcpServers: [],
167
+ },
168
+ {
169
+ key: "marketing-site",
170
+ name: "marketing-site",
171
+ path: "~/work/marketing-site",
172
+ shortPath: "~/work/marketing-site",
173
+ commands: [
174
+ { name: "dev", desc: "Start Next.js dev server", filepath: "" },
175
+ { name: "build", desc: "Build static export", filepath: "" },
176
+ ],
177
+ rules: [
178
+ { name: "content", desc: "All copy comes from CMS, never hardcode text", filepath: "" },
179
+ ],
180
+ desc: ["Public marketing website with blog and documentation."],
181
+ sections: [
182
+ { name: "Content", preview: ["MDX for blog posts", "Contentlayer for type-safe content"] },
183
+ ],
184
+ freshness: daysAgo(7),
185
+ freshnessText: "1 week ago",
186
+ freshnessClass: "fresh",
187
+ techStack: ["next"],
188
+ healthScore: 70,
189
+ healthReasons: ["Has CLAUDE.md", "Has commands", "Has rules"],
190
+ hasAgentsFile: true,
191
+ configPattern: "modular",
192
+ drift: { level: "low", commitsSince: 2 },
193
+ similarRepos: [{ name: "acme-web", similarity: 68 }],
194
+ matchedSkills: [{ name: "e2e-test" }],
195
+ mcpServers: [],
196
+ },
197
+ {
198
+ key: "shared-ui",
199
+ name: "shared-ui",
200
+ path: "~/work/shared-ui",
201
+ shortPath: "~/work/shared-ui",
202
+ commands: [
203
+ { name: "storybook", desc: "Start Storybook dev server", filepath: "" },
204
+ { name: "build", desc: "Build and publish to internal registry", filepath: "" },
205
+ ],
206
+ rules: [
207
+ { name: "components", desc: "All components must have stories and a11y tests", filepath: "" },
208
+ ],
209
+ desc: ["Shared component library used across web projects."],
210
+ sections: [
211
+ {
212
+ name: "Components",
213
+ preview: ["Radix primitives", "Tailwind variants", "Storybook for documentation"],
214
+ },
215
+ ],
216
+ freshness: daysAgo(14),
217
+ freshnessText: "2 weeks ago",
218
+ freshnessClass: "fresh",
219
+ techStack: ["react"],
220
+ healthScore: 75,
221
+ healthReasons: ["Has CLAUDE.md", "Has commands", "Has rules"],
222
+ hasAgentsFile: true,
223
+ configPattern: "modular",
224
+ drift: { level: "synced", commitsSince: 0 },
225
+ similarRepos: [{ name: "acme-web", similarity: 55 }],
226
+ matchedSkills: [],
227
+ mcpServers: [],
228
+ },
229
+ ];
230
+
231
+ const DEMO_UNCONFIGURED = [
232
+ {
233
+ key: "data-scripts",
234
+ name: "data-scripts",
235
+ path: "~/work/data-scripts",
236
+ shortPath: "~/work/data-scripts",
237
+ techStack: ["python"],
238
+ suggestions: ["Add CLAUDE.md with project overview", "Add commands for common tasks"],
239
+ exemplarName: "payments-api",
240
+ mcpServers: [],
241
+ },
242
+ {
243
+ key: "legacy-admin",
244
+ name: "legacy-admin",
245
+ path: "~/work/legacy-admin",
246
+ shortPath: "~/work/legacy-admin",
247
+ techStack: ["react"],
248
+ suggestions: ["Add CLAUDE.md", "Add architecture rules"],
249
+ exemplarName: "acme-web",
250
+ mcpServers: [],
251
+ },
252
+ {
253
+ key: "ops-runbooks",
254
+ name: "ops-runbooks",
255
+ path: "~/work/ops-runbooks",
256
+ shortPath: "~/work/ops-runbooks",
257
+ techStack: [],
258
+ suggestions: [],
259
+ exemplarName: "",
260
+ mcpServers: [],
261
+ },
262
+ ];
263
+
264
+ const DEMO_GLOBAL_CMDS = [
265
+ { name: "commit", desc: "Stage changes and create a conventional commit", filepath: "" },
266
+ { name: "review-pr", desc: "Fetch PR diff and perform code review", filepath: "" },
267
+ { name: "dashboard", desc: "Generate and open the config dashboard", filepath: "" },
268
+ { name: "test-all", desc: "Run full test suite with coverage report", filepath: "" },
269
+ ];
270
+
271
+ const DEMO_GLOBAL_RULES = [
272
+ { name: "git-workflow", desc: "Branch naming, commit conventions, PR process", filepath: "" },
273
+ {
274
+ name: "code-standards",
275
+ desc: "Architecture principles, error handling, quality gates",
276
+ filepath: "",
277
+ },
278
+ {
279
+ name: "communication",
280
+ desc: "Slack message formatting, draft-before-send policy",
281
+ filepath: "",
282
+ },
283
+ ];
284
+
285
+ const DEMO_GLOBAL_SKILLS = [
286
+ {
287
+ name: "e2e-test",
288
+ desc: "Run Playwright E2E tests against a branch",
289
+ filepath: "",
290
+ source: { type: "custom" },
291
+ category: "code-quality",
292
+ },
293
+ {
294
+ name: "react-doctor",
295
+ desc: "Catch common React bugs and performance issues",
296
+ filepath: "",
297
+ source: { type: "skills.sh", repo: "community/react-tools" },
298
+ category: "debugging",
299
+ },
300
+ {
301
+ name: "systematic-debugging",
302
+ desc: "Structured root cause analysis with diagnostic plans",
303
+ filepath: "",
304
+ source: { type: "superpowers", repo: "obra/superpowers-skills" },
305
+ category: "debugging",
306
+ },
307
+ {
308
+ name: "writing-plans",
309
+ desc: "Create implementation plans from specs before coding",
310
+ filepath: "",
311
+ source: { type: "superpowers", repo: "obra/superpowers-skills" },
312
+ category: "workflow",
313
+ },
314
+ {
315
+ name: "code-review",
316
+ desc: "Review PR diffs for correctness, style, and security",
317
+ filepath: "",
318
+ source: { type: "superpowers", repo: "obra/superpowers-skills" },
319
+ category: "code-quality",
320
+ },
321
+ {
322
+ name: "find-session",
323
+ desc: "Search past Claude Code sessions by keyword or date",
324
+ filepath: "",
325
+ source: { type: "custom" },
326
+ category: "research",
327
+ },
328
+ {
329
+ name: "slack-digest",
330
+ desc: "Extract action items and decisions from Slack threads",
331
+ filepath: "",
332
+ source: { type: "custom" },
333
+ category: "integrations",
334
+ },
335
+ {
336
+ name: "deploy-staging",
337
+ desc: "Deploy current branch to staging environment",
338
+ filepath: "",
339
+ source: { type: "custom" },
340
+ category: "workflow",
341
+ },
342
+ ];
343
+
344
+ function generateDemoHeatmap() {
345
+ const days = [];
346
+ const now = new Date();
347
+ for (let i = 364; i >= 0; i--) {
348
+ const d = new Date(now);
349
+ d.setDate(d.getDate() - i);
350
+ const date = d.toISOString().slice(0, 10);
351
+ // Weighted random: more activity on weekdays
352
+ const isWeekday = d.getDay() > 0 && d.getDay() < 6;
353
+ const base = isWeekday ? 8 : 2;
354
+ const messageCount = Math.floor(Math.random() * base * 3);
355
+ if (messageCount > 0) days.push({ date, messageCount });
356
+ }
357
+ return days;
358
+ }
359
+
360
+ function generateDemoHourCounts() {
361
+ const counts = {};
362
+ // Peak at 10am and 2pm
363
+ for (let h = 0; h < 24; h++) {
364
+ const peak = Math.exp(-((h - 10) ** 2) / 18) + Math.exp(-((h - 14) ** 2) / 12);
365
+ counts[String(h)] = Math.round(peak * 120 + Math.random() * 20);
366
+ }
367
+ return counts;
368
+ }
369
+
370
+ export function generateDemoData() {
371
+ const now = new Date();
372
+ const timestamp =
373
+ now
374
+ .toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })
375
+ .toLowerCase() +
376
+ " at " +
377
+ now.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" }).toLowerCase();
378
+
379
+ const configured = DEMO_CONFIGURED;
380
+ const unconfigured = DEMO_UNCONFIGURED;
381
+ const totalRepos = configured.length + unconfigured.length;
382
+
383
+ return {
384
+ configured,
385
+ unconfigured,
386
+ globalCmds: DEMO_GLOBAL_CMDS,
387
+ globalRules: DEMO_GLOBAL_RULES,
388
+ globalSkills: DEMO_GLOBAL_SKILLS,
389
+ chains: [
390
+ { nodes: ["shared-ui", "acme-web", "marketing-site"], arrow: "&rarr;" },
391
+ { nodes: ["payments-api", "acme-web"], arrow: "&rarr;" },
392
+ ],
393
+ mcpSummary: [
394
+ { name: "playwright", type: "stdio", projects: [], userLevel: true, disabledIn: 0 },
395
+ {
396
+ name: "github",
397
+ type: "stdio",
398
+ projects: ["~/work/acme-web", "~/work/payments-api"],
399
+ userLevel: false,
400
+ disabledIn: 0,
401
+ },
402
+ {
403
+ name: "postgres",
404
+ type: "stdio",
405
+ projects: ["~/work/payments-api"],
406
+ userLevel: false,
407
+ disabledIn: 0,
408
+ },
409
+ { name: "sentry", type: "http", projects: [], userLevel: true, disabledIn: 0 },
410
+ {
411
+ name: "figma",
412
+ type: "stdio",
413
+ projects: ["~/work/acme-web"],
414
+ userLevel: false,
415
+ disabledIn: 0,
416
+ recentlyActive: true,
417
+ },
418
+ ],
419
+ mcpPromotions: [{ name: "github", projects: ["~/work/acme-web", "~/work/payments-api"] }],
420
+ formerMcpServers: [
421
+ { name: "redis", projects: ["~/work/cache-service"], lastSeen: null },
422
+ { name: "datadog", projects: [], lastSeen: null },
423
+ ],
424
+ consolidationGroups: [
425
+ {
426
+ stack: "next",
427
+ repos: ["acme-web", "marketing-site"],
428
+ avgSimilarity: 68,
429
+ suggestion: "2 next repos with 68% avg similarity — consider shared global rules",
430
+ },
431
+ {
432
+ stack: "react",
433
+ repos: ["acme-web", "shared-ui", "mobile-app"],
434
+ avgSimilarity: 45,
435
+ suggestion: "3 react repos with 45% avg similarity — consider shared global rules",
436
+ },
437
+ ],
438
+ usageAnalytics: {
439
+ totalSessions: 247,
440
+ topTools: [
441
+ { name: "Read", count: 1842 },
442
+ { name: "Edit", count: 1356 },
443
+ { name: "Bash", count: 987 },
444
+ { name: "Grep", count: 654 },
445
+ { name: "Write", count: 432 },
446
+ { name: "Glob", count: 321 },
447
+ { name: "Agent", count: 198 },
448
+ { name: "WebSearch", count: 87 },
449
+ ],
450
+ topLanguages: [
451
+ { name: "TypeScript", count: 4521 },
452
+ { name: "Python", count: 2103 },
453
+ { name: "JavaScript", count: 1456 },
454
+ { name: "Go", count: 432 },
455
+ { name: "Markdown", count: 321 },
456
+ ],
457
+ errorCategories: [
458
+ { name: "lint_error", count: 45 },
459
+ { name: "type_error", count: 32 },
460
+ { name: "test_failure", count: 28 },
461
+ ],
462
+ heavySessions: 12,
463
+ },
464
+ ccusageData: {
465
+ totals: { totalCost: 47.82, totalTokens: 28_450_000 },
466
+ daily: [],
467
+ },
468
+ statsCache: {
469
+ dailyActivity: generateDemoHeatmap(),
470
+ hourCounts: generateDemoHourCounts(),
471
+ modelUsage: {
472
+ "claude-sonnet-4-6": { inputTokens: 18_200_000, outputTokens: 6_800_000 },
473
+ "claude-haiku-4-5": { inputTokens: 2_400_000, outputTokens: 1_050_000 },
474
+ },
475
+ },
476
+ timestamp,
477
+ coveragePct: Math.round((configured.length / totalRepos) * 100),
478
+ totalRepos,
479
+ configuredCount: configured.length,
480
+ unconfiguredCount: unconfigured.length,
481
+ totalRepoCmds: configured.reduce((sum, r) => sum + r.commands.length, 0),
482
+ avgHealth: Math.round(
483
+ configured.reduce((sum, r) => sum + r.healthScore, 0) / configured.length,
484
+ ),
485
+ driftCount: configured.filter((r) => r.drift.level === "medium" || r.drift.level === "high")
486
+ .length,
487
+ mcpCount: 4,
488
+ scanScope: "~/work (depth 5)",
489
+ };
490
+ }