bashstats 0.2.0 → 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.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleHookEvent
4
- } from "./chunk-7K77JJRD.js";
4
+ } from "./chunk-CLSVLWCR.js";
5
5
 
6
6
  // src/hooks/scripts/permission-request.ts
7
7
  handleHookEvent("PermissionRequest").catch(() => process.exit(0));
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleHookEvent
4
- } from "./chunk-7K77JJRD.js";
4
+ } from "./chunk-CLSVLWCR.js";
5
5
 
6
6
  // src/hooks/scripts/post-tool-failure.ts
7
7
  handleHookEvent("PostToolUseFailure").catch(() => process.exit(0));
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleHookEvent
4
- } from "./chunk-7K77JJRD.js";
4
+ } from "./chunk-CLSVLWCR.js";
5
5
 
6
6
  // src/hooks/scripts/post-tool-use.ts
7
7
  handleHookEvent("PostToolUse").catch(() => process.exit(0));
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleHookEvent
4
- } from "./chunk-7K77JJRD.js";
4
+ } from "./chunk-CLSVLWCR.js";
5
5
 
6
6
  // src/hooks/scripts/pre-compact.ts
7
7
  handleHookEvent("PreCompact").catch(() => process.exit(0));
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleHookEvent
4
- } from "./chunk-7K77JJRD.js";
4
+ } from "./chunk-CLSVLWCR.js";
5
5
 
6
6
  // src/hooks/scripts/pre-tool-use.ts
7
7
  handleHookEvent("PreToolUse").catch(() => process.exit(0));
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleHookEvent
4
- } from "./chunk-7K77JJRD.js";
4
+ } from "./chunk-CLSVLWCR.js";
5
5
 
6
6
  // src/hooks/scripts/session-start.ts
7
7
  handleHookEvent("SessionStart").catch(() => process.exit(0));
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleHookEvent
4
- } from "./chunk-7K77JJRD.js";
4
+ } from "./chunk-CLSVLWCR.js";
5
5
 
6
6
  // src/hooks/scripts/setup.ts
7
7
  handleHookEvent("Setup").catch(() => process.exit(0));
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleHookEvent
4
- } from "./chunk-7K77JJRD.js";
4
+ } from "./chunk-CLSVLWCR.js";
5
5
 
6
6
  // src/hooks/scripts/stop.ts
7
7
  handleHookEvent("Stop").catch(() => process.exit(0));
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleHookEvent
4
- } from "./chunk-7K77JJRD.js";
4
+ } from "./chunk-CLSVLWCR.js";
5
5
 
6
6
  // src/hooks/scripts/subagent-start.ts
7
7
  handleHookEvent("SubagentStart").catch(() => process.exit(0));
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleHookEvent
4
- } from "./chunk-7K77JJRD.js";
4
+ } from "./chunk-CLSVLWCR.js";
5
5
 
6
6
  // src/hooks/scripts/subagent-stop.ts
7
7
  handleHookEvent("SubagentStop").catch(() => process.exit(0));
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleHookEvent
4
- } from "./chunk-7K77JJRD.js";
4
+ } from "./chunk-CLSVLWCR.js";
5
5
 
6
6
  // src/hooks/scripts/user-prompt-submit.ts
7
7
  handleHookEvent("UserPromptSubmit").catch(() => process.exit(0));
package/dist/index.d.ts CHANGED
@@ -177,6 +177,12 @@ interface AllStats {
177
177
  sessions: SessionRecords;
178
178
  projects: ProjectStats;
179
179
  }
180
+ interface AgentBreakdown {
181
+ favoriteAgent: string;
182
+ sessionsPerAgent: Record<string, number>;
183
+ hoursPerAgent: Record<string, number>;
184
+ distinctAgents: number;
185
+ }
180
186
  type AgentType = 'claude-code' | 'gemini-cli' | 'copilot-cli' | 'opencode' | 'unknown';
181
187
  declare const AGENT_DISPLAY_NAMES: Record<AgentType, string>;
182
188
  type BadgeTier = 0 | 1 | 2 | 3 | 4 | 5;
