hacklab 0.10.4 → 0.10.5

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/README.md CHANGED
@@ -109,7 +109,8 @@ scan local AI usage → see your rank → sign in with GitHub → claim a userna
109
109
  machine-readable output an agent can drive.
110
110
  - `hacklab login` — re-authenticate with GitHub.
111
111
  - `hacklab logout` — clear your saved session on this machine.
112
- - `hacklab config <key> <value>` — set config (`cursor-api-key`, `cursor-email`).
112
+ - `hacklab config <key> <value>` — set config (`cursor-api-key`, `cursor-email`,
113
+ `prompt-stats`).
113
114
  Bare `hacklab config` prints the effective values and where each came from.
114
115
  - `hacklab project` — publish the repo you're standing in as a project. It reads
115
116
  the git remote, README, and package.json, shows a preview, and publishes on
@@ -209,6 +210,45 @@ otherwise, and all of it would land on your profile as your own.
209
210
  If a key is set but Cursor rejects it, the scan says so and falls back to the
210
211
  local estimate — it won't quietly hand you an estimate you think is exact.
211
212
 
213
+ ## Prompt stats
214
+
215
+ `sync` can also chart *how* you prompt, not just how many tokens you burned:
216
+ a histogram of your prompt lengths and a prompt count per project, shown on the
217
+ AI Usage tab of your profile. It reads your local Claude Code transcripts
218
+ (`~/.claude/projects`) on this machine.
219
+
220
+ Nothing conversation-derived is uploaded until you say so. The first
221
+ interactive `sync` asks, remembers the answer, and never asks again. There are
222
+ three tiers:
223
+
224
+ | Tier | What leaves your machine |
225
+ | ------- | ------------------------ |
226
+ | `none` | token counts only — exactly what the CLI did before this existed |
227
+ | `stats` | + prompt-length histogram and per-project counts. Numbers only; no prompt text |
228
+ | `full` | + a sample of your prompt text (≤20k chars), scored for how technical it is and then discarded server-side |
229
+
230
+ Projects are matched by their git `origin` remote, so a prompt count only lands
231
+ on a project you've already added to hacklab (`hacklab brag`). Directories
232
+ without a git remote are skipped entirely.
233
+
234
+ Answer up front, without the prompt — the agent-friendly path:
235
+
236
+ ```sh
237
+ hacklab sync --share-prompt-stats # numbers only
238
+ hacklab sync --share-prompt-stats=full # numbers + text sample
239
+ hacklab sync --no-share-prompt-stats # refuse
240
+ ```
241
+
242
+ Change or revoke it any time:
243
+
244
+ ```sh
245
+ hacklab config prompt-stats none # stop sharing; nothing further is uploaded
246
+ hacklab config # show the current tier
247
+ ```
248
+
249
+ The unattended daily sync never asks. A machine that has never answered
250
+ uploads token counts only.
251
+
212
252
  ## Choosing a backend
213
253
 
214
254
  Every command resolves which backend to talk to by the same precedence:
package/dist/cli.js CHANGED
@@ -82,6 +82,7 @@ function printHelp() {
82
82
  console.log(` ${dim('--env')} ${dim('<production|development>')} pick the backend (default: production)`);
83
83
  console.log(` ${dim('--cursor-api-key')} ${dim('<key>')} exact Cursor usage (or ${dim('CURSOR_API_KEY')})`);
84
84
  console.log(` ${dim('--cursor-email')} ${dim('<email>')} scope a Cursor team key to you (or ${dim('CURSOR_EMAIL')})`);
85
+ console.log(` ${dim('--share-prompt-stats')}${dim('[=stats|full]')} answer the prompt-stats consent up front`);
85
86
  console.log('');
86
87
  }
87
88
  // Node-version guard (T9). The CLI uses modern Node APIs (global fetch,
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAiBA,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,iBA0DjD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AA4BA,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,iBA8EjD"}
@@ -1,5 +1,11 @@
1
1
  import { loadConfig, resolveCursorAuth, saveConfig, } from '../config.js';
2
+ import { isPromptConsentTier, PROMPT_CONSENT_TIERS, } from '../prompt-consent.js';
2
3
  import { dim, error, info, success } from '../ui.js';
4
+ const PROMPT_CONSENT_DESCRIPTIONS = {
5
+ none: 'token counts only. nothing from your conversations leaves this machine.',
6
+ stats: 'prompt lengths and per-project counts. numbers only, no text.',
7
+ full: 'the above, plus a text sample scored for how technical it is (then discarded).',
8
+ };
3
9
  /**
4
10
  * Note where a value came from. Printing the *effective* value rather than the
5
11
  * file's is the point: with an env var or flag set, the file's value is dead
@@ -21,13 +27,22 @@ export async function configCommand(args) {
21
27
  if (auth.email) {
22
28
  info(` cursor-email: ${auth.email}${sourceNote(auth.emailSource, 'CURSOR_EMAIL')}`);
23
29
  }
30
+ const consent = (await loadConfig()).promptStatsConsent;
31
+ if (isPromptConsentTier(consent)) {
32
+ info(` prompt-stats: ${consent}`);
33
+ info(` ${dim(PROMPT_CONSENT_DESCRIPTIONS[consent])}`);
34
+ }
35
+ else {
36
+ info(` prompt-stats: ${dim('unset — sync will ask')}`);
37
+ }
24
38
  if (!auth.apiKey && !auth.email) {
25
- info(` ${dim('(empty)')}`);
39
+ info(` ${dim('(cursor: empty)')}`);
26
40
  }
27
41
  console.log('');
28
42
  info('available keys:');
29
43
  info(` ${dim('cursor-api-key')} your Cursor API key — exact token counts`);
30
44
  info(` ${dim('cursor-email')} your Cursor account email — scopes a team key to you`);
45
+ info(` ${dim('prompt-stats')} ${PROMPT_CONSENT_TIERS.join(' | ')} — what leaves this machine`);
31
46
  console.log('');
32
47
  info(dim('per-run overrides (both beat this file):'));
33
48
  info(dim(' hacklab --cursor-api-key <key> sync'));
@@ -51,9 +66,19 @@ export async function configCommand(args) {
51
66
  await saveConfig(config);
52
67
  success(`cursor-email set to ${value}`);
53
68
  break;
69
+ case 'prompt-stats':
70
+ if (!isPromptConsentTier(value)) {
71
+ error(`prompt-stats must be one of: ${PROMPT_CONSENT_TIERS.join(', ')}`);
72
+ process.exit(1);
73
+ }
74
+ config.promptStatsConsent = value;
75
+ await saveConfig(config);
76
+ success(`prompt-stats set to ${value}`);
77
+ info(dim(` ${PROMPT_CONSENT_DESCRIPTIONS[value]}`));
78
+ break;
54
79
  default:
55
80
  error(`unknown config key: ${key}`);
56
- info(`available: cursor-api-key, cursor-email`);
81
+ info(`available: cursor-api-key, cursor-email, prompt-stats`);
57
82
  process.exit(1);
58
83
  }
59
84
  }
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AA0BA;;;;;GAKG;AACH,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAU7D"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAiCA;;;;;GAKG;AACH,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB7D"}
@@ -1,9 +1,10 @@
1
1
  import * as clack from '@clack/prompts';
2
2
  import { appendSyncLog, clearSyncPaused, markSyncPaused, } from '../daily-sync.js';
3
3
  import { captureEvent } from '../posthog.js';
4
+ import { loadPromptConsent, parsePromptStatsFlag, resolvePromptConsent, savePromptConsent, } from '../prompt-consent.js';
4
5
  import { scanAllTools } from '../scanners/index.js';
5
6
  import { loadSessionState } from '../session.js';
6
- import { checkSession, ensureFreshSession, formatTokens, LOGIN_EXPIRED_MESSAGE, refreshSession, runSync, syncGithubRepos, uploadTokenScan, } from '../sync.js';
7
+ import { checkSession, ensureFreshSession, formatTokens, LOGIN_EXPIRED_MESSAGE, refreshSession, runSync, scanConsentedPromptStats, syncGithubRepos, uploadTokenScan, } from '../sync.js';
7
8
  import { bold, dim, error, info, success } from '../ui.js';
8
9
  import { daemon } from './daemon.js';
9
10
  const SESSION_EXPIRED_REASON = 'your hacklab session expired — run `hacklab login`';
@@ -14,6 +15,12 @@ const SESSION_EXPIRED_REASON = 'your hacklab session expired — run `hacklab lo
14
15
  * --quiet the unattended daily run (logs to a file, no output)
15
16
  */
