meter-ai 0.1.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 (126) hide show
  1. package/README.md +124 -0
  2. package/dist/auth/credentials.d.ts +9 -0
  3. package/dist/auth/credentials.d.ts.map +1 -0
  4. package/dist/auth/credentials.js +32 -0
  5. package/dist/auth/credentials.js.map +1 -0
  6. package/dist/auth/detect.d.ts +7 -0
  7. package/dist/auth/detect.d.ts.map +1 -0
  8. package/dist/auth/detect.js +20 -0
  9. package/dist/auth/detect.js.map +1 -0
  10. package/dist/commands/config.d.ts +2 -0
  11. package/dist/commands/config.d.ts.map +1 -0
  12. package/dist/commands/config.js +26 -0
  13. package/dist/commands/config.js.map +1 -0
  14. package/dist/commands/history.d.ts +2 -0
  15. package/dist/commands/history.d.ts.map +1 -0
  16. package/dist/commands/history.js +19 -0
  17. package/dist/commands/history.js.map +1 -0
  18. package/dist/commands/init.d.ts +10 -0
  19. package/dist/commands/init.d.ts.map +1 -0
  20. package/dist/commands/init.js +58 -0
  21. package/dist/commands/init.js.map +1 -0
  22. package/dist/commands/report.d.ts +2 -0
  23. package/dist/commands/report.d.ts.map +1 -0
  24. package/dist/commands/report.js +37 -0
  25. package/dist/commands/report.js.map +1 -0
  26. package/dist/commands/status.d.ts +2 -0
  27. package/dist/commands/status.d.ts.map +1 -0
  28. package/dist/commands/status.js +20 -0
  29. package/dist/commands/status.js.map +1 -0
  30. package/dist/commands/uninstall.d.ts +2 -0
  31. package/dist/commands/uninstall.d.ts.map +1 -0
  32. package/dist/commands/uninstall.js +20 -0
  33. package/dist/commands/uninstall.js.map +1 -0
  34. package/dist/commands/wrap.d.ts +2 -0
  35. package/dist/commands/wrap.d.ts.map +1 -0
  36. package/dist/commands/wrap.js +189 -0
  37. package/dist/commands/wrap.js.map +1 -0
  38. package/dist/constants.d.ts +30 -0
  39. package/dist/constants.d.ts.map +1 -0
  40. package/dist/constants.js +48 -0
  41. package/dist/constants.js.map +1 -0
  42. package/dist/estimation/heuristics.d.ts +8 -0
  43. package/dist/estimation/heuristics.d.ts.map +1 -0
  44. package/dist/estimation/heuristics.js +28 -0
  45. package/dist/estimation/heuristics.js.map +1 -0
  46. package/dist/estimation/history-matcher.d.ts +4 -0
  47. package/dist/estimation/history-matcher.d.ts.map +1 -0
  48. package/dist/estimation/history-matcher.js +27 -0
  49. package/dist/estimation/history-matcher.js.map +1 -0
  50. package/dist/estimation/llm-precheck.d.ts +3 -0
  51. package/dist/estimation/llm-precheck.d.ts.map +1 -0
  52. package/dist/estimation/llm-precheck.js +21 -0
  53. package/dist/estimation/llm-precheck.js.map +1 -0
  54. package/dist/estimation/pipeline.d.ts +16 -0
  55. package/dist/estimation/pipeline.d.ts.map +1 -0
  56. package/dist/estimation/pipeline.js +48 -0
  57. package/dist/estimation/pipeline.js.map +1 -0
  58. package/dist/index.d.ts +3 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +45 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/pty/resize.d.ts +7 -0
  63. package/dist/pty/resize.d.ts.map +1 -0
  64. package/dist/pty/resize.js +10 -0
  65. package/dist/pty/resize.js.map +1 -0
  66. package/dist/pty/screen.d.ts +6 -0
  67. package/dist/pty/screen.d.ts.map +1 -0
  68. package/dist/pty/screen.js +15 -0
  69. package/dist/pty/screen.js.map +1 -0
  70. package/dist/pty/wrapper.d.ts +15 -0
  71. package/dist/pty/wrapper.d.ts.map +1 -0
  72. package/dist/pty/wrapper.js +49 -0
  73. package/dist/pty/wrapper.js.map +1 -0
  74. package/dist/shell/binary-resolver.d.ts +2 -0
  75. package/dist/shell/binary-resolver.d.ts.map +1 -0
  76. package/dist/shell/binary-resolver.js +18 -0
  77. package/dist/shell/binary-resolver.js.map +1 -0
  78. package/dist/shell/detect.d.ts +5 -0
  79. package/dist/shell/detect.d.ts.map +1 -0
  80. package/dist/shell/detect.js +32 -0
  81. package/dist/shell/detect.js.map +1 -0
  82. package/dist/shell/path-inject.d.ts +5 -0
  83. package/dist/shell/path-inject.d.ts.map +1 -0
  84. package/dist/shell/path-inject.js +30 -0
  85. package/dist/shell/path-inject.js.map +1 -0
  86. package/dist/shell/shim-writer.d.ts +3 -0
  87. package/dist/shell/shim-writer.d.ts.map +1 -0
  88. package/dist/shell/shim-writer.js +22 -0
  89. package/dist/shell/shim-writer.js.map +1 -0
  90. package/dist/storage/config-store.d.ts +10 -0
  91. package/dist/storage/config-store.d.ts.map +1 -0
  92. package/dist/storage/config-store.js +42 -0
  93. package/dist/storage/config-store.js.map +1 -0
  94. package/dist/storage/db.d.ts +7 -0
  95. package/dist/storage/db.d.ts.map +1 -0
  96. package/dist/storage/db.js +53 -0
  97. package/dist/storage/db.js.map +1 -0
  98. package/dist/tracking/cost.d.ts +6 -0
  99. package/dist/tracking/cost.d.ts.map +1 -0
  100. package/dist/tracking/cost.js +6 -0
  101. package/dist/tracking/cost.js.map +1 -0
  102. package/dist/tracking/plan-usage.d.ts +6 -0
  103. package/dist/tracking/plan-usage.d.ts.map +1 -0
  104. package/dist/tracking/plan-usage.js +53 -0
  105. package/dist/tracking/plan-usage.js.map +1 -0
  106. package/dist/tracking/tokens.d.ts +7 -0
  107. package/dist/tracking/tokens.d.ts.map +1 -0
  108. package/dist/tracking/tokens.js +14 -0
  109. package/dist/tracking/tokens.js.map +1 -0
  110. package/dist/types.d.ts +70 -0
  111. package/dist/types.d.ts.map +1 -0
  112. package/dist/types.js +2 -0
  113. package/dist/types.js.map +1 -0
  114. package/dist/ui/keypress.d.ts +3 -0
  115. package/dist/ui/keypress.d.ts.map +1 -0
  116. package/dist/ui/keypress.js +20 -0
  117. package/dist/ui/keypress.js.map +1 -0
  118. package/dist/ui/notification.d.ts +11 -0
  119. package/dist/ui/notification.d.ts.map +1 -0
  120. package/dist/ui/notification.js +18 -0
  121. package/dist/ui/notification.js.map +1 -0
  122. package/dist/ui/statusbar.d.ts +15 -0
  123. package/dist/ui/statusbar.d.ts.map +1 -0
  124. package/dist/ui/statusbar.js +53 -0
  125. package/dist/ui/statusbar.js.map +1 -0
  126. package/package.json +34 -0