@@ -185,11 +191,11 @@ interface BadgeDefinition {
185
191
  name: string;
186
192
  icon: string;
187
193
  description: string;
188
- category: 'volume' | 'tool_mastery' | 'time' | 'behavioral' | 'resilience' | 'shipping' | 'multi_agent' | 'humor' | 'aspirational' | 'secret';
194
+ category: 'volume' | 'tool_mastery' | 'time' | 'behavioral' | 'resilience' | 'shipping' | 'multi_agent' | 'wild_card' | 'aspirational' | 'secret' | 'session_behavior' | 'prompt_patterns' | 'error_recovery' | 'tool_combos' | 'project_dedication' | 'token_usage';
189
195
  stat: string;
190
196
  tiers: [number, number, number, number, number];
197
+ trigger: string;
191
198
  secret?: boolean;
192
- humor?: boolean;
193
199
  aspirational?: boolean;
194
200
  }
195
201
  interface BadgeResult {
@@ -206,12 +212,14 @@ interface BadgeResult {
206
212
  nextThreshold: number;
207
213
  progress: number;
208
214
  maxed: boolean;
215
+ trigger: string;
209
216
  secret: boolean;
210
217
  unlocked: boolean;
211
218
  }
212
219
  interface XPResult {
213
220
  totalXP: number;
214
- rank: string;
221
+ rankNumber: number;
222
+ rankTier: string;
215
223
  nextRankXP: number;
216
224
  progress: number;
217
225
  }
@@ -221,6 +229,45 @@ interface AchievementsPayload {
221
229
  xp: XPResult;
222
230
  }
223
231
  declare const TIER_NAMES: Record<BadgeTier, string>;
232
+ interface WeeklyChallenge {
233
+ id: string;
234
+ description: string;
235
+ stat: string;
236
+ threshold: number;
237
+ xpReward: number;
238
+ weekScoped: boolean;
239
+ }
240
+ interface WeeklyGoalRow {
241
+ week_start: string;
242
+ challenge_id: string;
243
+ completed: number;
244
+ xp_reward: number;
245
+ }
246
+ interface WeeklyXPRow {
247
+ week_start: string;
248
+ base_xp: number;
249
+ multiplier: number;
250
+ bonus_xp: number;
251
+ }
252
+ interface WeeklyGoalsPayload {
253
+ weekStart: string;
254
+ daysActive: number;
255
+ multiplier: number;
256
+ challenges: Array<{
257
+ id: string;
258
+ description: string;
259
+ xpReward: number;
260
+ completed: boolean;
261
+ progress: number;
262
+ threshold: number;
263
+ current: number;
264
+ }>;
265
+ }
266
+ interface RankTierBracket {
267
+ tier: string;
268
+ minRank: number;
269
+ maxRank: number;
270
+ }
224
271
 
225
272
  declare class BashStatsDB {
226
273
  private db;
@@ -269,6 +316,11 @@ declare class BashStatsDB {
269
316
  markNotified(badgeId: string, tier: number): void;
270
317
  setMetadata(key: string, value: string): void;
271
318
  getMetadata(key: string): string | null;
319
+ insertWeeklyGoal(weekStart: string, challengeId: string, xpReward: number): void;
320
+ completeWeeklyGoal(weekStart: string, challengeId: string): void;
321
+ getWeeklyGoals(weekStart: string): WeeklyGoalRow[];
322
+ upsertWeeklyXP(weekStart: string, baseXP: number, multiplier: number, bonusXP: number): void;
323
+ getWeeklyXP(weekStart: string): WeeklyXPRow | null;
272
324
  prepare(sql: string): Database.Statement;
273
325
  }
274
326
 
@@ -291,21 +343,33 @@ declare class StatsEngine {
291
343
  private db;
292
344
  constructor(db: BashStatsDB);
293
345
  private queryScalar;
294
- getLifetimeStats(): LifetimeStats;
295
- getToolBreakdown(): ToolBreakdown;
296
- getTimeStats(): TimeStats;
297
- getSessionRecords(): SessionRecords;
298
- getProjectStats(): ProjectStats;
299
- getAllStats(): AllStats;
346
+ /** Returns a WHERE/AND clause filtering sessions by agent */
347
+ private agentWhere;
348
+ /** Returns a subquery filter for events/prompts tables */
349
+ private agentSessionFilter;
350
+ getLifetimeStats(agent?: string): LifetimeStats;
351
+ getToolBreakdown(agent?: string): ToolBreakdown;
352
+ getTimeStats(agent?: string): TimeStats;
353
+ getSessionRecords(agent?: string): SessionRecords;
354
+ getProjectStats(agent?: string): ProjectStats;
355
+ getAllStats(agent?: string): AllStats;
356
+ getAgentBreakdown(): {
357
+ favoriteAgent: string;
358
+ sessionsPerAgent: Record<string, number>;
359
+ hoursPerAgent: Record<string, number>;
360
+ distinctAgents: number;
361
+ };
362
+ getWeeklyGoalsPayload(): WeeklyGoalsPayload;
363
+ private computeWeeklyStat;
300
364
  }
301
365
 
302
366
  declare class AchievementEngine {
303
367
  private db;
304
368
  private stats;
305
369
  constructor(db: BashStatsDB, stats: StatsEngine);
306
- computeBadges(): BadgeResult[];
307
- computeXP(): XPResult;
308
- getAchievementsPayload(): AchievementsPayload;
370
+ computeBadges(agent?: string): BadgeResult[];
371
+ computeXP(agent?: string): XPResult;
372
+ getAchievementsPayload(agent?: string): AchievementsPayload;
309
373
  private flattenStats;
310
374
  private queryScalar;
311
375
  private queryTotalSearches;
@@ -333,6 +397,53 @@ declare class AchievementEngine {
333
397
  private queryHolidayActivity;
334
398
  private querySpeedRunSession;
335
399
  private queryAllToolsInSession;
400
+ private queryWitchingHourPrompts;
401
+ private queryLunchBreakDays;
402
+ private queryMondaySessions;
403
+ private queryFridayCommits;
404
+ private queryMaxUniqueHoursInDay;
405
+ private queryUniqueQuarters;
406
+ private queryExtendedSessionCount;
407
+ private queryQuickDrawSessions;
408
+ private queryDiverseToolSessions;
409
+ private queryPermissionRequests;
410
+ private queryReturnerDays;
411
+ private queryShortPromptCount;
412
+ private queryQuestionPromptCount;
413
+ private querySorryPromptCount;
414
+ private queryCapsLockPromptCount;
415
+ private queryEmojiPromptCount;
416
+ private queryCodeDumpPromptCount;
417
+ private queryRubberDuckCount;
418
+ private queryThirdTimeCharmCount;
419
+ private queryUndoEditCount;
420
+ private queryCrashySessions;
421
+ private queryReadEditRunCount;
422
+ private queryMaxFilesCreatedInSession;
423
+ private queryMaxSameFileEditsLifetime;
424
+ private querySearchThenEditCount;
425
+ private queryMaxProjectSessions;
426
+ private queryMaxProjectsInDay;
427
+ private queryFinishedProjects;
428
+ private queryLegacyReturns;
429
+ private queryMaxConcurrentSubagents;
430
+ private queryQuickSubagentStops;
431
+ private queryMaxSubagentsInSession;
432
+ private queryDejaVuCount;
433
+ private queryTrustIssueCount;
434
+ private queryBackseatDriverCount;
435
+ private queryNegotiatorCount;
436
+ private queryMaxConsecutivePermissions;
437
+ private queryBashRetrySuccessCount;
438
+ private queryEasterEggActivity;
439
+ private queryFullMoonSession;
440
+ private queryBirthdaySession;
441
+ private queryGhostSessions;
442
+ private queryBullseyeSessions;
443
+ private queryHeavyTokenSessions;
444
+ private queryLightTokenSessions;
445
+ private queryMaxOutputInSession;
446
+ private queryHasTenMillionSession;
336
447
  }
337
448
 
338
449
  /**
@@ -360,6 +471,71 @@ declare function uninstall(): {
360
471
  */
361
472
  declare function isInstalled(): boolean;
362
473
 
474
+ /**
475
+ * Checks if the ~/.gemini/ directory exists, indicating Gemini CLI is available.
476
+ */
477
+ declare function isGeminiAvailable(): boolean;
478
+ /**
479
+ * Full Gemini installation:
480
+ * - Creates ~/.bashstats/ directory
481
+ * - Initializes the database with metadata
482
+ * - Reads existing ~/.gemini/settings.json
483
+ * - Merges bashstats hooks
484
+ * - Writes settings back
485
+ */
486
+ declare function installGemini(): {
487
+ success: boolean;
488
+ message: string;
489
+ };
490
+ /**
491
+ * Removes all bashstats hooks from ~/.gemini/settings.json.
492
+ * Cleans up empty arrays and empty hooks objects.
493
+ */
494
+ declare function uninstallGemini(): {
495
+ success: boolean;
496
+ message: string;
497
+ };
498
+
499
+ /**
500
+ * Installs bashstats hooks for Copilot by writing bashstats-hooks.json
501
+ * to ~/.copilot/hooks/.
502
+ */
503
+ declare function installCopilot(): {
504
+ success: boolean;
505
+ message: string;
506
+ };
507
+ /**
508
+ * Uninstalls bashstats hooks for Copilot by deleting bashstats-hooks.json.
509
+ */
510
+ declare function uninstallCopilot(): {
511
+ success: boolean;
512
+ message: string;
513
+ };
514
+ /**
515
+ * Checks if the `copilot` binary is available on PATH.
516
+ */
517
+ declare function isCopilotAvailable(): boolean;
518
+
519
+ /**
520
+ * Checks whether OpenCode is available by looking for ~/.config/opencode/.
521
+ */
522
+ declare function isOpenCodeAvailable(): boolean;
523
+ /**
524
+ * Installs the bashstats plugin into OpenCode's plugins directory.
525
+ * Creates the plugins directory if it does not exist.
526
+ */
527
+ declare function installOpenCode(): {
528
+ success: boolean;
529
+ message: string;
530
+ };
531
+ /**
532
+ * Removes the bashstats plugin file from OpenCode's plugins directory.
533
+ */
534
+ declare function uninstallOpenCode(): {
535
+ success: boolean;
536
+ message: string;
537
+ };
538
+
363
539
  /**
364
540
  * Detect which CLI agent is running based on environment variables and process context.
365
541
  * Currently supports Claude Code (default), Gemini CLI, Copilot CLI, and OpenCode.
@@ -369,13 +545,14 @@ declare function parseHookEvent(input: string): Record<string, unknown> | null;
369
545
  declare function handleHookEvent(hookType: string): Promise<void>;
370
546
 
371
547
  declare const BADGE_DEFINITIONS: BadgeDefinition[];
372
- declare const RANK_THRESHOLDS: {
373
- rank: string;
374
- xp: number;
375
- }[];
548
+ declare const RANK_TIER_BRACKETS: RankTierBracket[];
549
+ declare function xpForRank(rank: number): number;
550
+ declare function rankTierForRank(rank: number): string;
376
551
  declare const TIER_XP: number[];
552
+ declare const ACTIVITY_MULTIPLIERS: Record<number, number>;
553
+ declare const WEEKLY_CHALLENGES: WeeklyChallenge[];
377
554
  declare const DATA_DIR = ".bashstats";
378
555
  declare const DB_FILENAME = "bashstats.db";
379
556
  declare const DEFAULT_PORT = 17900;
380
557
 
381
- export { AGENT_DISPLAY_NAMES, AchievementEngine, type AchievementUnlockRow, type AchievementsPayload, type AgentType, type AllStats, BADGE_DEFINITIONS, type BadgeDefinition, type BadgeResult, type BadgeTier, BashStatsDB, BashStatsWriter, DATA_DIR, DB_FILENAME, DEFAULT_PORT, type DailyActivityRow, type EventRow, type HookInput, type LifetimeStats, type NotificationInput, type PermissionRequestInput, type PostToolUseInput, type PreCompactInput, type PreToolUseInput, type ProjectStats, type PromptRow, RANK_THRESHOLDS, type SessionRecords, type SessionRow, type SessionStartInput, type SetupInput, StatsEngine, type StopInput, type SubagentStartInput, type SubagentStopInput, TIER_NAMES, TIER_XP, type TimeStats, type TokenUsage, type ToolBreakdown, type UserPromptInput, type XPResult, detectAgent, handleHookEvent, install, isInstalled, parseHookEvent, uninstall };
558
+ export { ACTIVITY_MULTIPLIERS, AGENT_DISPLAY_NAMES, AchievementEngine, type AchievementUnlockRow, type AchievementsPayload, type AgentBreakdown, type AgentType, type AllStats, BADGE_DEFINITIONS, type BadgeDefinition, type BadgeResult, type BadgeTier, BashStatsDB, BashStatsWriter, DATA_DIR, DB_FILENAME, DEFAULT_PORT, type DailyActivityRow, type EventRow, type HookInput, type LifetimeStats, type NotificationInput, type PermissionRequestInput, type PostToolUseInput, type PreCompactInput, type PreToolUseInput, type ProjectStats, type PromptRow, RANK_TIER_BRACKETS, type RankTierBracket, type SessionRecords, type SessionRow, type SessionStartInput, type SetupInput, StatsEngine, type StopInput, type SubagentStartInput, type SubagentStopInput, TIER_NAMES, TIER_XP, type TimeStats, type TokenUsage, type ToolBreakdown, type UserPromptInput, WEEKLY_CHALLENGES, type WeeklyChallenge, type WeeklyGoalRow, type WeeklyGoalsPayload, type WeeklyXPRow, type XPResult, detectAgent, handleHookEvent, install, installCopilot, installGemini, installOpenCode, isCopilotAvailable, isGeminiAvailable, isInstalled, isOpenCodeAvailable, parseHookEvent, rankTierForRank, uninstall, uninstallCopilot, uninstallGemini, uninstallOpenCode, xpForRank };
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ ACTIVITY_MULTIPLIERS,
3
4
  AGENT_DISPLAY_NAMES,
4
5
  AchievementEngine,
5
6
  BADGE_DEFINITIONS,
@@ -8,18 +9,31 @@ import {
8
9
  DATA_DIR,
9
10
  DB_FILENAME,
10
11
  DEFAULT_PORT,
11
- RANK_THRESHOLDS,
12
+ RANK_TIER_BRACKETS,
12
13
  StatsEngine,
13
14
  TIER_NAMES,
14
15
  TIER_XP,
16
+ WEEKLY_CHALLENGES,
15
17
  detectAgent,
16
18
  handleHookEvent,
17
19
  install,
20
+ installCopilot,
21
+ installGemini,
22
+ installOpenCode,
23
+ isCopilotAvailable,
24
+ isGeminiAvailable,
18
25
  isInstalled,
26
+ isOpenCodeAvailable,
19
27
  parseHookEvent,
20
- uninstall
21
- } from "./chunk-OYLQHCOY.js";
28
+ rankTierForRank,
29
+ uninstall,
30
+ uninstallCopilot,
31
+ uninstallGemini,
32
+ uninstallOpenCode,
33
+ xpForRank
34
+ } from "./chunk-YAJO5WNW.js";
22
35
  export {
36
+ ACTIVITY_MULTIPLIERS,
23
37
  AGENT_DISPLAY_NAMES,
24
38
  AchievementEngine,
25
39
  BADGE_DEFINITIONS,
@@ -28,15 +42,27 @@ export {
28
42
  DATA_DIR,
29
43
  DB_FILENAME,
30
44
  DEFAULT_PORT,
31
- RANK_THRESHOLDS,
45
+ RANK_TIER_BRACKETS,
32
46
  StatsEngine,
33
47
  TIER_NAMES,
34
48
  TIER_XP,
49
+ WEEKLY_CHALLENGES,
35
50
  detectAgent,
36
51
  handleHookEvent,
37
52
  install,
53
+ installCopilot,
54
+ installGemini,
55
+ installOpenCode,
56
+ isCopilotAvailable,
57
+ isGeminiAvailable,
38
58
  isInstalled,
59
+ isOpenCodeAvailable,
39
60
  parseHookEvent,
40
- uninstall
61
+ rankTierForRank,
62
+ uninstall,
63
+ uninstallCopilot,
64
+ uninstallGemini,
65
+ uninstallOpenCode,
66
+ xpForRank
41
67
  };
42
68
  //# sourceMappingURL=index.js.map