meter-ai 0.1.2 → 0.3.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.
Files changed (44) hide show
  1. package/dist/commands/init.d.ts.map +1 -1
  2. package/dist/commands/init.js +74 -3
  3. package/dist/commands/init.js.map +1 -1
  4. package/dist/commands/wrap.d.ts.map +1 -1
  5. package/dist/commands/wrap.js +23 -2
  6. package/dist/commands/wrap.js.map +1 -1
  7. package/dist/pty/wrapper.d.ts +9 -8
  8. package/dist/pty/wrapper.d.ts.map +1 -1
  9. package/dist/pty/wrapper.js +39 -14
  10. package/dist/pty/wrapper.js.map +1 -1
  11. package/package.json +1 -1
  12. package/src/auth/credentials.ts +44 -0
  13. package/src/auth/detect.ts +24 -0
  14. package/src/commands/config.ts +19 -0
  15. package/src/commands/history.ts +16 -0
  16. package/src/commands/init.ts +149 -0
  17. package/src/commands/report.ts +27 -0
  18. package/src/commands/status.ts +16 -0
  19. package/src/commands/uninstall.ts +20 -0
  20. package/src/commands/wrap.ts +235 -0
  21. package/src/constants.ts +52 -0
  22. package/src/estimation/heuristics.ts +36 -0
  23. package/src/estimation/history-matcher.ts +43 -0
  24. package/src/estimation/llm-precheck.ts +27 -0
  25. package/src/estimation/pipeline.ts +67 -0
  26. package/src/hooks/on-prompt.js +92 -0
  27. package/src/hooks/statusline.js +36 -0
  28. package/src/index.ts +50 -0
  29. package/src/pty/resize.ts +15 -0
  30. package/src/pty/screen.ts +15 -0
  31. package/src/pty/wrapper.ts +143 -0
  32. package/src/shell/binary-resolver.ts +21 -0
  33. package/src/shell/detect.ts +33 -0
  34. package/src/shell/path-inject.ts +31 -0
  35. package/src/shell/shim-writer.ts +28 -0
  36. package/src/storage/config-store.ts +46 -0
  37. package/src/storage/db.ts +63 -0
  38. package/src/tracking/cost.ts +7 -0
  39. package/src/tracking/plan-usage.ts +57 -0
  40. package/src/tracking/tokens.ts +16 -0
  41. package/src/types.ts +73 -0
  42. package/src/ui/keypress.ts +27 -0
  43. package/src/ui/notification.ts +31 -0
  44. package/src/ui/statusbar.ts +74 -0
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAmD9D"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAwD9D"}
@@ -1,5 +1,6 @@
1
- import { mkdir } from 'fs/promises';
2
- import { join } from 'path';
1
+ import { mkdir, readFile, writeFile, copyFile, chmod } from 'fs/promises';
2
+ import { join, dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
3
4
  import { detectShell, getShellConfigPath } from '../shell/detect.js';
4
5
  import { resolveTrueBinary } from '../shell/binary-resolver.js';
5
6
  import { writeShim } from '../shell/shim-writer.js';
@@ -8,7 +9,7 @@ import { writeConfig, ensureConfigDefaults } from '../storage/config-store.js';
8
9
  import { detectMode } from '../auth/detect.js';
9
10
  import { readCredentials } from '../auth/credentials.js';
10
11
  import { resolveOrgId } from '../tracking/plan-usage.js';
11
- import { CLAUDE_CREDENTIALS_PATH } from '../constants.js';
12
+ import { CLAUDE_CREDENTIALS_PATH, CLAUDE_SETTINGS_PATH } from '../constants.js';
12
13
  export async function runInit(opts) {
13
14
  const meterDir = opts.meterDir;
14
15
  const binDir = join(meterDir, 'bin');
@@ -52,7 +53,77 @@ export async function runInit(opts) {
52
53
  ...(orgId ? { org_id: orgId } : {}),
53
54
  });
54
55
  await writeConfig(join(meterDir, 'config.json'), config);
56
+ // Install Claude Code hooks (skip in tests)
57
+ if (!opts.skipPathInjection) {
58
+ await installClaudeHooks(meterDir);
59
+ }
55
60
  console.log(`✓ meter initialised (${mode} mode)`);
56
61
  console.log(` Restart your terminal or run: source ~/.zshrc`);
57
62
  }
