cc-usage-bar 0.4.0 → 0.4.2
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/AGENTS.md +9 -4
- package/README.md +37 -1
- package/README.zh-CN.md +37 -1
- package/dist/src/format.js +27 -12
- package/dist/src/providers/minimax.js +16 -15
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AGENTS.md — cc-usage-bar 全功能说明
|
|
2
2
|
|
|
3
|
-
> 这份文件是面向 AI 助手(Claude Code、Cursor、Codex 等)的安装/配置说明。如果用户对你说「装 cc-usage-bar」「帮我配 statusline 用量条」「装下 cc-usage-bar
|
|
3
|
+
> 这份文件是面向 AI 助手(Claude Code、Cursor、Codex 等)的安装/配置说明。如果用户对你说「装 cc-usage-bar」「帮我配 statusline 用量条」「装下 cc-usage-bar 帮我配好」之类的话,请按本文档完成全部步骤。**默认无需向用户追加确认**;只有用户没登录过 Claude Code(凭证查不到)时才停下来让用户先登录。
|
|
4
4
|
|
|
5
5
|
## 1. 这个包是什么
|
|
6
6
|
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
|
|
19
19
|
> **用户只描述偏好,你把 `statusLine.command` 配成 `cc-usage-bar-wrap`,并保留用户原有前缀。**
|
|
20
20
|
|
|
21
|
+
如果已有 `statusLine.command`、`statusline-command.sh`、自定义 shell 脚本、git/path/model 展示等前缀内容,**一律视为要保留的前缀**:按 3.4 抽出它,并用 `cc-usage-bar-wrap --prefix=...` 串起来。不要询问是否覆盖、追加或暂不修改;追加保留是本项目默认行为。
|
|
22
|
+
|
|
21
23
|
## 3. 安装流程(必走)
|
|
22
24
|
|
|
23
25
|
按顺序执行,每一步执行前简要告知用户:
|
|
@@ -39,7 +41,7 @@ which cc-usage-bar-wrap && which cc-usage-fetch
|
|
|
39
41
|
where.exe cc-usage-bar-wrap
|
|
40
42
|
```
|
|
41
43
|
|
|
42
|
-
要求:`cc-usage-bar` ≥ **0.4.
|
|
44
|
+
要求:`cc-usage-bar` ≥ **0.4.1**(自适应换行 + 周限额上色 + countdown 预设 + 颜色 ramp 自定义 + tint reverse 样式)。已装旧版的话用 `npm i -g cc-usage-bar@latest` 升级。
|
|
43
45
|
|
|
44
46
|
### 3.3 读取现有 statusLine.command
|
|
45
47
|
|
|
@@ -169,8 +171,11 @@ CC_USAGE_COLORS_BALANCE='0:cyan,60:yellow,90:red'
|
|
|
169
171
|
# 自定义填充/空槽字符(cells)
|
|
170
172
|
--bar-spec='{"mode":"cells","filled":"▰","empty":"▱","width":12}'
|
|
171
173
|
|
|
172
|
-
# 单色渐变(tint)——
|
|
173
|
-
--bar-spec='{"mode":"tint","text":"
|
|
174
|
+
# 单色渐变(tint)—— 默认 reverse:完成部分反色底块,剩余部分变暗
|
|
175
|
+
--bar-spec='{"mode":"tint","text":"Ciallo~(∠・ω< )⌒★"}'
|
|
176
|
+
|
|
177
|
+
# 想要旧的"只染前景"效果,显式加 style:"fg"
|
|
178
|
+
--bar-spec='{"mode":"tint","text":"████████","style":"fg","emptyStyle":"dim"}'
|
|
174
179
|
|
|
175
180
|
# 动画帧(frames)—— 按百分比从帧序列里挑一帧
|
|
176
181
|
--bar-spec='{"mode":"frames","frames":["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"]}'
|
package/README.md
CHANGED
|
@@ -20,6 +20,36 @@ Or, with `--format=bar-time`:
|
|
|
20
20
|
[█████░░░░░] 47% until 18:00 / [██████░░░░] 59% until 5/9 09:00
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
## Quick usage
|
|
24
|
+
|
|
25
|
+
### Method 1: Command line
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install -g cc-usage-bar@latest
|
|
29
|
+
cc-usage-bar install --format=bar-countdown
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
If you already have a Claude Code statusline command, the installer keeps it as the prefix and appends the usage bar. Run diagnostics any time with:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
cc-usage-bar status
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Method 2: Ask an AI assistant
|
|
39
|
+
|
|
40
|
+
In Claude Code, Cursor, Codex, or another coding assistant, say:
|
|
41
|
+
|
|
42
|
+
```text
|
|
43
|
+
Install cc-usage-bar for my Claude Code statusline.
|
|
44
|
+
Keep my existing statusline prefix and use the bar-countdown format.
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
If the assistant needs exact instructions, give it the AI-readable guide:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npx cc-usage-bar@latest agents
|
|
51
|
+
```
|
|
52
|
+
|
|
23
53
|
## Install
|
|
24
54
|
|
|
25
55
|
```bash
|
|
@@ -111,12 +141,18 @@ cc-usage-bar install --format=bar-time \
|
|
|
111
141
|
--bar-spec='{"mode":"tint","text":"Ciallo~(∠・ω< )⌒★"}'
|
|
112
142
|
```
|
|
113
143
|
|
|
114
|
-
`tint` keeps the whole text visible
|
|
144
|
+
`tint` keeps the whole text visible. By default the completed prefix is rendered as a reversed-color block (high contrast), and the rest is dimmed:
|
|
115
145
|
|
|
116
146
|
```json
|
|
117
147
|
{"mode":"tint","text":"Ciallo~(∠・ω< )⌒★"}
|
|
118
148
|
```
|
|
119
149
|
|
|
150
|
+
If you prefer the older "color the foreground only" look, set `style:"fg"`:
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{"mode":"tint","text":"Ciallo~(∠・ω< )⌒★","style":"fg"}
|
|
154
|
+
```
|
|
155
|
+
|
|
120
156
|
`cells` replaces the default block characters:
|
|
121
157
|
|
|
122
158
|
```json
|
package/README.zh-CN.md
CHANGED
|
@@ -22,6 +22,36 @@
|
|
|
22
22
|
[█████░░░░░] 47% until 18:00 / [██████░░░░] 59% until 5/9 09:00
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
## 快速使用
|
|
26
|
+
|
|
27
|
+
### 方法一:正常命令行
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install -g cc-usage-bar@latest
|
|
31
|
+
cc-usage-bar install --format=bar-countdown
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
如果你已经有自己的 Claude Code statusline 命令,安装器会把它保留为前缀,再追加用量条。需要诊断时运行:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
cc-usage-bar status
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 方法二:直接和大模型交流
|
|
41
|
+
|
|
42
|
+
在 Claude Code、Cursor、Codex 或其他编程助手里直接说:
|
|
43
|
+
|
|
44
|
+
```text
|
|
45
|
+
请安装 cc-usage-bar 并帮我配置 Claude Code statusline。
|
|
46
|
+
保留我原来的 statusline 前缀,使用 bar-countdown 格式。
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
如果大模型需要更精确的操作说明,把下面命令输出的 AI 可读安装指南发给它:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npx cc-usage-bar@latest agents
|
|
53
|
+
```
|
|
54
|
+
|
|
25
55
|
## 安装
|
|
26
56
|
|
|
27
57
|
```bash
|
|
@@ -111,7 +141,7 @@ cc-usage-bar install --format <preset> --bar-width <n>
|
|
|
111
141
|
|
|
112
142
|
#### tint:整段文字始终可见
|
|
113
143
|
|
|
114
|
-
推荐给颜文字、短句、logo
|
|
144
|
+
推荐给颜文字、短句、logo 风格文本。整段文字一直可见,**默认**已完成部分会用反色底块(reverse)增强对比,未完成部分变暗:
|
|
115
145
|
|
|
116
146
|
```bash
|
|
117
147
|
cc-usage-bar install --format=bar-time \
|
|
@@ -122,6 +152,12 @@ cc-usage-bar install --format=bar-time \
|
|
|
122
152
|
{"mode":"tint","text":"Ciallo~(∠・ω< )⌒★"}
|
|
123
153
|
```
|
|
124
154
|
|
|
155
|
+
如果更喜欢"只给完成部分上前景色、不反色"的旧风格,显式加 `style:"fg"`:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{"mode":"tint","text":"Ciallo~(∠・ω< )⌒★","style":"fg"}
|
|
159
|
+
```
|
|
160
|
+
|
|
125
161
|
#### cells:替换默认块字符
|
|
126
162
|
|
|
127
163
|
```json
|
package/dist/src/format.js
CHANGED
|
@@ -23,6 +23,7 @@ exports.FORMAT_PRESETS = [
|
|
|
23
23
|
'bar-countdown',
|
|
24
24
|
];
|
|
25
25
|
const ANSI_RESET = '\x1b[0m';
|
|
26
|
+
const ANSI_REVERSE = '\x1b[7m';
|
|
26
27
|
exports.COLOR_MAP = {
|
|
27
28
|
none: '',
|
|
28
29
|
dim: '\x1b[2m',
|
|
@@ -146,6 +147,7 @@ function parseBarSpec(raw) {
|
|
|
146
147
|
const out = { mode: 'tint', text: obj.text };
|
|
147
148
|
if (obj.emptyStyle === 'plain' || obj.emptyStyle === 'dim')
|
|
148
149
|
out.emptyStyle = obj.emptyStyle;
|
|
150
|
+
out.style = obj.style === 'fg' ? 'fg' : 'reverse';
|
|
149
151
|
return out;
|
|
150
152
|
}
|
|
151
153
|
if (obj.mode === 'frames') {
|
|
@@ -240,7 +242,8 @@ function formatBar(pct, width = 10, spec, activeColor = null, useColor = false)
|
|
|
240
242
|
const inactive = chars.slice(filled).join('');
|
|
241
243
|
if (!useColor)
|
|
242
244
|
return active + inactive;
|
|
243
|
-
const
|
|
245
|
+
const activeStyle = activeColor && spec.style === 'reverse' ? `${activeColor}${ANSI_REVERSE}` : activeColor;
|
|
246
|
+
const activePart = activeStyle && active ? paint(active, activeStyle, true) : active;
|
|
244
247
|
const inactivePart = inactive && spec.emptyStyle !== 'plain' ? paint(inactive, exports.COLOR_MAP.dim, true) : inactive;
|
|
245
248
|
return activePart + inactivePart;
|
|
246
249
|
}
|
|
@@ -257,10 +260,22 @@ function paint(text, color, useColor) {
|
|
|
257
260
|
return `${color}${text}${ANSI_RESET}`;
|
|
258
261
|
}
|
|
259
262
|
function applyTierPaint(text, color, opts, tpl) {
|
|
260
|
-
if (opts.barSpec?.mode === 'tint' && opts.color && tpl.includes('{bar}'))
|
|
261
|
-
return text;
|
|
262
263
|
return paint(text, color, opts.color);
|
|
263
264
|
}
|
|
265
|
+
function applyTintTemplate(tpl, vars, color, opts) {
|
|
266
|
+
if (!opts.color || !color)
|
|
267
|
+
return applyTemplate(tpl, vars);
|
|
268
|
+
return tpl
|
|
269
|
+
.split(/(\{bar\})/g)
|
|
270
|
+
.map((part) => (part === '{bar}' ? vars.bar ?? '{bar}' : paint(applyTemplate(part, vars), color, true)))
|
|
271
|
+
.join('');
|
|
272
|
+
}
|
|
273
|
+
function renderTemplate(tpl, vars, color, opts) {
|
|
274
|
+
if (opts.barSpec?.mode === 'tint' && tpl.includes('{bar}')) {
|
|
275
|
+
return applyTintTemplate(tpl, vars, color, opts);
|
|
276
|
+
}
|
|
277
|
+
return applyTierPaint(applyTemplate(tpl, vars), color, opts, tpl);
|
|
278
|
+
}
|
|
264
279
|
function prependProvider(text, planName, opts) {
|
|
265
280
|
return opts.showProviderName && planName ? `${planName} ${text}` : text;
|
|
266
281
|
}
|
|
@@ -272,15 +287,15 @@ function renderTier(ctx, opts) {
|
|
|
272
287
|
const tpl = opts.template ?? SUB_PRESET_TPL[opts.format];
|
|
273
288
|
const ramp = ctx.label === '5h' ? opts.colorRamp5h ?? exports.DEFAULT_RAMP : opts.colorRampWk ?? exports.DEFAULT_RAMP;
|
|
274
289
|
const color = colorFromRamp(pct, ramp);
|
|
275
|
-
const
|
|
290
|
+
const vars = {
|
|
276
291
|
label: ctx.label,
|
|
277
292
|
percent: String(pct),
|
|
278
293
|
bar: formatBar(pct, opts.barWidth, opts.barSpec, color, opts.color),
|
|
279
294
|
expiry: formatExpiry(ctx.tier.resets_at, opts.now),
|
|
280
295
|
countdown: formatCountdown(ctx.tier.resets_at, opts.now),
|
|
281
296
|
provider: ctx.provider,
|
|
282
|
-
}
|
|
283
|
-
return
|
|
297
|
+
};
|
|
298
|
+
return renderTemplate(tpl, vars, color, opts);
|
|
284
299
|
}
|
|
285
300
|
function currencySymbol(unit) {
|
|
286
301
|
switch (unit.toUpperCase()) {
|
|
@@ -315,18 +330,18 @@ function renderBalance(d, opts) {
|
|
|
315
330
|
}
|
|
316
331
|
if (typeof d.total !== 'number') {
|
|
317
332
|
const tpl = opts.template ?? BAL_PRESET_TPL.compact;
|
|
318
|
-
const
|
|
333
|
+
const vars = {
|
|
319
334
|
label: '', percent: '0', bar: '', expiry: '', countdown: '',
|
|
320
335
|
provider: d.planName ?? '',
|
|
321
336
|
amount: fmtMoney(d.remaining, d.unit),
|
|
322
|
-
}
|
|
323
|
-
return prependProvider(
|
|
337
|
+
};
|
|
338
|
+
return prependProvider(renderTemplate(tpl, vars, null, opts), d.planName, opts);
|
|
324
339
|
}
|
|
325
340
|
const total = d.total;
|
|
326
341
|
const usedPct = total > 0 ? ((total - d.remaining) / total) * 100 : 0;
|
|
327
342
|
const tpl = opts.template ?? BAL_PRESET_TPL[opts.format];
|
|
328
343
|
const color = colorFromRamp(usedPct, opts.colorRampBalance ?? exports.DEFAULT_RAMP);
|
|
329
|
-
const
|
|
344
|
+
const vars = {
|
|
330
345
|
label: '',
|
|
331
346
|
percent: String(Math.round(usedPct)),
|
|
332
347
|
bar: formatBar(usedPct, opts.barWidth, opts.barSpec, color, opts.color),
|
|
@@ -334,8 +349,8 @@ function renderBalance(d, opts) {
|
|
|
334
349
|
countdown: '',
|
|
335
350
|
provider: d.planName ?? '',
|
|
336
351
|
amount: `${fmtMoney(d.remaining, d.unit)}/${fmtMoney(total, d.unit)}`,
|
|
337
|
-
}
|
|
338
|
-
return prependProvider(
|
|
352
|
+
};
|
|
353
|
+
return prependProvider(renderTemplate(tpl, vars, color, opts), d.planName, opts);
|
|
339
354
|
}
|
|
340
355
|
function renderUsage(data, opts) {
|
|
341
356
|
if (!data)
|
|
@@ -3,13 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.minimaxAdapter = void 0;
|
|
4
4
|
exports.parseMinimax = parseMinimax;
|
|
5
5
|
const http_1 = require("./http");
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
return undefined;
|
|
9
|
-
return {
|
|
10
|
-
utilization: ((total - (total - used)) / total) * 100,
|
|
11
|
-
resets_at: typeof endMs === 'number' ? new Date(endMs).toISOString() : undefined,
|
|
12
|
-
};
|
|
6
|
+
function isoFromMs(ms) {
|
|
7
|
+
return typeof ms === 'number' ? new Date(ms).toISOString() : undefined;
|
|
13
8
|
}
|
|
14
9
|
function parseMinimax(body) {
|
|
15
10
|
if (!body || typeof body !== 'object')
|
|
@@ -19,16 +14,22 @@ function parseMinimax(body) {
|
|
|
19
14
|
if (typeof code === 'number' && code !== 0) {
|
|
20
15
|
return { error: r.base_resp?.status_msg ?? `MiniMax error ${code}` };
|
|
21
16
|
}
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
if (!Array.isArray(r.model_remains))
|
|
18
|
+
return null;
|
|
19
|
+
const item = r.model_remains.find((m) => m && m.model_name === 'general');
|
|
20
|
+
if (!item)
|
|
24
21
|
return null;
|
|
25
22
|
const out = { kind: 'subscription', planName: 'MiniMax' };
|
|
26
|
-
const
|
|
27
|
-
if (
|
|
28
|
-
out.five_hour =
|
|
29
|
-
|
|
30
|
-
if (
|
|
31
|
-
|
|
23
|
+
const fhRemain = item.current_interval_remaining_percent;
|
|
24
|
+
if (typeof fhRemain === 'number') {
|
|
25
|
+
out.five_hour = { utilization: 100 - fhRemain, resets_at: isoFromMs(item.end_time) };
|
|
26
|
+
}
|
|
27
|
+
if (item.current_weekly_status === 1) {
|
|
28
|
+
const wkRemain = item.current_weekly_remaining_percent;
|
|
29
|
+
if (typeof wkRemain === 'number') {
|
|
30
|
+
out.seven_day = { utilization: 100 - wkRemain, resets_at: isoFromMs(item.weekly_end_time) };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
32
33
|
if (!out.five_hour && !out.seven_day)
|
|
33
34
|
return null;
|
|
34
35
|
return out;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cc-usage-bar",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Show your Claude Code subscription usage (5h / 7d, or balance) in the statusline. Supports Anthropic, Kimi, GLM, MiniMax, DeepSeek, StepFun, SiliconFlow, OpenRouter, Novita.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|