@hackersbaby/plugin 0.4.1 → 0.5.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.
package/dist/cli.js CHANGED
@@ -9,6 +9,9 @@ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
9
  var __esm = (fn, res) => function __init() {
10
10
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
11
  };
12
+ var __commonJS = (cb, mod) => function __require() {
13
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
14
+ };
12
15
  var __export = (target, all) => {
13
16
  for (var name in all)
14
17
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -62,27 +65,197 @@ var init_config = __esm({
62
65
  }
63
66
  });
64
67
 
68
+ // ../shared/dist/types.js
69
+ var require_types = __commonJS({
70
+ "../shared/dist/types.js"(exports2) {
71
+ "use strict";
72
+ Object.defineProperty(exports2, "__esModule", { value: true });
73
+ }
74
+ });
75
+
76
+ // ../shared/dist/scoring.js
77
+ var require_scoring = __commonJS({
78
+ "../shared/dist/scoring.js"(exports2) {
79
+ "use strict";
80
+ Object.defineProperty(exports2, "__esModule", { value: true });
81
+ exports2.DEPLOY_PATTERNS = exports2.BASE_POINTS = exports2.MIN_SESSION_TOKENS = exports2.TOOL_CALLS_PER_HOUR_CAP = exports2.SESSION_BASE_POINT_CAP = void 0;
82
+ exports2.getBasePoints = getBasePoints;
83
+ exports2.calculateMultiplier = calculateMultiplier;
84
+ exports2.calculateSessionScore = calculateSessionScore;
85
+ exports2.isDeployCommand = isDeployCommand;
86
+ exports2.SESSION_BASE_POINT_CAP = 2e4;
87
+ exports2.TOOL_CALLS_PER_HOUR_CAP = 4e3;
88
+ exports2.MIN_SESSION_TOKENS = 2e3;
89
+ exports2.BASE_POINTS = {
90
+ token_input: { perUnit: 1, unitSize: 1e3 },
91
+ token_output: { perUnit: 2, unitSize: 1e3 },
92
+ tool_call: { perUnit: 5, unitSize: 1 },
93
+ file_created: { perUnit: 15, unitSize: 1 },
94
+ file_edited: { perUnit: 10, unitSize: 1 },
95
+ commit: { perUnit: 50, unitSize: 1 },
96
+ session_completed: { perUnit: 100, unitSize: 1 },
97
+ deployment: { perUnit: 200, unitSize: 1 },
98
+ prompt_submitted: { perUnit: 15, unitSize: 1 },
99
+ subagent_spawned: { perUnit: 40, unitSize: 1 },
100
+ context_compacted: { perUnit: 30, unitSize: 1 },
101
+ stop_response: { perUnit: 10, unitSize: 1 }
102
+ };
103
+ exports2.DEPLOY_PATTERNS = [
104
+ /^vercel\s+(--prod|deploy)/,
105
+ /^netlify\s+deploy/,
106
+ /^fly\s+deploy/,
107
+ /^railway\s+up/,
108
+ /^git\s+push\s+\S+\s+(main|master|production)/,
109
+ /^(npm|yarn|pnpm)\s+run\s+deploy/,
110
+ /^(yarn|pnpm)\s+deploy/
111
+ ];
112
+ function getBasePoints(actionType, value) {
113
+ const config = exports2.BASE_POINTS[actionType];
114
+ return Math.floor(value / config.unitSize) * config.perUnit;
115
+ }
116
+ function calculateMultiplier(input) {
117
+ let streak = 1;
118
+ if (input.streak_days >= 30)
119
+ streak = 3;
120
+ else if (input.streak_days >= 7)
121
+ streak = 2;
122
+ else if (input.streak_days >= 3)
123
+ streak = 1.5;
124
+ const quality = input.commit_quality ? 1.5 : 1;
125
+ const diversity = input.language_count >= 3 ? 1.2 : 1;
126
+ return streak * quality * diversity;
127
+ }
128
+ function calculateSessionScore(events, multiplier) {
129
+ let totalBase = 0;
130
+ for (const e of events)
131
+ totalBase += getBasePoints(e.action_type, e.value);
132
+ return Math.floor(Math.min(totalBase, exports2.SESSION_BASE_POINT_CAP) * multiplier);
133
+ }
134
+ function isDeployCommand(command2) {
135
+ return exports2.DEPLOY_PATTERNS.some((p) => p.test(command2.trim()));
136
+ }
137
+ }
138
+ });
139
+
140
+ // ../shared/dist/anticheat.js
141
+ var require_anticheat = __commonJS({
142
+ "../shared/dist/anticheat.js"(exports2) {
143
+ "use strict";
144
+ Object.defineProperty(exports2, "__esModule", { value: true });
145
+ exports2.hashEvent = hashEvent;
146
+ exports2.computeChainHash = computeChainHash2;
147
+ exports2.signBatch = signBatch2;
148
+ exports2.verifyBatchSignature = verifyBatchSignature;
149
+ var crypto_1 = require("crypto");
150
+ function hashEvent(event, prevHash) {
151
+ const payload = `${prevHash}|${event.action_type}|${event.value}|${event.timestamp}`;
152
+ return (0, crypto_1.createHash)("sha256").update(payload).digest("hex").slice(0, 16);
153
+ }
154
+ function computeChainHash2(events, initialHash = "0000000000000000") {
155
+ let hash = initialHash;
156
+ for (const event of events) {
157
+ hash = hashEvent(event, hash);
158
+ }
159
+ return hash;
160
+ }
161
+ function signBatch2(sessionId, events, chainHash, secret) {
162
+ const valueSum = events.reduce((s, e) => s + e.value, 0);
163
+ const message = `${sessionId}|${chainHash}|${events.length}|${valueSum}`;
164
+ return (0, crypto_1.createHmac)("sha256", secret).update(message).digest("hex");
165
+ }
166
+ function verifyBatchSignature(sessionId, events, chainHash, signature, secret) {
167
+ const expected = signBatch2(sessionId, events, chainHash, secret);
168
+ if (expected.length !== signature.length)
169
+ return false;
170
+ let mismatch = 0;
171
+ for (let i = 0; i < expected.length; i++) {
172
+ mismatch |= expected.charCodeAt(i) ^ signature.charCodeAt(i);
173
+ }
174
+ return mismatch === 0;
175
+ }
176
+ }
177
+ });
178
+
179
+ // ../shared/dist/index.js
180
+ var require_dist = __commonJS({
181
+ "../shared/dist/index.js"(exports2) {
182
+ "use strict";
183
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
184
+ if (k2 === void 0) k2 = k;
185
+ var desc = Object.getOwnPropertyDescriptor(m, k);
186
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
187
+ desc = { enumerable: true, get: function() {
188
+ return m[k];
189
+ } };
190
+ }
191
+ Object.defineProperty(o, k2, desc);
192
+ }) : (function(o, m, k, k2) {
193
+ if (k2 === void 0) k2 = k;
194
+ o[k2] = m[k];
195
+ }));
196
+ var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
197
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
198
+ };
199
+ Object.defineProperty(exports2, "__esModule", { value: true });
200
+ __exportStar(require_types(), exports2);
201
+ __exportStar(require_scoring(), exports2);
202
+ __exportStar(require_anticheat(), exports2);
203
+ }
204
+ });
205
+
65
206
  // src/api-client.ts
66
207
  var api_client_exports = {};
67
208
  __export(api_client_exports, {
68
209
  APIClient: () => APIClient
69
210
  });