63
+ async function installClaudeHooks(meterDir) {
64
+ const hooksDir = join(meterDir, 'hooks');
65
+ await mkdir(hooksDir, { recursive: true });
66
+ // Copy hook scripts to ~/.meter/hooks/
67
+ const srcDir = join(dirname(fileURLToPath(import.meta.url)), '..', 'hooks');
68
+ for (const file of ['on-prompt.js', 'statusline.js']) {
69
+ try {
70
+ await copyFile(join(srcDir, file), join(hooksDir, file));
71
+ await chmod(join(hooksDir, file), 0o755);
72
+ }
73
+ catch {
74
+ // If source doesn't exist (running from dist), try the dist/hooks path
75
+ const distDir = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'src', 'hooks');
76
+ try {
77
+ await copyFile(join(distDir, file), join(hooksDir, file));
78
+ await chmod(join(hooksDir, file), 0o755);
79
+ }
80
+ catch {
81
+ console.warn(` ⚠ Could not copy ${file} — skipping hook installation`);
82
+ }
83
+ }
84
+ }
85
+ // Update Claude Code settings.json to add meter hooks
86
+ try {
87
+ let settings = {};
88
+ try {
89
+ settings = JSON.parse(await readFile(CLAUDE_SETTINGS_PATH, 'utf-8'));
90
+ }
91
+ catch {
92
+ // settings file doesn't exist yet — we'll create it
93
+ }
94
+ // Add UserPromptSubmit hook if not already present
95
+ const meterHookCommand = `node "${join(hooksDir, 'on-prompt.js')}"`;
96
+ if (!settings.hooks)
97
+ settings.hooks = {};
98
+ if (!settings.hooks.UserPromptSubmit)
99
+ settings.hooks.UserPromptSubmit = [];
100
+ const alreadyHasHook = settings.hooks.UserPromptSubmit.some((h) => h.hooks?.some((hh) => hh.command?.includes('meter')));
101
+ if (!alreadyHasHook) {
102
+ settings.hooks.UserPromptSubmit.push({
103
+ hooks: [{ type: 'command', command: meterHookCommand }]
104
+ });
105
+ console.log('✓ Added meter estimation hook to Claude Code');
106
+ }
107
+ // Add/update statusline command
108
+ const meterStatuslineCommand = `node "${join(hooksDir, 'statusline.js')}"`;
109
+ const existingStatusLine = settings.statusLine;
110
+ if (!existingStatusLine || existingStatusLine.command?.includes('meter')) {
111
+ // No existing statusline or it's ours — set it
112
+ settings.statusLine = { type: 'command', command: meterStatuslineCommand };
113
+ console.log('✓ Added meter statusline to Claude Code');
114
+ }
115
+ else {
116
+ // There's an existing statusline from another tool — chain them
117
+ // Create a wrapper that runs both
118
+ const chainCommand = `${existingStatusLine.command} && echo " │ " && ${meterStatuslineCommand}`;
119
+ settings.statusLine = { type: 'command', command: chainCommand };
120
+ console.log('✓ Chained meter statusline with existing statusline');
121
+ }
122
+ await mkdir(dirname(CLAUDE_SETTINGS_PATH), { recursive: true });
123
+ await writeFile(CLAUDE_SETTINGS_PATH, JSON.stringify(settings, null, 2), 'utf-8');
124
+ }
125
+ catch (err) {
126
+ console.warn(` ⚠ Could not update Claude Code settings: ${err}`);
127
+ }
128
+ }
58
129
  //# sourceMappingURL=init.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../../src/commands/wrap.ts"],"names":[],"mappings":"AAmBA,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiM3D"}
1
+ {"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../../src/commands/wrap.ts"],"names":[],"mappings":"AAmBA,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuN3D"}
@@ -119,6 +119,26 @@ export async function runWrap(args) {
119
119
  }
120
120
  }, 15_000);
121
121
  }
