claude-accountant 1.0.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 (83) hide show
  1. package/.claude-plugin/plugin.json +14 -0
  2. package/.mcp.json +9 -0
  3. package/README.md +148 -0
  4. package/dist/admin-api.d.ts +3 -0
  5. package/dist/admin-api.d.ts.map +1 -0
  6. package/dist/admin-api.js +39 -0
  7. package/dist/admin-api.js.map +1 -0
  8. package/dist/budget.d.ts +4 -0
  9. package/dist/budget.d.ts.map +1 -0
  10. package/dist/budget.js +33 -0
  11. package/dist/budget.js.map +1 -0
  12. package/dist/config.d.ts +5 -0
  13. package/dist/config.d.ts.map +1 -0
  14. package/dist/config.js +42 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/db.d.ts +10 -0
  17. package/dist/db.d.ts.map +1 -0
  18. package/dist/db.js +111 -0
  19. package/dist/db.js.map +1 -0
  20. package/dist/estimator.d.ts +4 -0
  21. package/dist/estimator.d.ts.map +1 -0
  22. package/dist/estimator.js +90 -0
  23. package/dist/estimator.js.map +1 -0
  24. package/dist/index.d.ts +3 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +13 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/offload.d.ts +3 -0
  29. package/dist/offload.d.ts.map +1 -0
  30. package/dist/offload.js +68 -0
  31. package/dist/offload.js.map +1 -0
  32. package/dist/pricing.d.ts +5 -0
  33. package/dist/pricing.d.ts.map +1 -0
  34. package/dist/pricing.js +49 -0
  35. package/dist/pricing.js.map +1 -0
  36. package/dist/resources/budget-status.d.ts +7 -0
  37. package/dist/resources/budget-status.d.ts.map +1 -0
  38. package/dist/resources/budget-status.js +10 -0
  39. package/dist/resources/budget-status.js.map +1 -0
  40. package/dist/resources/pricing-table.d.ts +6 -0
  41. package/dist/resources/pricing-table.d.ts.map +1 -0
  42. package/dist/resources/pricing-table.js +9 -0
  43. package/dist/resources/pricing-table.js.map +1 -0
  44. package/dist/resources/usage-summary.d.ts +7 -0
  45. package/dist/resources/usage-summary.d.ts.map +1 -0
  46. package/dist/resources/usage-summary.js +10 -0
  47. package/dist/resources/usage-summary.js.map +1 -0
  48. package/dist/server.d.ts +3 -0
  49. package/dist/server.d.ts.map +1 -0
  50. package/dist/server.js +234 -0
  51. package/dist/server.js.map +1 -0
  52. package/dist/tools/check-budget.d.ts +11 -0
  53. package/dist/tools/check-budget.d.ts.map +1 -0
  54. package/dist/tools/check-budget.js +23 -0
  55. package/dist/tools/check-budget.js.map +1 -0
  56. package/dist/tools/configure-budget.d.ts +27 -0
  57. package/dist/tools/configure-budget.d.ts.map +1 -0
  58. package/dist/tools/configure-budget.js +54 -0
  59. package/dist/tools/configure-budget.js.map +1 -0
  60. package/dist/tools/estimate-task-cost.d.ts +30 -0
  61. package/dist/tools/estimate-task-cost.d.ts.map +1 -0
  62. package/dist/tools/estimate-task-cost.js +37 -0
  63. package/dist/tools/estimate-task-cost.js.map +1 -0
  64. package/dist/tools/get-recommendations.d.ts +27 -0
  65. package/dist/tools/get-recommendations.d.ts.map +1 -0
  66. package/dist/tools/get-recommendations.js +47 -0
  67. package/dist/tools/get-recommendations.js.map +1 -0
  68. package/dist/tools/get-usage-history.d.ts +34 -0
  69. package/dist/tools/get-usage-history.d.ts.map +1 -0
  70. package/dist/tools/get-usage-history.js +42 -0
  71. package/dist/tools/get-usage-history.js.map +1 -0
  72. package/dist/tools/log-usage.d.ts +42 -0
  73. package/dist/tools/log-usage.d.ts.map +1 -0
  74. package/dist/tools/log-usage.js +42 -0
  75. package/dist/tools/log-usage.js.map +1 -0
  76. package/dist/types.d.ts +73 -0
  77. package/dist/types.d.ts.map +1 -0
  78. package/dist/types.js +2 -0
  79. package/dist/types.js.map +1 -0
  80. package/hooks/hooks.json +10 -0
  81. package/package.json +51 -0
  82. package/scripts/post-tool-hook.sh +14 -0
  83. package/skills/usage-awareness/SKILL.md +29 -0
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "claude-accountant",
3
+ "version": "1.0.0",
4
+ "display_name": "Usage Tracker",
5
+ "description": "Tracks API usage, estimates costs, and recommends budget-aware actions for Claude Code sessions",
6
+ "author": "usage-tracker-plugin",
7
+ "mcp": {
8
+ "type": "stdio",
9
+ "command": "node",
10
+ "args": ["dist/index.js"]
11
+ },
12
+ "skills": ["skills/usage-awareness/SKILL.md"],
13
+ "hooks": ["hooks/hooks.json"]
14
+ }
package/.mcp.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "mcpServers": {
3
+ "usage-tracker": {
4
+ "type": "stdio",
5
+ "command": "node",
6
+ "args": ["dist/index.js"]
7
+ }
8
+ }
9
+ }
package/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # claude-accountant
2
+
3
+ A [Claude Code](https://docs.anthropic.com/en/docs/claude-code) MCP plugin that makes Claude budget-aware. It tracks API usage, estimates costs, and recommends actions based on your remaining daily budget.
4
+
5
+ ## What it does
6
+
7
+ - **Checks your budget** at the start of every session so Claude knows how much is left
8
+ - **Estimates costs** before expensive operations (large refactors, multi-file edits)
9
+ - **Tracks spending** in a local SQLite database -- no external API needed
10
+ - **Recommends offloading** when budget runs low (cheaper model, defer, reduce scope, Batch API)
11
+ - **Shows usage history** over the past week for planning
12
+
13
+ ## Install
14
+
15
+ ### Option 1: npx (recommended)
16
+
17
+ Add to your `~/.claude.json`:
18
+
19
+ ```json
20
+ {
21
+ "mcpServers": {
22
+ "usage-tracker": {
23
+ "type": "stdio",
24
+ "command": "npx",
25
+ "args": ["-y", "claude-accountant"]
26
+ }
27
+ }
28
+ }
29
+ ```
30
+
31
+ ### Option 2: Global install
32
+
33
+ ```bash
34
+ npm install -g claude-accountant
35
+ ```
36
+
37
+ Then add to `~/.claude.json`:
38
+
39
+ ```json
40
+ {
41
+ "mcpServers": {
42
+ "usage-tracker": {
43
+ "type": "stdio",
44
+ "command": "claude-accountant"
45
+ }
46
+ }
47
+ }
48
+ ```
49
+
50
+ ### Option 3: From source
51
+
52
+ ```bash
53
+ git clone <repo-url>
54
+ cd usage_plugin
55
+ npm install && npm run build
56
+ ```
57
+
58
+ Add to `~/.claude.json`:
59
+
60
+ ```json
61
+ {
62
+ "mcpServers": {
63
+ "usage-tracker": {
64
+ "type": "stdio",
65
+ "command": "node",
66
+ "args": ["/absolute/path/to/usage_plugin/dist/index.js"]
67
+ }
68
+ }
69
+ }
70
+ ```
71
+
72
+ ## Tools
73
+
74
+ Once installed, Claude Code gains these tools:
75
+
76
+ | Tool | Description |
77
+ |------|-------------|
78
+ | `check_budget` | Current daily spending vs limits, returns status (ok/warning/critical/exceeded) |
79
+ | `estimate_task_cost` | Predict token cost of an upcoming task before starting it |
80
+ | `log_usage` | Record token usage after completing work |
81
+ | `get_usage_history` | Daily spending breakdown over the past N days |
82
+ | `get_offload_recommendations` | Cost-saving suggestions based on budget status |
83
+ | `configure_budget` | Update budget limits and thresholds at runtime |
84
+
85
+ ## Configuration
86
+
87
+ Config is created automatically at `~/.config/usage-plugin/config.json` on first run:
88
+
89
+ ```json
90
+ {
91
+ "budget": {
92
+ "daily_limit_usd": 10.00,
93
+ "monthly_limit_usd": null,
94
+ "warning_threshold_pct": 80,
95
+ "critical_threshold_pct": 95
96
+ },
97
+ "pricing_tier": "standard",
98
+ "default_model": "claude-sonnet-4-5-20250514",
99
+ "data_dir": "~/.config/usage-plugin/data"
100
+ }
101
+ ```
102
+
103
+ You can edit this file directly or use the `configure_budget` tool during a session.
104
+
105
+ ### Optional: Anthropic Admin API
106
+
107
+ For exact usage data instead of estimates, add your Admin API credentials:
108
+
109
+ ```json
110
+ {
111
+ "admin_api": {
112
+ "api_key": "sk-ant-admin-...",
113
+ "organization_id": "org-...",
114
+ "sync_interval_minutes": 5
115
+ }
116
+ }
117
+ ```
118
+
119
+ ## How it works
120
+
121
+ The plugin uses an estimation-based approach since MCP tools can't introspect Claude's actual token usage mid-conversation:
122
+
123
+ 1. **Complexity tiers** (trivial/simple/moderate/complex/massive) map to token ranges
124
+ 2. **Per-file multipliers** account for reads (~1500 input tokens) and edits (~3000 output tokens)
125
+ 3. **Extended thinking** multiplies output estimates by 3x
126
+ 4. All data is stored locally in SQLite with WAL mode for fast concurrent access
127
+
128
+ When the Admin API is configured, real usage data supersedes local estimates.
129
+
130
+ ## Budget thresholds
131
+
132
+ | Status | % Used | Behavior |
133
+ |--------|--------|----------|
134
+ | OK | <80% | Work normally |
135
+ | Warning | 80-95% | Prioritize essential tasks, concise responses |
136
+ | Critical | 95-100% | Urgent requests only, recommend cheaper model |
137
+ | Exceeded | >100% | Inform user, suggest waiting or increasing limit |
138
+
139
+ ## Skills and hooks
140
+
141
+ The plugin ships with:
142
+
143
+ - **`skills/usage-awareness/SKILL.md`** -- persistent instructions that tell Claude when to check budgets and log usage
144
+ - **`hooks/hooks.json`** -- a PostToolUse hook that automatically tracks tool invocations
145
+
146
+ ## License
147
+
148
+ MIT
@@ -0,0 +1,3 @@
1
+ import type { Config } from "./types.js";
2
+ export declare function syncFromAdminApi(config: Config): Promise<number>;
3
+ //# sourceMappingURL=admin-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-api.d.ts","sourceRoot":"","sources":["../src/admin-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAgBzC,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiDtE"}
@@ -0,0 +1,39 @@
1
+ import { logUsage } from "./db.js";
2
+ import { calculateCost } from "./pricing.js";
3
+ export async function syncFromAdminApi(config) {
4
+ if (!config.admin_api) {
5
+ throw new Error("Admin API not configured");
6
+ }
7
+ const { api_key, organization_id } = config.admin_api;
8
+ const today = new Date().toISOString().split("T")[0];
9
+ const url = `https://api.anthropic.com/v1/organizations/${organization_id}/usage?start_date=${today}&end_date=${today}`;
10
+ const response = await fetch(url, {
11
+ headers: {
12
+ "x-api-key": api_key,
13
+ "anthropic-version": "2023-06-01",
14
+ },
15
+ });
16
+ if (!response.ok) {
17
+ throw new Error(`Admin API error: ${response.status} ${response.statusText}`);
18
+ }
19
+ const data = (await response.json());
20
+ let synced = 0;
21
+ for (const record of data.data) {
22
+ const cost = calculateCost(record.model, record.input_tokens, record.output_tokens, record.cache_read_input_tokens, record.cache_creation_input_tokens);
23
+ logUsage(config, {
24
+ timestamp: new Date().toISOString(),
25
+ session_id: "admin-api-sync",
26
+ model: record.model,
27
+ input_tokens: record.input_tokens,
28
+ output_tokens: record.output_tokens,
29
+ cache_read_tokens: record.cache_read_input_tokens,
30
+ cache_write_tokens: record.cache_creation_input_tokens,
31
+ estimated_cost_usd: cost,
32
+ task_description: "Synced from Admin API",
33
+ source: "admin_api",
34
+ });
35
+ synced++;
36
+ }
37
+ return synced;
38
+ }
39
+ //# sourceMappingURL=admin-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-api.js","sourceRoot":"","sources":["../src/admin-api.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAc7C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAc;IACnD,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC;IACtD,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAErD,MAAM,GAAG,GAAG,8CAA8C,eAAe,qBAAqB,KAAK,aAAa,KAAK,EAAE,CAAC;IAExH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,OAAO,EAAE;YACP,WAAW,EAAE,OAAO;YACpB,mBAAmB,EAAE,YAAY;SAClC;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,oBAAoB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAqB,CAAC;IACzD,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,aAAa,CACxB,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,YAAY,EACnB,MAAM,CAAC,aAAa,EACpB,MAAM,CAAC,uBAAuB,EAC9B,MAAM,CAAC,2BAA2B,CACnC,CAAC;QAEF,QAAQ,CAAC,MAAM,EAAE;YACf,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,UAAU,EAAE,gBAAgB;YAC5B,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,iBAAiB,EAAE,MAAM,CAAC,uBAAuB;YACjD,kBAAkB,EAAE,MAAM,CAAC,2BAA2B;YACtD,kBAAkB,EAAE,IAAI;YACxB,gBAAgB,EAAE,uBAAuB;YACzC,MAAM,EAAE,WAAW;SACpB,CAAC,CAAC;QACH,MAAM,EAAE,CAAC;IACX,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { BudgetSnapshot, BudgetStatus, Config } from "./types.js";
2
+ export declare function getBudgetStatus(config: Config): BudgetSnapshot;
3
+ export declare function computeStatus(pctUsed: number, warningPct: number, criticalPct: number): BudgetStatus;
4
+ //# sourceMappingURL=budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAGvE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CA6B9D;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,YAAY,CAKd"}
package/dist/budget.js ADDED
@@ -0,0 +1,33 @@
1
+ import { getTodayUsage, getMonthUsage } from "./db.js";
2
+ export function getBudgetStatus(config) {
3
+ const today = getTodayUsage(config);
4
+ const dailyLimit = config.budget.daily_limit_usd;
5
+ const spentToday = today.total_cost_usd;
6
+ const remaining = Math.max(0, dailyLimit - spentToday);
7
+ const pctUsed = dailyLimit > 0 ? (spentToday / dailyLimit) * 100 : 0;
8
+ const status = computeStatus(pctUsed, config.budget.warning_threshold_pct, config.budget.critical_threshold_pct);
9
+ const monthlyLimit = config.budget.monthly_limit_usd;
10
+ const spentThisMonth = monthlyLimit !== null ? getMonthUsage(config) : null;
11
+ return {
12
+ status,
13
+ daily_limit_usd: dailyLimit,
14
+ spent_today_usd: Math.round(spentToday * 10000) / 10000,
15
+ remaining_usd: Math.round(remaining * 10000) / 10000,
16
+ pct_used: Math.round(pctUsed * 100) / 100,
17
+ request_count_today: today.request_count,
18
+ monthly_limit_usd: monthlyLimit,
19
+ spent_this_month_usd: spentThisMonth !== null
20
+ ? Math.round(spentThisMonth * 10000) / 10000
21
+ : null,
22
+ };
23
+ }
24
+ export function computeStatus(pctUsed, warningPct, criticalPct) {
25
+ if (pctUsed >= 100)
26
+ return "exceeded";
27
+ if (pctUsed >= criticalPct)
28
+ return "critical";
29
+ if (pctUsed >= warningPct)
30
+ return "warning";
31
+ return "ok";
32
+ }
33
+ //# sourceMappingURL=budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.js","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAEvD,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC;IACjD,MAAM,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC;IACxC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAErE,MAAM,MAAM,GAAG,aAAa,CAC1B,OAAO,EACP,MAAM,CAAC,MAAM,CAAC,qBAAqB,EACnC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CACrC,CAAC;IAEF,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC;IACrD,MAAM,cAAc,GAAG,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE5E,OAAO;QACL,MAAM;QACN,eAAe,EAAE,UAAU;QAC3B,eAAe,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,GAAG,KAAK;QACvD,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,GAAG,KAAK;QACpD,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,GAAG,GAAG;QACzC,mBAAmB,EAAE,KAAK,CAAC,aAAa;QACxC,iBAAiB,EAAE,YAAY;QAC/B,oBAAoB,EAClB,cAAc,KAAK,IAAI;YACrB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC,GAAG,KAAK;YAC5C,CAAC,CAAC,IAAI;KACX,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,OAAe,EACf,UAAkB,EAClB,WAAmB;IAEnB,IAAI,OAAO,IAAI,GAAG;QAAE,OAAO,UAAU,CAAC;IACtC,IAAI,OAAO,IAAI,WAAW;QAAE,OAAO,UAAU,CAAC;IAC9C,IAAI,OAAO,IAAI,UAAU;QAAE,OAAO,SAAS,CAAC;IAC5C,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { Config } from "./types.js";
2
+ export declare function loadConfig(): Config;
3
+ export declare function saveConfig(config: Config): void;
4
+ export declare function resolveDataDir(config: Config): string;
5
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAkBzC,wBAAgB,UAAU,IAAI,MAAM,CAenC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAI/C;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAIrD"}
package/dist/config.js ADDED
@@ -0,0 +1,42 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import os from "node:os";
4
+ const DEFAULT_CONFIG = {
5
+ budget: {
6
+ daily_limit_usd: 10.0,
7
+ monthly_limit_usd: null,
8
+ warning_threshold_pct: 80,
9
+ critical_threshold_pct: 95,
10
+ },
11
+ pricing_tier: "standard",
12
+ default_model: "claude-sonnet-4-5-20250514",
13
+ data_dir: path.join(os.homedir(), ".config", "usage-plugin", "data"),
14
+ };
15
+ function getConfigPath() {
16
+ return path.join(os.homedir(), ".config", "usage-plugin", "config.json");
17
+ }
18
+ export function loadConfig() {
19
+ const configPath = getConfigPath();
20
+ if (!fs.existsSync(configPath)) {
21
+ fs.mkdirSync(path.dirname(configPath), { recursive: true });
22
+ fs.writeFileSync(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2));
23
+ return { ...DEFAULT_CONFIG };
24
+ }
25
+ const raw = JSON.parse(fs.readFileSync(configPath, "utf-8"));
26
+ return {
27
+ ...DEFAULT_CONFIG,
28
+ ...raw,
29
+ budget: { ...DEFAULT_CONFIG.budget, ...raw.budget },
30
+ };
31
+ }
32
+ export function saveConfig(config) {
33
+ const configPath = getConfigPath();
34
+ fs.mkdirSync(path.dirname(configPath), { recursive: true });
35
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
36
+ }
37
+ export function resolveDataDir(config) {
38
+ const dir = config.data_dir.replace(/^~/, os.homedir());
39
+ fs.mkdirSync(dir, { recursive: true });
40
+ return dir;
41
+ }
42
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAGzB,MAAM,cAAc,GAAW;IAC7B,MAAM,EAAE;QACN,eAAe,EAAE,IAAI;QACrB,iBAAiB,EAAE,IAAI;QACvB,qBAAqB,EAAE,EAAE;QACzB,sBAAsB,EAAE,EAAE;KAC3B;IACD,YAAY,EAAE,UAAU;IACxB,aAAa,EAAE,4BAA4B;IAC3C,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,CAAC;CACrE,CAAC;AAEF,SAAS,aAAa;IACpB,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IAEnC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACtE,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7D,OAAO;QACL,GAAG,cAAc;QACjB,GAAG,GAAG;QACN,MAAM,EAAE,EAAE,GAAG,cAAc,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE;KACpD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;IACxD,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,OAAO,GAAG,CAAC;AACb,CAAC"}
package/dist/db.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ import Database from "better-sqlite3";
2
+ import type { UsageLogEntry, DailySummary } from "./types.js";
3
+ import type { Config } from "./types.js";
4
+ export declare function getDb(config: Config): Database.Database;
5
+ export declare function logUsage(config: Config, entry: UsageLogEntry): void;
6
+ export declare function getTodayUsage(config: Config): DailySummary;
7
+ export declare function getUsageHistory(config: Config, days: number): DailySummary[];
8
+ export declare function getMonthUsage(config: Config): number;
9
+ export declare function closeDb(): void;
10
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAIzC,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CASvD;AAiCD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CAsBnE;AA6BD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAkB1D;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,YAAY,EAAE,CAWhB;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAYpD;AAED,wBAAgB,OAAO,IAAI,IAAI,CAK9B"}
package/dist/db.js ADDED
@@ -0,0 +1,111 @@
1
+ import Database from "better-sqlite3";
2
+ import path from "node:path";
3
+ import { resolveDataDir } from "./config.js";
4
+ let db = null;
5
+ export function getDb(config) {
6
+ if (db)
7
+ return db;
8
+ const dataDir = resolveDataDir(config);
9
+ const dbPath = path.join(dataDir, "usage.db");
10
+ db = new Database(dbPath);
11
+ db.pragma("journal_mode = WAL");
12
+ initSchema(db);
13
+ return db;
14
+ }
15
+ function initSchema(db) {
16
+ db.exec(`
17
+ CREATE TABLE IF NOT EXISTS usage_log (
18
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
19
+ timestamp TEXT NOT NULL,
20
+ session_id TEXT NOT NULL,
21
+ model TEXT NOT NULL,
22
+ input_tokens INTEGER NOT NULL DEFAULT 0,
23
+ output_tokens INTEGER NOT NULL DEFAULT 0,
24
+ cache_read_tokens INTEGER NOT NULL DEFAULT 0,
25
+ cache_write_tokens INTEGER NOT NULL DEFAULT 0,
26
+ estimated_cost_usd REAL NOT NULL DEFAULT 0,
27
+ task_description TEXT NOT NULL DEFAULT '',
28
+ source TEXT NOT NULL DEFAULT 'estimate'
29
+ );
30
+
31
+ CREATE TABLE IF NOT EXISTS daily_summary (
32
+ date TEXT PRIMARY KEY,
33
+ total_input_tokens INTEGER NOT NULL DEFAULT 0,
34
+ total_output_tokens INTEGER NOT NULL DEFAULT 0,
35
+ total_cache_read_tokens INTEGER NOT NULL DEFAULT 0,
36
+ total_cache_write_tokens INTEGER NOT NULL DEFAULT 0,
37
+ total_cost_usd REAL NOT NULL DEFAULT 0,
38
+ request_count INTEGER NOT NULL DEFAULT 0
39
+ );
40
+
41
+ CREATE INDEX IF NOT EXISTS idx_usage_log_timestamp ON usage_log(timestamp);
42
+ CREATE INDEX IF NOT EXISTS idx_usage_log_session ON usage_log(session_id);
43
+ `);
44
+ }
45
+ export function logUsage(config, entry) {
46
+ const d = getDb(config);
47
+ const stmt = d.prepare(`
48
+ INSERT INTO usage_log (timestamp, session_id, model, input_tokens, output_tokens,
49
+ cache_read_tokens, cache_write_tokens, estimated_cost_usd, task_description, source)
50
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
51
+ `);
52
+ stmt.run(entry.timestamp, entry.session_id, entry.model, entry.input_tokens, entry.output_tokens, entry.cache_read_tokens, entry.cache_write_tokens, entry.estimated_cost_usd, entry.task_description, entry.source);
53
+ updateDailySummary(config, entry);
54
+ }
55
+ function updateDailySummary(config, entry) {
56
+ const d = getDb(config);
57
+ const date = entry.timestamp.split("T")[0];
58
+ d.prepare(`
59
+ INSERT INTO daily_summary (date, total_input_tokens, total_output_tokens,
60
+ total_cache_read_tokens, total_cache_write_tokens, total_cost_usd, request_count)
61
+ VALUES (?, ?, ?, ?, ?, ?, 1)
62
+ ON CONFLICT(date) DO UPDATE SET
63
+ total_input_tokens = total_input_tokens + excluded.total_input_tokens,
64
+ total_output_tokens = total_output_tokens + excluded.total_output_tokens,
65
+ total_cache_read_tokens = total_cache_read_tokens + excluded.total_cache_read_tokens,
66
+ total_cache_write_tokens = total_cache_write_tokens + excluded.total_cache_write_tokens,
67
+ total_cost_usd = total_cost_usd + excluded.total_cost_usd,
68
+ request_count = request_count + 1
69
+ `).run(date, entry.input_tokens, entry.output_tokens, entry.cache_read_tokens, entry.cache_write_tokens, entry.estimated_cost_usd);
70
+ }
71
+ export function getTodayUsage(config) {
72
+ const d = getDb(config);
73
+ const today = new Date().toISOString().split("T")[0];
74
+ const row = d
75
+ .prepare("SELECT * FROM daily_summary WHERE date = ?")
76
+ .get(today);
77
+ return (row ?? {
78
+ date: today,
79
+ total_input_tokens: 0,
80
+ total_output_tokens: 0,
81
+ total_cache_read_tokens: 0,
82
+ total_cache_write_tokens: 0,
83
+ total_cost_usd: 0,
84
+ request_count: 0,
85
+ });
86
+ }
87
+ export function getUsageHistory(config, days) {
88
+ const d = getDb(config);
89
+ const since = new Date();
90
+ since.setDate(since.getDate() - days);
91
+ const sinceStr = since.toISOString().split("T")[0];
92
+ return d
93
+ .prepare("SELECT * FROM daily_summary WHERE date >= ? ORDER BY date DESC")
94
+ .all(sinceStr);
95
+ }
96
+ export function getMonthUsage(config) {
97
+ const d = getDb(config);
98
+ const now = new Date();
99
+ const monthStart = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-01`;
100
+ const row = d
101
+ .prepare("SELECT COALESCE(SUM(total_cost_usd), 0) as total FROM daily_summary WHERE date >= ?")
102
+ .get(monthStart);
103
+ return row.total;
104
+ }
105
+ export function closeDb() {
106
+ if (db) {
107
+ db.close();
108
+ db = null;
109
+ }
110
+ }
111
+ //# sourceMappingURL=db.js.map
package/dist/db.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ComplexityTier, CostEstimate } from "./types.js";
2
+ export declare function estimateTaskCost(model: string, complexity: ComplexityTier, fileCount: number, dailyLimitUsd: number, useExtendedThinking?: boolean): CostEstimate;
3
+ export declare function inferComplexity(description: string): ComplexityTier;
4
+ //# sourceMappingURL=estimator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"estimator.d.ts","sourceRoot":"","sources":["../src/estimator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA2C/D,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,cAAc,EAC1B,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,mBAAmB,GAAE,OAAe,GACnC,YAAY,CAkCd;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,CAqCnE"}
@@ -0,0 +1,90 @@
1
+ import { calculateCost } from "./pricing.js";
2
+ const COMPLEXITY_PROFILES = {
3
+ trivial: {
4
+ base_input_tokens: 500,
5
+ base_output_tokens: 200,
6
+ per_file_input: 0,
7
+ per_file_output: 0,
8
+ },
9
+ simple: {
10
+ base_input_tokens: 2_000,
11
+ base_output_tokens: 1_000,
12
+ per_file_input: 1_500,
13
+ per_file_output: 500,
14
+ },
15
+ moderate: {
16
+ base_input_tokens: 5_000,
17
+ base_output_tokens: 3_000,
18
+ per_file_input: 1_500,
19
+ per_file_output: 1_500,
20
+ },
21
+ complex: {
22
+ base_input_tokens: 15_000,
23
+ base_output_tokens: 8_000,
24
+ per_file_input: 2_000,
25
+ per_file_output: 3_000,
26
+ },
27
+ massive: {
28
+ base_input_tokens: 50_000,
29
+ base_output_tokens: 20_000,
30
+ per_file_input: 2_500,
31
+ per_file_output: 4_000,
32
+ },
33
+ };
34
+ export function estimateTaskCost(model, complexity, fileCount, dailyLimitUsd, useExtendedThinking = false) {
35
+ const profile = COMPLEXITY_PROFILES[complexity];
36
+ const inputTokens = profile.base_input_tokens + profile.per_file_input * fileCount;
37
+ let outputTokens = profile.base_output_tokens + profile.per_file_output * fileCount;
38
+ if (useExtendedThinking) {
39
+ outputTokens *= 3;
40
+ }
41
+ const cost = calculateCost(model, inputTokens, outputTokens);
42
+ const pctOfBudget = dailyLimitUsd > 0 ? (cost / dailyLimitUsd) * 100 : 0;
43
+ const parts = [
44
+ `Complexity: ${complexity}`,
45
+ `Files: ${fileCount}`,
46
+ `Est. input: ${inputTokens.toLocaleString()} tokens`,
47
+ `Est. output: ${outputTokens.toLocaleString()} tokens`,
48
+ ];
49
+ if (useExtendedThinking) {
50
+ parts.push("Extended thinking: 3x output multiplier");
51
+ }
52
+ return {
53
+ estimated_input_tokens: inputTokens,
54
+ estimated_output_tokens: outputTokens,
55
+ estimated_cost_usd: cost,
56
+ pct_of_daily_budget: Math.round(pctOfBudget * 100) / 100,
57
+ complexity,
58
+ breakdown: parts.join("; "),
59
+ };
60
+ }
61
+ export function inferComplexity(description) {
62
+ const lower = description.toLowerCase();
63
+ const hasWord = (word) => new RegExp(`\\b${word}\\b`).test(lower);
64
+ if (hasWord("refactor") ||
65
+ hasWord("rewrite") ||
66
+ hasWord("migrate") ||
67
+ hasWord("overhaul")) {
68
+ return "massive";
69
+ }
70
+ if (hasWord("implement") ||
71
+ hasWord("feature") ||
72
+ hasWord("complex") ||
73
+ lower.includes("multi-file")) {
74
+ return "complex";
75
+ }
76
+ if (hasWord("update") ||
77
+ hasWord("modify") ||
78
+ hasWord("add") ||
79
+ hasWord("change")) {
80
+ return "moderate";
81
+ }
82
+ if (hasWord("fix") ||
83
+ hasWord("bug") ||
84
+ hasWord("tweak") ||
85
+ hasWord("small")) {
86
+ return "simple";
87
+ }
88
+ return "trivial";
89
+ }
90
+ //# sourceMappingURL=estimator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"estimator.js","sourceRoot":"","sources":["../src/estimator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { createServer } from "./server.js";
4
+ async function main() {
5
+ const server = createServer();
6
+ const transport = new StdioServerTransport();
7
+ await server.connect(transport);
8
+ }
9
+ main().catch((error) => {
10
+ console.error("Fatal error:", error);
11
+ process.exit(1);
12
+ });
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { BudgetSnapshot, ComplexityTier, Recommendation } from "./types.js";
2
+ export declare function getRecommendations(budget: BudgetSnapshot, currentModel: string, taskComplexity?: ComplexityTier, isUrgent?: boolean): Recommendation[];
3
+ //# sourceMappingURL=offload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"offload.d.ts","sourceRoot":"","sources":["../src/offload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,cAAc,EACtB,YAAY,EAAE,MAAM,EACpB,cAAc,CAAC,EAAE,cAAc,EAC/B,QAAQ,GAAE,OAAc,GACvB,cAAc,EAAE,CAsFlB"}