@winston.wan/burn-your-money 2.1.1 → 2.2.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.
package/install.sh DELETED
@@ -1,271 +0,0 @@
1
- #!/bin/bash
2
- # Burn Your Money - 一键安装脚本
3
- # 用法: curl -fsSL https://raw.githubusercontent.com/winston-wwzhen/burn-your-money/main/install.sh | bash
4
-
5
- set -e
6
-
7
- # 颜色定义
8
- RED='\033[0;31m'
9
- GREEN='\033[0;32m'
10
- YELLOW='\033[1;33m'
11
- BLUE='\033[0;34m'
12
- PURPLE='\033[0;35m'
13
- CYAN='\033[0;36m'
14
- NC='\033[0m' # No Color
15
-
16
- # 打印带颜色的消息
17
- print_header() {
18
- echo ""
19
- echo -e "${PURPLE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
20
- echo -e "${PURPLE} $1${NC}"
21
- echo -e "${PURPLE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
22
- echo ""
23
- }
24
-
25
- print_step() {
26
- echo -e "${CYAN}▶ $1${NC}"
27
- }
28
-
29
- print_success() {
30
- echo -e "${GREEN}✓ $1${NC}"
31
- }
32
-
33
- print_warning() {
34
- echo -e "${YELLOW}⚠ $1${NC}"
35
- }
36
-
37
- print_error() {
38
- echo -e "${RED}✗ $1${NC}"
39
- }
40
-
41
- # 显示 Logo
42
- show_logo() {
43
- echo ""
44
- echo -e "${RED}"
45
- echo " ██╗ ██╗███████╗██████╗ ██████╗ ███████╗██████╗ ██████╗ "
46
- echo " ██║ ██║██╔════╝██╔══██╗██╔═══██╗██╔════╝██╔══██╗██╔══██╗"
47
- echo " ██║ █╗ ██║█████╗ ██████╔╝██║ ██║█████╗ ██████╔╝██║ ██║"
48
- echo " ██║███╗██║██╔══╝ ██╔══██╗██║ ██║██╔══╝ ██╔══██╗██║ ██║"
49
- echo " ╚███╔███╔╝███████╗██████╔╝╚██████╔╝███████╗██████╔╝██████╔╝"
50
- echo " ╚══╝╚══╝ ╚══════╝╚═════╝ ╚═════╝ ╚══════╝╚═════╝ ╚═════╝ "
51
- echo ""
52
- echo -e "${CYAN} 💸 Burn Your Money - 看着你的钱包燃烧${NC}"
53
- echo ""
54
- }
55
-
56
- # 检查依赖
57
- check_dependencies() {
58
- print_step "检查依赖..."
59
-
60
- # 检查 jq
61
- if ! command -v jq &> /dev/null; then
62
- print_error "jq 未安装!"
63
- echo ""
64
- echo "请先安装 jq:"
65
- echo " Ubuntu/Debian: sudo apt-get install jq"
66
- echo " macOS: brew install jq"
67
- echo " Arch: sudo pacman -S jq"
68
- echo ""
69
- exit 1
70
- fi
71
- print_success "jq 已安装"
72
-
73
- # 检查 Claude Code
74
- if ! command -v claude &> /dev/null; then
75
- print_warning "Claude Code 未找到"
76
- else
77
- CLAUDE_VERSION=$(claude --version 2>/dev/null || echo "unknown")
78
- print_success "Claude Code 版本: $CLAUDE_VERSION"
79
- fi
80
- }
81
-
82
- # 创建目录结构
83
- create_directories() {
84
- print_step "创建目录结构..."
85
-
86
- mkdir -p ~/.claude/scripts
87
- mkdir -p ~/.claude/cache
88
-
89
- print_success "目录已创建"
90
- }
91
-
92
- # 从 GitHub 下载文件
93
- download_file() {
94
- local url="$1"
95
- local dest="$2"
96
- local max_retries=3
97
- local retry=0
98
-
99
- while [ $retry -lt $max_retries ]; do
100
- if curl -fsSL "$url" -o "$dest" 2>/dev/null; then
101
- return 0
102
- fi
103
- retry=$((retry + 1))
104
- if [ $retry -lt $max_retries ]; then
105
- sleep 1
106
- fi
107
- done
108
- return 1
109
- }
110
-
111
- # 安装脚本文件
112
- install_scripts() {
113
- print_step "安装脚本文件..."
114
-
115
- # 获取脚本目录
116
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
117
-
118
- # 检查本地文件是否存在
119
- local use_remote=false
120
- if [ ! -f "$SCRIPT_DIR/src/statusline.sh" ] || [ ! -f "$SCRIPT_DIR/src/token-history.sh" ]; then
121
- print_warning "本地脚本文件不存在,从 GitHub 下载..."
122
- use_remote=true
123
- fi
124
-
125
- # GitHub 原始文件 URL 基础路径
126
- local BASE_URL="https://raw.githubusercontent.com/winston-wwzhen/burn-your-money/main"
127
-
128
- # 安装 statusline.sh
129
- if [ "$use_remote" = true ]; then
130
- print_step "下载 statusline.sh..."
131
- if download_file "$BASE_URL/src/statusline.sh" ~/.claude/statusline.sh; then
132
- chmod +x ~/.claude/statusline.sh
133
- print_success "statusline.sh 已下载并安装"
134
- else
135
- print_error "下载 statusline.sh 失败,请检查网络连接"
136
- exit 1
137
- fi
138
- else
139
- cp "$SCRIPT_DIR/src/statusline.sh" ~/.claude/statusline.sh
140
- chmod +x ~/.claude/statusline.sh
141
- print_success "statusline.sh 已安装"
142
- fi
143
-
144
- # 安装 token-history.sh
145
- mkdir -p ~/.claude/scripts
146
- if [ "$use_remote" = true ]; then
147
- print_step "下载 token-history.sh..."
148
- if download_file "$BASE_URL/src/token-history.sh" ~/.claude/scripts/token-history.sh; then
149
- chmod +x ~/.claude/scripts/token-history.sh
150
- print_success "token-history.sh 已下载并安装"
151
- else
152
- print_error "下载 token-history.sh 失败,请检查网络连接"
153
- exit 1
154
- fi
155
- else
156
- cp "$SCRIPT_DIR/src/token-history.sh" ~/.claude/scripts/token-history.sh
157
- chmod +x ~/.claude/scripts/token-history.sh
158
- print_success "token-history.sh 已安装"
159
- fi
160
- }
161
-
162
- # 配置 settings.json
163
- configure_settings() {
164
- print_step "配置 Claude Code..."
165
-
166
- SETTINGS_FILE="$HOME/.claude/settings.json"
167
-
168
- # 如果文件不存在,创建一个
169
- if [ ! -f "$SETTINGS_FILE" ]; then
170
- echo "{}" > "$SETTINGS_FILE"
171
- fi
172
-
173
- # 使用 jq 添加 statusline 配置
174
- if command -v jq &> /dev/null; then
175
- tmp_file=$(mktemp)
176
- jq '.statusLine = {"type": "command", "command": "~/.claude/statusline.sh"}' "$SETTINGS_FILE" > "$tmp_file"
177
- mv "$tmp_file" "$SETTINGS_FILE"
178
- print_success "settings.json 已更新"
179
- else
180
- print_warning "无法自动更新 settings.json,请手动添加:"
181
- echo ""
182
- echo '{
183
- "statusLine": {
184
- "type": "command",
185
- "command": "~/.claude/statusline.sh"
186
- }
187
- }'
188
- echo ""
189
- fi
190
- }
191
-
192
- # 测试安装
193
- test_installation() {
194
- print_step "测试安装..."
195
-
196
- # 测试 statusline 脚本
197
- test_json='{
198
- "model": {"display_name": "Test"},
199
- "context_window": {
200
- "total_input_tokens": 10000,
201
- "total_output_tokens": 2000,
202
- "context_window_size": 200000,
203
- "used_percentage": 6,
204
- "remaining_percentage": 94
205
- },
206
- "cost": {"total_cost_usd": 0.05}
207
- }'
208
-
209
- if output=$(echo "$test_json" | ~/.claude/statusline.sh 2>/dev/null); then
210
- print_success "statusline 脚本工作正常"
211
- echo " 输出: $output"
212
- else
213
- print_error "statusline 脚本测试失败"
214
- return 1
215
- fi
216
-
217
- # 测试 token-history 脚本
218
- if ~/.claude/scripts/token-history.sh summary > /dev/null 2>&1; then
219
- print_success "token-history 脚本工作正常"
220
- else
221
- print_warning "token-history 脚本测试失败(可能没有历史数据)"
222
- fi
223
- }
224
-
225
- # 显示完成信息
226
- show_completion() {
227
- print_header "安装完成!"
228
-
229
- echo -e "${GREEN}Burn Your Money 已成功安装!${NC}"
230
- echo ""
231
- echo "📝 已安装的文件:"
232
- echo " • ~/.claude/statusline.sh"
233
- echo " • ~/.claude/scripts/token-history.sh"
234
- echo ""
235
- echo "🔧 已更新配置:"
236
- echo " • ~/.claude/settings.json"
237
- echo ""
238
- echo -e "${YELLOW}下一步:${NC}"
239
- echo " 1. 重启 Claude Code"
240
- echo " 2. 观察状态栏是否显示 Token 信息"
241
- echo ""
242
- echo -e "${CYAN}如果状态栏没有显示,请检查:${NC}"
243
- echo " • Claude Code 版本是否 >= 2.1.6"
244
- echo " • 运行: claude --version"
245
- echo ""
246
- echo -e "${PURPLE}反馈与支持:${NC}"
247
- echo " • GitHub: https://github.com/winston-wwzhen/burn-your-money"
248
- echo " • Issues: https://github.com/winston-wwzhen/burn-your-money/issues"
249
- echo ""
250
- }
251
-
252
- # 主函数
253
- main() {
254
- show_logo
255
-
256
- print_header "开始安装 Burn Your Money..."
257
-
258
- check_dependencies
259
- create_directories
260
- install_scripts
261
- configure_settings
262
- test_installation
263
-
264
- show_completion
265
-
266
- echo -e "${GREEN}开始烧钱吧!🔥💸${NC}"
267
- echo ""
268
- }
269
-
270
- # 运行主函数
271
- main
package/src/statusline.sh DELETED
@@ -1,250 +0,0 @@
1
- #!/bin/bash
2
- # Burn Your Money - Claude Code 状态栏脚本
3
- # 格式:[模型] 今日:token 费用 🔥速度 | 总计:token 费用
4
-
5
- # 设置 jq 命令路径(支持自定义安装的 jq)
6
- if [ -n "$JQ_PATH" ]; then
7
- JQ_CMD="$JQ_PATH"
8
- elif [ -f "$HOME/.claude/bin/jq.exe" ]; then
9
- JQ_CMD="$HOME/.claude/bin/jq.exe"
10
- elif [ -f "$HOME/.claude/bin/jq" ]; then
11
- JQ_CMD="$HOME/.claude/bin/jq"
12
- else
13
- JQ_CMD="jq"
14
- fi
15
-
16
- # 验证 jq 是否可用
17
- if ! command -v "$JQ_CMD" >/dev/null 2>&1; then
18
- # jq 不可用,返回简单错误信息
19
- printf "[BurnYourMoney] Error: jq not found. Run: npm install -g @winston.wan/burn-your-money"
20
- exit 0
21
- fi
22
-
23
- # 配置文件
24
- CONFIG_FILE="$HOME/.claude/burn-your-money-config.json"
25
- SESSION_STATE="$HOME/.claude/cache/session-state.json"
26
- TODAY_STATE="$HOME/.claude/cache/today-state.json"
27
- HISTORY_CACHE="$HOME/.claude/cache/history-cache.json"
28
-
29
- # 初始化配置
30
- init_config() {
31
- if [ ! -f "$CONFIG_FILE" ]; then
32
- $JQ_CMD -n '{
33
- theme: "fire",
34
- alert_daily: 10.0,
35
- alert_weekly: 50.0,
36
- show_burn_rate: true,
37
- show_eta: true,
38
- show_trend: false
39
- }' > "$CONFIG_FILE"
40
- fi
41
- }
42
-
43
- # 1. 批量读取配置 (One JQ pass)
44
- init_config
45
- if [ -f "$CONFIG_FILE" ]; then
46
- # 使用 eval 批量赋值变量
47
- eval $("$JQ_CMD" -r '@sh "THEME=\(.theme // "fire") ALERT_DAILY=\(.alert_daily // 10) SHOW_BURN_RATE=\(.show_burn_rate // true)"' "$CONFIG_FILE" 2>/dev/null)
48
- else
49
- THEME="fire"
50
- ALERT_DAILY=10
51
- SHOW_BURN_RATE=true
52
- fi
53
-
54
- # 主题颜色定义
55
- case "$THEME" in
56
- fire) TODAY_COLOR="0;31"; COST_COLOR="0;31"; BURN_COLOR="0;31" ;;
57
- ocean) TODAY_COLOR="0;34"; COST_COLOR="0;36"; BURN_COLOR="0;36" ;;
58
- forest) TODAY_COLOR="0;32"; COST_COLOR="0;33"; BURN_COLOR="0;32" ;;
59
- golden) TODAY_COLOR="0;33"; COST_COLOR="0;33"; BURN_COLOR="1;33" ;;
60
- *) TODAY_COLOR="0;36"; COST_COLOR="0;34"; BURN_COLOR="0;31" ;;
61
- esac
62
-
63
- # 格式化函数 (纯 Bash/Awk 实现,无外部进程调用)
64
- format_number() {
65
- local num=$1
66
- if [ "$num" -ge 1000000000 ]; then awk "BEGIN {printf \"%.1fB\", $num/1000000000}";
67
- elif [ "$num" -ge 1000000 ]; then awk "BEGIN {printf \"%.1fM\", $num/1000000}";
68
- elif [ "$num" -ge 1000 ]; then awk "BEGIN {printf \"%.1fK\", $num/1000}";
69
- else echo "$num"; fi
70
- }
71
-
72
- format_cost() {
73
- awk "BEGIN {printf \"\$%.2f\", $1}"
74
- }
75
-
76
- format_burn_rate() {
77
- local rate=$1
78
- if [ "$rate" -ge 1000 ]; then awk "BEGIN {printf \"%.1fK tok/s\", $rate/1000}";
79
- else awk "BEGIN {printf \"%.0f tok/s\", $rate}"; fi
80
- }
81
-
82
- # 2. 核心数据解析 (One JQ pass from stdin)
83
- # 将 stdin 存入临时文件(避免大 JSON 管道卡顿)
84
- TEMP_JSON=$(mktemp)
85
- trap "rm -f $TEMP_JSON" EXIT
86
- cat > "$TEMP_JSON"
87
-
88
- # 一次性提取所有需要的字段
89
- # 注意:使用 @sh 确保字符串安全引用
90
- eval $("$JQ_CMD" -r '
91
- @sh "model_name=\(.model.display_name // "Unknown")
92
- session_id=\(.session_id // "default")
93
- input=\(.context_window.total_input_tokens // 0)
94
- output=\(.context_window.total_output_tokens // 0)
95
- cache=\(.context_window.current_usage.cache_read_input_tokens // 0)
96
- current_cost=\(.cost.total_cost_usd // 0)"
97
- ' "$TEMP_JSON" 2>/dev/null)
98
-
99
- # 计算当前会话 Token 总量
100
- current_session_tokens=$((input + output + cache))
101
-
102
- # 3. 燃烧速度计算 (Burn Rate)
103
- current_time=$(date +%s)
104
- start_time_cache=0
105
-
106
- # 读取 Session State (尽可能不做写入,除非是新 Session)
107
- if [ -f "$SESSION_STATE" ]; then
108
- eval $("$JQ_CMD" -r '@sh "cached_id=\(.session_id // "") cached_time=\(.start_time // 0)"' "$SESSION_STATE" 2>/dev/null)
109
- else
110
- cached_id=""
111
- cached_time=0
112
- fi
113
-
114
- if [ "$cached_id" = "$session_id" ] && [ "$cached_time" -ne 0 ]; then
115
- start_time_cache=$cached_time
116
- else
117
- # New session detected - 使用原子写入
118
- start_time_cache=$current_time
119
- SESSION_STATE_TMP="${SESSION_STATE}.tmp.$$"
120
- $JQ_CMD -n --arg id "$session_id" --arg time "$current_time" '{session_id: $id, start_time: ($time | tonumber)}' > "$SESSION_STATE_TMP" 2>/dev/null && mv "$SESSION_STATE_TMP" "$SESSION_STATE"
121
- fi
122
-
123
- elapsed=$((current_time - start_time_cache))
124
- burn_rate=0
125
- if [ "$elapsed" -gt 0 ] && [ "$current_session_tokens" -gt 0 ]; then
126
- burn_rate=$(awk "BEGIN {printf \"%.0f\", ${current_session_tokens} / ${elapsed}}")
127
- fi
128
-
129
- # 4. 历史数据缓存 (每 30 秒刷新)
130
- # 确保 cache 目录存在
131
- mkdir -p "$(dirname "$HISTORY_CACHE")" 2>/dev/null
132
-
133
- now=$(date +%s)
134
- cache_age=999999
135
- if [ -f "$HISTORY_CACHE" ]; then
136
- # Portable modification time check
137
- if [ "$(uname)" = "Darwin" ]; then
138
- cache_time=$(stat -f %m "$HISTORY_CACHE" 2>/dev/null || echo 0)
139
- else
140
- cache_time=$(stat -c %Y "$HISTORY_CACHE" 2>/dev/null || echo 0)
141
- fi
142
- cache_age=$((now - cache_time))
143
- else
144
- echo '{}' > "$HISTORY_CACHE"
145
- fi
146
-
147
- # 如果缓存太旧,并在后台刷新(虽然后台刷新可能在 statusline 不合适,但我们可以同步调用历史脚本)
148
- # 为了性能,这里我们仍然做同步调用,但减少频率
149
- if [ $cache_age -gt 30 ]; then
150
- # 重新生成历史数据
151
- ~/.claude/scripts/token-history.sh summary > "$HISTORY_CACHE" 2>/dev/null
152
- fi
153
-
154
- # 读取历史总计 (One pass)
155
- eval $("$JQ_CMD" -r '@sh "history_total_tokens=\(.total_tokens_all // 0) history_total_cost=\(.total_cost // 0)"' "$HISTORY_CACHE" 2>/dev/null)
156
-
157
- # 5. 今日数据持久化 (One-pass Read & Write)
158
- # 逻辑:读取旧状态 -> 计算差值 -> 写入新状态
159
- today_date=$(date +%Y-%m-%d)
160
-
161
- if [ -f "$TODAY_STATE" ]; then
162
- eval $("$JQ_CMD" -r '@sh "saved_date=\(.date // "") saved_tokens=\(.tokens // 0) saved_cost=\(.cost // 0) last_session_tokens=\(.last_session_tokens // 0) last_session_cost=\(.last_session_cost // 0)"' "$TODAY_STATE" 2>/dev/null)
163
- else
164
- saved_date=""
165
- saved_tokens=0
166
- saved_cost=0
167
- last_session_tokens=0
168
- last_session_cost=0
169
- fi
170
-
171
- if [ "$saved_date" != "$today_date" ]; then
172
- # 新的一天,重置累计数据
173
- saved_tokens=0
174
- saved_cost=0
175
- last_session_tokens=0
176
- last_session_cost=0
177
- fi
178
-
179
- # 计算增量
180
- token_increment=$((current_session_tokens - last_session_tokens))
181
- if [ "$token_increment" -lt 0 ]; then token_increment=0; fi # 防御性编程
182
-
183
- # 浮点数增量计算
184
- cost_increment=$(awk "BEGIN {print ($current_cost - $last_session_cost < 0 ? 0 : $current_cost - $last_session_cost)}")
185
-
186
- # 计算新的今日累计
187
- new_today_tokens=$((saved_tokens + token_increment))
188
- new_today_cost=$(awk "BEGIN {printf \"%.5f\", $saved_cost + $cost_increment}")
189
-
190
- # 写入新状态 (一次性写入,使用原子写入避免并发问题)
191
- # 先写入临时文件,然后重命名,确保原子性
192
- TODAY_STATE_TMP="${TODAY_STATE}.tmp.$$"
193
- $JQ_CMD -n \
194
- --arg date "$today_date" \
195
- --arg tokens "$new_today_tokens" \
196
- --arg cost "$new_today_cost" \
197
- --arg last_sess_tok "$current_session_tokens" \
198
- --arg last_sess_cost "$current_cost" \
199
- '{
200
- date: $date,
201
- tokens: ($tokens|tonumber),
202
- cost: ($cost|tonumber),
203
- last_session_tokens: ($last_sess_tok|tonumber),
204
- last_session_cost: ($last_sess_cost|tonumber)
205
- }' > "$TODAY_STATE_TMP" 2>/dev/null && mv "$TODAY_STATE_TMP" "$TODAY_STATE"
206
-
207
- # 6. 最终计算与显示
208
- total_tokens_all=$((history_total_tokens + current_session_tokens))
209
- total_cost_all=$(awk "BEGIN {print $history_total_cost + $current_cost}")
210
-
211
- # 警报检查
212
- is_alert=false
213
- if awk "BEGIN {exit !($new_today_cost >= $ALERT_DAILY)}"; then
214
- is_alert=true
215
- fi
216
-
217
- # 构建输出字符串
218
- output=""
219
-
220
- # [Model]
221
- if [ "$is_alert" = true ]; then
222
- output+="\\033[1;31m[${model_name}]\\033[0m "
223
- else
224
- output+="\\033[0;90m[${model_name}]\\033[0m "
225
- fi
226
-
227
- # Today
228
- d_today_tokens=$(format_number $new_today_tokens)
229
- d_today_cost=$(format_cost $new_today_cost)
230
-
231
- if [ "$new_today_tokens" -gt 0 ]; then
232
- output+="\\033[${TODAY_COLOR}m今日:${d_today_tokens}\\033[0m "
233
- output+="\\033[${COST_COLOR}m${d_today_cost}\\033[0m "
234
- else
235
- output+="\\033[0;90m今日:0\\033[0m \\033[0;90m\$0.00\\033[0m "
236
- fi
237
-
238
- # Burn Rate
239
- if [ "$SHOW_BURN_RATE" = "true" ] && [ "$burn_rate" -gt 0 ]; then
240
- d_burn=$(format_burn_rate $burn_rate)
241
- output+="\\033[${BURN_COLOR}m🔥${d_burn}\\033[0m "
242
- fi
243
-
244
- # Total
245
- d_total_tokens=$(format_number $total_tokens_all)
246
- d_total_cost=$(format_cost $total_cost_all)
247
- output+="| \\033[0;90m总计:${d_total_tokens}\\033[0m \\033[0;90m${d_total_cost}\\033[0m "
248
-
249
- # Print final result
250
- printf "%b" "$output"