122
+ // Per-prompt estimation: when user submits a new prompt inside the interactive
123
+ // session, re-run the estimation pipeline and update the status bar
124
+ let lastPrompt = prompt; // initial prompt from CLI args
125
+ wrapper.on('input', async (newPrompt) => {
126
+ lastPrompt = newPrompt;
127
+ const newEstimation = await runEstimationPipeline({
128
+ prompt: newPrompt,
129
+ repoFileCount,
130
+ db,
131
+ repo,
132
+ config: config.estimation,
133
+ });
134
+ state.estimatedCost = newEstimation.estimated_cost;
135
+ state.complexity = newEstimation.complexity;
136
+ // Reset elapsed cost for the new prompt
137
+ state.elapsedCost = 0;
138
+ thresholdNotified = false;
139
+ statusBarShown = false; // allow fallback mode to re-print
140
+ updateBar();
141
+ });
122
142
  wrapper.on('data', (chunk) => {
123
143
  outputBuffer += chunk;
124
144
  // Rough running cost estimate from output volume
@@ -176,12 +196,13 @@ export async function runWrap(args) {
176
196
  clearInterval(pollInterval);
177
197
  // Parse final token counts
178
198
  const tokens = parseTokensFromOutput(outputBuffer);
179
- const promptHash = createHash('sha256').update(prompt.toLowerCase().trim()).digest('hex').slice(0, 16);
199
+ const finalPrompt = lastPrompt || prompt;
200
+ const promptHash = createHash('sha256').update(finalPrompt.toLowerCase().trim()).digest('hex').slice(0, 16);
180
201
  insertTask(db, {
181
202
  created_at: taskStart,
182
203
  repo,
183
204
  prompt_hash: promptHash,
184
- prompt_text: prompt,
205
+ prompt_text: finalPrompt,
185
206
  model: state.model,
186
207
  complexity: estimation.complexity,
187
208
  est_layer: estimation.layer_used,
@@ -1 +1 @@
1
- {"version":3,"file":"wrap.js","sourceRoot":"","sources":["../../src/commands/wrap.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wrap.js","sourceRoot":"","sources":["../../src/commands/wrap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAA;AACjE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAClF,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAChF,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAC1E,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAA;AAC1D,OAAO,EACL,WAAW,EAAE,eAAe,EAAE,uBAAuB,EACtD,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAInC,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAc;IAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;IAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC/B,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAElC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAA;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,WAAW,CAAC,CAAA;IAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,kDAAkD;QAClD,MAAM,CAAC,GAAG,IAAI,UAAU,EAAE,CAAA;QAC1B,CAAC,CAAC,KAAK,CAAC,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC,GAAwB,CAAC,CAAA;QAChE,MAAM,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;QACjE,OAAM;IACR,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAA;IAExC,sBAAsB;IACtB,IAAI,IAAI,GAAkB,IAAI,CAAA;IAC9B,IAAI,CAAC;QAAC,IAAI,GAAG,QAAQ,CAAC,uCAAuC,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAA;IAAC,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAC3F,IAAI,CAAC,IAAI,EAAE,CAAC;QAAC,IAAI,CAAC;YAAC,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IAAC,CAAC;IAEpD,qCAAqC;IACrC,IAAI,aAAa,GAAG,GAAG,CAAA;IACvB,IAAI,CAAC;QAAC,aAAa,GAAG,QAAQ,CAAC,QAAQ,CAAC,kCAAkC,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,GAAG,CAAA;IAAC,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEpH,wCAAwC;IACxC,MAAM,UAAU,GAAG,MAAM,qBAAqB,CAAC;QAC7C,MAAM;QACN,aAAa;QACb,EAAE;QACF,IAAI;QACJ,MAAM,EAAE,MAAM,CAAC,UAAU;KAC1B,CAAC,CAAA;IAEF,wCAAwC;IACxC,IAAI,SAAS,GAA+C,IAAI,CAAA;IAChE,IAAI,KAAK,GAAgD,IAAI,CAAA;IAC7D,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAC5C,KAAK,GAAG,MAAM,eAAe,CAAC,uBAAuB,CAAC,CAAA;QACtD,IAAI,KAAK;YAAE,SAAS,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IACnE,CAAC;IAED,uBAAuB;IACvB,MAAM,KAAK,GAAmB;QAC5B,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;QACpC,aAAa,EAAE,UAAU,CAAC,cAAc;QACxC,UAAU,EAAE,UAAU,CAAC,UAAwB;QAC/C,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,WAAW,EAAE,CAAC;QACd,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY;QACrC,SAAS,EAAE,SAAS,EAAE,aAAa,IAAI,IAAI;QAC3C,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,IAAI;KACrF,CAAA;IAED,mFAAmF;IACnF,MAAM,OAAO,GAAG,IAAI,UAAU,EAAE,CAAA;IAChC,IAAI,YAAY,GAAG,EAAE,CAAA;IACrB,IAAI,iBAAiB,GAAG,KAAK,CAAA;IAC7B,IAAI,aAAa,GAAG,CAAC,CAAA;IAErB,8DAA8D;IAC9D,IAAI,cAAc,GAAG,KAAK,CAAA;IAC1B,MAAM,SAAS,GAAG,GAAG,EAAE;QACrB,IAAI,OAAO,CAAC,mBAAmB;YAAE,OAAM;QACvC,MAAM,OAAO,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;QAEtC,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;YAC1B,0EAA0E;YAC1E,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA;gBACpC,cAAc,GAAG,IAAI,CAAA;YACvB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,sDAAsD;YACtD,MAAM,CAAC,GAAG,uBAAuB,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAA;YAC5G,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;QAC7B,CAAC;IACH,CAAC,CAAA;IAED,+BAA+B;IAC/B,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,gBAAgB,CAAC,uBAAuB,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YAC3D,IAAI,QAAQ;gBAAE,KAAK,GAAG,QAAQ,CAAA;QAChC,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,8CAA8C;IAC9C,IAAI,YAAY,GAA0B,IAAI,CAAA;IAC9C,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;QACrD,YAAY,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;YACpC,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,MAAM;gBAAE,OAAM;YACpC,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;YACxD,IAAI,KAAK,EAAE,CAAC;gBACV,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,aAAa,CAAA;gBACrC,KAAK,CAAC,aAAa,GAAG,oBAAoB,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAA;gBACpE,SAAS,EAAE,CAAA;YACb,CAAC;QACH,CAAC,EAAE,MAAM,CAAC,CAAA;IACZ,CAAC;IAED,+EAA+E;IAC/E,oEAAoE;IACpE,IAAI,UAAU,GAAG,MAAM,CAAA,CAAC,+BAA+B;IACvD,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,SAAiB,EAAE,EAAE;QAC9C,UAAU,GAAG,SAAS,CAAA;QACtB,MAAM,aAAa,GAAG,MAAM,qBAAqB,CAAC;YAChD,MAAM,EAAE,SAAS;YACjB,aAAa;YACb,EAAE;YACF,IAAI;YACJ,MAAM,EAAE,MAAM,CAAC,UAAU;SAC1B,CAAC,CAAA;QACF,KAAK,CAAC,aAAa,GAAG,aAAa,CAAC,cAAc,CAAA;QAClD,KAAK,CAAC,UAAU,GAAG,aAAa,CAAC,UAAwB,CAAA;QACzD,wCAAwC;QACxC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAA;QACrB,iBAAiB,GAAG,KAAK,CAAA;QACzB,cAAc,GAAG,KAAK,CAAA,CAAC,kCAAkC;QACzD,SAAS,EAAE,CAAA;IACb,CAAC,CAAC,CAAA;IAEF,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;QACnC,YAAY,IAAI,KAAK,CAAA;QACrB,iDAAiD;QACjD,KAAK,CAAC,WAAW,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC,GAAG,EAAE,CAAA;QAClF,SAAS,EAAE,CAAA;QAEX,kBAAkB;QAClB,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,KAAK,KAAK;gBACpC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,aAAa;gBAC9F,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAA;YAE9D,IAAI,QAAQ,EAAE,CAAC;gBACb,iBAAiB,GAAG,IAAI,CAAA;gBACxB,eAAe,EAAE,CAAA;YACnB,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,KAAK,UAAU,eAAe;QAC5B,uEAAuE;QACvE,MAAM,GAAG,GAAG,MAAO,CAAA;QACnB,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,IAAI,CAAA;QACpD,MAAM,YAAY,GAAG,kBAAkB,CAAC;YACtC,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,YAAY,EAAE,GAAG,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB;YAC3F,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,YAAY;YAClC,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,SAAS;SACV,CAAC,CAAA;QAEF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,YAAY,GAAG,IAAI,CAAC,CAAA;QAEhD,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;QAExD,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,EAAE,CAAA;QAChB,CAAC;aAAM,IAAI,MAAM,KAAK,GAAG,IAAI,SAAS,EAAE,CAAC;YACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,SAAS,wDAAwD,CAAC,CAAA;YAC9G,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAA;YAClD,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnB,OAAO,CAAC,IAAI,EAAE,CAAA;gBACd,KAAK,CAAC,KAAK,GAAG,SAAS,CAAA;gBACvB,aAAa,GAAG,CAAC,CAAA;gBACjB,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,GAAwB,CAAC,CAAA;YAC5G,CAAC;QACH,CAAC;QACD,4BAA4B;IAC9B,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAE5B,oCAAoC;IACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAC1B,SAAS,EAAE,CAAA;IACX,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC,GAAwB,CAAC,CAAA;IAEtE,MAAM,QAAQ,GAAG,MAAM,IAAI,OAAO,CAAS,OAAO,CAAC,EAAE;QACnD,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;IACrD,CAAC,CAAC,CAAA;IAEF,IAAI,YAAY;QAAE,aAAa,CAAC,YAAY,CAAC,CAAA;IAE7C,2BAA2B;IAC3B,MAAM,MAAM,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAA;IAClD,MAAM,WAAW,GAAG,UAAU,IAAI,MAAM,CAAA;IACxC,MAAM,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAE3G,UAAU,CAAC,EAAE,EAAE;QACb,UAAU,EAAE,SAAS;QACrB,IAAI;QACJ,WAAW,EAAE,UAAU;QACvB,WAAW,EAAE,WAAW;QACxB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,UAAU,EAAE,UAAU,CAAC,UAAwB;QAC/C,SAAS,EAAE,UAAU,CAAC,UAAU;QAChC,QAAQ,EAAE,UAAU,CAAC,cAAc;QACnC,gBAAgB,EAAE,MAAM,EAAE,KAAK,IAAI,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC;QACrE,iBAAiB,EAAE,MAAM,EAAE,MAAM,IAAI,IAAI;QACzC,WAAW,EAAE,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;QACvE,gBAAgB,EAAE,SAAS,EAAE,aAAa,IAAI,IAAI;QAClD,cAAc,EAAE,KAAK,CAAC,SAAS;QAC/B,cAAc,EAAE,aAAa;QAC7B,SAAS,EAAE,QAAQ;KACpB,CAAC,CAAA;IAEF,EAAE,CAAC,KAAK,EAAE,CAAA;IACV,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;AACxB,CAAC"}
@@ -1,25 +1,26 @@
1
1
  import { EventEmitter } from 'events';
2
2
  export interface WrapperEvents {
3
3
  data: (chunk: string) => void;
4
+ input: (prompt: string) => void;
4
5
  exit: (code: number, signal: number) => void;
5
6
  }
6
7
  /**
7
- * PtyWrapper with automatic fallback.
8
+ * PtyWrapper with automatic fallback and input capture.
8
9
  *
9
- * Strategy:
10
- * 1. Try node-pty (full PTY enables status bar injection)
11
- * 2. If node-pty fails (incompatible Node version, missing native bindings),
12
- * fall back to child_process.spawn with piped stdio
10
+ * In PTY mode:
11
+ * - Captures all user input keystroke by keystroke
12
+ * - Buffers input and emits 'input' event on Enter (prompt submission)
13
+ * - This enables per-prompt estimation during interactive sessions
13
14
  *
14
- * The fallback still captures output for token counting and cost tracking,
15
- * but the status bar is written above the agent output instead of injected
16
- * at a fixed terminal position.
15
+ * In fallback mode:
16
+ * - stdio is inherited, no input capture possible
17
17
  */
18
18
  export declare class PtyWrapper extends EventEmitter {
19
19
  private ptyProcess;
20
20
  private childProcess;
21
21
  private screenTracker;
22
22
  private _usingFallback;
23
+ private inputBuffer;
23
24
  get isInAlternateScreen(): boolean;
24
25
  get usingFallback(): boolean;
25
26
  spawn(binary: string, args: string[], env: NodeJS.ProcessEnv): void;
@@ -1 +1 @@
1
- {"version":3,"file":"wrapper.d.ts","sourceRoot":"","sources":["../../src/pty/wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAKrC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CAC7C;AAID;;;;;;;;;;;GAWG;AACH,qBAAa,UAAW,SAAQ,YAAY;IAC1C,OAAO,CAAC,UAAU,CAAuC;IACzD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,cAAc,CAAQ;IAE9B,IAAI,mBAAmB,IAAI,OAAO,CAEjC;IAED,IAAI,aAAa,IAAI,OAAO,CAE3B;IAED,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,IAAI;IAYnE,OAAO,CAAC,aAAa;IAoCrB,OAAO,CAAC,sBAAsB;IAc9B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQzB,IAAI,CAAC,MAAM,GAAE,MAAM,CAAC,OAAmB,GAAG,IAAI;IAQ9C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;CAGzC"}
1
+ {"version":3,"file":"wrapper.d.ts","sourceRoot":"","sources":["../../src/pty/wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAKrC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CAC7C;AAID;;;;;;;;;;GAUG;AACH,qBAAa,UAAW,SAAQ,YAAY;IAC1C,OAAO,CAAC,UAAU,CAAuC;IACzD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,WAAW,CAAK;IAExB,IAAI,mBAAmB,IAAI,OAAO,CAEjC;IAED,IAAI,aAAa,IAAI,OAAO,CAE3B;IAED,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,IAAI;IAUnE,OAAO,CAAC,aAAa;IA8DrB,OAAO,CAAC,sBAAsB;IAY9B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQzB,IAAI,CAAC,MAAM,GAAE,MAAM,CAAC,OAAmB,GAAG,IAAI;IAQ9C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;CAGzC"}
@@ -3,22 +3,22 @@ import { spawn as cpSpawn } from 'child_process';
3
3
  import { AlternateScreenTracker } from './screen.js';
4
4
  import { getTerminalSize } from './resize.js';
5
5
  /**
6
- * PtyWrapper with automatic fallback.
6
+ * PtyWrapper with automatic fallback and input capture.
7
7
  *
8
- * Strategy:
9
- * 1. Try node-pty (full PTY enables status bar injection)
10
- * 2. If node-pty fails (incompatible Node version, missing native bindings),
11
- * fall back to child_process.spawn with piped stdio
8
+ * In PTY mode:
9
+ * - Captures all user input keystroke by keystroke
10
+ * - Buffers input and emits 'input' event on Enter (prompt submission)
11
+ * - This enables per-prompt estimation during interactive sessions
12
12
  *
13
- * The fallback still captures output for token counting and cost tracking,
14
- * but the status bar is written above the agent output instead of injected
15
- * at a fixed terminal position.
13
+ * In fallback mode:
14
+ * - stdio is inherited, no input capture possible
16
15
  */
17
16
  export class PtyWrapper extends EventEmitter {
18
17
  ptyProcess = null;
19
18
  childProcess = null;
20
19
  screenTracker = new AlternateScreenTracker();
21
20
  _usingFallback = false;
21
+ inputBuffer = '';
22
22
  get isInAlternateScreen() {
23
23
  return this.screenTracker.isActive;
24
24
  }
@@ -26,13 +26,11 @@ export class PtyWrapper extends EventEmitter {
26
26
  return this._usingFallback;
27
27
  }
28
28
  spawn(binary, args, env) {
29
- // Try node-pty first
30
29
  try {
31
30
  const pty = require('node-pty');
32
31
  this._spawnWithPty(pty, binary, args, env);
33
32
  }
34
33
  catch {
35
- // node-pty failed — fall back to child_process
36
34
  this._usingFallback = true;
37
35
  this._spawnWithChildProcess(binary, args, env);
38
36
  }
@@ -54,12 +52,41 @@ export class PtyWrapper extends EventEmitter {
54
52
  this.ptyProcess.onExit(({ exitCode, signal }) => {
55
53
  this.emit('exit', exitCode, signal ?? 0);
56
54
  });
57
- // Forward stdin to PTY
55
+ // Forward stdin to PTY and capture input for per-prompt estimation
58
56
  if (process.stdin.isTTY) {
59
57
  process.stdin.setRawMode(true);
60
58
  }
61
59
  process.stdin.on('data', (data) => {
62
- this.ptyProcess?.write(data.toString());
60
+ const str = data.toString();
61
+ this.ptyProcess?.write(str);
62
+ // Track user input for prompt detection
63
+ for (const char of str) {
64
+ if (char === '\r' || char === '\n') {
65
+ // Enter pressed — emit the buffered input as a prompt
66
+ const prompt = this.inputBuffer.trim();
67
+ if (prompt.length > 0) {
68
+ this.emit('input', prompt);
69
+ }
70
+ this.inputBuffer = '';
71
+ }
72
+ else if (char === '\x7f' || char === '\b') {
73
+ // Backspace — remove last char from buffer
74
+ this.inputBuffer = this.inputBuffer.slice(0, -1);
75
+ }
76
+ else if (char === '\x03') {
77
+ // Ctrl+C — clear buffer
78
+ this.inputBuffer = '';
79
+ }
80
+ else if (char === '\x15') {
81
+ // Ctrl+U — clear line
82
+ this.inputBuffer = '';
83
+ }
84
+ else if (char.charCodeAt(0) >= 32) {
85
+ // Printable character — append to buffer
86
+ this.inputBuffer += char;
87
+ }
88
+ // Ignore other control characters (arrows, escape sequences, etc.)
89
+ }
63
90
  });
64
91
  // Handle terminal resize
65
92
  process.on('SIGWINCH', () => {
@@ -68,8 +95,6 @@ export class PtyWrapper extends EventEmitter {
68
95
  });
69
96
  }
70
97
  _spawnWithChildProcess(binary, args, env) {
71
- // Use fully inherited stdio so Claude Code's interactive TUI works.
72
- // We lose per-chunk output capture, but the agent runs correctly.
73
98
  this.childProcess = cpSpawn(binary, args, {
74
99
  env: { ...env },
75
100
  cwd: process.cwd(),
@@ -1 +1 @@
1
- {"version":3,"file":"wrapper.js","sourceRoot":"","sources":["../../src/pty/wrapper.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wrapper.js","sourceRoot":"","sources":["../../src/pty/wrapper.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "meter-ai",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
4
  "description": "Intelligent CLI wrapper for Claude Code — pre-task cost estimation, live status bar, budget protection",
5
5
  "bin": {
6
6
  "meter": "dist/index.js"
@@ -0,0 +1,44 @@
1
+ import { watch } from 'fs'
2
+ import { readFile as readFileAsync } from 'fs/promises'
3
+
4
+ export interface ClaudeCredentials {
5
+ accessToken: string
6
+ refreshToken?: string
7
+ expiresAt?: number
8
+ [key: string]: unknown
9
+ }
10
+
11
+ export async function readCredentials(path: string): Promise<ClaudeCredentials | null> {
12
+ async function tryRead(): Promise<ClaudeCredentials | null> {
13
+ try {
14
+ const raw = await readFileAsync(path, 'utf-8')
15
+ return JSON.parse(raw) as ClaudeCredentials
16
+ } catch {
17
+ return null
18
+ }
19
+ }
20
+
21
+ const first = await tryRead()
22
+ if (first) return first
23
+
24
+ // retry once after 200ms (handles partial writes on macOS kqueue)
25
+ await new Promise(r => setTimeout(r, 200))
26
+ return tryRead()
27
+ }
28
+
29
+ export function watchCredentials(
30
+ path: string,
31
+ onChange: (creds: ClaudeCredentials | null) => void
32
+ ): () => void {
33
+ let debounceTimer: NodeJS.Timeout | null = null
34
+
35
+ const watcher = watch(path, () => {
36
+ if (debounceTimer) clearTimeout(debounceTimer)
37
+ debounceTimer = setTimeout(async () => {
38
+ const creds = await readCredentials(path)
39
+ onChange(creds)
40
+ }, 100) // 100ms debounce to avoid partial-write reads
41
+ })
42
+
43
+ return () => watcher.close()
44
+ }
@@ -0,0 +1,24 @@
1
+ import { access } from 'fs/promises'
2
+ import type { UserMode } from '../types.js'
3
+
4
+ interface DetectOptions {
5
+ credentialsPath: string
6
+ }
7
+
8
+ async function fileExists(path: string): Promise<boolean> {
9
+ try {
10
+ await access(path)
11
+ return true
12
+ } catch {
13
+ return false
14
+ }
15
+ }
16
+
17
+ export async function detectMode(opts: DetectOptions): Promise<UserMode | null> {
18
+ const hasApiKey = Boolean(process.env.ANTHROPIC_API_KEY)
19
+ const hasCredentials = await fileExists(opts.credentialsPath)
20
+
21
+ if (hasCredentials) return 'plan'
22
+ if (hasApiKey) return 'api'
23
+ return null
24
+ }
@@ -0,0 +1,19 @@
1
+ import { readConfig, writeConfig } from '../storage/config-store.js'
2
+ import { CONFIG_PATH } from '../constants.js'
3
+
4
+ export async function runConfig(args: string[]): Promise<void> {
5
+ const config = await readConfig(CONFIG_PATH)
6
+ if (!config) { console.log('Run meter init first.'); return }
7
+ if (args.length === 0) { console.log(JSON.stringify(config, null, 2)); return }
8
+ if (args[0] === 'set' && args[1] && args[2]) {
9
+ const field = args[1]
10
+ const val = args[2]
11
+ if (field === 'budget') config.budget.per_task_usd = parseFloat(val)
12
+ else if (field === 'threshold') {
13
+ config.budget.threshold_pct = parseInt(val, 10)
14
+ config.plan.window_threshold_pct = parseInt(val, 10)
15
+ }
16
+ await writeConfig(CONFIG_PATH, config)
17
+ console.log(`✓ ${field} set to ${val}`)
18
+ }
19
+ }
@@ -0,0 +1,16 @@
1
+ import { openDb, getRecentTasks } from '../storage/db.js'
2
+ import { HISTORY_DB_PATH } from '../constants.js'
3
+
4
+ export async function runHistory(args: string[]): Promise<void> {
5
+ const limit = parseInt(args[0] ?? '30', 10)
6
+ const db = await openDb(HISTORY_DB_PATH)
7
+ const tasks = getRecentTasks(db, limit)
8
+ db.close()
9
+ if (tasks.length === 0) { console.log('No tasks recorded yet.'); return }
10
+ console.log(`\n◆ meter history (last ${limit})\n`)
11
+ for (const t of tasks) {
12
+ const date = new Date(t.created_at).toLocaleString()
13
+ const cost = t.actual_cost != null ? `$${t.actual_cost.toFixed(3)}` : t.window_pct_end != null ? `${t.window_pct_end.toFixed(0)}% window` : '—'
14
+ console.log(` ${date} ${t.complexity.padEnd(8)} ${cost.padStart(10)} ${t.prompt_text.slice(0, 50)}`)
15
+ }
16
+ }
@@ -0,0 +1,149 @@
1
+ import { mkdir, readFile, writeFile, copyFile, chmod } from 'fs/promises'
2
+ import { join, dirname } from 'path'
3
+ import { fileURLToPath } from 'url'
4
+ import { detectShell, getShellConfigPath } from '../shell/detect.js'
5
+ import { resolveTrueBinary } from '../shell/binary-resolver.js'
6
+ import { writeShim } from '../shell/shim-writer.js'
7
+ import { injectPath, isPathAlreadyInjected } from '../shell/path-inject.js'
8
+ import { writeConfig, ensureConfigDefaults } from '../storage/config-store.js'
9
+ import { detectMode } from '../auth/detect.js'
10
+ import { readCredentials } from '../auth/credentials.js'
11
+ import { resolveOrgId } from '../tracking/plan-usage.js'
12
+ import { METER_BIN_DIR, CLAUDE_CREDENTIALS_PATH, CLAUDE_SETTINGS_PATH } from '../constants.js'
13
+ import type { UserMode } from '../types.js'
14
+
15
+ export interface InitOptions {
16
+ meterDir: string
17
+ trueBinary?: string
18
+ mode?: UserMode
19
+ skipPathInjection?: boolean
20
+ orgId?: string | null
21
+ }
22
+
23
+ export async function runInit(opts: InitOptions): Promise<void> {
24
+ const meterDir = opts.meterDir
25
+ const binDir = join(meterDir, 'bin')
26
+ await mkdir(binDir, { recursive: true })
27
+ await mkdir(join(meterDir, 'cache'), { recursive: true })
28
+ await mkdir(join(meterDir, 'reports'), { recursive: true })
29
+
30
+ // Resolve true claude binary
31
+ const trueBinary = opts.trueBinary ?? await resolveTrueBinary('claude', binDir)
32
+ if (!trueBinary) {
33
+ throw new Error('claude not found in PATH. Install Claude Code first.')
34
+ }
35
+
36
+ // Detect mode
37
+ const mode = opts.mode ?? await detectMode({ credentialsPath: CLAUDE_CREDENTIALS_PATH })
38
+ if (!mode) {
39
+ throw new Error('No Claude credentials found. Run `claude` first to authenticate.')
40
+ }
41
+
42
+ // Resolve org_id for Plan Mode
43
+ let orgId = opts.orgId ?? null
44
+ if (mode === 'plan' && orgId === null) {
45
+ const creds = await readCredentials(CLAUDE_CREDENTIALS_PATH)
46
+ if (creds) orgId = await resolveOrgId(creds)
47
+ }
48
+
49
+ // Write shim
50
+ const shimPath = join(binDir, 'claude')
51
+ await writeShim(shimPath, trueBinary)
52
+
53
+ // Inject PATH (skip in tests)
54
+ if (!opts.skipPathInjection) {
55
+ const shell = detectShell()
56
+ const configPath = getShellConfigPath(shell)
57
+ const already = await isPathAlreadyInjected(configPath)
58
+ await injectPath(shell, configPath)
59
+ if (!already) {
60
+ console.log(`✓ Added ~/.meter/bin to PATH in ${configPath}`)
61
+ }
62
+ }
63
+
64
+ // Write config
65
+ const config = ensureConfigDefaults({
66
+ mode,
67
+ resolved_binaries: { claude: trueBinary },
68
+ ...(orgId ? { org_id: orgId } : {}),
69
+ })
70
+ await writeConfig(join(meterDir, 'config.json'), config)
71
+
72
+ // Install Claude Code hooks (skip in tests)
73
+ if (!opts.skipPathInjection) {
74
+ await installClaudeHooks(meterDir)
75
+ }
76
+
77
+ console.log(`✓ meter initialised (${mode} mode)`)
78
+ console.log(` Restart your terminal or run: source ~/.zshrc`)
79
+ }
80
+
81
+ async function installClaudeHooks(meterDir: string): Promise<void> {
82
+ const hooksDir = join(meterDir, 'hooks')
83
+ await mkdir(hooksDir, { recursive: true })
84
+
85
+ // Copy hook scripts to ~/.meter/hooks/
86
+ const srcDir = join(dirname(fileURLToPath(import.meta.url)), '..', 'hooks')
87
+ for (const file of ['on-prompt.js', 'statusline.js']) {
88
+ try {
89
+ await copyFile(join(srcDir, file), join(hooksDir, file))
90
+ await chmod(join(hooksDir, file), 0o755)
91
+ } catch {
92
+ // If source doesn't exist (running from dist), try the dist/hooks path
93
+ const distDir = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'src', 'hooks')
94
+ try {
95
+ await copyFile(join(distDir, file), join(hooksDir, file))
96
+ await chmod(join(hooksDir, file), 0o755)
97
+ } catch {
98
+ console.warn(` ⚠ Could not copy ${file} — skipping hook installation`)
99
+ }
100
+ }
101
+ }
102
+
103
+ // Update Claude Code settings.json to add meter hooks
104
+ try {
105
+ let settings: Record<string, any> = {}
106
+ try {
107
+ settings = JSON.parse(await readFile(CLAUDE_SETTINGS_PATH, 'utf-8'))
108
+ } catch {
109
+ // settings file doesn't exist yet — we'll create it
110
+ }
111
+
112
+ // Add UserPromptSubmit hook if not already present
113
+ const meterHookCommand = `node "${join(hooksDir, 'on-prompt.js')}"`
114
+ if (!settings.hooks) settings.hooks = {}
115
+ if (!settings.hooks.UserPromptSubmit) settings.hooks.UserPromptSubmit = []
116
+
117
+ const alreadyHasHook = settings.hooks.UserPromptSubmit.some((h: any) =>
118
+ h.hooks?.some((hh: any) => hh.command?.includes('meter'))
119
+ )
120
+
121
+ if (!alreadyHasHook) {
122
+ settings.hooks.UserPromptSubmit.push({
123
+ hooks: [{ type: 'command', command: meterHookCommand }]
124
+ })
125
+ console.log('✓ Added meter estimation hook to Claude Code')
126
+ }
127
+
128
+ // Add/update statusline command
129
+ const meterStatuslineCommand = `node "${join(hooksDir, 'statusline.js')}"`
130
+ const existingStatusLine = settings.statusLine
131
+
132
+ if (!existingStatusLine || existingStatusLine.command?.includes('meter')) {
133
+ // No existing statusline or it's ours — set it
134
+ settings.statusLine = { type: 'command', command: meterStatuslineCommand }
135
+ console.log('✓ Added meter statusline to Claude Code')
136
+ } else {
137
+ // There's an existing statusline from another tool — chain them
138
+ // Create a wrapper that runs both
139
+ const chainCommand = `${existingStatusLine.command} && echo " │ " && ${meterStatuslineCommand}`
140
+ settings.statusLine = { type: 'command', command: chainCommand }
141
+ console.log('✓ Chained meter statusline with existing statusline')
142
+ }
143
+
144
+ await mkdir(dirname(CLAUDE_SETTINGS_PATH), { recursive: true })
145
+ await writeFile(CLAUDE_SETTINGS_PATH, JSON.stringify(settings, null, 2), 'utf-8')
146
+ } catch (err) {
147
+ console.warn(` ⚠ Could not update Claude Code settings: ${err}`)
148
+ }
149
+ }