bashstats 0.2.1 → 0.2.2

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/dist/cli.js CHANGED
@@ -8,37 +8,22 @@ import {
8
8
  StatsEngine,
9
9
  getDbPath,
10
10
  install,
11
+ installCopilot,
12
+ installGemini,
13
+ installOpenCode,
14
+ isCopilotAvailable,
15
+ isGeminiAvailable,
11
16
  isInstalled,
12
- uninstall
13
- } from "./chunk-4HVDBCTU.js";
17
+ isOpenCodeAvailable,
18
+ uninstall,
19
+ uninstallCopilot,
20
+ uninstallGemini,
21
+ uninstallOpenCode
22
+ } from "./chunk-YAJO5WNW.js";
14
23
 
15
24
  // src/cli.ts
16
25
  import { Command } from "commander";
17
26
 
18
- // src/commands/init.ts
19
- function runInit() {
20
- if (isInstalled()) {
21
- console.log("bashstats hooks are already installed. Reinstalling...");
22
- }
23
- const result = install();
24
- if (result.success) {
25
- console.log("");
26
- console.log(" bashstats installed successfully!");
27
- console.log("");
28
- console.log(" " + result.message);
29
- console.log("");
30
- console.log(' Run "bashstats" to open the dashboard.');
31
- console.log(" Your Claude Code sessions are now being tracked.");
32
- console.log("");
33
- console.log(" [SECRET ACHIEVEMENT UNLOCKED] Launch Day");
34
- console.log(' "Welcome to bashstats. Your stats are now being watched. Forever."');
35
- console.log("");
36
- } else {
37
- console.error("Installation failed: " + result.message);
38
- process.exit(1);
39
- }
40
- }
41
-
42
27
  // src/commands/web.ts
43
28
  import fs from "fs";
44
29
  import { exec } from "child_process";