16
17
  export async function sync(args = []) {
18
+ // Pull --share-prompt-stats out first so it works alongside every mode
19
+ // below (an agent can set consent on the same run that installs the daemon).
20
+ const { tier: flagTier, rest } = parsePromptStatsFlag(args);
21
+ if (flagTier)
22
+ await savePromptConsent(flagTier);
23
+ args = rest;
17
24
  if (args.includes('--install-daily')) {
18
25
  // Kept working (it shipped, and installed CLIs / old docs still say it) but
19
26
  // no longer advertised: scheduling the daemon is `hacklab daemon` now, which
@@ -47,11 +54,14 @@ async function quietSync() {
47
54
  }
48
55
  const session = await ensureFreshSession(state.session);
49
56
  const scan = await scanAllTools();
57
+ // Whatever the user already consented to. The unattended run never asks, so
58
+ // a machine that has never answered uploads token counts only.
59
+ const promptStats = await scanConsentedPromptStats((await loadPromptConsent()) ?? 'none');
50
60
  // Upload tokens AND mirror pinned repos together, so the after-refresh retry
51
61
  // below does the exact same work as the happy path (no silently-skipped repo
52
62
  // sync on a day the session had to be refreshed mid-run).
53
63
  const push = async (s) => {
54
- await uploadTokenScan(s, scan);
64
+ await uploadTokenScan(s, scan, { promptStats });
55
65
  await syncGithubRepos(s);
56
66
  };
57
67
  try {
@@ -104,6 +114,9 @@ async function interactiveSync() {
104
114
  // Proactively slide a near-expiry session forward — same behavior as the daily
105
115
  // job, so expiry management doesn't differ by entry point.
106
116
  const session = await ensureFreshSession(sessionState.session);
117
+ // Ask before scanning anything conversational. Asked once, then remembered;
118
+ // an unanswered or non-TTY run resolves to 'none'.
119
+ const promptConsent = await resolvePromptConsent(null, { interactive: true });
107
120
  console.log('');
108
121
  console.log(bold(' hacklab sync'));
109
122
  console.log(dim(' scanning local AI tool usage...'));
@@ -112,7 +125,7 @@ async function interactiveSync() {
112
125
  try {
113
126
  // Manual `hacklab sync` — tag the upload as interactive so the backend counts
114
127
  // it as user activity (the daily background job and join's upload don't).
115
- result = await runSync(session, { interactive: true });
128
+ result = await runSync(session, { interactive: true, promptConsent });
116
129
  }
117
130
  catch (e) {
118
131
  error(e instanceof Error ? e.message : 'sync failed');
@@ -146,6 +159,22 @@ async function interactiveSync() {
146
159
  if (Number(r.tokensDelta) > 0) {
147
160
  info(` +${formatTokens(Number(r.tokensDelta))} since last sync`);
148
161
  }
162
+ if (result.promptStats) {
163
+ const { totalPrompts } = result.promptStats;
164
+ info(` prompts ${formatTokens(totalPrompts)} scanned${promptConsent === 'full' ? dim(' (+ text sample)') : ''}`);
165
+ // The backend can only attach a project's count if the repo matches one of
166
+ // this user's own projects. Reporting the match rate keeps a scan that
167
+ // matched nothing from reading as a success.
168
+ const summary = result.result.promptStats;
169
+ const reported = summary?.projectsReported ?? 0;
170
+ const matched = summary?.projectsMatched ?? 0;
171
+ if (reported > 0 && matched === 0) {
172
+ info(dim(` none of your ${reported} local repos matched a hacklab project — run \`hacklab brag\` in one`));
173
+ }
174
+ else if (matched > 0) {
175
+ info(dim(` matched ${matched} of ${reported} local repos to projects`));
176
+ }
177
+ }
149
178
  // Mirror pinned GitHub repos into projects (best-effort; never fails sync).
150
179
  const repos = await syncGithubRepos(session);
151
180
  if (repos && (repos.synced > 0 || repos.removed > 0)) {
@@ -1 +1 @@
1
- {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAA;AAEvC,OAAO,EACL,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,gBAAgB,EAAgB,MAAM,eAAe,CAAA;AAC9D,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,qBAAqB,EACrB,cAAc,EACd,OAAO,EACP,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,MAAM,sBAAsB,GAC1B,oDAAoD,CAAA;AAEtD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,OAAiB,EAAE;IAC5C,IAAI,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACrC,4EAA4E;QAC5E,6EAA6E;QAC7E,uDAAuD;QACvD,IAAI,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAC,CAAA;QAC3E,OAAO,MAAM,EAAE,CAAA;IACjB,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,EAAE,CAAA;IAChD,OAAO,eAAe,EAAE,CAAA;AAC1B,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,SAAS;IACtB,MAAM,KAAK,GAAG,MAAM,gBAAgB,EAAE,CAAA;IACtC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACnB,MAAM,aAAa,CAAC,SAAS,KAAK,CAAC,MAAM,EAAE,CAAC,CAAA;QAC5C,4EAA4E;QAC5E,2EAA2E;QAC3E,kCAAkC;QAClC,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7D,MAAM,cAAc,CAClB,KAAK,CAAC,MAAM,KAAK,SAAS;gBACxB,CAAC,CAAC,+DAA+D;gBACjE,CAAC,CAAC,sBAAsB,CAC3B,CAAA;QACH,CAAC;QACD,OAAM;IACR,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACvD,MAAM,IAAI,GAAG,MAAM,YAAY,EAAE,CAAA;IAEjC,6EAA6E;IAC7E,6EAA6E;IAC7E,0DAA0D;IAC1D,MAAM,IAAI,GAAG,KAAK,EAAE,CAAU,EAAE,EAAE;QAChC,MAAM,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;QAC9B,MAAM,eAAe,CAAC,CAAC,CAAC,CAAA;IAC1B,CAAC,CAAA;IAED,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,OAAO,CAAC,CAAA;QACnB,MAAM,eAAe,EAAE,CAAA;QACvB,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;IAC3B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACtD,IAAI,GAAG,KAAK,qBAAqB,EAAE,CAAC;YAClC,MAAM,aAAa,CAAC,UAAU,GAAG,EAAE,CAAC,CAAA;YACpC,OAAM;QACR,CAAC;QACD,2DAA2D;QAC3D,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,CAAA;QAC/C,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,SAAS,CAAC,CAAA;gBACrB,MAAM,eAAe,EAAE,CAAA;gBACvB,MAAM,aAAa,CAAC,oBAAoB,CAAC,CAAA;gBACzC,OAAM;YACR,CAAC;YAAC,MAAM,CAAC;gBACP,wBAAwB;YAC1B,CAAC;QACH,CAAC;QACD,MAAM,cAAc,CAAC,sBAAsB,CAAC,CAAA;QAC5C,MAAM,aAAa,CAAC,yBAAyB,CAAC,CAAA;IAChD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,eAAe;IAC5B,MAAM,YAAY,GAAG,MAAM,gBAAgB,EAAE,CAAA;IAC7C,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;QAC1B,KAAK,CAAC,YAAY,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC,CAAA;QAC5E,IAAI,CAAC,OAAO,GAAG,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAA;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,+EAA+E;IAC/E,0BAA0B;IAC1B,MAAM,YAAY,GAAG,MAAM,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;IAC7D,IAAI,YAAY,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;QAC3C,KAAK,CAAC,eAAe,CAAC,CAAA;QACtB,IAAI,CAAC,OAAO,GAAG,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAA;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,IAAI,YAAY,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACrC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;QAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,+EAA+E;IAC/E,2DAA2D;IAC3D,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;IAE9D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAA;IACnC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC,CAAA;IACrD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAEf,IAAI,MAA2C,CAAA;IAC/C,IAAI,CAAC;QACH,8EAA8E;QAC9E,0EAA0E;QAC1E,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAA;IACxD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,KAAK,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAA;QACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,EACJ,WAAW,EACX,UAAU,EACV,WAAW,EACX,aAAa,EACb,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,MAAM,EAAE,CAAC,GACV,GAAG,MAAM,CAAA;IAEV,IAAI,WAAW,GAAG,CAAC;QACjB,IAAI,CAAC,kBAAkB,YAAY,CAAC,WAAW,CAAC,SAAS,CAAC,CAAA;IAC5D,IAAI,UAAU,GAAG,CAAC;QAAE,IAAI,CAAC,kBAAkB,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;IAC7E,IAAI,WAAW,GAAG,CAAC;QACjB,IAAI,CAAC,kBAAkB,YAAY,CAAC,WAAW,CAAC,SAAS,CAAC,CAAA;IAC5D,IAAI,aAAa,GAAG,CAAC;QACnB,IAAI,CAAC,kBAAkB,YAAY,CAAC,aAAa,CAAC,SAAS,CAAC,CAAA;IAC9D,IAAI,WAAW,GAAG,CAAC;QACjB,IAAI,CAAC,kBAAkB,YAAY,CAAC,WAAW,CAAC,SAAS,CAAC,CAAA;IAC5D,IAAI,aAAa,GAAG,CAAC;QACnB,IAAI,CAAC,kBAAkB,YAAY,CAAC,aAAa,CAAC,SAAS,CAAC,CAAA;IAE9D,6EAA6E;IAC7E,2EAA2E;IAC3E,IAAI,gBAAgB,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QAC7C,KAAK,CAAC,aAAa,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAA;QAC7C,IAAI,CACF,GAAG,CAAC,oEAAoE,CAAC,CAC1E,CAAA;QACD,IAAI,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC,CAAA;IAClE,CAAC;SAAM,IAAI,gBAAgB,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;QACrD,IAAI,CAAC,GAAG,CAAC,4BAA4B,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IAClE,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CACL,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,QAAQ,CAC1F,CAAA;IACD,IAAI,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,kBAAkB,CAAC,CAAA;IACnE,CAAC;IAED,4EAA4E;IAC5E,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,CAAA;IAC5C,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC;QACrD,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,WAAW,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAA;QACzE,IAAI,KAAK,CAAC,OAAO,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QAC7D,IAAI,CAAC,aAAa,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACvC,CAAC;IAED,MAAM,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,oBAAoB,EAAE;QACvD,aAAa,EAAE,WAAW;QAC1B,YAAY,EAAE,UAAU;QACxB,aAAa,EAAE,WAAW;QAC1B,eAAe,EAAE,aAAa;QAC9B,aAAa,EAAE,WAAW;QAC1B,eAAe,EAAE,aAAa;QAC9B,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,KAAK,EAAE,CAAC,CAAC,KAAK;KACf,CAAC,CAAA;IAEF,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAA;AAC7B,CAAC"}
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -1,6 +1,12 @@
1
1
  export type HacklabConfig = {
2
2
  cursorApiKey?: string;
3
3
  cursorEmail?: string;
4
+ /**
5
+ * Consent for uploading Claude Code conversation data: 'none' | 'stats' |
6
+ * 'full'. Absent means never asked — see prompt-consent.ts, which owns the
7
+ * tiers and treats an unset value as "ask", never as a yes.
8
+ */
9
+ promptStatsConsent?: string;
4
10
  };
5
11
  /** Where a resolved credential came from, so `config` can show what actually wins. */
6
12
  export type CursorAuthSource = 'env' | 'config' | 'none';
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAID,sFAAsF;AACtF,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;AAExD,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,gBAAgB,CAAA;IAC9B,WAAW,EAAE,gBAAgB,CAAA;CAC9B,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,UAAU,CAAC,CAgB7D;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,CAOzD;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B,CAAA;AAID,sFAAsF;AACtF,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;AAExD,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,gBAAgB,CAAA;IAC9B,WAAW,EAAE,gBAAgB,CAAA;CAC9B,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,UAAU,CAAC,CAgB7D;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,CAOzD;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrE"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAOzC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,aAAa,CAAC,CAAA;AAY9D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAA;IACjC,MAAM,IAAI,GAAG,CACX,OAAe,EACf,WAA+B,EACS,EAAE;QAC1C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAA;QAC7C,IAAI,QAAQ;YAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;QACtC,IAAI,WAAW;YAAE,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;QAC/C,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;IAC5B,CAAC,CAAA;IAED,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,YAAY,CAAC,CAAA;IAC1E,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;IAErE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,CAAA;AACrD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;QAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkB,CAAA;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAqB;IACpD,MAAM,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACtD,MAAM,SAAS,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AAC9E,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAazC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,aAAa,CAAC,CAAA;AAY9D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAA;IACjC,MAAM,IAAI,GAAG,CACX,OAAe,EACf,WAA+B,EACS,EAAE;QAC1C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAA;QAC7C,IAAI,QAAQ;YAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;QACtC,IAAI,WAAW;YAAE,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;QAC/C,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;IAC5B,CAAC,CAAA;IAED,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,YAAY,CAAC,CAAA;IAC1E,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;IAErE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,CAAA;AACrD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;QAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkB,CAAA;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAqB;IACpD,MAAM,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACtD,MAAM,SAAS,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AAC9E,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Consent for uploading anything derived from the user's Claude Code
3
+ * conversations.
4
+ *
5
+ * Nothing conversation-derived leaves the machine until someone has answered
6
+ * this explicitly. The tiers are additive:
7
+ *
8
+ * none token counts only — exactly what the CLI did before this existed
9
+ * stats + prompt-length histogram and per-project prompt counts (numbers
10
+ * only; no prompt text ever leaves the machine)
11
+ * full + a sample of the raw prompt text, so the backend can score how
12
+ * technical the prompting is. It scores the sample and discards it.
13
+ *
14
+ * The answer is remembered in ~/.hacklab/config.json so the question is asked
15
+ * once, and can be changed or revoked at any time with
16
+ * `hacklab config prompt-stats <tier>`.
17
+ */
18
+ export declare const PROMPT_CONSENT_TIERS: readonly ["none", "stats", "full"];
19
+ export type PromptConsentTier = (typeof PROMPT_CONSENT_TIERS)[number];
20
+ export declare function isPromptConsentTier(value: unknown): value is PromptConsentTier;
21
+ /** The stored answer, or null when the user has never been asked. */
22
+ export declare function loadPromptConsent(): Promise<PromptConsentTier | null>;
23
+ export declare function savePromptConsent(tier: PromptConsentTier): Promise<void>;
24
+ /**
25
+ * Read `--share-prompt-stats[=<tier>]` out of a command's args.
26
+ *
27
+ * This is the agent-friendly path: it answers the question up front so an
28
+ * unattended run never blocks on a prompt it can't see. Bare
29
+ * `--share-prompt-stats` means the numbers-only tier — the safe reading of an
30
+ * unqualified yes, since sending prompt *text* should always be deliberate.
31
+ * `--no-share-prompt-stats` is an explicit refusal.
32
+ *
33
+ * Returns the chosen tier, or null when the flag is absent. `rest` is the args
34
+ * with the flag removed so per-command parsing never sees it.
35
+ */
36
+ export declare function parsePromptStatsFlag(args: string[]): {
37
+ tier: PromptConsentTier | null;
38
+ rest: string[];
39
+ };
40
+ /**
41
+ * Ask a yes/no question with no default: Enter alone re-asks, and only `y` or
42
+ * `n` settles it. Deliberately not @clack/prompts' confirm, which ships a
43
+ * highlighted default that can be accepted with a stray Enter — consent to
44
+ * upload conversation data should never be something you agree to by
45
+ * reflex.
46
+ *
47
+ * Returns null on a non-TTY stdin or EOF, which callers treat as "unanswered"
48
+ * rather than as a yes.
49
+ */
50
+ export declare function askYesNo(question: string): Promise<boolean | null>;
51
+ /**
52
+ * Resolve the consent tier for this run.
53
+ *
54
+ * Precedence: an explicit flag wins (and is remembered), then the stored
55
+ * answer, then the interactive questions. An unattended run that has never
56
+ * answered gets `none` — silence is never consent.
57
+ */
58
+ export declare function resolvePromptConsent(flagTier: PromptConsentTier | null, opts?: {
59
+ interactive?: boolean;
60
+ }): Promise<PromptConsentTier>;
61
+ //# sourceMappingURL=prompt-consent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-consent.d.ts","sourceRoot":"","sources":["../src/prompt-consent.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;GAgBG;AAEH,eAAO,MAAM,oBAAoB,oCAAqC,CAAA;AACtE,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAA;AAErE,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,iBAAiB,CAK5B;AAED,qEAAqE;AACrE,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAK3E;AAED,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IACpD,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAC9B,IAAI,EAAE,MAAM,EAAE,CAAA;CACf,CAsBA;AAED;;;;;;;;;GASG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAoBxE;AA+BD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,EAClC,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACnC,OAAO,CAAC,iBAAiB,CAAC,CAyC5B"}
@@ -0,0 +1,167 @@
1
+ import { createInterface } from 'node:readline';
2
+ import { loadConfig, saveConfig } from './config.js';
3
+ import { bold, dim, info } from './ui.js';
4
+ /**
5
+ * Consent for uploading anything derived from the user's Claude Code
6
+ * conversations.
7
+ *
8
+ * Nothing conversation-derived leaves the machine until someone has answered
9
+ * this explicitly. The tiers are additive:
10
+ *
11
+ * none token counts only — exactly what the CLI did before this existed
12
+ * stats + prompt-length histogram and per-project prompt counts (numbers
13
+ * only; no prompt text ever leaves the machine)
14
+ * full + a sample of the raw prompt text, so the backend can score how
15
+ * technical the prompting is. It scores the sample and discards it.
16
+ *
17
+ * The answer is remembered in ~/.hacklab/config.json so the question is asked
18
+ * once, and can be changed or revoked at any time with
19
+ * `hacklab config prompt-stats <tier>`.
20
+ */
21
+ export const PROMPT_CONSENT_TIERS = ['none', 'stats', 'full'];
22
+ export function isPromptConsentTier(value) {
23
+ return (typeof value === 'string' &&
24
+ PROMPT_CONSENT_TIERS.includes(value));
25
+ }
26
+ /** The stored answer, or null when the user has never been asked. */
27
+ export async function loadPromptConsent() {
28
+ const config = await loadConfig();
29
+ return isPromptConsentTier(config.promptStatsConsent)
30
+ ? config.promptStatsConsent
31
+ : null;
32
+ }
33
+ export async function savePromptConsent(tier) {
34
+ const config = await loadConfig();
35
+ config.promptStatsConsent = tier;
36
+ await saveConfig(config);
37
+ }
38
+ /**
39
+ * Read `--share-prompt-stats[=<tier>]` out of a command's args.
40
+ *
41
+ * This is the agent-friendly path: it answers the question up front so an
42
+ * unattended run never blocks on a prompt it can't see. Bare
43
+ * `--share-prompt-stats` means the numbers-only tier — the safe reading of an
44
+ * unqualified yes, since sending prompt *text* should always be deliberate.
45
+ * `--no-share-prompt-stats` is an explicit refusal.
46
+ *
47
+ * Returns the chosen tier, or null when the flag is absent. `rest` is the args
48
+ * with the flag removed so per-command parsing never sees it.
49
+ */
50
+ export function parsePromptStatsFlag(args) {
51
+ const rest = [];
52
+ let tier = null;
53
+ for (const arg of args) {
54
+ if (arg === '--no-share-prompt-stats') {
55
+ tier = 'none';
56
+ continue;
57
+ }
58
+ if (arg === '--share-prompt-stats') {
59
+ tier = 'stats';
60
+ continue;
61
+ }
62
+ if (arg.startsWith('--share-prompt-stats=')) {
63
+ const value = arg.slice('--share-prompt-stats='.length);
64
+ tier = isPromptConsentTier(value) ? value : 'stats';
65
+ continue;
66
+ }
67
+ rest.push(arg);
68
+ }
69
+ return { tier, rest };
70
+ }
71
+ /**
72
+ * Ask a yes/no question with no default: Enter alone re-asks, and only `y` or
73
+ * `n` settles it. Deliberately not @clack/prompts' confirm, which ships a
74
+ * highlighted default that can be accepted with a stray Enter — consent to
75
+ * upload conversation data should never be something you agree to by
76
+ * reflex.
77
+ *
78
+ * Returns null on a non-TTY stdin or EOF, which callers treat as "unanswered"
79
+ * rather than as a yes.
80
+ */
81
+ export async function askYesNo(question) {
82
+ if (!process.stdin.isTTY)
83
+ return null;
84
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
85
+ try {
86
+ for (;;) {
87
+ const answer = await new Promise((resolve) => {
88
+ rl.question(`${question} ${dim('[y/n]')} `, (value) => resolve(value));
89
+ rl.once('close', () => resolve(null));
90
+ });
91
+ if (answer === null)
92
+ return null;
93
+ const normalized = answer.trim().toLowerCase();
94
+ if (normalized === 'y' || normalized === 'yes')
95
+ return true;
96
+ if (normalized === 'n' || normalized === 'no')
97
+ return false;
98
+ // Anything else (including a bare Enter) is not an answer.
99
+ console.log(dim(' please press y or n.'));
100
+ }
101
+ }
102
+ finally {
103
+ rl.close();
104
+ }
105
+ }
106
+ /** The disclosure. Printed verbatim before the first question. */
107
+ function printDisclosure() {
108
+ console.log('');
109
+ console.log(bold(' share prompt stats?'));
110
+ console.log('');
111
+ info(' hacklab can read your local Claude Code history to chart how you prompt.');
112
+ info(` it is read on this machine, from ${dim('~/.claude/projects')}.`);
113
+ console.log('');
114
+ info(` ${bold('what would be uploaded')}`);
115
+ info(' how many prompts you have sent, and how long they are in words');
116
+ info(' a prompt count per project, matched by its git remote');
117
+ console.log('');
118
+ info(` ${bold('what would not')}`);
119
+ info(' the text of your prompts, unless you separately say yes below');
120
+ info(' anything from a project without a git remote');
121
+ console.log('');
122
+ info(dim(' hacklab stores the numbers on your profile. you can change or revoke'));
123
+ info(dim(' this later with `hacklab config prompt-stats <none|stats|full>`.'));
124
+ console.log('');
125
+ }
126
+ /**
127
+ * Resolve the consent tier for this run.
128
+ *
129
+ * Precedence: an explicit flag wins (and is remembered), then the stored
130
+ * answer, then the interactive questions. An unattended run that has never
131
+ * answered gets `none` — silence is never consent.
132
+ */
133
+ export async function resolvePromptConsent(flagTier, opts = {}) {
134
+ if (flagTier) {
135
+ await savePromptConsent(flagTier);
136
+ return flagTier;
137
+ }
138
+ const stored = await loadPromptConsent();
139
+ if (stored)
140
+ return stored;
141
+ if (!opts.interactive || !process.stdin.isTTY)
142
+ return 'none';
143
+ printDisclosure();
144
+ const shareNumbers = await askYesNo(' share these numbers with hacklab?');
145
+ if (shareNumbers === null)
146
+ return 'none';
147
+ if (!shareNumbers) {
148
+ await savePromptConsent('none');
149
+ console.log('');
150
+ info(dim(' no problem — syncing token counts only, as before.'));
151
+ return 'none';
152
+ }
153
+ console.log('');
154
+ info(' optional: a sample of your prompt text (up to 20k characters) can be');
155
+ info(' sent so an LLM can score how technical your prompting is. hacklab');
156
+ info(` scores it and ${bold('discards it')} — the text is never stored.`);
157
+ console.log('');
158
+ const shareText = await askYesNo(' also send a sample of your prompt text?');
159
+ const tier = shareText === true ? 'full' : 'stats';
160
+ await savePromptConsent(tier);
161
+ console.log('');
162
+ info(dim(tier === 'full'
163
+ ? ' sharing prompt stats and a text sample.'
164
+ : ' sharing prompt stats. numbers only, no text.'));
165
+ return tier;
166
+ }
167
+ //# sourceMappingURL=prompt-consent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-consent.js","sourceRoot":"","sources":["../src/prompt-consent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /** Buckets are `1..bucketMax`, so the axis stays readable at any prompt length. */
2
+ export declare const PROMPT_LENGTH_BUCKET_MIN = 10;
3
+ export declare const PROMPT_LENGTH_BUCKET_MAX = 100;
4
+ /** The percentile that sets `bucketMax`; everything above lands in the overflow. */
5
+ export declare const PROMPT_LENGTH_OVERFLOW_PERCENTILE = 0.9;
6
+ /** Matches the backend's cap — anything longer is truncated before upload. */
7
+ export declare const CONVERSATION_SAMPLE_MAX_CHARS = 20000;
8
+ export type PromptStatsProject = {
9
+ repoUrl: string;
10
+ promptCount: number;
11
+ lastActiveAt: string;
12
+ };
13
+ export type PromptStats = {
14
+ totalPrompts: number;
15
+ bucketMax: number;
16
+ histogram: {
17
+ length: number;
18
+ count: number;
19
+ }[];
20
+ projects: PromptStatsProject[];
21
+ /** Only ever set under the `full` consent tier. */
22
+ conversationSample?: string;
23
+ };
24
+ /**
25
+ * The user's own prompt text from one transcript line, or null when the line
26
+ * isn't one.
27
+ *
28
+ * A transcript's `user` entries cover more than typed prompts: tool results
29
+ * come back as synthetic user turns too. Those carry `tool_result` content
30
+ * blocks, so a line only counts when its content is a plain string or an array
31
+ * of nothing but `text` blocks. Sidechain entries (subagent conversations) are
32
+ * the agent talking to itself, not the person typing, so they're excluded.
33
+ */
34
+ export declare function promptTextFrom(entry: unknown): string | null;
35
+ /** Whitespace-separated word count. Zero-word prompts are dropped by callers. */
36
+ export declare function countWords(text: string): number;
37
+ /**
38
+ * The overflow threshold for this user's own distribution: their p90 prompt
39
+ * length rounded up to a multiple of 10, clamped to [10, 100].
40
+ *
41
+ * Per-user rather than fixed because prompt length varies enormously between
42
+ * people — a fixed axis would either crush a terse user's histogram into the
43
+ * first two buckets or run a verbose one off the end.
44
+ */
45
+ export declare function bucketMaxFor(wordCounts: number[]): number;
46
+ /**
47
+ * Bucket the word counts. Buckets `1..bucketMax-1` are exact word counts; the
48
+ * bucket at `bucketMax` is the overflow, holding every prompt that long or
49
+ * longer. Empty buckets are omitted — the chart fills the gaps.
50
+ */
51
+ export declare function buildHistogram(wordCounts: number[], bucketMax: number): {
52
+ length: number;
53
+ count: number;
54
+ }[];
55
+ /**
56
+ * The `origin` remote of the repo at `cwd`, or null when there isn't one (not
57
+ * a repo, no origin, no git binary, or the directory is gone). The URL is sent
58
+ * as-is; the backend normalizes it before matching against the user's own
59
+ * projects.
60
+ */
61
+ export declare function gitOriginUrl(cwd: string): Promise<string | null>;
62
+ /**
63
+ * Scan the local Claude Code transcripts.
64
+ *
65
+ * `includeSample` gates the raw prompt text: only the `full` consent tier
66
+ * passes true, and the sample never touches disk here — it goes straight into
67
+ * the upload payload the caller builds.
68
+ */
69
+ export declare function scanPromptStats(options?: {
70
+ includeSample?: boolean;
71
+ }): Promise<PromptStats | null>;
72
+ //# sourceMappingURL=prompt-stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-stats.d.ts","sourceRoot":"","sources":["../src/prompt-stats.ts"],"names":[],"mappings":"AA6BA,mFAAmF;AACnF,eAAO,MAAM,wBAAwB,KAAK,CAAA;AAC1C,eAAO,MAAM,wBAAwB,MAAM,CAAA;AAC3C,oFAAoF;AACpF,eAAO,MAAM,iCAAiC,MAAM,CAAA;AACpD,8EAA8E;AAC9E,eAAO,MAAM,6BAA6B,QAAS,CAAA;AAEnD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC9C,QAAQ,EAAE,kBAAkB,EAAE,CAAA;IAC9B,mDAAmD;IACnD,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B,CAAA;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAwB5D;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/C;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAazD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAAE,EACpB,SAAS,EAAE,MAAM,GAChB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAUrC;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAYtE;AAQD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAoF7B"}
@@ -0,0 +1,244 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { homedir } from 'node:os';
4
+ import { dirname, join } from 'node:path';
5
+ import { promisify } from 'node:util';
6
+ import { findFiles } from './scanners/util.js';
7
+ /**
8
+ * Prompt statistics, computed entirely on this machine from the local Claude
9
+ * Code transcripts and uploaded only under an explicit consent tier (see
10
+ * prompt-consent.ts).
11
+ *
12
+ * Two numbers come out of a scan:
13
+ *
14
+ * - a histogram of how long the user's own prompts are, in words
15
+ * - a per-project prompt count, keyed by the project's git origin
16
+ *
17
+ * and, under the `full` tier only, a sample of the raw prompt text so the
18
+ * backend can score "how technical is this person's prompting". The backend
19
+ * scores that sample and throws it away; it is never stored.
20
+ *
21
+ * Everything here is deliberately best-effort: an unreadable transcript, a
22
+ * project that isn't a git repo, a missing `git` binary — each drops its own
23
+ * contribution and the rest of the scan still uploads.
24
+ */
25
+ const execFileAsync = promisify(execFile);
26
+ /** Buckets are `1..bucketMax`, so the axis stays readable at any prompt length. */
27
+ export const PROMPT_LENGTH_BUCKET_MIN = 10;
28
+ export const PROMPT_LENGTH_BUCKET_MAX = 100;
29
+ /** The percentile that sets `bucketMax`; everything above lands in the overflow. */
30
+ export const PROMPT_LENGTH_OVERFLOW_PERCENTILE = 0.9;
31
+ /** Matches the backend's cap — anything longer is truncated before upload. */
32
+ export const CONVERSATION_SAMPLE_MAX_CHARS = 20_000;
33
+ /**
34
+ * The user's own prompt text from one transcript line, or null when the line
35
+ * isn't one.
36
+ *
37
+ * A transcript's `user` entries cover more than typed prompts: tool results
38
+ * come back as synthetic user turns too. Those carry `tool_result` content
39
+ * blocks, so a line only counts when its content is a plain string or an array
40
+ * of nothing but `text` blocks. Sidechain entries (subagent conversations) are
41
+ * the agent talking to itself, not the person typing, so they're excluded.
42
+ */
43
+ export function promptTextFrom(entry) {
44
+ if (!entry || typeof entry !== 'object')
45
+ return null;
46
+ const line = entry;
47
+ if (line.type !== 'user')
48
+ return null;
49
+ if (line.isSidechain === true)
50
+ return null;
51
+ const content = line.message?.content;
52
+ if (typeof content === 'string')
53
+ return content;
54
+ if (!Array.isArray(content))
55
+ return null;
56
+ const texts = [];
57
+ for (const block of content) {
58
+ if (!block || typeof block !== 'object')
59
+ return null;
60
+ const { type, text } = block;
61
+ // One non-text block (a tool_result, an image) disqualifies the whole
62
+ // entry: it isn't a prompt the person typed.
63
+ if (type !== 'text' || typeof text !== 'string')
64
+ return null;
65
+ texts.push(text);
66
+ }
67
+ return texts.length > 0 ? texts.join('\n') : null;
68
+ }
69
+ /** Whitespace-separated word count. Zero-word prompts are dropped by callers. */
70
+ export function countWords(text) {
71
+ const matches = text.match(/\S+/g);
72
+ return matches ? matches.length : 0;
73
+ }
74
+ /**
75
+ * The overflow threshold for this user's own distribution: their p90 prompt
76
+ * length rounded up to a multiple of 10, clamped to [10, 100].
77
+ *
78
+ * Per-user rather than fixed because prompt length varies enormously between
79
+ * people — a fixed axis would either crush a terse user's histogram into the
80
+ * first two buckets or run a verbose one off the end.
81
+ */
82
+ export function bucketMaxFor(wordCounts) {
83
+ if (wordCounts.length === 0)
84
+ return PROMPT_LENGTH_BUCKET_MIN;
85
+ const sorted = [...wordCounts].sort((a, b) => a - b);
86
+ const index = Math.min(sorted.length - 1, Math.floor(sorted.length * PROMPT_LENGTH_OVERFLOW_PERCENTILE));
87
+ const p90 = sorted[index] ?? PROMPT_LENGTH_BUCKET_MIN;
88
+ const rounded = Math.ceil(p90 / 10) * 10;
89
+ return Math.min(PROMPT_LENGTH_BUCKET_MAX, Math.max(PROMPT_LENGTH_BUCKET_MIN, rounded));
90
+ }
91
+ /**
92
+ * Bucket the word counts. Buckets `1..bucketMax-1` are exact word counts; the
93
+ * bucket at `bucketMax` is the overflow, holding every prompt that long or
94
+ * longer. Empty buckets are omitted — the chart fills the gaps.
95
+ */
96
+ export function buildHistogram(wordCounts, bucketMax) {
97
+ const counts = new Map();
98
+ for (const words of wordCounts) {
99
+ if (words <= 0)
100
+ continue;
101
+ const bucket = words >= bucketMax ? bucketMax : words;
102
+ counts.set(bucket, (counts.get(bucket) ?? 0) + 1);
103
+ }
104
+ return [...counts.entries()]
105
+ .map(([length, count]) => ({ length, count }))
106
+ .sort((a, b) => a.length - b.length);
107
+ }
108
+ /**
109
+ * The `origin` remote of the repo at `cwd`, or null when there isn't one (not
110
+ * a repo, no origin, no git binary, or the directory is gone). The URL is sent
111
+ * as-is; the backend normalizes it before matching against the user's own
112
+ * projects.
113
+ */
114
+ export async function gitOriginUrl(cwd) {
115
+ try {
116
+ const { stdout } = await execFileAsync('git', ['-C', cwd, 'remote', 'get-url', 'origin'], { timeout: 5_000 });
117
+ const url = stdout.trim();
118
+ return url.length > 0 ? url : null;
119
+ }
120
+ catch {
121
+ return null;
122
+ }
123
+ }
124
+ /**
125
+ * Scan the local Claude Code transcripts.
126
+ *
127
+ * `includeSample` gates the raw prompt text: only the `full` consent tier
128
+ * passes true, and the sample never touches disk here — it goes straight into
129
+ * the upload payload the caller builds.
130
+ */
131
+ export async function scanPromptStats(options = {}) {
132
+ const root = join(homedir(), '.claude', 'projects');
133
+ const files = await findFiles(root, '.jsonl');
134
+ if (files.length === 0)
135
+ return null;
136
+ const wordCounts = [];
137
+ const sampleParts = [];
138
+ let sampleChars = 0;
139
+ // Keyed by the transcript's project directory, which is Claude Code's own
140
+ // grouping. The directory name is a lossy encoding of the path, so the real
141
+ // working directory comes from the `cwd` recorded inside the entries.
142
+ const byProjectDir = new Map();
143
+ for (const filePath of files) {
144
+ const projectDir = dirname(filePath);
145
+ let project = byProjectDir.get(projectDir);
146
+ if (!project) {
147
+ project = { cwd: null, promptCount: 0, lastActiveAt: 0 };
148
+ byProjectDir.set(projectDir, project);
149
+ }
150
+ let content;
151
+ try {
152
+ content = await readFile(filePath, 'utf8');
153
+ }
154
+ catch {
155
+ continue;
156
+ }
157
+ for (const line of content.split('\n')) {
158
+ if (!line.trim())
159
+ continue;
160
+ let parsed;
161
+ try {
162
+ parsed = JSON.parse(line);
163
+ }
164
+ catch {
165
+ continue;
166
+ }
167
+ const entry = parsed;
168
+ if (!project.cwd && typeof entry.cwd === 'string' && entry.cwd) {
169
+ project.cwd = entry.cwd;
170
+ }
171
+ const text = promptTextFrom(parsed);
172
+ if (text === null)
173
+ continue;
174
+ const words = countWords(text);
175
+ if (words <= 0)
176
+ continue;
177
+ wordCounts.push(words);
178
+ project.promptCount += 1;
179
+ if (typeof entry.timestamp === 'string') {
180
+ const at = Date.parse(entry.timestamp);
181
+ if (Number.isFinite(at) && at > project.lastActiveAt) {
182
+ project.lastActiveAt = at;
183
+ }
184
+ }
185
+ if (options.includeSample &&
186
+ sampleChars < CONVERSATION_SAMPLE_MAX_CHARS) {
187
+ sampleParts.push(text);
188
+ sampleChars += text.length + 2;
189
+ }
190
+ }
191
+ }
192
+ if (wordCounts.length === 0)
193
+ return null;
194
+ const bucketMax = bucketMaxFor(wordCounts);
195
+ const stats = {
196
+ totalPrompts: wordCounts.length,
197
+ bucketMax,
198
+ histogram: buildHistogram(wordCounts, bucketMax),
199
+ projects: await resolveProjects(byProjectDir),
200
+ };
201
+ if (options.includeSample && sampleParts.length > 0) {
202
+ stats.conversationSample = sampleParts
203
+ .join('\n\n')
204
+ .slice(0, CONVERSATION_SAMPLE_MAX_CHARS);
205
+ }
206
+ return stats;
207
+ }
208
+ /**
209
+ * Turn the per-directory tallies into repo-keyed entries. Directories with no
210
+ * prompts, no recorded `cwd`, or no git origin drop out — the backend can only
211
+ * match a project by its repo URL, so an entry without one is dead weight.
212
+ *
213
+ * Two transcript directories can resolve to the same repo (the same project
214
+ * opened at different paths), so counts are summed per origin.
215
+ */
216
+ async function resolveProjects(byProjectDir) {
217
+ const byRepo = new Map();
218
+ for (const project of byProjectDir.values()) {
219
+ if (project.promptCount === 0 || !project.cwd)
220
+ continue;
221
+ const repoUrl = await gitOriginUrl(project.cwd);
222
+ if (!repoUrl)
223
+ continue;
224
+ const existing = byRepo.get(repoUrl);
225
+ if (existing) {
226
+ existing.promptCount += project.promptCount;
227
+ existing.lastActiveAt = Math.max(existing.lastActiveAt, project.lastActiveAt);
228
+ }
229
+ else {
230
+ byRepo.set(repoUrl, {
231
+ promptCount: project.promptCount,
232
+ lastActiveAt: project.lastActiveAt,
233
+ });
234
+ }
235
+ }
236
+ return [...byRepo.entries()].map(([repoUrl, entry]) => ({
237
+ repoUrl,
238
+ promptCount: entry.promptCount,
239
+ // A transcript with no usable timestamp still happened; dating it now is
240
+ // more honest than dropping the project or claiming the epoch.
241
+ lastActiveAt: new Date(entry.lastActiveAt > 0 ? entry.lastActiveAt : Date.now()).toISOString(),
242
+ }));
243
+ }
244
+ //# sourceMappingURL=prompt-stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-stats.js","sourceRoot":"","sources":["../src/prompt-stats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAErC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAE9C;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAA;AAEzC,mFAAmF;AACnF,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAA;AAC1C,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAA;AAC3C,oFAAoF;AACpF,MAAM,CAAC,MAAM,iCAAiC,GAAG,GAAG,CAAA;AACpD,8EAA8E;AAC9E,MAAM,CAAC,MAAM,6BAA6B,GAAG,MAAM,CAAA;AAiBnD;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IACpD,MAAM,IAAI,GAAG,KAIZ,CAAA;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,IAAI,CAAA;IACrC,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAE1C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAA;IACrC,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAA;IAC/C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAA;IAExC,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAA;QACpD,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,KAA2C,CAAA;QAClE,sEAAsE;QACtE,6CAA6C;QAC7C,IAAI,IAAI,KAAK,MAAM,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAA;QAC5D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAClB,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AACnD,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IAClC,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;AACrC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,UAAoB;IAC/C,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,wBAAwB,CAAA;IAC5D,MAAM,MAAM,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACpD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,MAAM,CAAC,MAAM,GAAG,CAAC,EACjB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,iCAAiC,CAAC,CAC9D,CAAA;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,wBAAwB,CAAA;IACrD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE,CAAA;IACxC,OAAO,IAAI,CAAC,GAAG,CACb,wBAAwB,EACxB,IAAI,CAAC,GAAG,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAC5C,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,UAAoB,EACpB,SAAiB;IAEjB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAA;IACxC,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,IAAI,KAAK,IAAI,CAAC;YAAE,SAAQ;QACxB,MAAM,MAAM,GAAG,KAAK,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAA;QACrD,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACnD,CAAC;IACD,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;SACzB,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;SAC7C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAA;AACxC,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAW;IAC5C,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CACpC,KAAK,EACL,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,EAC1C,EAAE,OAAO,EAAE,KAAK,EAAE,CACnB,CAAA;QACD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;QACzB,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAA;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAQD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,UAAuC,EAAE;IAEzC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAA;IACnD,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IAC7C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAEnC,MAAM,UAAU,GAAa,EAAE,CAAA;IAC/B,MAAM,WAAW,GAAa,EAAE,CAAA;IAChC,IAAI,WAAW,GAAG,CAAC,CAAA;IACnB,0EAA0E;IAC1E,4EAA4E;IAC5E,sEAAsE;IACtE,MAAM,YAAY,GAAG,IAAI,GAAG,EAA8B,CAAA;IAE1D,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;QACpC,IAAI,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAA;YACxD,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;QACvC,CAAC;QAED,IAAI,OAAe,CAAA;QACnB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAC5C,CAAC;QAAC,MAAM,CAAC;YACP,SAAQ;QACV,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;gBAAE,SAAQ;YAC1B,IAAI,MAAe,CAAA;YACnB,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YAC3B,CAAC;YAAC,MAAM,CAAC;gBACP,SAAQ;YACV,CAAC;YAED,MAAM,KAAK,GAAG,MAAgD,CAAA;YAC9D,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;gBAC/D,OAAO,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAA;YACzB,CAAC;YAED,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAA;YACnC,IAAI,IAAI,KAAK,IAAI;gBAAE,SAAQ;YAC3B,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;YAC9B,IAAI,KAAK,IAAI,CAAC;gBAAE,SAAQ;YAExB,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACtB,OAAO,CAAC,WAAW,IAAI,CAAC,CAAA;YAExB,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;gBACxC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;gBACtC,IAAI,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;oBACrD,OAAO,CAAC,YAAY,GAAG,EAAE,CAAA;gBAC3B,CAAC;YACH,CAAC;YAED,IACE,OAAO,CAAC,aAAa;gBACrB,WAAW,GAAG,6BAA6B,EAC3C,CAAC;gBACD,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBACtB,WAAW,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;YAChC,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAExC,MAAM,SAAS,GAAG,YAAY,CAAC,UAAU,CAAC,CAAA;IAC1C,MAAM,KAAK,GAAgB;QACzB,YAAY,EAAE,UAAU,CAAC,MAAM;QAC/B,SAAS;QACT,SAAS,EAAE,cAAc,CAAC,UAAU,EAAE,SAAS,CAAC;QAChD,QAAQ,EAAE,MAAM,eAAe,CAAC,YAAY,CAAC;KAC9C,CAAA;IAED,IAAI,OAAO,CAAC,aAAa,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpD,KAAK,CAAC,kBAAkB,GAAG,WAAW;aACnC,IAAI,CAAC,MAAM,CAAC;aACZ,KAAK,CAAC,CAAC,EAAE,6BAA6B,CAAC,CAAA;IAC5C,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,eAAe,CAC5B,YAA6C;IAE7C,MAAM,MAAM,GAAG,IAAI,GAAG,EAGnB,CAAA;IAEH,KAAK,MAAM,OAAO,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC;QAC5C,IAAI,OAAO,CAAC,WAAW,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG;YAAE,SAAQ;QACvD,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC/C,IAAI,CAAC,OAAO;YAAE,SAAQ;QAEtB,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;QACpC,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,WAAW,IAAI,OAAO,CAAC,WAAW,CAAA;YAC3C,QAAQ,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAC9B,QAAQ,CAAC,YAAY,EACrB,OAAO,CAAC,YAAY,CACrB,CAAA;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE;gBAClB,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,YAAY,EAAE,OAAO,CAAC,YAAY;aACnC,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QACtD,OAAO;QACP,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,yEAAyE;QACzE,+DAA+D;QAC/D,YAAY,EAAE,IAAI,IAAI,CACpB,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CACzD,CAAC,WAAW,EAAE;KAChB,CAAC,CAAC,CAAA;AACL,CAAC"}
package/dist/sync.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { PromptConsentTier } from './prompt-consent.js';
2
+ import { type PromptStats } from './prompt-stats.js';
1
3
  import { type AggregateScan, type CursorScanStatus, type CursorStats, type DailyToolEntry, formatBytes, formatTokens } from './scanners/index.js';
2
4
  import { type Session } from './session.js';
3
5
  export type { CursorScanStatus, CursorStats, DailyToolEntry };
@@ -18,6 +20,8 @@ export type SyncResult = {
18
20
  tokens: number;
19
21
  }>;
20
22
  cursorScanStatus: CursorScanStatus;
23
+ /** What was uploaded under the consent tier, or null when opted out. */
24
+ promptStats: PromptStats | null;
21
25
  };
22
26
  export declare const LOGIN_EXPIRED_MESSAGE = "login expired. run hacklab login again";
23
27
  type SessionCheck = {
@@ -54,6 +58,8 @@ export declare function syncGithubRepos(session: Session): Promise<{
54
58
  export declare function uploadTokenScan(session: Session, scan: AggregateScan, opts?: {
55
59
  timeoutMs?: number;
56
60
  interactive?: boolean;
61
+ /** Consented prompt statistics. Omitted entirely unless the user opted in. */
62
+ promptStats?: PromptStats | null;
57
63
  }): Promise<Record<string, unknown>>;
58
64
  /**
59
65
  * Ask the backend to slide this session's expiry forward (token unchanged) and
@@ -69,5 +75,13 @@ export declare function refreshSession(session: Session): Promise<Session | null
69
75
  export declare function ensureFreshSession(session: Session): Promise<Session>;
70
76
  export declare function runSync(session: Session, opts?: {
71
77
  interactive?: boolean;
78
+ promptConsent?: PromptConsentTier;
72
79
  }): Promise<SyncResult>;
80
+ /**
81
+ * Scan the local transcripts for the given consent tier, or return null when
82
+ * there's no consent (or nothing to find). Never throws: prompt stats are an
83
+ * extra on top of the token sync, so a scan failure must not cost the user
84
+ * their token upload.
85
+ */
86
+ export declare function scanConsentedPromptStats(tier: PromptConsentTier | undefined): Promise<PromptStats | null>;
73
87
  //# sourceMappingURL=sync.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,WAAW,EACX,YAAY,EAEb,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAGL,KAAK,OAAO,EAEb,MAAM,cAAc,CAAA;AAGrB,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,cAAc,EAAE,CAAA;AAK7D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,CAAA;AAEpC,MAAM,MAAM,UAAU,GAAG;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,cAAc,EAAE,CAAA;IAC5B,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC/C,gBAAgB,EAAE,gBAAgB,CAAA;CACnC,CAAA;AAED,eAAO,MAAM,qBAAqB,2CAA2C,CAAA;AAE7E,KAAK,YAAY,GACb;IAAE,MAAM,EAAE,IAAI,CAAA;CAAE,GAChB;IAAE,MAAM,EAAE,cAAc,CAAA;CAAE,GAC1B;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAwCzC,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,WAAW,GACjB,OAAO,CAAC,QAAQ,CAAC,CAMnB;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CAgC1E;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,OAAO,GACf,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAWrD;AAoBD;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,aAAa,EACnB,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACvD,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAmClC;AAMD;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAyBzB;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAK3E;AAED,wBAAsB,OAAO,CAC3B,OAAO,EAAE,OAAO,EAChB,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACnC,OAAO,CAAC,UAAU,CAAC,CA2BrB"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"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"}
package/dist/sync.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { getMachineIdentity } from './machine.js';
2
+ import { scanPromptStats } from './prompt-stats.js';
2
3
  import { formatBytes, formatTokens, scanAllTools, } from './scanners/index.js';
3
4
  import { getSessionExpiresAt, resolveAppUrl, saveSession, } from './session.js';
4
5
  import { dim } from './ui.js';
@@ -151,6 +152,9 @@ export async function uploadTokenScan(session, scan, opts = {}) {
151
152
  toolTotals: toolTotalsRecord(scan),
152
153
  modelTotals: scan.modelTotals,
153
154
  hourlyTotals: scan.hourlyTotals,
155
+ // Absent unless consented — the backend's field is optional, so an
156
+ // opted-out sync is byte-identical to the pre-prompt-stats payload.
157
+ ...(opts.promptStats ? { promptStats: opts.promptStats } : {}),
154
158
  }),
155
159
  ...(opts.timeoutMs ? { signal: AbortSignal.timeout(opts.timeoutMs) } : {}),
156
160
  });
@@ -212,8 +216,12 @@ export async function ensureFreshSession(session) {
212
216
  }
213
217
  export async function runSync(session, opts = {}) {
214
218
  const scan = await scanAllTools();
219
+ // Scanning transcripts is skipped entirely at the 'none' tier — an opted-out
220
+ // user's conversations are never even read.
221
+ const promptStats = await scanConsentedPromptStats(opts.promptConsent);
215
222
  const result = await uploadTokenScan(session, scan, {
216
223
  interactive: opts.interactive,
224
+ promptStats,
217
225
  });
218
226
  const totals = toolTotalsRecord(scan);
219
227
  const allEntries = scan.dailyTotals;
@@ -234,6 +242,23 @@ export async function runSync(session, opts = {}) {
234
242
  result,
235
243
  models,
236
244
  cursorScanStatus: scan.cursorScanStatus,
245
+ promptStats,
237
246
  };
238
247
  }
248
+ /**
249
+ * Scan the local transcripts for the given consent tier, or return null when
250
+ * there's no consent (or nothing to find). Never throws: prompt stats are an
251
+ * extra on top of the token sync, so a scan failure must not cost the user
252
+ * their token upload.
253
+ */
254
+ export async function scanConsentedPromptStats(tier) {
255
+ if (!tier || tier === 'none')
256
+ return null;
257
+ try {
258
+ return await scanPromptStats({ includeSample: tier === 'full' });
259
+ }
260
+ catch {
261
+ return null;
262
+ }
263
+ }
239
264
  //# sourceMappingURL=sync.js.map
package/dist/sync.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hacklab",
3
- "version": "0.10.4",
3
+ "version": "0.10.5",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"