70
- var APIClient;
211
+ var import_shared, APIClient;
71
212
  var init_api_client = __esm({
72
213
  "src/api-client.ts"() {
73
214
  "use strict";
74
215
  init_config();
216
+ import_shared = __toESM(require_dist());
75
217
  APIClient = class {
76
218
  config = loadConfig();
219
+ sessionSecret = null;
220
+ chainHash = "0000000000000000";
77
221
  get headers() {
78
222
  return {
79
223
  "Content-Type": "application/json",
80
224
  Authorization: `Bearer ${this.config?.token || ""}`
81
225
  };
82
226
  }
227
+ /** Register session with server and get cryptographic secret */
228
+ async startSession(sessionId) {
229
+ try {
230
+ const server = this.config?.server || "https://hackers.baby";
231
+ const res = await fetch(`${server}/api/sessions/start`, {
232
+ method: "POST",
233
+ headers: this.headers,
234
+ body: JSON.stringify({ session_id: sessionId })
235
+ });
236
+ if (res.ok) {
237
+ const data = await res.json();
238
+ this.sessionSecret = data.session_secret;
239
+ this.chainHash = data.initial_chain_hash;
240
+ return true;
241
+ }
242
+ return false;
243
+ } catch {
244
+ return false;
245
+ }
246
+ }
83
247
  async sendBatch(batch) {
84
248
  try {
85
249
  const server = this.config?.server || "https://hackers.baby";
250
+ if (this.sessionSecret) {
251
+ const prevChainHash = this.chainHash;
252
+ const newChainHash = (0, import_shared.computeChainHash)(batch.events, prevChainHash);
253
+ const signature = (0, import_shared.signBatch)(batch.session_id, batch.events, newChainHash, this.sessionSecret);
254
+ batch.signature = signature;
255
+ batch.chain_hash = newChainHash;
256
+ batch.prev_chain_hash = prevChainHash;
257
+ this.chainHash = newChainHash;
258
+ }
86
259
  const res = await fetch(`${server}/api/scores/batch`, {
87
260
  method: "POST",
88
261
  headers: this.headers,
@@ -464,6 +637,7 @@ function registerCursorHooks() {
464
637
  if (import_fs2.default.existsSync(cursorHooksPath)) {
465
638
  hooksConfig = JSON.parse(import_fs2.default.readFileSync(cursorHooksPath, "utf-8"));
466
639
  }
640
+ if (!hooksConfig.version) hooksConfig.version = 1;
467
641
  if (!hooksConfig.hooks) hooksConfig.hooks = {};
468
642
  const distDir = import_path2.default.resolve(__dirname);
469
643
  const hookEntries = {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts","../src/api-client.ts","../src/cli.ts","../src/commands/status.ts","../src/commands/leaderboard.ts","../src/commands/dashboard.ts","../src/commands/flex.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\n\nexport const CONFIG_DIR = path.join(os.homedir(), '.hackersbaby');\nexport const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');\nexport const QUEUE_FILE = path.join(CONFIG_DIR, 'queue.jsonl');\n\nexport type Source = 'claude' | 'cursor';\n\nexport interface PluginConfig {\n token: string;\n refresh_token: string;\n user_id: string;\n server: string;\n targets?: Source[];\n preferences: {\n dashboard_port: number;\n batch_interval_ms: number;\n };\n}\n\nexport function sessionStateFile(source: Source): string {\n return path.join(CONFIG_DIR, `active-session-${source}.json`);\n}\n\nexport function ensureConfigDir(): void {\n if (!fs.existsSync(CONFIG_DIR)) {\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n }\n}\n\nexport function loadConfig(): PluginConfig | null {\n try {\n if (!fs.existsSync(CONFIG_FILE)) return null;\n const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');\n return JSON.parse(raw) as PluginConfig;\n } catch {\n return null;\n }\n}\n\nexport function saveConfig(config: PluginConfig): void {\n ensureConfigDir();\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');\n}\n","import { loadConfig, saveConfig } from './config';\nimport type { EventBatch } from '@hackersbaby/shared';\n\nexport class APIClient {\n private config = loadConfig();\n\n private get headers(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.config?.token || ''}`,\n };\n }\n\n async sendBatch(batch: EventBatch): Promise<boolean> {\n try {\n const server = this.config?.server || 'https://hackers.baby';\n const res = await fetch(`${server}/api/scores/batch`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify(batch),\n });\n return res.ok;\n } catch {\n return false;\n }\n }\n\n async refreshTokenIfNeeded(): Promise<void> {\n if (!this.config) return;\n try {\n const parts = this.config.token.split('.');\n if (parts.length !== 3) return;\n const payload = JSON.parse(Buffer.from(parts[1], 'base64').toString('utf-8'));\n const expMs = payload.exp * 1000;\n const oneDayMs = 24 * 60 * 60 * 1000;\n if (Date.now() + oneDayMs < expMs) return; // more than 1 day remaining, no refresh needed\n\n const res = await fetch(`${this.config.server}/api/auth/cli-token/refresh`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify({ refresh_token: this.config.refresh_token }),\n });\n if (res.ok) {\n const data = (await res.json()) as { token?: string; refresh_token?: string };\n if (data.token) {\n this.config.token = data.token;\n if (data.refresh_token) this.config.refresh_token = data.refresh_token;\n saveConfig(this.config);\n }\n }\n } catch {\n // silently ignore refresh errors\n }\n }\n\n async getStatus(): Promise<Record<string, unknown>> {\n const server = this.config?.server || 'https://hackers.baby';\n const res = await fetch(`${server}/api/users/me`, { headers: this.headers });\n if (!res.ok) throw new Error(`getStatus failed: ${res.status}`);\n return res.json() as Promise<Record<string, unknown>>;\n }\n\n async getRank(): Promise<Record<string, unknown>> {\n const server = this.config?.server || 'https://hackers.baby';\n const res = await fetch(`${server}/api/users/me/rank`, { headers: this.headers });\n if (!res.ok) throw new Error(`getRank failed: ${res.status}`);\n return res.json() as Promise<Record<string, unknown>>;\n }\n\n async getLeaderboard(): Promise<Record<string, unknown>> {\n const server = this.config?.server || 'https://hackers.baby';\n const res = await fetch(`${server}/api/leaderboard/global?limit=10`, { headers: this.headers });\n if (!res.ok) throw new Error(`getLeaderboard failed: ${res.status}`);\n return res.json() as Promise<Record<string, unknown>>;\n }\n\n async getPublicStats(): Promise<Record<string, unknown> | null> {\n try {\n const server = this.config?.server || 'https://hackers.baby';\n const res = await fetch(`${server}/api/stats/public`);\n if (!res.ok) return null;\n return res.json() as Promise<Record<string, unknown>>;\n } catch {\n return null;\n }\n }\n\n async getNotifications(): Promise<{ notifications: Array<{ type: string; message: string }> } | null> {\n try {\n const server = this.config?.server || 'https://hackers.baby';\n const res = await fetch(`${server}/api/users/me/notifications`, { headers: this.headers });\n if (!res.ok) return null;\n return res.json() as Promise<{ notifications: Array<{ type: string; message: string }> }>;\n } catch {\n return null;\n }\n }\n\n async claimReferral(code: string): Promise<Record<string, unknown> | null> {\n try {\n const server = this.config?.server || 'https://hackers.baby';\n const res = await fetch(`${server}/api/referral/claim`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify({ referral_code: code }),\n });\n if (!res.ok) return null;\n return res.json() as Promise<Record<string, unknown>>;\n } catch {\n return null;\n }\n }\n\n async getReferralStats(): Promise<Record<string, unknown> | null> {\n try {\n const server = this.config?.server || 'https://hackers.baby';\n const res = await fetch(`${server}/api/referral/stats`, { headers: this.headers });\n if (!res.ok) return null;\n return res.json() as Promise<Record<string, unknown>>;\n } catch {\n return null;\n }\n }\n}\n","import { loadConfig, saveConfig, ensureConfigDir } from './config';\nimport type { Source } from './config';\nimport { statusCommand } from './commands/status';\nimport { leaderboardCommand } from './commands/leaderboard';\nimport { dashboardCommand } from './commands/dashboard';\nimport { flexCommand } from './commands/flex';\nimport fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { execFile } from 'child_process';\nimport readline from 'readline';\n\nconst args = process.argv.slice(2);\nconst command = args[0];\n\nasync function main() {\n switch (command) {\n case 'init': await init(); break;\n case 'status': console.log(await statusCommand()); break;\n case 'leaderboard': console.log(await leaderboardCommand()); break;\n case 'dashboard': console.log(await dashboardCommand()); break;\n case 'flex': await flexCommand(process.argv.slice(3)); break;\n default: console.log('Usage: hackersbaby <init|status|leaderboard|dashboard|flex>'); break;\n }\n}\n\nasync function init() {\n ensureConfigDir();\n const server = process.env.HACKERSBABY_SERVER || 'https://hackers.baby';\n console.log('Opening browser for GitHub authentication...');\n\n const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'cmd' : 'xdg-open';\n const browserArgs = process.platform === 'win32' ? ['/c', 'start', `${server}/cli-setup`] : [`${server}/cli-setup`];\n execFile(cmd, browserArgs, () => {});\n\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const question = (q: string): Promise<string> => new Promise((resolve) => rl.question(q, resolve));\n\n console.log('After authenticating, paste your CLI token:');\n const token = await question('Token: ');\n const refresh_token = await question('Refresh Token: ');\n\n try {\n const payload = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());\n\n // Ask which tool(s) to integrate with\n console.log('\\nWhich tool do you use?');\n console.log(' 1) Claude Code');\n console.log(' 2) Cursor');\n console.log(' 3) Both');\n const choice = await question('> ');\n\n let targets: Source[];\n switch (choice.trim()) {\n case '2': targets = ['cursor']; break;\n case '3': targets = ['claude', 'cursor']; break;\n default: targets = ['claude']; break;\n }\n\n saveConfig({\n token, refresh_token,\n user_id: payload.userId,\n server,\n targets,\n preferences: { dashboard_port: 3847, batch_interval_ms: 10000 },\n });\n console.log('Configuration saved! hackers.baby is active.');\n\n if (targets.includes('claude')) {\n registerClaudeHooks();\n }\n if (targets.includes('cursor')) {\n registerCursorHooks();\n }\n\n // Auto-claim referral if --ref flag or HACKERSBABY_REF env var is set\n const refFlag = args.find((a) => a.startsWith('--ref='))?.split('=')[1];\n const refCode = refFlag || process.env.HACKERSBABY_REF;\n if (refCode) {\n try {\n const { APIClient } = await import('./api-client');\n const client = new APIClient();\n const result = await client.claimReferral(refCode);\n if (result) {\n console.log(`\\x1b[32m🎁 Referral claimed! 2x multiplier active for 24 hours.\\x1b[0m`);\n }\n } catch {}\n }\n } catch {\n console.error('Invalid token format');\n }\n rl.close();\n}\n\nfunction registerClaudeHooks() {\n const claudeSettingsPath = path.join(os.homedir(), '.claude', 'settings.json');\n let settings: Record<string, any> = {};\n if (fs.existsSync(claudeSettingsPath)) {\n settings = JSON.parse(fs.readFileSync(claudeSettingsPath, 'utf-8'));\n }\n if (!settings.hooks) settings.hooks = {};\n\n const distDir = path.resolve(__dirname);\n const hookEntries: Record<string, { command: string; timeout: number; matcher?: string }> = {\n SessionStart: { command: `node ${path.join(distDir, 'hooks', 'session-start.js')}`, timeout: 10 },\n UserPromptSubmit: { command: `node ${path.join(distDir, 'hooks', 'prompt-submit.js')}`, timeout: 5 },\n PostToolUse: { command: `node ${path.join(distDir, 'hooks', 'tool-call.js')}`, timeout: 5 },\n Stop: { command: `node ${path.join(distDir, 'hooks', 'stop.js')}`, timeout: 5 },\n SubagentStart: { command: `node ${path.join(distDir, 'hooks', 'subagent.js')}`, timeout: 5 },\n PreCompact: { command: `node ${path.join(distDir, 'hooks', 'compact.js')}`, timeout: 5 },\n SessionEnd: { command: `node ${path.join(distDir, 'hooks', 'session-end.js')}`, timeout: 30 },\n };\n\n for (const [event, cfg] of Object.entries(hookEntries)) {\n if (!settings.hooks[event]) settings.hooks[event] = [];\n const hookDef = {\n matcher: cfg.matcher || '',\n hooks: [{ type: 'command', command: cfg.command, timeout: cfg.timeout }],\n };\n const exists = settings.hooks[event].some((entry: any) =>\n entry.hooks?.some((h: any) => h.command === cfg.command)\n );\n if (!exists) settings.hooks[event].push(hookDef);\n }\n\n fs.writeFileSync(claudeSettingsPath, JSON.stringify(settings, null, 2));\n console.log('Claude Code hooks registered.');\n}\n\nfunction registerCursorHooks() {\n const cursorDir = path.join(os.homedir(), '.cursor');\n if (!fs.existsSync(cursorDir)) {\n fs.mkdirSync(cursorDir, { recursive: true });\n }\n\n const cursorHooksPath = path.join(cursorDir, 'hooks.json');\n let hooksConfig: Record<string, any> = {};\n if (fs.existsSync(cursorHooksPath)) {\n hooksConfig = JSON.parse(fs.readFileSync(cursorHooksPath, 'utf-8'));\n }\n if (!hooksConfig.hooks) hooksConfig.hooks = {};\n\n const distDir = path.resolve(__dirname);\n // Cursor uses camelCase hook names and millisecond timeouts\n const hookEntries: Record<string, { command: string; timeout: number }> = {\n sessionStart: { command: `node ${path.join(distDir, 'hooks', 'cursor', 'session-start.js')}`, timeout: 10000 },\n beforeSubmitPrompt: { command: `node ${path.join(distDir, 'hooks', 'cursor', 'prompt-submit.js')}`, timeout: 5000 },\n postToolUse: { command: `node ${path.join(distDir, 'hooks', 'cursor', 'tool-call.js')}`, timeout: 5000 },\n stop: { command: `node ${path.join(distDir, 'hooks', 'cursor', 'stop.js')}`, timeout: 5000 },\n subagentStart: { command: `node ${path.join(distDir, 'hooks', 'cursor', 'subagent.js')}`, timeout: 5000 },\n preCompact: { command: `node ${path.join(distDir, 'hooks', 'cursor', 'compact.js')}`, timeout: 5000 },\n sessionEnd: { command: `node ${path.join(distDir, 'hooks', 'cursor', 'session-end.js')}`, timeout: 30000 },\n };\n\n for (const [event, cfg] of Object.entries(hookEntries)) {\n if (!hooksConfig.hooks[event]) hooksConfig.hooks[event] = [];\n const hookDef = { command: cfg.command, timeout: cfg.timeout };\n // Avoid duplicates\n const exists = hooksConfig.hooks[event].some((entry: any) => entry.command === cfg.command);\n if (!exists) hooksConfig.hooks[event].push(hookDef);\n }\n\n fs.writeFileSync(cursorHooksPath, JSON.stringify(hooksConfig, null, 2));\n console.log('Cursor hooks registered.');\n}\n\nmain().catch(console.error);\n","import { APIClient } from '../api-client';\n\nexport async function statusCommand(): Promise<string> {\n const client = new APIClient();\n try {\n const [me, rank] = await Promise.all([client.getStatus(), client.getRank()]);\n return [\n 'hackers.baby Status',\n ` Score: ${(me as any).total_score?.toLocaleString() || 0}`,\n ` Global Rank: #${(rank as any).global || '-'}`,\n ` Streak: ${(me as any).streak_days || 0} days`,\n ` Languages: ${((me as any).languages || []).join(', ') || 'none set'}`,\n ].join('\\n');\n } catch {\n return 'Error fetching status. Run `hackersbaby init` to set up.';\n }\n}\n","import { APIClient } from '../api-client';\n\nexport async function leaderboardCommand(): Promise<string> {\n const client = new APIClient();\n try {\n const data = await client.getLeaderboard();\n const lines = ['Global Leaderboard', ''];\n for (const entry of (data as any).entries || []) {\n const marker = entry.rank <= 3 ? ['', '#1', '#2', '#3'][entry.rank] : `#${entry.rank}`;\n lines.push(` ${marker.padEnd(4)} ${entry.username.padEnd(20)} ${entry.score.toLocaleString()}`);\n }\n return lines.join('\\n');\n } catch {\n return 'Error fetching leaderboard.';\n }\n}\n","import { loadConfig } from '../config';\nimport { execFile } from 'child_process';\n\nexport async function dashboardCommand(): Promise<string> {\n const config = loadConfig();\n const url = `${config?.server || 'https://hackers.baby'}/dashboard`;\n\n const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'cmd' : 'xdg-open';\n const args = process.platform === 'win32' ? ['/c', 'start', url] : [url];\n execFile(cmd, args, () => {});\n\n return `Opening dashboard at ${url}`;\n}\n","import { loadConfig } from '../config';\nimport { APIClient } from '../api-client';\nimport { execFileSync } from 'child_process';\n\nexport async function flexCommand(args: string[]) {\n const config = loadConfig();\n if (!config?.token) {\n console.log('Not logged in. Run: hackersbaby init');\n return;\n }\n\n const client = new APIClient();\n const [status, rankData, stats] = await Promise.all([\n client.getStatus().catch(() => null),\n client.getRank().catch(() => null),\n client.getPublicStats(),\n ]);\n\n if (!status) {\n console.log('Could not fetch your stats. Are you logged in?');\n return;\n }\n\n const username = String(status.github_username ?? 'unknown');\n const score = Number(status.total_score ?? 0).toLocaleString();\n const rank = rankData?.global_rank ?? '—';\n const streak = Number(status.streak_days ?? 0);\n const totalUsers = stats?.total_users ?? '?';\n const season = stats?.current_season ?? 0;\n\n const refCode = `${username}-${(config.user_id ?? '').slice(0, 3)}`;\n const refUrl = `hackers.baby/ref/${refCode}`;\n\n const c = '\\x1b[36m'; // cyan\n const g = '\\x1b[32m'; // green\n const y = '\\x1b[33m'; // yellow\n const b = '\\x1b[1m'; // bold\n const d = '\\x1b[2m'; // dim\n const r = '\\x1b[0m'; // reset\n\n const pad = (s: string, n: number) => s.length >= n ? s.slice(0, n) : s + ' '.repeat(n - s.length);\n\n const card = [\n '',\n `${c}╔══════════════════════════════════════╗${r}`,\n `${c}║${r} ${b}${g}hackers.baby${r} /// ${y}SEASON ${season}${r} ${c}║${r}`,\n `${c}╠══════════════════════════════════════╣${r}`,\n `${c}║${r} ${b}@${pad(username, 24)}${r}${b}RANK #${pad(String(rank), 4)}${r} ${c}║${r}`,\n `${c}║${r} Score: ${g}${pad(score, 14)}${r} pts ${c}║${r}`,\n `${c}║${r} Streak: ${y}${pad(String(streak), 3)}${r} days ${c}║${r}`,\n `${c}║${r} Players: ${pad(String(totalUsers), 26)}${c}║${r}`,\n `${c}╠══════════════════════════════════════╣${r}`,\n `${c}║${r} ${d}npm i -g @hackersbaby/plugin${r} ${c}║${r}`,\n `${c}║${r} ${d}${pad(refUrl, 34)}${r} ${c}║${r}`,\n `${c}╚══════════════════════════════════════╝${r}`,\n '',\n ].join('\\n');\n\n console.log(card);\n\n if (args.includes('--share')) {\n const shareText = [\n `I'm ranked #${rank} on hackers.baby with ${score} points`,\n '',\n `${streak}-day streak | Season ${season}`,\n '',\n 'Think you can beat me?',\n 'npm i -g @hackersbaby/plugin',\n `https://${refUrl}`,\n ].join('\\n');\n\n let copied = false;\n try {\n const platform = process.platform;\n if (platform === 'darwin') {\n execFileSync('pbcopy', { input: shareText });\n copied = true;\n } else if (platform === 'win32') {\n execFileSync('clip', { input: shareText });\n copied = true;\n } else {\n // Linux: try xclip, fall back to xsel\n try {\n execFileSync('xclip', ['-selection', 'clipboard'], { input: shareText });\n copied = true;\n } catch {\n try {\n execFileSync('xsel', ['--clipboard', '--input'], { input: shareText });\n copied = true;\n } catch {\n // no clipboard tool available\n }\n }\n }\n } catch {\n // clipboard failed\n }\n\n if (copied) {\n console.log(`${g}Copied to clipboard! Paste it on X, Discord, or wherever devs hang out.${r}`);\n } else {\n console.log('\\nShare this:\\n');\n console.log(shareText);\n }\n }\n}\n"],"mappings":"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","names":["fs","path","os","args","import_child_process","args","import_fs","import_path","import_os","import_child_process","readline","APIClient","path","os","fs"]}
1
+ {"version":3,"sources":["../src/config.ts","../../shared/dist/types.js","../../shared/src/scoring.ts","../../shared/src/anticheat.ts","../../shared/src/index.ts","../src/api-client.ts","../src/cli.ts","../src/commands/status.ts","../src/commands/leaderboard.ts","../src/commands/dashboard.ts","../src/commands/flex.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\n\nexport const CONFIG_DIR = path.join(os.homedir(), '.hackersbaby');\nexport const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');\nexport const QUEUE_FILE = path.join(CONFIG_DIR, 'queue.jsonl');\n\nexport type Source = 'claude' | 'cursor';\n\nexport interface PluginConfig {\n token: string;\n refresh_token: string;\n user_id: string;\n server: string;\n targets?: Source[];\n preferences: {\n dashboard_port: number;\n batch_interval_ms: number;\n };\n}\n\nexport function sessionStateFile(source: Source): string {\n return path.join(CONFIG_DIR, `active-session-${source}.json`);\n}\n\nexport function ensureConfigDir(): void {\n if (!fs.existsSync(CONFIG_DIR)) {\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n }\n}\n\nexport function loadConfig(): PluginConfig | null {\n try {\n if (!fs.existsSync(CONFIG_FILE)) return null;\n const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');\n return JSON.parse(raw) as PluginConfig;\n } catch {\n return null;\n }\n}\n\nexport function saveConfig(config: PluginConfig): void {\n ensureConfigDir();\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=types.js.map","import type { ActionType } from './types';\n\nexport const SESSION_BASE_POINT_CAP = 20000;\nexport const TOOL_CALLS_PER_HOUR_CAP = 4000;\nexport const MIN_SESSION_TOKENS = 2000;\n\nexport const BASE_POINTS: Record<ActionType, { perUnit: number; unitSize: number }> = {\n token_input: { perUnit: 1, unitSize: 1000 },\n token_output: { perUnit: 2, unitSize: 1000 },\n tool_call: { perUnit: 5, unitSize: 1 },\n file_created: { perUnit: 15, unitSize: 1 },\n file_edited: { perUnit: 10, unitSize: 1 },\n commit: { perUnit: 50, unitSize: 1 },\n session_completed: { perUnit: 100, unitSize: 1 },\n deployment: { perUnit: 200, unitSize: 1 },\n prompt_submitted: { perUnit: 15, unitSize: 1 },\n subagent_spawned: { perUnit: 40, unitSize: 1 },\n context_compacted: { perUnit: 30, unitSize: 1 },\n stop_response: { perUnit: 10, unitSize: 1 },\n};\n\nexport const DEPLOY_PATTERNS = [\n /^vercel\\s+(--prod|deploy)/, /^netlify\\s+deploy/, /^fly\\s+deploy/, /^railway\\s+up/,\n /^git\\s+push\\s+\\S+\\s+(main|master|production)/,\n /^(npm|yarn|pnpm)\\s+run\\s+deploy/, /^(yarn|pnpm)\\s+deploy/,\n];\n\nexport function getBasePoints(actionType: ActionType, value: number): number {\n const config = BASE_POINTS[actionType];\n return Math.floor(value / config.unitSize) * config.perUnit;\n}\n\ninterface MultiplierInput { streak_days: number; commit_quality: boolean; language_count: number; }\n\nexport function calculateMultiplier(input: MultiplierInput): number {\n let streak = 1.0;\n if (input.streak_days >= 30) streak = 3.0;\n else if (input.streak_days >= 7) streak = 2.0;\n else if (input.streak_days >= 3) streak = 1.5;\n const quality = input.commit_quality ? 1.5 : 1.0;\n const diversity = input.language_count >= 3 ? 1.2 : 1.0;\n return streak * quality * diversity;\n}\n\nexport function calculateSessionScore(events: Array<{ action_type: ActionType; value: number }>, multiplier: number): number {\n let totalBase = 0;\n for (const e of events) totalBase += getBasePoints(e.action_type, e.value);\n return Math.floor(Math.min(totalBase, SESSION_BASE_POINT_CAP) * multiplier);\n}\n\nexport function isDeployCommand(command: string): boolean {\n return DEPLOY_PATTERNS.some((p) => p.test(command.trim()));\n}\n","/**\n * Anti-cheat cryptographic primitives.\n * Shared between plugin (client) and server.\n *\n * - Event chain: each event hash includes the previous, creating a tamper-evident chain\n * - Batch HMAC: the entire batch is signed with a server-issued session secret\n */\n\nimport { createHmac, createHash } from 'crypto';\n\n/** Hash a single event, chaining it to the previous hash */\nexport function hashEvent(\n event: { action_type: string; value: number; timestamp: string },\n prevHash: string,\n): string {\n const payload = `${prevHash}|${event.action_type}|${event.value}|${event.timestamp}`;\n return createHash('sha256').update(payload).digest('hex').slice(0, 16);\n}\n\n/** Compute the chain hash for an array of events */\nexport function computeChainHash(\n events: Array<{ action_type: string; value: number; timestamp: string }>,\n initialHash: string = '0000000000000000',\n): string {\n let hash = initialHash;\n for (const event of events) {\n hash = hashEvent(event, hash);\n }\n return hash;\n}\n\n/** Sign a batch with HMAC-SHA256 using the session secret */\nexport function signBatch(\n sessionId: string,\n events: Array<{ action_type: string; value: number; timestamp: string }>,\n chainHash: string,\n secret: string,\n): string {\n // Canonical form: sessionId + chainHash + event count + sum of values\n const valueSum = events.reduce((s, e) => s + e.value, 0);\n const message = `${sessionId}|${chainHash}|${events.length}|${valueSum}`;\n return createHmac('sha256', secret).update(message).digest('hex');\n}\n\n/** Verify a batch HMAC signature */\nexport function verifyBatchSignature(\n sessionId: string,\n events: Array<{ action_type: string; value: number; timestamp: string }>,\n chainHash: string,\n signature: string,\n secret: string,\n): boolean {\n const expected = signBatch(sessionId, events, chainHash, secret);\n // Constant-time comparison\n if (expected.length !== signature.length) return false;\n let mismatch = 0;\n for (let i = 0; i < expected.length; i++) {\n mismatch |= expected.charCodeAt(i) ^ signature.charCodeAt(i);\n }\n return mismatch === 0;\n}\n","export * from './types';\nexport * from './scoring';\nexport * from './anticheat';\n","import { loadConfig, saveConfig } from './config';\nimport { computeChainHash, signBatch } from '@hackersbaby/shared';\nimport type { EventBatch } from '@hackersbaby/shared';\n\nexport class APIClient {\n private config = loadConfig();\n private sessionSecret: string | null = null;\n private chainHash: string = '0000000000000000';\n\n private get headers(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.config?.token || ''}`,\n };\n }\n\n /** Register session with server and get cryptographic secret */\n async startSession(sessionId: string): Promise<boolean> {\n try {\n const server = this.config?.server || 'https://hackers.baby';\n const res = await fetch(`${server}/api/sessions/start`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify({ session_id: sessionId }),\n });\n if (res.ok) {\n const data = await res.json() as { session_secret: string; initial_chain_hash: string };\n this.sessionSecret = data.session_secret;\n this.chainHash = data.initial_chain_hash;\n return true;\n }\n return false;\n } catch {\n return false;\n }\n }\n\n async sendBatch(batch: EventBatch): Promise<boolean> {\n try {\n const server = this.config?.server || 'https://hackers.baby';\n\n // Sign the batch if we have a session secret\n if (this.sessionSecret) {\n const prevChainHash = this.chainHash;\n const newChainHash = computeChainHash(batch.events, prevChainHash);\n const signature = signBatch(batch.session_id, batch.events, newChainHash, this.sessionSecret);\n\n batch.signature = signature;\n batch.chain_hash = newChainHash;\n batch.prev_chain_hash = prevChainHash;\n\n // Update local chain hash for next batch\n this.chainHash = newChainHash;\n }\n\n const res = await fetch(`${server}/api/scores/batch`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify(batch),\n });\n return res.ok;\n } catch {\n return false;\n }\n }\n\n async refreshTokenIfNeeded(): Promise<void> {\n if (!this.config) return;\n try {\n const parts = this.config.token.split('.');\n if (parts.length !== 3) return;\n const payload = JSON.parse(Buffer.from(parts[1], 'base64').toString('utf-8'));\n const expMs = payload.exp * 1000;\n const oneDayMs = 24 * 60 * 60 * 1000;\n if (Date.now() + oneDayMs < expMs) return; // more than 1 day remaining, no refresh needed\n\n const res = await fetch(`${this.config.server}/api/auth/cli-token/refresh`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify({ refresh_token: this.config.refresh_token }),\n });\n if (res.ok) {\n const data = (await res.json()) as { token?: string; refresh_token?: string };\n if (data.token) {\n this.config.token = data.token;\n if (data.refresh_token) this.config.refresh_token = data.refresh_token;\n saveConfig(this.config);\n }\n }\n } catch {\n // silently ignore refresh errors\n }\n }\n\n async getStatus(): Promise<Record<string, unknown>> {\n const server = this.config?.server || 'https://hackers.baby';\n const res = await fetch(`${server}/api/users/me`, { headers: this.headers });\n if (!res.ok) throw new Error(`getStatus failed: ${res.status}`);\n return res.json() as Promise<Record<string, unknown>>;\n }\n\n async getRank(): Promise<Record<string, unknown>> {\n const server = this.config?.server || 'https://hackers.baby';\n const res = await fetch(`${server}/api/users/me/rank`, { headers: this.headers });\n if (!res.ok) throw new Error(`getRank failed: ${res.status}`);\n return res.json() as Promise<Record<string, unknown>>;\n }\n\n async getLeaderboard(): Promise<Record<string, unknown>> {\n const server = this.config?.server || 'https://hackers.baby';\n const res = await fetch(`${server}/api/leaderboard/global?limit=10`, { headers: this.headers });\n if (!res.ok) throw new Error(`getLeaderboard failed: ${res.status}`);\n return res.json() as Promise<Record<string, unknown>>;\n }\n\n async getPublicStats(): Promise<Record<string, unknown> | null> {\n try {\n const server = this.config?.server || 'https://hackers.baby';\n const res = await fetch(`${server}/api/stats/public`);\n if (!res.ok) return null;\n return res.json() as Promise<Record<string, unknown>>;\n } catch {\n return null;\n }\n }\n\n async getNotifications(): Promise<{ notifications: Array<{ type: string; message: string }> } | null> {\n try {\n const server = this.config?.server || 'https://hackers.baby';\n const res = await fetch(`${server}/api/users/me/notifications`, { headers: this.headers });\n if (!res.ok) return null;\n return res.json() as Promise<{ notifications: Array<{ type: string; message: string }> }>;\n } catch {\n return null;\n }\n }\n\n async claimReferral(code: string): Promise<Record<string, unknown> | null> {\n try {\n const server = this.config?.server || 'https://hackers.baby';\n const res = await fetch(`${server}/api/referral/claim`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify({ referral_code: code }),\n });\n if (!res.ok) return null;\n return res.json() as Promise<Record<string, unknown>>;\n } catch {\n return null;\n }\n }\n\n async getReferralStats(): Promise<Record<string, unknown> | null> {\n try {\n const server = this.config?.server || 'https://hackers.baby';\n const res = await fetch(`${server}/api/referral/stats`, { headers: this.headers });\n if (!res.ok) return null;\n return res.json() as Promise<Record<string, unknown>>;\n } catch {\n return null;\n }\n }\n}\n","import { loadConfig, saveConfig, ensureConfigDir } from './config';\nimport type { Source } from './config';\nimport { statusCommand } from './commands/status';\nimport { leaderboardCommand } from './commands/leaderboard';\nimport { dashboardCommand } from './commands/dashboard';\nimport { flexCommand } from './commands/flex';\nimport fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { execFile } from 'child_process';\nimport readline from 'readline';\n\nconst args = process.argv.slice(2);\nconst command = args[0];\n\nasync function main() {\n switch (command) {\n case 'init': await init(); break;\n case 'status': console.log(await statusCommand()); break;\n case 'leaderboard': console.log(await leaderboardCommand()); break;\n case 'dashboard': console.log(await dashboardCommand()); break;\n case 'flex': await flexCommand(process.argv.slice(3)); break;\n default: console.log('Usage: hackersbaby <init|status|leaderboard|dashboard|flex>'); break;\n }\n}\n\nasync function init() {\n ensureConfigDir();\n const server = process.env.HACKERSBABY_SERVER || 'https://hackers.baby';\n console.log('Opening browser for GitHub authentication...');\n\n const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'cmd' : 'xdg-open';\n const browserArgs = process.platform === 'win32' ? ['/c', 'start', `${server}/cli-setup`] : [`${server}/cli-setup`];\n execFile(cmd, browserArgs, () => {});\n\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const question = (q: string): Promise<string> => new Promise((resolve) => rl.question(q, resolve));\n\n console.log('After authenticating, paste your CLI token:');\n const token = await question('Token: ');\n const refresh_token = await question('Refresh Token: ');\n\n try {\n const payload = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());\n\n // Ask which tool(s) to integrate with\n console.log('\\nWhich tool do you use?');\n console.log(' 1) Claude Code');\n console.log(' 2) Cursor');\n console.log(' 3) Both');\n const choice = await question('> ');\n\n let targets: Source[];\n switch (choice.trim()) {\n case '2': targets = ['cursor']; break;\n case '3': targets = ['claude', 'cursor']; break;\n default: targets = ['claude']; break;\n }\n\n saveConfig({\n token, refresh_token,\n user_id: payload.userId,\n server,\n targets,\n preferences: { dashboard_port: 3847, batch_interval_ms: 10000 },\n });\n console.log('Configuration saved! hackers.baby is active.');\n\n if (targets.includes('claude')) {\n registerClaudeHooks();\n }\n if (targets.includes('cursor')) {\n registerCursorHooks();\n }\n\n // Auto-claim referral if --ref flag or HACKERSBABY_REF env var is set\n const refFlag = args.find((a) => a.startsWith('--ref='))?.split('=')[1];\n const refCode = refFlag || process.env.HACKERSBABY_REF;\n if (refCode) {\n try {\n const { APIClient } = await import('./api-client');\n const client = new APIClient();\n const result = await client.claimReferral(refCode);\n if (result) {\n console.log(`\\x1b[32m🎁 Referral claimed! 2x multiplier active for 24 hours.\\x1b[0m`);\n }\n } catch {}\n }\n } catch {\n console.error('Invalid token format');\n }\n rl.close();\n}\n\nfunction registerClaudeHooks() {\n const claudeSettingsPath = path.join(os.homedir(), '.claude', 'settings.json');\n let settings: Record<string, any> = {};\n if (fs.existsSync(claudeSettingsPath)) {\n settings = JSON.parse(fs.readFileSync(claudeSettingsPath, 'utf-8'));\n }\n if (!settings.hooks) settings.hooks = {};\n\n const distDir = path.resolve(__dirname);\n const hookEntries: Record<string, { command: string; timeout: number; matcher?: string }> = {\n SessionStart: { command: `node ${path.join(distDir, 'hooks', 'session-start.js')}`, timeout: 10 },\n UserPromptSubmit: { command: `node ${path.join(distDir, 'hooks', 'prompt-submit.js')}`, timeout: 5 },\n PostToolUse: { command: `node ${path.join(distDir, 'hooks', 'tool-call.js')}`, timeout: 5 },\n Stop: { command: `node ${path.join(distDir, 'hooks', 'stop.js')}`, timeout: 5 },\n SubagentStart: { command: `node ${path.join(distDir, 'hooks', 'subagent.js')}`, timeout: 5 },\n PreCompact: { command: `node ${path.join(distDir, 'hooks', 'compact.js')}`, timeout: 5 },\n SessionEnd: { command: `node ${path.join(distDir, 'hooks', 'session-end.js')}`, timeout: 30 },\n };\n\n for (const [event, cfg] of Object.entries(hookEntries)) {\n if (!settings.hooks[event]) settings.hooks[event] = [];\n const hookDef = {\n matcher: cfg.matcher || '',\n hooks: [{ type: 'command', command: cfg.command, timeout: cfg.timeout }],\n };\n const exists = settings.hooks[event].some((entry: any) =>\n entry.hooks?.some((h: any) => h.command === cfg.command)\n );\n if (!exists) settings.hooks[event].push(hookDef);\n }\n\n fs.writeFileSync(claudeSettingsPath, JSON.stringify(settings, null, 2));\n console.log('Claude Code hooks registered.');\n}\n\nfunction registerCursorHooks() {\n const cursorDir = path.join(os.homedir(), '.cursor');\n if (!fs.existsSync(cursorDir)) {\n fs.mkdirSync(cursorDir, { recursive: true });\n }\n\n const cursorHooksPath = path.join(cursorDir, 'hooks.json');\n let hooksConfig: Record<string, any> = {};\n if (fs.existsSync(cursorHooksPath)) {\n hooksConfig = JSON.parse(fs.readFileSync(cursorHooksPath, 'utf-8'));\n }\n if (!hooksConfig.version) hooksConfig.version = 1;\n if (!hooksConfig.hooks) hooksConfig.hooks = {};\n\n const distDir = path.resolve(__dirname);\n // Cursor uses camelCase hook names and millisecond timeouts\n const hookEntries: Record<string, { command: string; timeout: number }> = {\n sessionStart: { command: `node ${path.join(distDir, 'hooks', 'cursor', 'session-start.js')}`, timeout: 10000 },\n beforeSubmitPrompt: { command: `node ${path.join(distDir, 'hooks', 'cursor', 'prompt-submit.js')}`, timeout: 5000 },\n postToolUse: { command: `node ${path.join(distDir, 'hooks', 'cursor', 'tool-call.js')}`, timeout: 5000 },\n stop: { command: `node ${path.join(distDir, 'hooks', 'cursor', 'stop.js')}`, timeout: 5000 },\n subagentStart: { command: `node ${path.join(distDir, 'hooks', 'cursor', 'subagent.js')}`, timeout: 5000 },\n preCompact: { command: `node ${path.join(distDir, 'hooks', 'cursor', 'compact.js')}`, timeout: 5000 },\n sessionEnd: { command: `node ${path.join(distDir, 'hooks', 'cursor', 'session-end.js')}`, timeout: 30000 },\n };\n\n for (const [event, cfg] of Object.entries(hookEntries)) {\n if (!hooksConfig.hooks[event]) hooksConfig.hooks[event] = [];\n const hookDef = { command: cfg.command, timeout: cfg.timeout };\n // Avoid duplicates\n const exists = hooksConfig.hooks[event].some((entry: any) => entry.command === cfg.command);\n if (!exists) hooksConfig.hooks[event].push(hookDef);\n }\n\n fs.writeFileSync(cursorHooksPath, JSON.stringify(hooksConfig, null, 2));\n console.log('Cursor hooks registered.');\n}\n\nmain().catch(console.error);\n","import { APIClient } from '../api-client';\n\nexport async function statusCommand(): Promise<string> {\n const client = new APIClient();\n try {\n const [me, rank] = await Promise.all([client.getStatus(), client.getRank()]);\n return [\n 'hackers.baby Status',\n ` Score: ${(me as any).total_score?.toLocaleString() || 0}`,\n ` Global Rank: #${(rank as any).global || '-'}`,\n ` Streak: ${(me as any).streak_days || 0} days`,\n ` Languages: ${((me as any).languages || []).join(', ') || 'none set'}`,\n ].join('\\n');\n } catch {\n return 'Error fetching status. Run `hackersbaby init` to set up.';\n }\n}\n","import { APIClient } from '../api-client';\n\nexport async function leaderboardCommand(): Promise<string> {\n const client = new APIClient();\n try {\n const data = await client.getLeaderboard();\n const lines = ['Global Leaderboard', ''];\n for (const entry of (data as any).entries || []) {\n const marker = entry.rank <= 3 ? ['', '#1', '#2', '#3'][entry.rank] : `#${entry.rank}`;\n lines.push(` ${marker.padEnd(4)} ${entry.username.padEnd(20)} ${entry.score.toLocaleString()}`);\n }\n return lines.join('\\n');\n } catch {\n return 'Error fetching leaderboard.';\n }\n}\n","import { loadConfig } from '../config';\nimport { execFile } from 'child_process';\n\nexport async function dashboardCommand(): Promise<string> {\n const config = loadConfig();\n const url = `${config?.server || 'https://hackers.baby'}/dashboard`;\n\n const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'cmd' : 'xdg-open';\n const args = process.platform === 'win32' ? ['/c', 'start', url] : [url];\n execFile(cmd, args, () => {});\n\n return `Opening dashboard at ${url}`;\n}\n","import { loadConfig } from '../config';\nimport { APIClient } from '../api-client';\nimport { execFileSync } from 'child_process';\n\nexport async function flexCommand(args: string[]) {\n const config = loadConfig();\n if (!config?.token) {\n console.log('Not logged in. Run: hackersbaby init');\n return;\n }\n\n const client = new APIClient();\n const [status, rankData, stats] = await Promise.all([\n client.getStatus().catch(() => null),\n client.getRank().catch(() => null),\n client.getPublicStats(),\n ]);\n\n if (!status) {\n console.log('Could not fetch your stats. Are you logged in?');\n return;\n }\n\n const username = String(status.github_username ?? 'unknown');\n const score = Number(status.total_score ?? 0).toLocaleString();\n const rank = rankData?.global_rank ?? '—';\n const streak = Number(status.streak_days ?? 0);\n const totalUsers = stats?.total_users ?? '?';\n const season = stats?.current_season ?? 0;\n\n const refCode = `${username}-${(config.user_id ?? '').slice(0, 3)}`;\n const refUrl = `hackers.baby/ref/${refCode}`;\n\n const c = '\\x1b[36m'; // cyan\n const g = '\\x1b[32m'; // green\n const y = '\\x1b[33m'; // yellow\n const b = '\\x1b[1m'; // bold\n const d = '\\x1b[2m'; // dim\n const r = '\\x1b[0m'; // reset\n\n const pad = (s: string, n: number) => s.length >= n ? s.slice(0, n) : s + ' '.repeat(n - s.length);\n\n const card = [\n '',\n `${c}╔══════════════════════════════════════╗${r}`,\n `${c}║${r} ${b}${g}hackers.baby${r} /// ${y}SEASON ${season}${r} ${c}║${r}`,\n `${c}╠══════════════════════════════════════╣${r}`,\n `${c}║${r} ${b}@${pad(username, 24)}${r}${b}RANK #${pad(String(rank), 4)}${r} ${c}║${r}`,\n `${c}║${r} Score: ${g}${pad(score, 14)}${r} pts ${c}║${r}`,\n `${c}║${r} Streak: ${y}${pad(String(streak), 3)}${r} days ${c}║${r}`,\n `${c}║${r} Players: ${pad(String(totalUsers), 26)}${c}║${r}`,\n `${c}╠══════════════════════════════════════╣${r}`,\n `${c}║${r} ${d}npm i -g @hackersbaby/plugin${r} ${c}║${r}`,\n `${c}║${r} ${d}${pad(refUrl, 34)}${r} ${c}║${r}`,\n `${c}╚══════════════════════════════════════╝${r}`,\n '',\n ].join('\\n');\n\n console.log(card);\n\n if (args.includes('--share')) {\n const shareText = [\n `I'm ranked #${rank} on hackers.baby with ${score} points`,\n '',\n `${streak}-day streak | Season ${season}`,\n '',\n 'Think you can beat me?',\n 'npm i -g @hackersbaby/plugin',\n `https://${refUrl}`,\n ].join('\\n');\n\n let copied = false;\n try {\n const platform = process.platform;\n if (platform === 'darwin') {\n execFileSync('pbcopy', { input: shareText });\n copied = true;\n } else if (platform === 'win32') {\n execFileSync('clip', { input: shareText });\n copied = true;\n } else {\n // Linux: try xclip, fall back to xsel\n try {\n execFileSync('xclip', ['-selection', 'clipboard'], { input: shareText });\n copied = true;\n } catch {\n try {\n execFileSync('xsel', ['--clipboard', '--input'], { input: shareText });\n copied = true;\n } catch {\n // no clipboard tool available\n }\n }\n }\n } catch {\n // clipboard failed\n }\n\n if (copied) {\n console.log(`${g}Copied to clipboard! Paste it on X, Discord, or wherever devs hang out.${r}`);\n } else {\n console.log('\\nShare this:\\n');\n console.log(shareText);\n }\n }\n}\n"],"mappings":"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","names":["fs","path","os","exports","exports","command","exports","computeChainHash","signBatch","exports","args","import_child_process","args","import_fs","import_path","import_os","import_child_process","readline","APIClient","path","os","fs"]}
@@ -6,6 +6,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __commonJS = (cb, mod) => function __require() {
10
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
+ };
9
12
  var __copyProps = (to, from, except, desc) => {
10
13
  if (from && typeof from === "object" || typeof from === "function") {
11
14
  for (let key of __getOwnPropNames(from))
@@ -23,6 +26,144 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
26
  mod
24
27
  ));
25
28
 
29
+ // ../shared/dist/types.js
30
+ var require_types = __commonJS({
31
+ "../shared/dist/types.js"(exports2) {
32
+ "use strict";
33
+ Object.defineProperty(exports2, "__esModule", { value: true });
34
+ }
35
+ });
36
+
37
+ // ../shared/dist/scoring.js
38
+ var require_scoring = __commonJS({
39
+ "../shared/dist/scoring.js"(exports2) {
40
+ "use strict";
41
+ Object.defineProperty(exports2, "__esModule", { value: true });
42
+ exports2.DEPLOY_PATTERNS = exports2.BASE_POINTS = exports2.MIN_SESSION_TOKENS = exports2.TOOL_CALLS_PER_HOUR_CAP = exports2.SESSION_BASE_POINT_CAP = void 0;
43
+ exports2.getBasePoints = getBasePoints;
44
+ exports2.calculateMultiplier = calculateMultiplier;
45
+ exports2.calculateSessionScore = calculateSessionScore;
46
+ exports2.isDeployCommand = isDeployCommand;
47
+ exports2.SESSION_BASE_POINT_CAP = 2e4;
48
+ exports2.TOOL_CALLS_PER_HOUR_CAP = 4e3;
49
+ exports2.MIN_SESSION_TOKENS = 2e3;
50
+ exports2.BASE_POINTS = {
51
+ token_input: { perUnit: 1, unitSize: 1e3 },
52
+ token_output: { perUnit: 2, unitSize: 1e3 },
53
+ tool_call: { perUnit: 5, unitSize: 1 },
54
+ file_created: { perUnit: 15, unitSize: 1 },
55
+ file_edited: { perUnit: 10, unitSize: 1 },
56
+ commit: { perUnit: 50, unitSize: 1 },
57
+ session_completed: { perUnit: 100, unitSize: 1 },
58
+ deployment: { perUnit: 200, unitSize: 1 },
59
+ prompt_submitted: { perUnit: 15, unitSize: 1 },
60
+ subagent_spawned: { perUnit: 40, unitSize: 1 },
61
+ context_compacted: { perUnit: 30, unitSize: 1 },
62
+ stop_response: { perUnit: 10, unitSize: 1 }
63
+ };
64
+ exports2.DEPLOY_PATTERNS = [
65
+ /^vercel\s+(--prod|deploy)/,
66
+ /^netlify\s+deploy/,
67
+ /^fly\s+deploy/,
68
+ /^railway\s+up/,
69
+ /^git\s+push\s+\S+\s+(main|master|production)/,
70
+ /^(npm|yarn|pnpm)\s+run\s+deploy/,
71
+ /^(yarn|pnpm)\s+deploy/
72
+ ];
73
+ function getBasePoints(actionType, value) {
74
+ const config = exports2.BASE_POINTS[actionType];
75
+ return Math.floor(value / config.unitSize) * config.perUnit;
76
+ }
77
+ function calculateMultiplier(input) {
78
+ let streak = 1;
79
+ if (input.streak_days >= 30)
80
+ streak = 3;
81
+ else if (input.streak_days >= 7)
82
+ streak = 2;
83
+ else if (input.streak_days >= 3)
84
+ streak = 1.5;
85
+ const quality = input.commit_quality ? 1.5 : 1;
86
+ const diversity = input.language_count >= 3 ? 1.2 : 1;
87
+ return streak * quality * diversity;
88
+ }
89
+ function calculateSessionScore(events, multiplier) {
90
+ let totalBase = 0;
91
+ for (const e of events)
92
+ totalBase += getBasePoints(e.action_type, e.value);
93
+ return Math.floor(Math.min(totalBase, exports2.SESSION_BASE_POINT_CAP) * multiplier);
94
+ }
95
+ function isDeployCommand(command) {
96
+ return exports2.DEPLOY_PATTERNS.some((p) => p.test(command.trim()));
97
+ }
98
+ }
99
+ });
100
+
101
+ // ../shared/dist/anticheat.js
102
+ var require_anticheat = __commonJS({
103
+ "../shared/dist/anticheat.js"(exports2) {
104
+ "use strict";
105
+ Object.defineProperty(exports2, "__esModule", { value: true });
106
+ exports2.hashEvent = hashEvent;
107
+ exports2.computeChainHash = computeChainHash2;
108
+ exports2.signBatch = signBatch2;
109
+ exports2.verifyBatchSignature = verifyBatchSignature;
110
+ var crypto_1 = require("crypto");
111
+ function hashEvent(event, prevHash) {
112
+ const payload = `${prevHash}|${event.action_type}|${event.value}|${event.timestamp}`;
113
+ return (0, crypto_1.createHash)("sha256").update(payload).digest("hex").slice(0, 16);
114
+ }
115
+ function computeChainHash2(events, initialHash = "0000000000000000") {
116
+ let hash = initialHash;
117
+ for (const event of events) {
118
+ hash = hashEvent(event, hash);
119
+ }
120
+ return hash;
121
+ }
122
+ function signBatch2(sessionId, events, chainHash, secret) {
123
+ const valueSum = events.reduce((s, e) => s + e.value, 0);
124
+ const message = `${sessionId}|${chainHash}|${events.length}|${valueSum}`;
125
+ return (0, crypto_1.createHmac)("sha256", secret).update(message).digest("hex");
126
+ }
127
+ function verifyBatchSignature(sessionId, events, chainHash, signature, secret) {
128
+ const expected = signBatch2(sessionId, events, chainHash, secret);
129
+ if (expected.length !== signature.length)
130
+ return false;
131
+ let mismatch = 0;
132
+ for (let i = 0; i < expected.length; i++) {
133
+ mismatch |= expected.charCodeAt(i) ^ signature.charCodeAt(i);
134
+ }
135
+ return mismatch === 0;
136
+ }
137
+ }
138
+ });
139
+
140
+ // ../shared/dist/index.js
141
+ var require_dist = __commonJS({
142
+ "../shared/dist/index.js"(exports2) {
143
+ "use strict";
144
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
145
+ if (k2 === void 0) k2 = k;
146
+ var desc = Object.getOwnPropertyDescriptor(m, k);
147
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
148
+ desc = { enumerable: true, get: function() {
149
+ return m[k];
150
+ } };
151
+ }
152
+ Object.defineProperty(o, k2, desc);
153
+ }) : (function(o, m, k, k2) {
154
+ if (k2 === void 0) k2 = k;
155
+ o[k2] = m[k];
156
+ }));
157
+ var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
158
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
159
+ };
160
+ Object.defineProperty(exports2, "__esModule", { value: true });
161
+ __exportStar(require_types(), exports2);
162
+ __exportStar(require_scoring(), exports2);
163
+ __exportStar(require_anticheat(), exports2);
164
+ }
165
+ });
166
+
26
167
  // src/collector.ts
27
168
  var import_uuid = require("uuid");
28
169
 
@@ -56,17 +197,49 @@ function saveConfig(config) {
56
197
  }
57
198
 
58
199
  // src/api-client.ts
200
+ var import_shared = __toESM(require_dist());
59
201
  var APIClient = class {
60
202
  config = loadConfig();
203
+ sessionSecret = null;
204
+ chainHash = "0000000000000000";
61
205
  get headers() {
62
206
  return {
63
207
  "Content-Type": "application/json",
64
208
  Authorization: `Bearer ${this.config?.token || ""}`
65
209
  };
66
210
  }
211
+ /** Register session with server and get cryptographic secret */
212
+ async startSession(sessionId) {
213
+ try {
214
+ const server = this.config?.server || "https://hackers.baby";
215
+ const res = await fetch(`${server}/api/sessions/start`, {
216
+ method: "POST",
217
+ headers: this.headers,
218
+ body: JSON.stringify({ session_id: sessionId })
219
+ });
220
+ if (res.ok) {
221
+ const data = await res.json();
222
+ this.sessionSecret = data.session_secret;
223
+ this.chainHash = data.initial_chain_hash;
224
+ return true;
225
+ }
226
+ return false;
227
+ } catch {
228
+ return false;
229
+ }
230
+ }
67
231
  async sendBatch(batch) {
68
232
  try {
69
233
  const server = this.config?.server || "https://hackers.baby";
234
+ if (this.sessionSecret) {
235
+ const prevChainHash = this.chainHash;
236
+ const newChainHash = (0, import_shared.computeChainHash)(batch.events, prevChainHash);
237
+ const signature = (0, import_shared.signBatch)(batch.session_id, batch.events, newChainHash, this.sessionSecret);
238
+ batch.signature = signature;
239
+ batch.chain_hash = newChainHash;
240
+ batch.prev_chain_hash = prevChainHash;
241
+ this.chainHash = newChainHash;
242
+ }
70
243
  const res = await fetch(`${server}/api/scores/batch`, {
71
244
  method: "POST",
72
245
  headers: this.headers,
@@ -230,6 +403,7 @@ var EventCollector = class {
230
403
  }
231
404
  async start() {
232
405
  await this.client.refreshTokenIfNeeded();
406
+ await this.client.startSession(this.sessionId);
233
407
  const queued = drainQueue();
234
408
  if (queued.length > 0) {
235
409
  const batch = { session_id: this.sessionId, events: queued };
@@ -285,6 +459,11 @@ function readStdin() {
285
459
  process.stdin.on("end", () => resolve(input));
286
460
  });
287
461
  }
462
+ function detectSource(payload) {
463
+ if (process.env.CURSOR_VERSION) return "cursor";
464
+ if (payload?.cursor_version) return "cursor";
465
+ return "claude";
466
+ }
288
467
  function normalizePayload(source, raw) {
289
468
  if (source === "cursor") {
290
469
  return { ...raw };
@@ -296,9 +475,11 @@ function normalizePayload(source, raw) {
296
475
  async function handleCompact(source) {
297
476
  const input = await readStdin();
298
477
  try {
299
- const hookData = normalizePayload(source, JSON.parse(input));
300
- const sessionId = hookData.session_id || loadSessionId(source);
301
- const collector = new EventCollector(sessionId, source);
478
+ const raw = JSON.parse(input);
479
+ const detected = detectSource(raw);
480
+ const hookData = normalizePayload(detected, raw);
481
+ const sessionId = hookData.session_id || loadSessionId(detected);
482
+ const collector = new EventCollector(sessionId, detected);
302
483
  collector.addEvent({
303
484
  action_type: "context_compacted",
304
485
  value: 1,