@@ -56,16 +41,18 @@ function createApp(db) {
56
41
  app.get("/api/health", (_req, res) => {
57
42
  res.json({ status: "ok", version: "0.1.0" });
58
43
  });
59
- app.get("/api/stats", (_req, res) => {
44
+ app.get("/api/stats", (req, res) => {
60
45
  try {
61
- res.json(stats.getAllStats());
46
+ const agent = req.query.agent;
47
+ res.json(stats.getAllStats(agent));
62
48
  } catch (error) {
63
49
  res.status(500).json({ error: "Failed to fetch stats" });
64
50
  }
65
51
  });
66
- app.get("/api/achievements", (_req, res) => {
52
+ app.get("/api/achievements", (req, res) => {
67
53
  try {
68
- res.json(achievements.getAchievementsPayload());
54
+ const agent = req.query.agent;
55
+ res.json(achievements.getAchievementsPayload(agent));
69
56
  } catch (error) {
70
57
  res.status(500).json({ error: "Failed to fetch achievements" });
71
58
  }
@@ -78,14 +65,36 @@ function createApp(db) {
78
65
  res.status(500).json({ error: "Failed to fetch activity" });
79
66
  }
80
67
  });
81
- app.get("/api/sessions", (_req, res) => {
68
+ app.get("/api/sessions", (req, res) => {
82
69
  try {
83
- const sessions = db.prepare("SELECT * FROM sessions ORDER BY started_at DESC LIMIT 100").all();
70
+ const agent = req.query.agent;
71
+ let sql = "SELECT * FROM sessions";
72
+ const params = [];
73
+ if (agent) {
74
+ sql += " WHERE agent = ?";
75
+ params.push(agent);
76
+ }
77
+ sql += " ORDER BY started_at DESC LIMIT 100";
78
+ const sessions = db.prepare(sql).all(...params);
84
79
  res.json(sessions);
85
80
  } catch (error) {
86
81
  res.status(500).json({ error: "Failed to fetch sessions" });
87
82
  }
88
83
  });
84
+ app.get("/api/weekly-goals", (_req, res) => {
85
+ try {
86
+ res.json(stats.getWeeklyGoalsPayload());
87
+ } catch (error) {
88
+ res.status(500).json({ error: "Failed to fetch weekly goals" });
89
+ }
90
+ });
91
+ app.get("/api/agents", (_req, res) => {
92
+ try {
93
+ res.json(stats.getAgentBreakdown());
94
+ } catch (error) {
95
+ res.status(500).json({ error: "Failed to fetch agent breakdown" });
96
+ }
97
+ });
89
98
  app.get("/{*splat}", (_req, res) => {
90
99
  res.sendFile(path.join(__dirname, "static", "index.html"));
91
100
  });
@@ -136,6 +145,46 @@ function runWeb(options) {
136
145
  }
137
146
  }
138
147
 
148
+ // src/commands/init.ts
149
+ function runInit() {
150
+ if (isInstalled()) {
151
+ console.log("bashstats hooks are already installed. Reinstalling...");
152
+ }
153
+ const claudeResult = install();
154
+ if (!claudeResult.success) {
155
+ console.error("Installation failed: " + claudeResult.message);
156
+ process.exit(1);
157
+ }
158
+ const installed = ["Claude Code"];
159
+ if (isGeminiAvailable()) {
160
+ const result = installGemini();
161
+ if (result.success) installed.push("Gemini CLI");
162
+ else console.log(` Note: ${result.message}`);
163
+ }
164
+ if (isCopilotAvailable()) {
165
+ const result = installCopilot();
166
+ if (result.success) installed.push("Copilot CLI");
167
+ else console.log(` Note: ${result.message}`);
168
+ }
169
+ if (isOpenCodeAvailable()) {
170
+ const result = installOpenCode();
171
+ if (result.success) installed.push("OpenCode");
172
+ else console.log(` Note: ${result.message}`);
173
+ }
174
+ console.log("");
175
+ console.log(" bashstats installed successfully!");
176
+ console.log("");
177
+ console.log(` Installed hooks for: ${installed.join(", ")}`);
178
+ console.log(" Your coding sessions are now being tracked.");
179
+ console.log("");
180
+ console.log(" [SECRET ACHIEVEMENT UNLOCKED] Launch Day");
181
+ console.log(' "Welcome to bashstats. Your stats are now being watched. Forever."');
182
+ console.log("");
183
+ console.log(" Opening dashboard...");
184
+ console.log("");
185
+ runWeb({});
186
+ }
187
+
139
188
  // src/commands/stats.ts
140
189
  import os from "os";
141
190
  import path2 from "path";
@@ -234,7 +283,7 @@ function runAchievements() {
234
283
  const payload = engine.getAchievementsPayload();
235
284
  console.log("");
236
285
  console.log(` bashstats - Achievements`);
237
- console.log(` Rank: ${payload.xp.rank} XP: ${payload.xp.totalXP.toLocaleString()} / ${payload.xp.nextRankXP.toLocaleString()}`);
286
+ console.log(` Rank ${payload.xp.rankNumber} [${payload.xp.rankTier}] XP: ${payload.xp.totalXP.toLocaleString()} / ${payload.xp.nextRankXP.toLocaleString()}`);
238
287
  console.log(` ${progressBar(payload.xp.progress, 40)} ${Math.round(payload.xp.progress * 100)}%`);
239
288
  console.log("");
240
289
  const categories = /* @__PURE__ */ new Map();
@@ -247,12 +296,18 @@ function runAchievements() {
247
296
  const categoryNames = {
248
297
  volume: "VOLUME",
249
298
  tool_mastery: "TOOL MASTERY",
250
- time: "TIME & STREAKS",
299
+ time: "TIME & PATTERNS",
300
+ session_behavior: "SESSION BEHAVIOR",
251
301
  behavioral: "BEHAVIORAL",
302
+ prompt_patterns: "PROMPT PATTERNS",
252
303
  resilience: "RESILIENCE",
304
+ error_recovery: "ERROR & RECOVERY",
305
+ tool_combos: "TOOL COMBOS",
253
306
  shipping: "SHIPPING & PROJECTS",
307
+ project_dedication: "PROJECT DEDICATION",
254
308
  multi_agent: "MULTI-AGENT",
255
- humor: "HUMOR",
309
+ wild_card: "WILD CARD",
310
+ token_usage: "TOKEN USAGE",
256
311
  aspirational: "ASPIRATIONAL",
257
312
  secret: "SECRET"
258
313
  };
@@ -264,7 +319,7 @@ function runAchievements() {
264
319
  const value = badge.value.toLocaleString();
265
320
  const next = badge.maxed ? "" : ` / ${badge.nextThreshold.toLocaleString()}`;
266
321
  console.log(` ${tier.padEnd(12)} ${badge.name.padEnd(22)} ${value}${next}${bar}`);
267
- if (badge.description && (badge.category === "humor" || badge.category === "secret")) {
322
+ if (badge.description && (badge.category === "wild_card" || badge.category === "secret")) {
268
323
  console.log(` "${badge.description}"`);
269
324
  }
270
325
  }
@@ -300,11 +355,12 @@ function runStreak() {
300
355
  console.log(" Last 30 days:");
301
356
  const dates = new Set(daily.map((d) => d.date));
302
357
  const today = /* @__PURE__ */ new Date();
358
+ const pad = (n) => String(n).padStart(2, "0");
303
359
  let line = " ";
304
360
  for (let i = 29; i >= 0; i--) {
305
361
  const d = new Date(today);
306
362
  d.setDate(d.getDate() - i);
307
- const dateStr = d.toISOString().slice(0, 10);
363
+ const dateStr = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
308
364
  line += dates.has(dateStr) ? "#" : ".";
309
365
  }
310
366
  console.log(line);
@@ -364,14 +420,21 @@ import os6 from "os";
364
420
  import path7 from "path";
365
421
  import fs3 from "fs";
366
422
  function runUninstall() {
367
- const hookResult = uninstall();
368
- console.log(hookResult.message);
423
+ const claudeResult = uninstall();
424
+ console.log(claudeResult.message);
425
+ const geminiResult = uninstallGemini();
426
+ if (geminiResult.success && !geminiResult.message.includes("nothing to uninstall")) console.log(geminiResult.message);
427
+ else if (!geminiResult.success) console.log(geminiResult.message);
428
+ const copilotResult = uninstallCopilot();
429
+ console.log(copilotResult.message);
430
+ const openCodeResult = uninstallOpenCode();
431
+ console.log(openCodeResult.message);
369
432
  const dataDir = path7.join(os6.homedir(), DATA_DIR);
370
433
  if (fs3.existsSync(dataDir)) {
371
434
  fs3.rmSync(dataDir, { recursive: true });
372
435
  console.log(`Removed data directory: ${dataDir}`);
373
436
  }
374
- console.log("bashstats has been uninstalled.");
437
+ console.log("bashstats has been fully uninstalled.");
375
438
  }
376
439
 
377
440
  // src/cli.ts
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/commands/init.ts","../src/commands/web.ts","../src/dashboard/server.ts","../src/commands/stats.ts","../src/commands/achievements.ts","../src/commands/streak.ts","../src/commands/export-data.ts","../src/commands/reset.ts","../src/commands/uninstall.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { runInit } from './commands/init.js'\nimport { runWeb } from './commands/web.js'\nimport { runStats } from './commands/stats.js'\nimport { runAchievements } from './commands/achievements.js'\nimport { runStreak } from './commands/streak.js'\nimport { runExport } from './commands/export-data.js'\nimport { runReset } from './commands/reset.js'\nimport { runUninstall } from './commands/uninstall.js'\nimport { DEFAULT_PORT } from './constants.js'\n\nconst program = new Command()\n\nprogram\n .name('bashstats')\n .description('Obsessive stat tracking, achievements, and badges for Claude Code')\n .version('0.1.0')\n\nprogram.command('init').description('Install hooks and set up database').action(runInit)\nprogram.command('web')\n .description('Open browser dashboard')\n .option('-p, --port <number>', 'Port to run on', String(DEFAULT_PORT))\n .option('--no-open', 'Do not open browser automatically')\n .action(runWeb)\nprogram.command('stats').description('Quick stat summary').action(runStats)\nprogram.command('achievements').description('List all badges with progress').action(runAchievements)\nprogram.command('streak').description('Show current and longest streak').action(runStreak)\nprogram.command('export').description('Export all data as JSON').action(runExport)\nprogram.command('reset').description('Wipe all data').action(runReset)\nprogram.command('uninstall').description('Remove hooks and data').action(runUninstall)\n\nprogram.action(() => {\n console.log('bashstats - Obsessive stat tracking for Claude Code')\n console.log('')\n console.log('Use \"bashstats init\" to install hooks.')\n console.log('Use \"bashstats stats\" for a quick summary.')\n console.log('Use \"bashstats --help\" for all commands.')\n})\n\nprogram.parse()\n","import { install, isInstalled } from '../installer/installer.js'\n\nexport function runInit(): void {\n if (isInstalled()) {\n console.log('bashstats hooks are already installed. Reinstalling...')\n }\n\n const result = install()\n if (result.success) {\n console.log('')\n console.log(' bashstats installed successfully!')\n console.log('')\n console.log(' ' + result.message)\n console.log('')\n console.log(' Run \"bashstats\" to open the dashboard.')\n console.log(' Your Claude Code sessions are now being tracked.')\n console.log('')\n console.log(' [SECRET ACHIEVEMENT UNLOCKED] Launch Day')\n console.log(' \"Welcome to bashstats. Your stats are now being watched. Forever.\"')\n console.log('')\n } else {\n console.error('Installation failed: ' + result.message)\n process.exit(1)\n }\n}\n","import fs from 'fs'\nimport { exec } from 'child_process'\nimport { getDbPath } from '../hooks/handler.js'\nimport { BashStatsDB } from '../db/database.js'\nimport { startServer } from '../dashboard/server.js'\nimport { DEFAULT_PORT } from '../constants.js'\n\nfunction openBrowser(url: string): void {\n const platform = process.platform\n let command: string\n\n if (platform === 'win32') {\n command = `start \"\" \"${url}\"`\n } else if (platform === 'darwin') {\n command = `open \"${url}\"`\n } else {\n command = `xdg-open \"${url}\"`\n }\n\n exec(command, (err) => {\n if (err) {\n console.log(`Could not open browser automatically. Visit: ${url}`)\n }\n })\n}\n\nexport function runWeb(options: { port?: string; open?: boolean }): void {\n const dbPath = getDbPath()\n\n if (!fs.existsSync(dbPath)) {\n console.log('No bashstats database found.')\n console.log('Run \"bashstats init\" first to set up tracking.')\n return\n }\n\n const port = options.port ? parseInt(options.port, 10) : DEFAULT_PORT\n\n if (isNaN(port) || port < 1 || port > 65535) {\n console.log(`Invalid port: ${options.port}`)\n return\n }\n\n const db = new BashStatsDB(dbPath)\n const url = `http://127.0.0.1:${port}`\n\n startServer(db, port)\n\n const shouldOpen = options.open !== false\n if (shouldOpen) {\n // Small delay to let the server start before opening\n setTimeout(() => openBrowser(url), 500)\n }\n}\n","import express from 'express'\nimport path from 'path'\nimport { fileURLToPath } from 'url'\nimport { BashStatsDB } from '../db/database.js'\nimport { StatsEngine } from '../stats/engine.js'\nimport { AchievementEngine } from '../achievements/compute.js'\nimport { DEFAULT_PORT } from '../constants.js'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\n\nexport function createApp(db: BashStatsDB): express.Express {\n const app = express()\n const stats = new StatsEngine(db)\n const achievements = new AchievementEngine(db, stats)\n\n // Serve static files\n app.use(express.static(path.join(__dirname, 'static')))\n\n // API endpoints\n app.get('/api/health', (_req, res) => {\n res.json({ status: 'ok', version: '0.1.0' })\n })\n\n app.get('/api/stats', (_req, res) => {\n try {\n res.json(stats.getAllStats())\n } catch (error) {\n res.status(500).json({ error: 'Failed to fetch stats' })\n }\n })\n\n app.get('/api/achievements', (_req, res) => {\n try {\n res.json(achievements.getAchievementsPayload())\n } catch (error) {\n res.status(500).json({ error: 'Failed to fetch achievements' })\n }\n })\n\n app.get('/api/activity', (_req, res) => {\n try {\n const days = parseInt((_req.query.days as string) || '365')\n res.json(db.getAllDailyActivity(days))\n } catch (error) {\n res.status(500).json({ error: 'Failed to fetch activity' })\n }\n })\n\n app.get('/api/sessions', (_req, res) => {\n try {\n const sessions = db.prepare('SELECT * FROM sessions ORDER BY started_at DESC LIMIT 100').all()\n res.json(sessions)\n } catch (error) {\n res.status(500).json({ error: 'Failed to fetch sessions' })\n }\n })\n\n // Fallback to index.html for SPA\n app.get('/{*splat}', (_req, res) => {\n res.sendFile(path.join(__dirname, 'static', 'index.html'))\n })\n\n return app\n}\n\nexport function startServer(db: BashStatsDB, port: number = DEFAULT_PORT): void {\n const app = createApp(db)\n app.listen(port, '127.0.0.1', () => {\n console.log(`bashstats dashboard running at http://127.0.0.1:${port}`)\n })\n}\n","import os from 'os'\nimport path from 'path'\nimport { BashStatsDB } from '../db/database.js'\nimport { StatsEngine } from '../stats/engine.js'\nimport { DATA_DIR, DB_FILENAME } from '../constants.js'\n\nfunction formatDuration(seconds: number): string {\n const hours = Math.floor(seconds / 3600)\n const minutes = Math.floor((seconds % 3600) / 60)\n if (hours > 0) return `${hours}h ${minutes}m`\n return `${minutes}m`\n}\n\nfunction formatNumber(n: number): string {\n return n.toLocaleString()\n}\n\nexport function runStats(): void {\n const dbPath = path.join(os.homedir(), DATA_DIR, DB_FILENAME)\n let db: BashStatsDB\n try {\n db = new BashStatsDB(dbPath)\n } catch {\n console.log('No data yet. Run \"bashstats init\" to start tracking.')\n return\n }\n\n const engine = new StatsEngine(db)\n\n try {\n const lifetime = engine.getLifetimeStats()\n const tools = engine.getToolBreakdown()\n const time = engine.getTimeStats()\n const records = engine.getSessionRecords()\n const projects = engine.getProjectStats()\n\n console.log('')\n console.log(' bashstats - Your Claude Code Stats')\n console.log(' ===================================')\n\n // Lifetime Totals\n console.log('')\n console.log(' LIFETIME TOTALS')\n console.log(` Sessions: ${formatNumber(lifetime.totalSessions)}`)\n console.log(` Time: ${formatDuration(lifetime.totalDurationSeconds)}`)\n console.log(` Prompts: ${formatNumber(lifetime.totalPrompts)}`)\n console.log(` Chars typed: ${formatNumber(lifetime.totalCharsTyped)}`)\n console.log(` Tool calls: ${formatNumber(lifetime.totalToolCalls)}`)\n console.log(` Errors: ${formatNumber(lifetime.totalErrors)}`)\n\n // Tool Breakdown\n if (Object.keys(tools).length > 0) {\n console.log('')\n console.log(' TOOL BREAKDOWN')\n const sorted = Object.entries(tools).sort((a, b) => b[1] - a[1])\n for (const [name, count] of sorted.slice(0, 10)) {\n console.log(` ${name.padEnd(15)} ${formatNumber(count)}`)\n }\n }\n\n // Time & Streaks\n console.log('')\n console.log(' TIME & STREAKS')\n console.log(` Current streak: ${time.currentStreak} days`)\n console.log(` Longest streak: ${time.longestStreak} days`)\n console.log(` Peak hour: ${time.peakHour}:00 (${formatNumber(time.peakHourCount)} prompts)`)\n console.log(` Night owl: ${formatNumber(time.nightOwlCount)} late-night prompts`)\n console.log(` Weekend: ${formatNumber(time.weekendSessions)} weekend sessions`)\n\n // Session Records\n console.log('')\n console.log(' SESSION RECORDS')\n console.log(` Longest: ${formatDuration(records.longestSessionSeconds)}`)\n console.log(` Most tools: ${formatNumber(records.mostToolsInSession)} in one session`)\n console.log(` Most prompts: ${formatNumber(records.mostPromptsInSession)} in one session`)\n console.log(` Avg duration: ${formatDuration(records.avgDurationSeconds)}`)\n\n // Projects\n if (projects.uniqueProjects > 0) {\n console.log('')\n console.log(' PROJECTS')\n console.log(` Unique: ${projects.uniqueProjects}`)\n console.log(` Most visited: ${projects.mostVisitedProject} (${formatNumber(projects.mostVisitedProjectCount)} sessions)`)\n }\n\n console.log('')\n } finally {\n db.close()\n }\n}\n","import os from 'os'\nimport path from 'path'\nimport { BashStatsDB } from '../db/database.js'\nimport { StatsEngine } from '../stats/engine.js'\nimport { AchievementEngine } from '../achievements/compute.js'\nimport { DATA_DIR, DB_FILENAME } from '../constants.js'\nimport type { BadgeResult } from '../types.js'\n\nfunction progressBar(progress: number, width: number = 20): string {\n const filled = Math.round(progress * width)\n const empty = width - filled\n return '#'.repeat(filled) + '.'.repeat(empty)\n}\n\nfunction tierColor(tierName: string): string {\n return `[${tierName}]`\n}\n\nexport function runAchievements(): void {\n const dbPath = path.join(os.homedir(), DATA_DIR, DB_FILENAME)\n let db: BashStatsDB\n try {\n db = new BashStatsDB(dbPath)\n } catch {\n console.log('No data yet. Run \"bashstats init\" to start tracking.')\n return\n }\n\n const stats = new StatsEngine(db)\n const engine = new AchievementEngine(db, stats)\n\n try {\n const payload = engine.getAchievementsPayload()\n\n // Header\n console.log('')\n console.log(` bashstats - Achievements`)\n console.log(` Rank: ${payload.xp.rank} XP: ${payload.xp.totalXP.toLocaleString()} / ${payload.xp.nextRankXP.toLocaleString()}`)\n console.log(` ${progressBar(payload.xp.progress, 40)} ${Math.round(payload.xp.progress * 100)}%`)\n console.log('')\n\n // Group badges by category\n const categories = new Map<string, BadgeResult[]>()\n for (const badge of payload.badges) {\n // Skip secrets that aren't unlocked\n if (badge.secret && !badge.unlocked) continue\n const cat = badge.category\n if (!categories.has(cat)) categories.set(cat, [])\n categories.get(cat)!.push(badge)\n }\n\n const categoryNames: Record<string, string> = {\n volume: 'VOLUME',\n tool_mastery: 'TOOL MASTERY',\n time: 'TIME & STREAKS',\n behavioral: 'BEHAVIORAL',\n resilience: 'RESILIENCE',\n shipping: 'SHIPPING & PROJECTS',\n multi_agent: 'MULTI-AGENT',\n humor: 'HUMOR',\n aspirational: 'ASPIRATIONAL',\n secret: 'SECRET',\n }\n\n for (const [cat, badges] of categories) {\n console.log(` ${categoryNames[cat] || cat.toUpperCase()}`)\n for (const badge of badges) {\n const tier = badge.tier > 0 ? tierColor(badge.tierName) : '[Locked]'\n const bar = badge.maxed ? ' MAXED' : ` ${progressBar(badge.progress, 15)}`\n const value = badge.value.toLocaleString()\n const next = badge.maxed ? '' : ` / ${badge.nextThreshold.toLocaleString()}`\n console.log(` ${tier.padEnd(12)} ${badge.name.padEnd(22)} ${value}${next}${bar}`)\n if (badge.description && (badge.category === 'humor' || badge.category === 'secret')) {\n console.log(` \"${badge.description}\"`)\n }\n }\n console.log('')\n }\n } finally {\n db.close()\n }\n}\n","import os from 'os'\nimport path from 'path'\nimport { BashStatsDB } from '../db/database.js'\nimport { StatsEngine } from '../stats/engine.js'\nimport { DATA_DIR, DB_FILENAME } from '../constants.js'\n\nexport function runStreak(): void {\n const dbPath = path.join(os.homedir(), DATA_DIR, DB_FILENAME)\n let db: BashStatsDB\n try {\n db = new BashStatsDB(dbPath)\n } catch {\n console.log('No data yet. Run \"bashstats init\" to start tracking.')\n return\n }\n\n const engine = new StatsEngine(db)\n\n try {\n const time = engine.getTimeStats()\n const daily = db.getAllDailyActivity(30)\n\n console.log('')\n console.log(' bashstats - Streak')\n console.log(` Current streak: ${time.currentStreak} days`)\n console.log(` Longest streak: ${time.longestStreak} days`)\n console.log('')\n\n // Last 30 days calendar\n if (daily.length > 0) {\n console.log(' Last 30 days:')\n const dates = new Set(daily.map(d => d.date))\n const today = new Date()\n let line = ' '\n for (let i = 29; i >= 0; i--) {\n const d = new Date(today)\n d.setDate(d.getDate() - i)\n const dateStr = d.toISOString().slice(0, 10)\n line += dates.has(dateStr) ? '#' : '.'\n }\n console.log(line)\n }\n console.log('')\n } finally {\n db.close()\n }\n}\n","import os from 'os'\nimport path from 'path'\nimport { BashStatsDB } from '../db/database.js'\nimport { StatsEngine } from '../stats/engine.js'\nimport { AchievementEngine } from '../achievements/compute.js'\nimport { DATA_DIR, DB_FILENAME } from '../constants.js'\n\nexport function runExport(): void {\n const dbPath = path.join(os.homedir(), DATA_DIR, DB_FILENAME)\n let db: BashStatsDB\n try {\n db = new BashStatsDB(dbPath)\n } catch {\n console.error('No data found. Run \"bashstats init\" first.')\n process.exit(1)\n }\n\n const stats = new StatsEngine(db)\n const achievements = new AchievementEngine(db, stats)\n\n try {\n const payload = {\n exported_at: new Date().toISOString(),\n stats: stats.getAllStats(),\n achievements: achievements.getAchievementsPayload(),\n daily_activity: db.getAllDailyActivity(),\n }\n console.log(JSON.stringify(payload, null, 2))\n } finally {\n db.close()\n }\n}\n","import os from 'os'\nimport path from 'path'\nimport fs from 'fs'\nimport { BashStatsDB } from '../db/database.js'\nimport { DATA_DIR, DB_FILENAME } from '../constants.js'\n\nexport function runReset(): void {\n const dbPath = path.join(os.homedir(), DATA_DIR, DB_FILENAME)\n\n if (!fs.existsSync(dbPath)) {\n console.log('No data to reset.')\n return\n }\n\n // Delete and recreate\n fs.unlinkSync(dbPath)\n const db = new BashStatsDB(dbPath)\n db.setMetadata('first_run', new Date().toISOString())\n db.close()\n\n console.log('All data has been reset. Starting fresh.')\n}\n","import os from 'os'\nimport path from 'path'\nimport fs from 'fs'\nimport { uninstall as removeHooks } from '../installer/installer.js'\nimport { DATA_DIR } from '../constants.js'\n\nexport function runUninstall(): void {\n // Remove hooks\n const hookResult = removeHooks()\n console.log(hookResult.message)\n\n // Remove data directory\n const dataDir = path.join(os.homedir(), DATA_DIR)\n if (fs.existsSync(dataDir)) {\n fs.rmSync(dataDir, { recursive: true })\n console.log(`Removed data directory: ${dataDir}`)\n }\n\n console.log('bashstats has been uninstalled.')\n}\n"],"mappings":"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","names":["path","path","os","path","path","os","os","path","path","os","os","path","path","os","os","path","fs","path","os","fs","os","path","fs","path","os","fs"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/commands/web.ts","../src/dashboard/server.ts","../src/commands/init.ts","../src/commands/stats.ts","../src/commands/achievements.ts","../src/commands/streak.ts","../src/commands/export-data.ts","../src/commands/reset.ts","../src/commands/uninstall.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { runInit } from './commands/init.js'\nimport { runWeb } from './commands/web.js'\nimport { runStats } from './commands/stats.js'\nimport { runAchievements } from './commands/achievements.js'\nimport { runStreak } from './commands/streak.js'\nimport { runExport } from './commands/export-data.js'\nimport { runReset } from './commands/reset.js'\nimport { runUninstall } from './commands/uninstall.js'\nimport { DEFAULT_PORT } from './constants.js'\n\nconst program = new Command()\n\nprogram\n .name('bashstats')\n .description('Obsessive stat tracking, achievements, and badges for Claude Code')\n .version('0.1.0')\n\nprogram.command('init').description('Install hooks and set up database').action(runInit)\nprogram.command('web')\n .description('Open browser dashboard')\n .option('-p, --port <number>', 'Port to run on', String(DEFAULT_PORT))\n .option('--no-open', 'Do not open browser automatically')\n .action(runWeb)\nprogram.command('stats').description('Quick stat summary').action(runStats)\nprogram.command('achievements').description('List all badges with progress').action(runAchievements)\nprogram.command('streak').description('Show current and longest streak').action(runStreak)\nprogram.command('export').description('Export all data as JSON').action(runExport)\nprogram.command('reset').description('Wipe all data').action(runReset)\nprogram.command('uninstall').description('Remove hooks and data').action(runUninstall)\n\nprogram.action(() => {\n console.log('bashstats - Obsessive stat tracking for Claude Code')\n console.log('')\n console.log('Use \"bashstats init\" to install hooks.')\n console.log('Use \"bashstats stats\" for a quick summary.')\n console.log('Use \"bashstats --help\" for all commands.')\n})\n\nprogram.parse()\n","import fs from 'fs'\nimport { exec } from 'child_process'\nimport { getDbPath } from '../hooks/handler.js'\nimport { BashStatsDB } from '../db/database.js'\nimport { startServer } from '../dashboard/server.js'\nimport { DEFAULT_PORT } from '../constants.js'\n\nfunction openBrowser(url: string): void {\n const platform = process.platform\n let command: string\n\n if (platform === 'win32') {\n command = `start \"\" \"${url}\"`\n } else if (platform === 'darwin') {\n command = `open \"${url}\"`\n } else {\n command = `xdg-open \"${url}\"`\n }\n\n exec(command, (err) => {\n if (err) {\n console.log(`Could not open browser automatically. Visit: ${url}`)\n }\n })\n}\n\nexport function runWeb(options: { port?: string; open?: boolean }): void {\n const dbPath = getDbPath()\n\n if (!fs.existsSync(dbPath)) {\n console.log('No bashstats database found.')\n console.log('Run \"bashstats init\" first to set up tracking.')\n return\n }\n\n const port = options.port ? parseInt(options.port, 10) : DEFAULT_PORT\n\n if (isNaN(port) || port < 1 || port > 65535) {\n console.log(`Invalid port: ${options.port}`)\n return\n }\n\n const db = new BashStatsDB(dbPath)\n const url = `http://127.0.0.1:${port}`\n\n startServer(db, port)\n\n const shouldOpen = options.open !== false\n if (shouldOpen) {\n // Small delay to let the server start before opening\n setTimeout(() => openBrowser(url), 500)\n }\n}\n","import express from 'express'\nimport path from 'path'\nimport { fileURLToPath } from 'url'\nimport { BashStatsDB } from '../db/database.js'\nimport { StatsEngine } from '../stats/engine.js'\nimport { AchievementEngine } from '../achievements/compute.js'\nimport { DEFAULT_PORT } from '../constants.js'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\n\nexport function createApp(db: BashStatsDB): express.Express {\n const app = express()\n const stats = new StatsEngine(db)\n const achievements = new AchievementEngine(db, stats)\n\n // Serve static files\n app.use(express.static(path.join(__dirname, 'static')))\n\n // API endpoints\n app.get('/api/health', (_req, res) => {\n res.json({ status: 'ok', version: '0.1.0' })\n })\n\n app.get('/api/stats', (req, res) => {\n try {\n const agent = req.query.agent as string | undefined\n res.json(stats.getAllStats(agent))\n } catch (error) {\n res.status(500).json({ error: 'Failed to fetch stats' })\n }\n })\n\n app.get('/api/achievements', (req, res) => {\n try {\n const agent = req.query.agent as string | undefined\n res.json(achievements.getAchievementsPayload(agent))\n } catch (error) {\n res.status(500).json({ error: 'Failed to fetch achievements' })\n }\n })\n\n app.get('/api/activity', (_req, res) => {\n try {\n const days = parseInt((_req.query.days as string) || '365')\n res.json(db.getAllDailyActivity(days))\n } catch (error) {\n res.status(500).json({ error: 'Failed to fetch activity' })\n }\n })\n\n app.get('/api/sessions', (req, res) => {\n try {\n const agent = req.query.agent as string | undefined\n let sql = 'SELECT * FROM sessions'\n const params: unknown[] = []\n if (agent) {\n sql += ' WHERE agent = ?'\n params.push(agent)\n }\n sql += ' ORDER BY started_at DESC LIMIT 100'\n const sessions = db.prepare(sql).all(...params)\n res.json(sessions)\n } catch (error) {\n res.status(500).json({ error: 'Failed to fetch sessions' })\n }\n })\n\n app.get('/api/weekly-goals', (_req, res) => {\n try {\n res.json(stats.getWeeklyGoalsPayload())\n } catch (error) {\n res.status(500).json({ error: 'Failed to fetch weekly goals' })\n }\n })\n\n app.get('/api/agents', (_req, res) => {\n try {\n res.json(stats.getAgentBreakdown())\n } catch (error) {\n res.status(500).json({ error: 'Failed to fetch agent breakdown' })\n }\n })\n\n // Fallback to index.html for SPA\n app.get('/{*splat}', (_req, res) => {\n res.sendFile(path.join(__dirname, 'static', 'index.html'))\n })\n\n return app\n}\n\nexport function startServer(db: BashStatsDB, port: number = DEFAULT_PORT): void {\n const app = createApp(db)\n app.listen(port, '127.0.0.1', () => {\n console.log(`bashstats dashboard running at http://127.0.0.1:${port}`)\n })\n}\n","import { install, isInstalled } from '../installer/installer.js'\nimport { installGemini, isGeminiAvailable } from '../installer/gemini.js'\nimport { installCopilot, isCopilotAvailable } from '../installer/copilot.js'\nimport { installOpenCode, isOpenCodeAvailable } from '../installer/opencode.js'\nimport { runWeb } from './web.js'\n\nexport function runInit(): void {\n if (isInstalled()) {\n console.log('bashstats hooks are already installed. Reinstalling...')\n }\n\n // Always install Claude Code hooks\n const claudeResult = install()\n if (!claudeResult.success) {\n console.error('Installation failed: ' + claudeResult.message)\n process.exit(1)\n }\n\n const installed: string[] = ['Claude Code']\n\n // Auto-detect and install for other agents\n if (isGeminiAvailable()) {\n const result = installGemini()\n if (result.success) installed.push('Gemini CLI')\n else console.log(` Note: ${result.message}`)\n }\n\n if (isCopilotAvailable()) {\n const result = installCopilot()\n if (result.success) installed.push('Copilot CLI')\n else console.log(` Note: ${result.message}`)\n }\n\n if (isOpenCodeAvailable()) {\n const result = installOpenCode()\n if (result.success) installed.push('OpenCode')\n else console.log(` Note: ${result.message}`)\n }\n\n console.log('')\n console.log(' bashstats installed successfully!')\n console.log('')\n console.log(` Installed hooks for: ${installed.join(', ')}`)\n console.log(' Your coding sessions are now being tracked.')\n console.log('')\n console.log(' [SECRET ACHIEVEMENT UNLOCKED] Launch Day')\n console.log(' \"Welcome to bashstats. Your stats are now being watched. Forever.\"')\n console.log('')\n console.log(' Opening dashboard...')\n console.log('')\n\n runWeb({})\n}\n","import os from 'os'\nimport path from 'path'\nimport { BashStatsDB } from '../db/database.js'\nimport { StatsEngine } from '../stats/engine.js'\nimport { DATA_DIR, DB_FILENAME } from '../constants.js'\n\nfunction formatDuration(seconds: number): string {\n const hours = Math.floor(seconds / 3600)\n const minutes = Math.floor((seconds % 3600) / 60)\n if (hours > 0) return `${hours}h ${minutes}m`\n return `${minutes}m`\n}\n\nfunction formatNumber(n: number): string {\n return n.toLocaleString()\n}\n\nexport function runStats(): void {\n const dbPath = path.join(os.homedir(), DATA_DIR, DB_FILENAME)\n let db: BashStatsDB\n try {\n db = new BashStatsDB(dbPath)\n } catch {\n console.log('No data yet. Run \"bashstats init\" to start tracking.')\n return\n }\n\n const engine = new StatsEngine(db)\n\n try {\n const lifetime = engine.getLifetimeStats()\n const tools = engine.getToolBreakdown()\n const time = engine.getTimeStats()\n const records = engine.getSessionRecords()\n const projects = engine.getProjectStats()\n\n console.log('')\n console.log(' bashstats - Your Claude Code Stats')\n console.log(' ===================================')\n\n // Lifetime Totals\n console.log('')\n console.log(' LIFETIME TOTALS')\n console.log(` Sessions: ${formatNumber(lifetime.totalSessions)}`)\n console.log(` Time: ${formatDuration(lifetime.totalDurationSeconds)}`)\n console.log(` Prompts: ${formatNumber(lifetime.totalPrompts)}`)\n console.log(` Chars typed: ${formatNumber(lifetime.totalCharsTyped)}`)\n console.log(` Tool calls: ${formatNumber(lifetime.totalToolCalls)}`)\n console.log(` Errors: ${formatNumber(lifetime.totalErrors)}`)\n\n // Tool Breakdown\n if (Object.keys(tools).length > 0) {\n console.log('')\n console.log(' TOOL BREAKDOWN')\n const sorted = Object.entries(tools).sort((a, b) => b[1] - a[1])\n for (const [name, count] of sorted.slice(0, 10)) {\n console.log(` ${name.padEnd(15)} ${formatNumber(count)}`)\n }\n }\n\n // Time & Streaks\n console.log('')\n console.log(' TIME & STREAKS')\n console.log(` Current streak: ${time.currentStreak} days`)\n console.log(` Longest streak: ${time.longestStreak} days`)\n console.log(` Peak hour: ${time.peakHour}:00 (${formatNumber(time.peakHourCount)} prompts)`)\n console.log(` Night owl: ${formatNumber(time.nightOwlCount)} late-night prompts`)\n console.log(` Weekend: ${formatNumber(time.weekendSessions)} weekend sessions`)\n\n // Session Records\n console.log('')\n console.log(' SESSION RECORDS')\n console.log(` Longest: ${formatDuration(records.longestSessionSeconds)}`)\n console.log(` Most tools: ${formatNumber(records.mostToolsInSession)} in one session`)\n console.log(` Most prompts: ${formatNumber(records.mostPromptsInSession)} in one session`)\n console.log(` Avg duration: ${formatDuration(records.avgDurationSeconds)}`)\n\n // Projects\n if (projects.uniqueProjects > 0) {\n console.log('')\n console.log(' PROJECTS')\n console.log(` Unique: ${projects.uniqueProjects}`)\n console.log(` Most visited: ${projects.mostVisitedProject} (${formatNumber(projects.mostVisitedProjectCount)} sessions)`)\n }\n\n console.log('')\n } finally {\n db.close()\n }\n}\n","import os from 'os'\nimport path from 'path'\nimport { BashStatsDB } from '../db/database.js'\nimport { StatsEngine } from '../stats/engine.js'\nimport { AchievementEngine } from '../achievements/compute.js'\nimport { DATA_DIR, DB_FILENAME } from '../constants.js'\nimport type { BadgeResult } from '../types.js'\n\nfunction progressBar(progress: number, width: number = 20): string {\n const filled = Math.round(progress * width)\n const empty = width - filled\n return '#'.repeat(filled) + '.'.repeat(empty)\n}\n\nfunction tierColor(tierName: string): string {\n return `[${tierName}]`\n}\n\nexport function runAchievements(): void {\n const dbPath = path.join(os.homedir(), DATA_DIR, DB_FILENAME)\n let db: BashStatsDB\n try {\n db = new BashStatsDB(dbPath)\n } catch {\n console.log('No data yet. Run \"bashstats init\" to start tracking.')\n return\n }\n\n const stats = new StatsEngine(db)\n const engine = new AchievementEngine(db, stats)\n\n try {\n const payload = engine.getAchievementsPayload()\n\n // Header\n console.log('')\n console.log(` bashstats - Achievements`)\n console.log(` Rank ${payload.xp.rankNumber} [${payload.xp.rankTier}] XP: ${payload.xp.totalXP.toLocaleString()} / ${payload.xp.nextRankXP.toLocaleString()}`)\n console.log(` ${progressBar(payload.xp.progress, 40)} ${Math.round(payload.xp.progress * 100)}%`)\n console.log('')\n\n // Group badges by category\n const categories = new Map<string, BadgeResult[]>()\n for (const badge of payload.badges) {\n // Skip secrets that aren't unlocked\n if (badge.secret && !badge.unlocked) continue\n const cat = badge.category\n if (!categories.has(cat)) categories.set(cat, [])\n categories.get(cat)!.push(badge)\n }\n\n const categoryNames: Record<string, string> = {\n volume: 'VOLUME',\n tool_mastery: 'TOOL MASTERY',\n time: 'TIME & PATTERNS',\n session_behavior: 'SESSION BEHAVIOR',\n behavioral: 'BEHAVIORAL',\n prompt_patterns: 'PROMPT PATTERNS',\n resilience: 'RESILIENCE',\n error_recovery: 'ERROR & RECOVERY',\n tool_combos: 'TOOL COMBOS',\n shipping: 'SHIPPING & PROJECTS',\n project_dedication: 'PROJECT DEDICATION',\n multi_agent: 'MULTI-AGENT',\n wild_card: 'WILD CARD',\n token_usage: 'TOKEN USAGE',\n aspirational: 'ASPIRATIONAL',\n secret: 'SECRET',\n }\n\n for (const [cat, badges] of categories) {\n console.log(` ${categoryNames[cat] || cat.toUpperCase()}`)\n for (const badge of badges) {\n const tier = badge.tier > 0 ? tierColor(badge.tierName) : '[Locked]'\n const bar = badge.maxed ? ' MAXED' : ` ${progressBar(badge.progress, 15)}`\n const value = badge.value.toLocaleString()\n const next = badge.maxed ? '' : ` / ${badge.nextThreshold.toLocaleString()}`\n console.log(` ${tier.padEnd(12)} ${badge.name.padEnd(22)} ${value}${next}${bar}`)\n if (badge.description && (badge.category === 'wild_card' || badge.category === 'secret')) {\n console.log(` \"${badge.description}\"`)\n }\n }\n console.log('')\n }\n } finally {\n db.close()\n }\n}\n","import os from 'os'\nimport path from 'path'\nimport { BashStatsDB } from '../db/database.js'\nimport { StatsEngine } from '../stats/engine.js'\nimport { DATA_DIR, DB_FILENAME } from '../constants.js'\n\nexport function runStreak(): void {\n const dbPath = path.join(os.homedir(), DATA_DIR, DB_FILENAME)\n let db: BashStatsDB\n try {\n db = new BashStatsDB(dbPath)\n } catch {\n console.log('No data yet. Run \"bashstats init\" to start tracking.')\n return\n }\n\n const engine = new StatsEngine(db)\n\n try {\n const time = engine.getTimeStats()\n const daily = db.getAllDailyActivity(30)\n\n console.log('')\n console.log(' bashstats - Streak')\n console.log(` Current streak: ${time.currentStreak} days`)\n console.log(` Longest streak: ${time.longestStreak} days`)\n console.log('')\n\n // Last 30 days calendar\n if (daily.length > 0) {\n console.log(' Last 30 days:')\n const dates = new Set(daily.map(d => d.date))\n const today = new Date()\n const pad = (n: number) => String(n).padStart(2, '0')\n let line = ' '\n for (let i = 29; i >= 0; i--) {\n const d = new Date(today)\n d.setDate(d.getDate() - i)\n const dateStr = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`\n line += dates.has(dateStr) ? '#' : '.'\n }\n console.log(line)\n }\n console.log('')\n } finally {\n db.close()\n }\n}\n","import os from 'os'\nimport path from 'path'\nimport { BashStatsDB } from '../db/database.js'\nimport { StatsEngine } from '../stats/engine.js'\nimport { AchievementEngine } from '../achievements/compute.js'\nimport { DATA_DIR, DB_FILENAME } from '../constants.js'\n\nexport function runExport(): void {\n const dbPath = path.join(os.homedir(), DATA_DIR, DB_FILENAME)\n let db: BashStatsDB\n try {\n db = new BashStatsDB(dbPath)\n } catch {\n console.error('No data found. Run \"bashstats init\" first.')\n process.exit(1)\n }\n\n const stats = new StatsEngine(db)\n const achievements = new AchievementEngine(db, stats)\n\n try {\n const payload = {\n exported_at: new Date().toISOString(),\n stats: stats.getAllStats(),\n achievements: achievements.getAchievementsPayload(),\n daily_activity: db.getAllDailyActivity(),\n }\n console.log(JSON.stringify(payload, null, 2))\n } finally {\n db.close()\n }\n}\n","import os from 'os'\nimport path from 'path'\nimport fs from 'fs'\nimport { BashStatsDB } from '../db/database.js'\nimport { DATA_DIR, DB_FILENAME } from '../constants.js'\n\nexport function runReset(): void {\n const dbPath = path.join(os.homedir(), DATA_DIR, DB_FILENAME)\n\n if (!fs.existsSync(dbPath)) {\n console.log('No data to reset.')\n return\n }\n\n // Delete and recreate\n fs.unlinkSync(dbPath)\n const db = new BashStatsDB(dbPath)\n db.setMetadata('first_run', new Date().toISOString())\n db.close()\n\n console.log('All data has been reset. Starting fresh.')\n}\n","import os from 'os'\nimport path from 'path'\nimport fs from 'fs'\nimport { uninstall as removeClaudeHooks } from '../installer/installer.js'\nimport { uninstallGemini } from '../installer/gemini.js'\nimport { uninstallCopilot } from '../installer/copilot.js'\nimport { uninstallOpenCode } from '../installer/opencode.js'\nimport { DATA_DIR } from '../constants.js'\n\nexport function runUninstall(): void {\n // Remove all agent hooks\n const claudeResult = removeClaudeHooks()\n console.log(claudeResult.message)\n\n const geminiResult = uninstallGemini()\n if (geminiResult.success && !geminiResult.message.includes('nothing to uninstall')) console.log(geminiResult.message)\n else if (!geminiResult.success) console.log(geminiResult.message)\n\n const copilotResult = uninstallCopilot()\n console.log(copilotResult.message)\n\n const openCodeResult = uninstallOpenCode()\n console.log(openCodeResult.message)\n\n // Remove data directory\n const dataDir = path.join(os.homedir(), DATA_DIR)\n if (fs.existsSync(dataDir)) {\n fs.rmSync(dataDir, { recursive: true })\n console.log(`Removed data directory: ${dataDir}`)\n }\n\n console.log('bashstats has been fully uninstalled.')\n}\n"],"mappings":"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","names":["path","path","os","path","path","os","os","path","path","os","os","path","path","os","os","path","fs","path","os","fs","os","path","fs","path","os","fs"]}