@winston.wan/burn-your-money 3.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/package.json +29 -29
- package/src/statusline.js +36 -13
- package/src/token-history.js +44 -18
- package/nul +0 -0
- package/src/commands/burn-your-money-uninstall.md +0 -23
package/README.md
CHANGED
|
@@ -90,6 +90,18 @@ npm install -g "@winston.wan/burn-your-money"
|
|
|
90
90
|
- **历史统计**:从 `~/.claude/stats-cache.json` 读取
|
|
91
91
|
- **本地计算**:零网络请求,纯本地处理
|
|
92
92
|
|
|
93
|
+
### 💰 价格说明
|
|
94
|
+
|
|
95
|
+
费用计算基于 **Claude 模型官方定价**(截至 2025 年):
|
|
96
|
+
|
|
97
|
+
| Token 类型 | 价格 |
|
|
98
|
+
|-----------|------|
|
|
99
|
+
| Input Tokens | $3 / 百万 tokens |
|
|
100
|
+
| Output Tokens | $15 / 百万 tokens |
|
|
101
|
+
| Cache Read Tokens | $0.30 / 百万 tokens (90% 折扣) |
|
|
102
|
+
|
|
103
|
+
> **注意**:如果你使用的是其他兼容模型(如本地部署的模型),实际费用可能不同。本插件仅按 Claude 官方价格估算,不代表实际账单。
|
|
104
|
+
|
|
93
105
|
---
|
|
94
106
|
|
|
95
107
|
## 📋 常见问题
|
package/package.json
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@winston.wan/burn-your-money",
|
|
3
|
-
"version": "3.0.
|
|
4
|
-
"description": "💸 Burn Your Money - 实时显示 Claude Code 的 token 消耗,看着你的钱包燃烧!",
|
|
5
|
-
"main": "src/statusline.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"postinstall": "node install.js",
|
|
8
|
-
"postuninstall": "node uninstall.js"
|
|
9
|
-
},
|
|
10
|
-
"repository": {
|
|
11
|
-
"type": "git",
|
|
12
|
-
"url": "git+https://github.com/winston-wwzhen/burn-your-money.git"
|
|
13
|
-
},
|
|
14
|
-
"keywords": [
|
|
15
|
-
"claude-code",
|
|
16
|
-
"token-monitor",
|
|
17
|
-
"statusline",
|
|
18
|
-
"claude",
|
|
19
|
-
"ai",
|
|
20
|
-
"cost-tracker",
|
|
21
|
-
"burn-money"
|
|
22
|
-
],
|
|
23
|
-
"author": "winston-wwzhen",
|
|
24
|
-
"license": "MIT",
|
|
25
|
-
"bugs": {
|
|
26
|
-
"url": "https://github.com/winston-wwzhen/burn-your-money/issues"
|
|
27
|
-
},
|
|
28
|
-
"homepage": "https://github.com/winston-wwzhen/burn-your-money#readme"
|
|
29
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@winston.wan/burn-your-money",
|
|
3
|
+
"version": "3.0.1",
|
|
4
|
+
"description": "💸 Burn Your Money - 实时显示 Claude Code 的 token 消耗,看着你的钱包燃烧!",
|
|
5
|
+
"main": "src/statusline.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"postinstall": "node install.js",
|
|
8
|
+
"postuninstall": "node uninstall.js"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/winston-wwzhen/burn-your-money.git"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"claude-code",
|
|
16
|
+
"token-monitor",
|
|
17
|
+
"statusline",
|
|
18
|
+
"claude",
|
|
19
|
+
"ai",
|
|
20
|
+
"cost-tracker",
|
|
21
|
+
"burn-money"
|
|
22
|
+
],
|
|
23
|
+
"author": "winston-wwzhen",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/winston-wwzhen/burn-your-money/issues"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/winston-wwzhen/burn-your-money#readme"
|
|
29
|
+
}
|
package/src/statusline.js
CHANGED
|
@@ -166,6 +166,21 @@ function main() {
|
|
|
166
166
|
const now = Math.floor(Date.now() / 1000);
|
|
167
167
|
let historyData = readJsonFile(HISTORY_CACHE, {});
|
|
168
168
|
|
|
169
|
+
// 如果缓存过期(超过 5 分钟),重新获取
|
|
170
|
+
const CACHE_EXPIRY = 300; // 5 分钟
|
|
171
|
+
if (!historyData._cache_time || (now - historyData._cache_time) > CACHE_EXPIRY) {
|
|
172
|
+
try {
|
|
173
|
+
const { execSync } = require('child_process');
|
|
174
|
+
const scriptPath = path.join(__dirname, 'token-history.js');
|
|
175
|
+
const freshData = execSync(`node "${scriptPath}" summary`, { encoding: 'utf8' });
|
|
176
|
+
historyData = JSON.parse(freshData);
|
|
177
|
+
historyData._cache_time = now;
|
|
178
|
+
writeJsonFile(HISTORY_CACHE, historyData);
|
|
179
|
+
} catch (e) {
|
|
180
|
+
// 如果获取失败,使用旧缓存
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
169
184
|
// 如果缓存不存在或无效,使用默认值(但保留已有数据)
|
|
170
185
|
if (!historyData || typeof historyData !== 'object') {
|
|
171
186
|
historyData = {};
|
|
@@ -176,34 +191,42 @@ function main() {
|
|
|
176
191
|
historyData._cache_time = now;
|
|
177
192
|
}
|
|
178
193
|
|
|
179
|
-
//
|
|
194
|
+
// 使用历史数据的今日统计(包含缓存 tokens)
|
|
195
|
+
const historyTodayTokens = historyData.today_tokens || 0;
|
|
196
|
+
const historyTodayCost = parseFloat(historyData.today_cost || 0);
|
|
197
|
+
|
|
198
|
+
// 今日数据持久化(用于当前会话增量)
|
|
180
199
|
const todayDate = new Date().toISOString().split('T')[0];
|
|
181
200
|
ensureDir(TODAY_STATE);
|
|
182
201
|
const todayState = readJsonFile(TODAY_STATE, {
|
|
183
202
|
date: todayDate,
|
|
184
|
-
tokens:
|
|
185
|
-
cost:
|
|
203
|
+
tokens: historyTodayTokens,
|
|
204
|
+
cost: historyTodayCost,
|
|
186
205
|
last_session_tokens: 0,
|
|
187
206
|
last_session_cost: 0
|
|
188
207
|
});
|
|
189
208
|
|
|
190
|
-
//
|
|
209
|
+
// 如果是新的一天,重置为历史数据
|
|
191
210
|
if (todayState.date !== todayDate) {
|
|
192
211
|
todayState.date = todayDate;
|
|
193
|
-
todayState.tokens =
|
|
194
|
-
todayState.cost =
|
|
212
|
+
todayState.tokens = historyTodayTokens;
|
|
213
|
+
todayState.cost = historyTodayCost;
|
|
195
214
|
todayState.last_session_tokens = 0;
|
|
196
215
|
todayState.last_session_cost = 0;
|
|
197
216
|
}
|
|
198
217
|
|
|
199
|
-
//
|
|
218
|
+
// 计算增量(当前会话相对于历史数据的增量)
|
|
200
219
|
let tokenIncrement = currentSessionTokens - (todayState.last_session_tokens || 0);
|
|
201
|
-
if (tokenIncrement < 0)
|
|
220
|
+
if (tokenIncrement < 0) {
|
|
221
|
+
tokenIncrement = currentSessionTokens;
|
|
222
|
+
}
|
|
202
223
|
|
|
203
224
|
let costIncrement = currentCost - (todayState.last_session_cost || 0);
|
|
204
|
-
if (costIncrement < 0
|
|
225
|
+
if (costIncrement < 0 || todayState.last_session_tokens === 0) {
|
|
226
|
+
costIncrement = currentCost;
|
|
227
|
+
}
|
|
205
228
|
|
|
206
|
-
//
|
|
229
|
+
// 新的今日数据 = 历史基础 + 当前增量
|
|
207
230
|
const newTodayTokens = (todayState.tokens || 0) + tokenIncrement;
|
|
208
231
|
const newTodayCost = (todayState.cost || 0) + costIncrement;
|
|
209
232
|
|
|
@@ -215,9 +238,9 @@ function main() {
|
|
|
215
238
|
last_session_cost: currentCost
|
|
216
239
|
});
|
|
217
240
|
|
|
218
|
-
//
|
|
219
|
-
const totalTokens = (historyData.total_tokens_all || 0)
|
|
220
|
-
const totalCost = (historyData.total_cost || 0)
|
|
241
|
+
// 计算总计(使用历史数据 + 当前会话)
|
|
242
|
+
const totalTokens = (historyData.total_tokens_all || 0);
|
|
243
|
+
const totalCost = parseFloat(historyData.total_cost || 0);
|
|
221
244
|
|
|
222
245
|
// 检查是否超过警报阈值
|
|
223
246
|
const isAlert = newTodayCost >= config.alert_daily;
|
package/src/token-history.js
CHANGED
|
@@ -78,18 +78,38 @@ function readStats() {
|
|
|
78
78
|
const totalOutputTokens = Object.values(data.modelUsage || {}).reduce((sum, model) => sum + (model.outputTokens || 0), 0);
|
|
79
79
|
const totalCacheReadTokens = Object.values(data.modelUsage || {}).reduce((sum, model) => sum + (model.cacheReadInputTokens || 0), 0);
|
|
80
80
|
|
|
81
|
-
//
|
|
81
|
+
// 获取今日 tokens
|
|
82
|
+
// 注意:dailyModelTokens 不包含缓存 tokens,且可能更新不及时
|
|
83
|
+
// 如果 lastComputedDate 不是今天,今日数据可能不准确
|
|
84
|
+
const lastComputedDate = data.lastComputedDate || '';
|
|
82
85
|
const dailyTokens = data.dailyModelTokens || [];
|
|
83
|
-
let historySum = 0;
|
|
84
|
-
dailyTokens.forEach(day => {
|
|
85
|
-
if (day.date !== TODAY) {
|
|
86
|
-
const models = day.tokensByModel || {};
|
|
87
|
-
historySum += Object.values(models).reduce((sum, tokens) => sum + (tokens || 0), 0);
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
86
|
|
|
91
|
-
const
|
|
92
|
-
|
|
87
|
+
const totalTokensAll = totalInputTokens + totalOutputTokens + totalCacheReadTokens;
|
|
88
|
+
|
|
89
|
+
// 检查是否有今日的 dailyModelTokens 记录
|
|
90
|
+
const todayEntry = dailyTokens.find(day => day.date === TODAY);
|
|
91
|
+
let todayTokens = 0;
|
|
92
|
+
if (todayEntry) {
|
|
93
|
+
const models = todayEntry.tokensByModel || {};
|
|
94
|
+
todayTokens = Object.values(models).reduce((sum, tokens) => sum + (tokens || 0), 0);
|
|
95
|
+
// 补偿缓存 tokens(按比例估算)
|
|
96
|
+
const cacheRatio = totalCacheReadTokens / (totalTokensAll || 1);
|
|
97
|
+
todayTokens = Math.floor(todayTokens * (1 + cacheRatio));
|
|
98
|
+
} else if (lastComputedDate !== TODAY) {
|
|
99
|
+
// lastComputedDate 不是今天,无法准确计算今日 tokens
|
|
100
|
+
todayTokens = 0;
|
|
101
|
+
} else {
|
|
102
|
+
// 尝试从总量推算(可能不准确)
|
|
103
|
+
let historySum = 0;
|
|
104
|
+
dailyTokens.forEach(day => {
|
|
105
|
+
if (day.date !== TODAY) {
|
|
106
|
+
const models = day.tokensByModel || {};
|
|
107
|
+
historySum += Object.values(models).reduce((sum, tokens) => sum + (tokens || 0), 0);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
todayTokens = totalTokensAll - historySum;
|
|
111
|
+
if (todayTokens < 0) todayTokens = 0;
|
|
112
|
+
}
|
|
93
113
|
|
|
94
114
|
// 本周 tokens(排除今天,用上面的 todayTokens)
|
|
95
115
|
const WEEK_START = getWeekStart();
|
|
@@ -123,18 +143,17 @@ function readStats() {
|
|
|
123
143
|
}
|
|
124
144
|
});
|
|
125
145
|
|
|
126
|
-
//
|
|
146
|
+
// 计算费用(按 3/15/0.3 规则:Input $3/M, Output $15/M, Cache $0.3/M)
|
|
127
147
|
const totalCost = (totalInputTokens / 1000000 * 3) +
|
|
128
148
|
(totalOutputTokens / 1000000 * 15) +
|
|
129
149
|
(totalCacheReadTokens / 1000000 * 0.3);
|
|
130
150
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
const
|
|
136
|
-
const
|
|
137
|
-
const lastMonthCost = lastMonthTokens > 0 ? (lastMonthTokens / (totalInputTokens + totalOutputTokens) * totalCost) : 0;
|
|
151
|
+
// 计算各周期费用(按 token 数量比例分摊)
|
|
152
|
+
const totalTokensForRatio = totalTokensAll || 1;
|
|
153
|
+
const todayCost = todayTokens > 0 ? (todayTokens / totalTokensForRatio * totalCost) : 0;
|
|
154
|
+
const weekCost = weekTokens > 0 ? (weekTokens / totalTokensForRatio * totalCost) : 0;
|
|
155
|
+
const monthCost = monthTokens > 0 ? (monthTokens / totalTokensForRatio * totalCost) : 0;
|
|
156
|
+
const lastMonthCost = lastMonthTokens > 0 ? (lastMonthTokens / totalTokensForRatio * totalCost) : 0;
|
|
138
157
|
|
|
139
158
|
// 获取每日数据(用于趋势图)
|
|
140
159
|
const dailyData = dailyTokens.slice(-7).map(day => ({
|
|
@@ -257,6 +276,13 @@ function main() {
|
|
|
257
276
|
console.log('');
|
|
258
277
|
|
|
259
278
|
// 统计数据
|
|
279
|
+
console.log('💰 Token 价格说明');
|
|
280
|
+
console.log('─'.repeat(40));
|
|
281
|
+
console.log(' Input: $3.00 / 百万 tokens');
|
|
282
|
+
console.log(' Output: $15.00 / 百万 tokens');
|
|
283
|
+
console.log(' Cache: $0.30 / 百万 tokens (90% 折扣)');
|
|
284
|
+
console.log('');
|
|
285
|
+
|
|
260
286
|
console.log('📆 本周消费');
|
|
261
287
|
console.log('─'.repeat(40));
|
|
262
288
|
console.log(` Tokens: ${formatNumber(stats.week_tokens)}`);
|
package/nul
DELETED
|
File without changes
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: burn-your-money-uninstall
|
|
3
|
-
description: 🗑️ 完全卸载 Burn Your Money 插件
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# 🗑️ Burn Your Money - 卸载
|
|
7
|
-
|
|
8
|
-
我将帮你完全卸载 Burn Your Money 插件,包括:
|
|
9
|
-
- 删除所有插件文件
|
|
10
|
-
- 移除 settings.json 中的配置
|
|
11
|
-
|
|
12
|
-
请执行以下命令:
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
node ~/.claude/scripts/token-history.js uninstall
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
卸载完成后请重启 Claude Code。
|
|
19
|
-
|
|
20
|
-
如果你是通过 npm 全局安装的,也可以运行:
|
|
21
|
-
```bash
|
|
22
|
-
npm uninstall -g @winston.wan/burn-your-money
|
|
23
|
-
```
|