package/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # meter
2
+
3
+ **Intelligent CLI wrapper for Claude Code** — pre-task cost estimation, live status bar, budget protection.
4
+
5
+ meter sits transparently between you and Claude Code via PATH shimming. You keep typing `claude` exactly as before. meter adds:
6
+
7
+ - **Pre-task estimation** — know what a task will cost before it runs
8
+ - **Live status bar** — ambient cost/usage ticker while the agent works
9
+ - **Budget protection** — non-blocking notification when thresholds are hit, with one-keypress model switching
10
+ - **Works for both API users and plan subscribers**
11
+
12
+ ```
13
+ $ claude "refactor the auth layer"
14
+ ◆ meter claude-opus ~$0.38 heavy ████████████░░░░ 68% 5hr window | $0.12 elapsed
15
+ ```
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ npm install -g meter-ai
21
+ meter init
22
+ # restart your terminal
23
+ ```
24
+
25
+ That's it. `meter init` detects your shell, finds the real `claude` binary, sets up a transparent shim, and writes your config. From now on, every `claude` invocation runs through meter automatically.
26
+
27
+ ## How It Works
28
+
29
+ meter uses a PTY (pseudo-terminal) wrapper — the same mechanism used by VS Code's integrated terminal, tmux, and asciinema. Claude Code runs inside a PTY slave and believes it owns a real terminal. meter is the PTY master: it passes all I/O through unchanged while injecting a status bar at the bottom of your terminal.
30
+
31
+ ### For API users (paying per token)
32
+
33
+ ```
34
+ ◆ meter claude-opus ~$0.38 heavy │ ████████████░░░░ $0.21 / $0.50
35
+ ```
36
+
37
+ meter tracks actual dollar cost in real time. When your per-task budget threshold is hit, you get a non-blocking notification:
38
+
39
+ ```
40
+ ⚠ 80% budget hit ($0.40/$0.50) [s]witch to sonnet [d]ismiss [c]ancel
41
+ ```
42
+
43
+ ### For plan users (Claude Max, Pro)
44
+
45
+ ```
46
+ ◆ meter claude-opus ~$0.38 heavy │ ████████████░░░░ 68% 5hr window reset in 2h 14m
47
+ ```
48
+
49
+ meter polls your 5-hour usage window percentage and warns before you hit the rate limit wall mid-task.
50
+
51
+ ## Pre-Task Estimation
52
+
53
+ meter estimates task cost/weight using a three-layer pipeline:
54
+
55
+ 1. **Heuristics** (~50ms, free) — keyword scoring + repo size analysis
56
+ 2. **Historical baseline** (~10ms, free) — trigram similarity against your past tasks
57
+ 3. **LLM pre-call** (~1-2s, ~$0.0001) — only fires on ambiguous tasks
58
+
59
+ Simple tasks never hit layer 3. The estimate shows instantly and the agent starts immediately — no confirmation gate, no pause.
60
+
61
+ ## Commands
62
+
63
+ ```bash
64
+ meter init # Set up PATH shim and config
65
+ meter status # Show current mode, model, usage, and config
66
+ meter report # Weekly digest of usage and costs
67
+ meter history # Browse past task records
68
+ meter config # View and set budgets, thresholds, model chain
69
+ meter uninstall # Clean removal of all shims and data
70
+ ```
71
+
72
+ ### Configuration
73
+
74
+ ```bash
75
+ meter config set budget 1.00 # Set per-task budget to $1.00
76
+ meter config set threshold 90 # Notify at 90% instead of 80%
77
+ meter config # View current config as JSON
78
+ ```
79
+
80
+ ## Model Switching
81
+
82
+ When a budget threshold is hit, press `s` to switch to a cheaper model:
83
+
84
+ ```
85
+ claude-opus-4 → claude-sonnet-4 → claude-haiku-4
86
+ ```
87
+
88
+ meter warns you that conversation context will reset, and gives you 5 seconds to cancel before proceeding.
89
+
90
+ ## Data Storage
91
+
92
+ All data stays local. No telemetry, no cloud, no accounts.
93
+
94
+ ```
95
+ ~/.meter/
96
+ config.json # Mode, budgets, thresholds, resolved binary path
97
+ history.db # SQLite: task history, costs, estimates
98
+ pricing.json # Model pricing table (updated weekly)
99
+ bin/claude # PATH shim
100
+ cache/ # Usage data, session state
101
+ reports/ # Weekly digest snapshots
102
+ ```
103
+
104
+ ## Uninstall
105
+
106
+ ```bash
107
+ meter uninstall # Removes shim and PATH entry
108
+ npm uninstall -g meter-ai
109
+ ```
110
+
111
+ ## Roadmap
112
+
113
+ - **v1.1** — Aider support
114
+ - **v1.2** — Gemini CLI support
115
+ - **v1.3** — Codex CLI support
116
+ - **v2.0** — CSV/JSON export, `--dry-run` estimation, team usage sharing
117
+
118
+ ## Support
119
+
120
+ If meter saved you from a surprise bill or a rate limit wall, consider [buying me a coffee](https://buymeacoffee.com/catancs).
121
+
122
+ ## License
123
+
124
+ MIT
@@ -0,0 +1,9 @@
1
+ export interface ClaudeCredentials {
2
+ accessToken: string;
3
+ refreshToken?: string;
4
+ expiresAt?: number;
5
+ [key: string]: unknown;
6
+ }
7
+ export declare function readCredentials(path: string): Promise<ClaudeCredentials | null>;
8
+ export declare function watchCredentials(path: string, onChange: (creds: ClaudeCredentials | null) => void): () => void;
9
+ //# sourceMappingURL=credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/auth/credentials.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAgBrF;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,KAAK,IAAI,GAClD,MAAM,IAAI,CAYZ"}
@@ -0,0 +1,32 @@
1
+ import { watch } from 'fs';
2
+ import { readFile as readFileAsync } from 'fs/promises';
3
+ export async function readCredentials(path) {
4
+ async function tryRead() {
5
+ try {
6
+ const raw = await readFileAsync(path, 'utf-8');
7
+ return JSON.parse(raw);
8
+ }
9
+ catch {
10
+ return null;
11
+ }
12
+ }
13
+ const first = await tryRead();
14
+ if (first)
15
+ return first;
16
+ // retry once after 200ms (handles partial writes on macOS kqueue)
17
+ await new Promise(r => setTimeout(r, 200));
18
+ return tryRead();
19
+ }
20
+ export function watchCredentials(path, onChange) {
21
+ let debounceTimer = null;
22
+ const watcher = watch(path, () => {
23
+ if (debounceTimer)
24
+ clearTimeout(debounceTimer);
25
+ debounceTimer = setTimeout(async () => {
26
+ const creds = await readCredentials(path);
27
+ onChange(creds);
28
+ }, 100); // 100ms debounce to avoid partial-write reads
29
+ });
30
+ return () => watcher.close();
31
+ }
32
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/auth/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,IAAI,CAAA;AAC1B,OAAO,EAAE,QAAQ,IAAI,aAAa,EAAE,MAAM,aAAa,CAAA;AASvD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY;IAChD,KAAK,UAAU,OAAO;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAsB,CAAA;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,OAAO,EAAE,CAAA;IAC7B,IAAI,KAAK;QAAE,OAAO,KAAK,CAAA;IAEvB,kEAAkE;IAClE,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;IAC1C,OAAO,OAAO,EAAE,CAAA;AAClB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,QAAmD;IAEnD,IAAI,aAAa,GAA0B,IAAI,CAAA;IAE/C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE;QAC/B,IAAI,aAAa;YAAE,YAAY,CAAC,aAAa,CAAC,CAAA;QAC9C,aAAa,GAAG,UAAU,CAAC,KAAK,IAAI,EAAE;YACpC,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,CAAA;YACzC,QAAQ,CAAC,KAAK,CAAC,CAAA;QACjB,CAAC,EAAE,GAAG,CAAC,CAAA,CAAC,8CAA8C;IACxD,CAAC,CAAC,CAAA;IAEF,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;AAC9B,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { UserMode } from '../types.js';
2
+ interface DetectOptions {
3
+ credentialsPath: string;
4
+ }
5
+ export declare function detectMode(opts: DetectOptions): Promise<UserMode | null>;
6
+ export {};
7
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/auth/detect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,UAAU,aAAa;IACrB,eAAe,EAAE,MAAM,CAAA;CACxB;AAWD,wBAAsB,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAO9E"}
@@ -0,0 +1,20 @@
1
+ import { access } from 'fs/promises';
2
+ async function fileExists(path) {
3
+ try {
4
+ await access(path);
5
+ return true;
6
+ }
7
+ catch {
8
+ return false;
9
+ }
10
+ }
11
+ export async function detectMode(opts) {
12
+ const hasApiKey = Boolean(process.env.ANTHROPIC_API_KEY);
13
+ const hasCredentials = await fileExists(opts.credentialsPath);
14
+ if (hasCredentials)
15
+ return 'plan';
16
+ if (hasApiKey)
17
+ return 'api';
18
+ return null;
19
+ }
20
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/auth/detect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAOpC,KAAK,UAAU,UAAU,CAAC,IAAY;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,CAAA;QAClB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAmB;IAClD,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;IACxD,MAAM,cAAc,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;IAE7D,IAAI,cAAc;QAAE,OAAO,MAAM,CAAA;IACjC,IAAI,SAAS;QAAE,OAAO,KAAK,CAAA;IAC3B,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function runConfig(args: string[]): Promise<void>;
2
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAGA,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAe7D"}
@@ -0,0 +1,26 @@
1
+ import { readConfig, writeConfig } from '../storage/config-store.js';
2
+ import { CONFIG_PATH } from '../constants.js';
3
+ export async function runConfig(args) {
4
+ const config = await readConfig(CONFIG_PATH);
5
+ if (!config) {
6
+ console.log('Run meter init first.');
7
+ return;
8
+ }
9
+ if (args.length === 0) {
10
+ console.log(JSON.stringify(config, null, 2));
11
+ return;
12
+ }
13
+ if (args[0] === 'set' && args[1] && args[2]) {
14
+ const field = args[1];
15
+ const val = args[2];
16
+ if (field === 'budget')
17
+ config.budget.per_task_usd = parseFloat(val);
18
+ else if (field === 'threshold') {
19
+ config.budget.threshold_pct = parseInt(val, 10);
20
+ config.plan.window_threshold_pct = parseInt(val, 10);
21
+ }
22
+ await writeConfig(CONFIG_PATH, config);
23
+ console.log(`✓ ${field} set to ${val}`);
24
+ }
25
+ }
26
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAE7C,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAc;IAC5C,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,WAAW,CAAC,CAAA;IAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QAAC,OAAM;IAAC,CAAC;IAC7D,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAAC,OAAM;IAAC,CAAC;IAC/E,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACnB,IAAI,KAAK,KAAK,QAAQ;YAAE,MAAM,CAAC,MAAM,CAAC,YAAY,GAAG,UAAU,CAAC,GAAG,CAAC,CAAA;aAC/D,IAAI,KAAK,KAAK,WAAW,EAAE,CAAC;YAC/B,MAAM,CAAC,MAAM,CAAC,aAAa,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;YAC/C,MAAM,CAAC,IAAI,CAAC,oBAAoB,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;QACtD,CAAC;QACD,MAAM,WAAW,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;QACtC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,WAAW,GAAG,EAAE,CAAC,CAAA;IACzC,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function runHistory(args: string[]): Promise<void>;
2
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/commands/history.ts"],"names":[],"mappings":"AAGA,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAY9D"}
@@ -0,0 +1,19 @@
1
+ import { openDb, getRecentTasks } from '../storage/db.js';
2
+ import { HISTORY_DB_PATH } from '../constants.js';
3
+ export async function runHistory(args) {
4
+ const limit = parseInt(args[0] ?? '30', 10);
5
+ const db = await openDb(HISTORY_DB_PATH);
6
+ const tasks = getRecentTasks(db, limit);
7
+ db.close();
8
+ if (tasks.length === 0) {
9
+ console.log('No tasks recorded yet.');
10
+ return;
11
+ }
12
+ console.log(`\n◆ meter history (last ${limit})\n`);
13
+ for (const t of tasks) {
14
+ const date = new Date(t.created_at).toLocaleString();
15
+ const cost = t.actual_cost != null ? `$${t.actual_cost.toFixed(3)}` : t.window_pct_end != null ? `${t.window_pct_end.toFixed(0)}% window` : '—';
16
+ console.log(` ${date} ${t.complexity.padEnd(8)} ${cost.padStart(10)} ${t.prompt_text.slice(0, 50)}`);
17
+ }
18
+ }
19
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/commands/history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAc;IAC7C,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAA;IAC3C,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAA;IACxC,MAAM,KAAK,GAAG,cAAc,CAAC,EAAE,EAAE,KAAK,CAAC,CAAA;IACvC,EAAE,CAAC,KAAK,EAAE,CAAA;IACV,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QAAC,OAAM;IAAC,CAAC;IACzE,OAAO,CAAC,GAAG,CAAC,6BAA6B,KAAK,KAAK,CAAC,CAAA;IACpD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,cAAc,EAAE,CAAA;QACpD,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAA;QAC/I,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAA;IAC1G,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { UserMode } from '../types.js';
2
+ export interface InitOptions {
3
+ meterDir: string;
4
+ trueBinary?: string;
5
+ mode?: UserMode;
6
+ skipPathInjection?: boolean;
7
+ orgId?: string | null;
8
+ }
9
+ export declare function runInit(opts: InitOptions): Promise<void>;
10
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,58 @@
1
+ import { mkdir } from 'fs/promises';
2
+ import { join } from 'path';
3
+ import { detectShell, getShellConfigPath } from '../shell/detect.js';
4
+ import { resolveTrueBinary } from '../shell/binary-resolver.js';
5
+ import { writeShim } from '../shell/shim-writer.js';
6
+ import { injectPath, isPathAlreadyInjected } from '../shell/path-inject.js';
7
+ import { writeConfig, ensureConfigDefaults } from '../storage/config-store.js';
8
+ import { detectMode } from '../auth/detect.js';
9
+ import { readCredentials } from '../auth/credentials.js';
10
+ import { resolveOrgId } from '../tracking/plan-usage.js';
11
+ import { CLAUDE_CREDENTIALS_PATH } from '../constants.js';
12
+ export async function runInit(opts) {
13
+ const meterDir = opts.meterDir;
14
+ const binDir = join(meterDir, 'bin');
15
+ await mkdir(binDir, { recursive: true });
16
+ await mkdir(join(meterDir, 'cache'), { recursive: true });
17
+ await mkdir(join(meterDir, 'reports'), { recursive: true });
18
+ // Resolve true claude binary
19
+ const trueBinary = opts.trueBinary ?? await resolveTrueBinary('claude', binDir);
20
+ if (!trueBinary) {
21
+ throw new Error('claude not found in PATH. Install Claude Code first.');
22
+ }
23
+ // Detect mode
24
+ const mode = opts.mode ?? await detectMode({ credentialsPath: CLAUDE_CREDENTIALS_PATH });
25
+ if (!mode) {
26
+ throw new Error('No Claude credentials found. Run `claude` first to authenticate.');
27
+ }
28
+ // Resolve org_id for Plan Mode
29
+ let orgId = opts.orgId ?? null;
30
+ if (mode === 'plan' && orgId === null) {
31
+ const creds = await readCredentials(CLAUDE_CREDENTIALS_PATH);
32
+ if (creds)
33
+ orgId = await resolveOrgId(creds);
34
+ }
35
+ // Write shim
36
+ const shimPath = join(binDir, 'claude');
37
+ await writeShim(shimPath, trueBinary);
38
+ // Inject PATH (skip in tests)
39
+ if (!opts.skipPathInjection) {
40
+ const shell = detectShell();
41
+ const configPath = getShellConfigPath(shell);
42
+ const already = await isPathAlreadyInjected(configPath);
43
+ await injectPath(shell, configPath);
44
+ if (!already) {
45
+ console.log(`✓ Added ~/.meter/bin to PATH in ${configPath}`);
46
+ }
47
+ }
48
+ // Write config
49
+ const config = ensureConfigDefaults({
50
+ mode,
51
+ resolved_binaries: { claude: trueBinary },
52
+ ...(orgId ? { org_id: orgId } : {}),
53
+ });
54
+ await writeConfig(join(meterDir, 'config.json'), config);
55
+ console.log(`✓ meter initialised (${mode} mode)`);
56
+ console.log(` Restart your terminal or run: source ~/.zshrc`);
57
+ }
58
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runReport(): Promise<void>;
2
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/commands/report.ts"],"names":[],"mappings":"AAIA,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAsB/C"}
@@ -0,0 +1,37 @@
1
+ import { readConfig } from '../storage/config-store.js';
2
+ import { openDb, getRecentTasks } from '../storage/db.js';
3
+ import { CONFIG_PATH, HISTORY_DB_PATH } from '../constants.js';
4
+ export async function runReport() {
5
+ const config = await readConfig(CONFIG_PATH);
6
+ if (!config) {
7
+ console.log('Run meter init first.');
8
+ return;
9
+ }
10
+ const db = await openDb(HISTORY_DB_PATH);
11
+ const weekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
12
+ const allTasks = getRecentTasks(db, 500).filter(t => t.created_at >= weekAgo);
13
+ db.close();
14
+ if (allTasks.length === 0) {
15
+ console.log('No tasks recorded this week.');
16
+ return;
17
+ }
18
+ const totalCost = allTasks.reduce((s, t) => s + (t.actual_cost ?? 0), 0);
19
+ const heaviest = allTasks.sort((a, b) => (b.actual_cost ?? 0) - (a.actual_cost ?? 0))[0];
20
+ const byComplexity = { low: 0, medium: 0, heavy: 0, critical: 0 };
21
+ for (const t of allTasks)
22
+ byComplexity[t.complexity] = (byComplexity[t.complexity] ?? 0) + 1;
23
+ console.log(`\n◆ meter weekly report\n`);
24
+ console.log(` Mode ${config.mode}`);
25
+ console.log(` Tasks run ${allTasks.length}`);
26
+ if (config.mode === 'api') {
27
+ console.log(` Total spend $${totalCost.toFixed(3)}`);
28
+ console.log(` Avg task cost $${(totalCost / allTasks.length).toFixed(3)}`);
29
+ }
30
+ if (heaviest)
31
+ console.log(` Heaviest task "${heaviest.prompt_text.slice(0, 40)}"`);
32
+ console.log(`\n By complexity:`);
33
+ for (const [k, v] of Object.entries(byComplexity))
34
+ if (v > 0)
35
+ console.log(` ${k.padEnd(10)} ${v} tasks`);
36
+ }
37
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/commands/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runStatus(): Promise<void>;
2
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAGA,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAY/C"}
@@ -0,0 +1,20 @@
1
+ import { readConfig } from '../storage/config-store.js';
2
+ import { CONFIG_PATH } from '../constants.js';
3
+ export async function runStatus() {
4
+ const config = await readConfig(CONFIG_PATH);
5
+ if (!config) {
6
+ console.log('meter not initialised. Run: meter init');
7
+ return;
8
+ }
9
+ console.log(`◆ meter status\n`);
10
+ console.log(` Mode: ${config.mode}`);
11
+ console.log(` Model: ${config.models.claude_chain[0]}`);
12
+ console.log(` Claude: ${config.resolved_binaries.claude}`);
13
+ if (config.mode === 'api') {
14
+ console.log(` Budget: $${config.budget.per_task_usd} per task (notify at ${config.budget.threshold_pct}%)`);
15
+ }
16
+ else {
17
+ console.log(` Window: notify at ${config.plan.window_threshold_pct}%`);
18
+ }
19
+ }
20
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAE7C,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,WAAW,CAAC,CAAA;IAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;QAAC,OAAM;IAAC,CAAC;IAC9E,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;IAC/B,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;IACxC,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAC1D,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,iBAAiB,CAAC,MAAM,EAAE,CAAC,CAAA;IAC5D,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,MAAM,CAAC,YAAY,yBAAyB,MAAM,CAAC,MAAM,CAAC,aAAa,IAAI,CAAC,CAAA;IAChH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,wBAAwB,MAAM,CAAC,IAAI,CAAC,oBAAoB,GAAG,CAAC,CAAA;IAC1E,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function runUninstall(): Promise<void>;
2
+ //# sourceMappingURL=uninstall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../../src/commands/uninstall.ts"],"names":[],"mappings":"AAMA,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAalD"}
@@ -0,0 +1,20 @@
1
+ import { rm } from 'fs/promises';
2
+ import { removePath } from '../shell/path-inject.js';
3
+ import { detectShell, getShellConfigPath } from '../shell/detect.js';
4
+ import { METER_DIR } from '../constants.js';
5
+ import * as readline from 'readline/promises';
6
+ export async function runUninstall() {
7
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
8
+ const answer = await rl.question('Remove all meter data (~/.meter/)? [y/N] ');
9
+ rl.close();
10
+ const shell = detectShell();
11
+ const configPath = getShellConfigPath(shell);
12
+ await removePath(configPath);
13
+ console.log(`✓ Removed PATH entry from ${configPath}`);
14
+ if (answer.toLowerCase() === 'y') {
15
+ await rm(METER_DIR, { recursive: true, force: true });
16
+ console.log('✓ Removed ~/.meter/');
17
+ }
18
+ console.log('✓ Uninstall complete. Run: npm uninstall -g meter-ai');
19
+ }
20
+ //# sourceMappingURL=uninstall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../src/commands/uninstall.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,QAAQ,MAAM,mBAAmB,CAAA;AAE7C,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IACrF,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC,CAAA;IAC7E,EAAE,CAAC,KAAK,EAAE,CAAA;IACV,MAAM,KAAK,GAAG,WAAW,EAAE,CAAA;IAC3B,MAAM,UAAU,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAA;IAC5C,MAAM,UAAU,CAAC,UAAU,CAAC,CAAA;IAC5B,OAAO,CAAC,GAAG,CAAC,6BAA6B,UAAU,EAAE,CAAC,CAAA;IACtD,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,GAAG,EAAE,CAAC;QACjC,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QACrD,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAA;IACpC,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAA;AACrE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function runWrap(args: string[]): Promise<void>;
2
+ //# sourceMappingURL=wrap.d.ts.map
@@ -0,0 +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,CAsL3D"}