claude-token-saver 2.9.0 โ 2.9.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/README.en.md +26 -5
- package/README.md +27 -6
- package/bin/cli.js +31 -17
- package/package.json +1 -1
- package/src/config.js +36 -17
package/README.en.md
CHANGED
|
@@ -33,17 +33,21 @@ claude-token-saver install
|
|
|
33
33
|
After install, Claude Code's bottom statusline updates every 5 seconds with cache state (postinstall registers it in `~/.claude/settings.json` automatically).
|
|
34
34
|
|
|
35
35
|
```
|
|
36
|
-
๐ค Opus 4.7 ยท ๐ง Cache hit 98.0% ยท โณ Cache expires
|
|
36
|
+
๐ค Opus 4.7 ยท ๐ง Cache hit 98.0% ยท โณ Cache expires 58:38 ยท โฆ current โโโโโโ 15% ๐ 08:50 ยท ๐
weekly โโโโโโ 24% ๐ Thu 13:00 ยท ๐ฆ Ctx 200k ยท ๐ฐ Cache saved $205 ยท last 1d
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
Segments โ `๐ค model` ยท `๐ง cache hit rate` ยท `โณ TTL countdown` ยท `โฆ current` (5-hour window) ยท `๐
weekly` (7-day window) ยท `๐ฆ context` ยท `๐ฐ cumulative savings` ยท `last <window>`.
|
|
40
|
+
|
|
41
|
+
When excessive token usage is detected, a warning chip is prepended at the front of the statusline:
|
|
40
42
|
|
|
41
43
|
```
|
|
42
|
-
๐จ 5H 94% (resets in 12m) ยท ๐ค Opus 4.7 ยท ๐ง Cache hit 72.1% ยท โ Cache miss ยท ๐ฆ Ctx 200k ยท last 1d
|
|
44
|
+
๐จ 5H 94% (resets in 12m) ยท ๐ค Opus 4.7 ยท ๐ง Cache hit 72.1% ยท โ Cache miss ยท โฆ current โโโโโโ 94% ยท ๐ฆ Ctx 200k ยท last 1d
|
|
43
45
|
```
|
|
44
46
|
|
|
45
47
|
Risk chips: `๐จ 5H/7D NN%`, `โ 1M ON`, `โ Input spike`, `โ Cache miss`, `โ 5m TTL`, `โ Rebuild churn`, `โ Output heavy`, `โ Call surge`.
|
|
46
48
|
|
|
49
|
+
**What to do** โ run the `/claude-token-saver` Skill in Claude. It calls `claude-token-saver last` and surfaces the root cause + step-by-step fix. Saying the chip wording out loud (e.g. "5H cap is up", "cache miss") also auto-activates the same Skill. See the [Skill workflow](#when-a-warning-chip-appears--skill-workflow) section below for the full flow.
|
|
50
|
+
|
|
47
51
|
If postinstall was skipped (you already use a different statusline, etc.), wire it manually:
|
|
48
52
|
|
|
49
53
|
```json
|
|
@@ -58,9 +62,16 @@ If postinstall was skipped (you already use a different statusline, etc.), wire
|
|
|
58
62
|
|
|
59
63
|
`refreshInterval: 5` keeps the TTL countdown ticking while idle. For Windows PowerShell see `examples/statusline-command.ps1`.
|
|
60
64
|
|
|
61
|
-
##
|
|
65
|
+
## When a warning chip appears โ Skill workflow
|
|
66
|
+
|
|
67
|
+
The Claude Code Skill registered at install time bridges "warning chip โ remediation":
|
|
68
|
+
|
|
69
|
+
1. **A risk chip appears in the statusline** โ e.g. `๐จ 5H 94%`, `โ Cache miss`, `โ 1M ON`.
|
|
70
|
+
2. **Run `/claude-token-saver`** โ invoking the Skill via slash is the simplest path. Mentioning the chip wording to Claude ("5H cap is up", "cache miss showing", "why is 1M context on?") auto-activates the same Skill.
|
|
71
|
+
3. **The Skill fetches the remediation.** Internally it runs `claude-token-saver last` to surface the most recent warning + root-cause code + step-by-step fix, and recommends `claude-token-saver handoff` when a cap is imminent.
|
|
72
|
+
4. **Run manually any time.** `claude-token-saver last` (latest event), `claude-token-saver history` (last 7 days of transitions), `claude-token-saver handoff` (back up before a cap blocks you) โ same information, on demand.
|
|
62
73
|
|
|
63
|
-
|
|
74
|
+
> v2.6.0 folded the legacy `/token-monitor` slash command into this Skill. On older installs, run `claude-token-saver install` once and the legacy file is cleaned up automatically.
|
|
64
75
|
|
|
65
76
|
## One-shot report
|
|
66
77
|
|
|
@@ -90,6 +101,8 @@ claude-token-saver mode # show current settings
|
|
|
90
101
|
|
|
91
102
|
## Commands
|
|
92
103
|
|
|
104
|
+
All of the commands below run in your **shell (terminal)**. Inside a Claude Code session, the only entry point is the `/claude-token-saver` Skill, which calls these commands for you. The `--statusline` form is invoked automatically by Claude Code on each statusline refresh โ you never type it yourself.
|
|
105
|
+
|
|
93
106
|
| Command | What it does |
|
|
94
107
|
|---|---|
|
|
95
108
|
| `claude-token-saver` | Last-1-day diagnostic report (`--days N` to change window) |
|
|
@@ -178,6 +191,14 @@ Node.js โฅ 18 ยท macOS / Windows / Linux / WSL ยท zero dependencies.
|
|
|
178
191
|
|
|
179
192
|
## Release notes
|
|
180
193
|
|
|
194
|
+
### v2.9.2 (2026-04-27)
|
|
195
|
+
- `last` / `history` empty-state messages now respect the language setting too. Previously they were hard-coded English, so users on `mode ko` still saw English when there were no warnings to report.
|
|
196
|
+
|
|
197
|
+
### v2.9.1 (2026-04-27)
|
|
198
|
+
- Fix the README statusline sample so it matches actual output (includes the `โฆ current` / `๐
weekly` window segments that were missing).
|
|
199
|
+
- Add a 4-step "When a warning chip appears" Skill workflow โ spot the chip โ mention its wording to Claude โ Skill runs `last` โ apply remediation.
|
|
200
|
+
- Move `language` from `cfg.statusline.language` to top-level `cfg.language` (it doesn't belong with statusline toggles). The legacy location is still read as a fallback so existing configs migrate transparently. `mode` output also splits the statusline section from the output-language section.
|
|
201
|
+
|
|
181
202
|
### v2.9.0 (2026-04-27)
|
|
182
203
|
- **Output language is now configurable.** `last` / `history` / advice render in a single language at a time. English by default; switch with `claude-token-saver mode ko`. Statusline chips remain symbolic.
|
|
183
204
|
- History files stay bilingual on disk; the language toggle is applied at display time.
|
package/README.md
CHANGED
|
@@ -33,16 +33,20 @@ claude-token-saver install
|
|
|
33
33
|
์ค์น ํ Claude Code ํ๋จ statusline์ ์บ์ ์ํ๊ฐ 5์ด๋ง๋ค ๊ฐฑ์ ๋ฉ๋๋ค (postinstall์ด `~/.claude/settings.json`์ ์๋ ๋ฑ๋ก).
|
|
34
34
|
|
|
35
35
|
```
|
|
36
|
-
๐ค Opus 4.7 ยท ๐ง Cache hit 98.0% ยท โณ Cache expires
|
|
36
|
+
๐ค Opus 4.7 ยท ๐ง Cache hit 98.0% ยท โณ Cache expires 58:38 ยท โฆ current โโโโโโ 15% ๐ 08:50 ยท ๐
weekly โโโโโโ 24% ๐ Thu 13:00 ยท ๐ฆ Ctx 200k ยท ๐ฐ Cache saved $205 ยท last 1d
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
์ธ๊ทธ๋จผํธ โ `๐ค ๋ชจ๋ธ` ยท `๐ง ์บ์ ํํธ์จ` ยท `โณ TTL ์นด์ดํธ๋ค์ด` ยท `โฆ current` (5์๊ฐ ์๋) ยท `๐
weekly` (7์ผ ์๋) ยท `๐ฆ ์ปจํ
์คํธ` ยท `๐ฐ ๋์ ์ ๊ฐ์ก` ยท `last <๊ธฐ๊ฐ>`.
|
|
40
|
+
|
|
41
|
+
ํ ํฐ์ด ๊ณผ๋ํ๊ฒ ์ฌ์ฉ๋๋ ์ํฉ์ด ๊ฐ์ง๋๋ฉด ๊ฒฝ๊ณ ์นฉ์ด ๋งจ ์์ ๋
ธ์ถ๋ฉ๋๋ค.
|
|
40
42
|
|
|
41
43
|
```
|
|
42
|
-
๐จ 5H 94% (resets in 12m) ยท ๐ค Opus 4.7 ยท ๐ง Cache hit 72.1% ยท โ Cache miss ยท ๐ฆ Ctx 200k ยท last 1d
|
|
44
|
+
๐จ 5H 94% (resets in 12m) ยท ๐ค Opus 4.7 ยท ๐ง Cache hit 72.1% ยท โ Cache miss ยท โฆ current โโโโโโ 94% ยท ๐ฆ Ctx 200k ยท last 1d
|
|
43
45
|
```
|
|
44
46
|
|
|
45
|
-
|
|
47
|
+
๊ฒฝ๊ณ ์นฉ ์ข
๋ฅ โ `๐จ 5H/7D NN%`, `โ 1M ON`, `โ Input spike`, `โ Cache miss`, `โ 5m TTL`, `โ Rebuild churn`, `โ Output heavy`, `โ Call surge`.
|
|
48
|
+
|
|
49
|
+
**ํด์ผ ํ ์ผ** โ Claude์์ `/claude-token-saver` Skill์ ์คํํ๋ฉด ๋ฉ๋๋ค. Skill์ด `claude-token-saver last`๋ฅผ ํธ์ถํด ์์ธ ์ฝ๋์ ๋จ๊ณ๋ณ ํด๊ฒฐ ๋ช
๋ น์ ์๋์ผ๋ก ๋ณด์ฌ์ค๋๋ค. ์นฉ ๋ฌธ๊ตฌ(์: "5H cap ๋ด์ด", "cache miss")๋ง ๋งํด๋ ๋์ผํ Skill์ด ์๋ ํ์ฑํ๋ฉ๋๋ค. ์์ธํ ํ๋ฆ์ ์๋ [Skill ์ํฌํ๋ก](#๊ฒฝ๊ณ -์นฉ์ด-๋ด์-๋--skill-์ํฌํ๋ก) ์ฐธ๊ณ .
|
|
46
50
|
|
|
47
51
|
์๋ ๋ฑ๋ก์ด ํ์ํ ๊ฒฝ์ฐ(๋ค๋ฅธ statusline์ ์ด๋ฏธ ์ฐ๊ณ ์์ด postinstall์ด ๊ฑด๋๋ด ๊ฒฝ์ฐ ๋ฑ):
|
|
48
52
|
|
|
@@ -58,9 +62,16 @@ claude-token-saver install
|
|
|
58
62
|
|
|
59
63
|
`refreshInterval: 5`๋ idle ์ํ์์๋ TTL ์นด์ดํธ๋ค์ด์ 5์ด๋ง๋ค ๊ฐฑ์ ํฉ๋๋ค. Windows(PowerShell)๋ `examples/statusline-command.ps1` ์ฐธ๊ณ .
|
|
60
64
|
|
|
61
|
-
##
|
|
65
|
+
## ๊ฒฝ๊ณ ์นฉ์ด ๋ด์ ๋ โ Skill ์ํฌํ๋ก
|
|
66
|
+
|
|
67
|
+
์ค์น ์ ํจ๊ป ๋ฑ๋ก๋๋ Claude Code Skill์ด "๊ฒฝ๊ณ ์นฉ โ ์ฒ๋ฐฉ"์ ๋ค๋ฆฌ ์ญํ ์ ํฉ๋๋ค.
|
|
68
|
+
|
|
69
|
+
1. **statusline์ ๊ฒฝ๊ณ ์นฉ์ด ๋ฌ๋ค** โ ์: `๐จ 5H 94%`, `โ Cache miss`, `โ 1M ON`.
|
|
70
|
+
2. **`/claude-token-saver` Skill์ ์คํํ๋ค** โ Claude์์ ์ฌ๋์๋ก Skill์ ์ง์ ํธ์ถํ๋ ๊ฒ ๊ฐ์ฅ ๊ฐ๋จํฉ๋๋ค. ๋๋ ์นฉ ๋ฌธ๊ตฌ๋ฅผ ๊ทธ๋๋ก ๋งํด๋ ๋์ผํ Skill์ด ์๋ ํ์ฑํ๋ฉ๋๋ค ("5H cap ๋ด์ด", "cache miss ๋ด์ด", "1M context ์ ์ผ์ก์ง?" ๋ฑ โ ์นฉ ํ
์คํธ๊ฐ ํธ๋ฆฌ๊ฑฐ ๋จ์ด๋ก ๋ฑ๋ก๋ผ ์์).
|
|
71
|
+
3. **Skill์ด ์ฒ๋ฐฉ์ ๊ฐ์ ธ์จ๋ค** โ ๋ด๋ถ์ ์ผ๋ก `claude-token-saver last`๋ฅผ ์คํํด ๊ฐ์ฅ ์ต๊ทผ ๊ฒฝ๊ณ + ์์ธ ์ฝ๋ + ๋จ๊ณ๋ณ ํด๊ฒฐ ๋ช
๋ น์ ํ ๋ฒ์ ๋ณด์ฌ์ฃผ๊ณ , ์บก ์๋ฐ ์์๋ `claude-token-saver handoff`๋ก ํ์ฌ ์์
๋ฐฑ์
์ ๊ถํฉ๋๋ค.
|
|
72
|
+
4. **์๋ ํ์ธ์ด ํ์ํ๋ฉด** โ `claude-token-saver last` (์ต๊ทผ 1๊ฑด), `claude-token-saver history` (์ต๊ทผ 7์ผ ์ ์ด ๋ก๊ทธ), `claude-token-saver handoff` (cap ์ง์ ๋ฐฑ์
)๋ฅผ ์ง์ ์คํํด๋ ๊ฐ์ ์ ๋ณด๋ฅผ ์ป์ ์ ์์ต๋๋ค.
|
|
62
73
|
|
|
63
|
-
|
|
74
|
+
> v2.6.0์์ ๋ ๊ฑฐ์ `/token-monitor` ์ฌ๋์ ์ปค๋งจ๋๋ ์ด Skill๋ก ํก์๋์ต๋๋ค. ์ด์ ๋ฒ์ ์ฌ์ฉ์๋ `claude-token-saver install`์ ํ ๋ฒ ๋ ์คํํ๋ฉด ์๋ ์ ๋ฆฌ๋ฉ๋๋ค.
|
|
64
75
|
|
|
65
76
|
## ๋จ๋ฐ ๋ฆฌํฌํธ
|
|
66
77
|
|
|
@@ -90,6 +101,8 @@ claude-token-saver mode # ํ์ฌ ์ค์ ํ์ธ
|
|
|
90
101
|
|
|
91
102
|
## ์ฃผ์ ๋ช
๋ น
|
|
92
103
|
|
|
104
|
+
์๋ ๋ช
๋ น์ ๋ชจ๋ **์
ธ(ํฐ๋ฏธ๋)์์ ์ง์ ์คํ**ํฉ๋๋ค. Claude Code ์ธ์
์์์๋ `/claude-token-saver` Skill ํ๋๋ง ์ฐ๋ฉฐ, Skill์ด ๋ด๋ถ์ ์ผ๋ก ์ด ๋ช
๋ น๋ค์ ํธ์ถํฉ๋๋ค. `--statusline` ํ์์ Claude Code๊ฐ statusline ๊ฐฑ์ ๋ง๋ค ์๋์ผ๋ก ํธ์ถํ๋ฏ๋ก ์ฌ์ฉ์๊ฐ ์ง์ ์
๋ ฅํ์ง ์์ต๋๋ค.
|
|
105
|
+
|
|
93
106
|
| ๋ช
๋ น | ์ค๋ช
|
|
|
94
107
|
|---|---|
|
|
95
108
|
| `claude-token-saver` | ์ต๊ทผ 1์ผ ์ง๋จ ๋ฆฌํฌํธ (`--days N`๋ก ๊ธฐ๊ฐ ๋ณ๊ฒฝ) |
|
|
@@ -138,6 +151,14 @@ Node.js โฅ 18 ยท macOS / Linux / Windows / WSL ยท ์์กด์ฑ 0.
|
|
|
138
151
|
|
|
139
152
|
## ๋ฆด๋ฆฌ์ค ๋
ธํธ
|
|
140
153
|
|
|
154
|
+
### v2.9.2 (2026-04-27)
|
|
155
|
+
- `last`/`history`๊ฐ ๊ฒฝ๊ณ ์์ ๋ ์ถ๋ ฅํ๋ ์๋ด ๋ฌธ๊ตฌ๋ ์ธ์ด ์ค์ ์ ๋ฐ๋ฅด๋๋ก ์์ (์ด์ ์ ํญ์ ์๋ฌธ ์ถ๋ ฅ โ ํ๊ตญ์ด ๋ชจ๋์ธ๋ฐ๋ ์๋ฌธ์ด ๋ณด์ด๋ ๋ฒ๊ทธ).
|
|
156
|
+
|
|
157
|
+
### v2.9.1 (2026-04-27)
|
|
158
|
+
- README์ statusline ์์๋ฅผ ์ค์ ์ถ๋ ฅ(`โฆ current` / `๐
weekly` ์๋ ์ธ๊ทธ๋จผํธ ํฌํจ)์ผ๋ก ์ ์ .
|
|
159
|
+
- "๊ฒฝ๊ณ ์นฉ์ด ๋ด์ ๋" Skill ์ํฌํ๋ก 4๋จ๊ณ ๊ฐ์ด๋ ์ถ๊ฐ โ ์นฉ ๋ฐ๊ฒฌ โ Claude์๊ฒ ์นฉ ๋ฌธ๊ตฌ ๊ทธ๋๋ก ๋งํ๊ธฐ โ Skill์ด `last` ์คํ โ ์ฒ๋ฐฉ ์ ์ฉ.
|
|
160
|
+
- `language` ์ค์ ์์น๋ฅผ `cfg.statusline` ํ์์์ top-level `cfg.language`๋ก ์ด๋(statusline ํ ๊ธ์ด ์๋๋ฏ๋ก). ๊ตฌ๋ฒ์ ์์น๋ fallback์ผ๋ก ๊ณ์ ์ฝ์ด ๋ง์ด๊ทธ๋ ์ด์
์ ์๋. `mode` ์ถ๋ ฅ๋ statusline / output language๋ฅผ ๋ถ๋ฆฌํด์ ํ์.
|
|
161
|
+
|
|
141
162
|
### v2.9.0 (2026-04-27)
|
|
142
163
|
- **์ถ๋ ฅ ์ธ์ด ์ ํ ์ถ๊ฐ** โ `last` / `history` / ์ฒ๋ฐฉ ๋ฉ์์ง๊ฐ ํ ๋ฒ์ ํ ์ธ์ด๋ง ์ถ๋ ฅํฉ๋๋ค. ๊ธฐ๋ณธ์ ์์ด, `claude-token-saver mode ko`๋ก ํ๊ตญ์ด ์ ํ (statusline ์นฉ์ ์ํฅ ์์).
|
|
143
164
|
- ๊ธฐ์กด history ํ์ผ์ ์ด์ค์ธ์ด๋ก ๋ณด๊ด๋๋ฉฐ, ํ์ํ ๋ ์ ํํ ์ธ์ด๋ง ํํฐ๋ง๋ฉ๋๋ค.
|
package/bin/cli.js
CHANGED
|
@@ -236,8 +236,13 @@ async function main() {
|
|
|
236
236
|
const recent = readRecent(days);
|
|
237
237
|
const latest = findLatestWarning(recent, CHIP_TO_CODES);
|
|
238
238
|
if (!latest) {
|
|
239
|
-
|
|
240
|
-
|
|
239
|
+
if (lang === 'ko') {
|
|
240
|
+
console.log(`์ต๊ทผ ${days}์ผ ๋ด ๊ฒฝ๊ณ ๊ฐ ์์ต๋๋ค.`);
|
|
241
|
+
console.log(`(ํ์คํ ๋ฆฌ ๋๋ ํฐ๋ฆฌ: ${historyDir()})`);
|
|
242
|
+
} else {
|
|
243
|
+
console.log(`No warnings in the last ${days} day${days === 1 ? '' : 's'}.`);
|
|
244
|
+
console.log(`(History dir: ${historyDir()})`);
|
|
245
|
+
}
|
|
241
246
|
return;
|
|
242
247
|
}
|
|
243
248
|
// Header
|
|
@@ -303,18 +308,25 @@ async function main() {
|
|
|
303
308
|
if (hasFlag('--list')) {
|
|
304
309
|
const dates = listDates();
|
|
305
310
|
if (dates.length === 0) {
|
|
306
|
-
console.log(
|
|
311
|
+
console.log(lang === 'ko'
|
|
312
|
+
? `ํ์คํ ๋ฆฌ๊ฐ ์์ง ์์ต๋๋ค. ํ์ผ์ ๋ค์ ์์น์ ์์ฑ๋ฉ๋๋ค: ${historyDir()}`
|
|
313
|
+
: `No history yet. Files will appear under: ${historyDir()}`);
|
|
307
314
|
return;
|
|
308
315
|
}
|
|
309
|
-
console.log(`History (${historyDir()}):`);
|
|
316
|
+
console.log(lang === 'ko' ? `ํ์คํ ๋ฆฌ (${historyDir()}):` : `History (${historyDir()}):`);
|
|
310
317
|
for (const d of dates) console.log(` ${d}`);
|
|
311
318
|
return;
|
|
312
319
|
}
|
|
313
320
|
const days = parseFloat(getArg('--days') || '7');
|
|
314
321
|
const recent = readRecent(days);
|
|
315
322
|
if (recent.length === 0) {
|
|
316
|
-
|
|
317
|
-
|
|
323
|
+
if (lang === 'ko') {
|
|
324
|
+
console.log(`์ต๊ทผ ${days}์ผ ๋ด ๊ฒฝ๊ณ ํ์คํ ๋ฆฌ๊ฐ ์์ต๋๋ค.`);
|
|
325
|
+
console.log(`(ํ์ผ์ด ์์ฑ๋ ์์น: ${historyDir()})`);
|
|
326
|
+
} else {
|
|
327
|
+
console.log(`No warning history in the last ${days} day${days === 1 ? '' : 's'}.`);
|
|
328
|
+
console.log(`(Files would be written to: ${historyDir()})`);
|
|
329
|
+
}
|
|
318
330
|
return;
|
|
319
331
|
}
|
|
320
332
|
for (const { content } of recent) {
|
|
@@ -396,21 +408,23 @@ async function main() {
|
|
|
396
408
|
// claude-token-saver mode icon verbose # set icon + verbose
|
|
397
409
|
// claude-token-saver mode reset # clear back to defaults
|
|
398
410
|
if (args[0] === 'mode') {
|
|
399
|
-
const { applyMode, loadConfig, configPath, statuslineDefaults, VALID_KEYWORDS } =
|
|
411
|
+
const { applyMode, loadConfig, configPath, statuslineDefaults, userLanguage, VALID_KEYWORDS } =
|
|
400
412
|
await import('../src/config.js');
|
|
401
413
|
const words = args.slice(1);
|
|
402
414
|
if (words.length === 0) {
|
|
403
415
|
const eff = statuslineDefaults();
|
|
404
|
-
const raw = loadConfig()
|
|
405
|
-
console.log('Statusline
|
|
406
|
-
console.log(` icon:
|
|
407
|
-
console.log(` verbose:
|
|
408
|
-
console.log(` timer:
|
|
409
|
-
console.log(` color:
|
|
410
|
-
console.log(`
|
|
411
|
-
console.log(
|
|
416
|
+
const raw = loadConfig();
|
|
417
|
+
console.log('Statusline (effective):');
|
|
418
|
+
console.log(` icon: ${eff.icon}`);
|
|
419
|
+
console.log(` verbose: ${eff.verbose}`);
|
|
420
|
+
console.log(` timer: ${eff.timer}`);
|
|
421
|
+
console.log(` color: ${eff.color}`);
|
|
422
|
+
console.log(` window: ${eff.windowLabel} (${eff.windowHours}h)`);
|
|
423
|
+
console.log('');
|
|
424
|
+
console.log('Output language (advice / history / last):');
|
|
425
|
+
console.log(` language: ${userLanguage()}`);
|
|
412
426
|
console.log('');
|
|
413
|
-
console.log(`Stored config (${configPath()}):`);
|
|
427
|
+
console.log(`Stored config file (${configPath()}):`);
|
|
414
428
|
console.log(` ${Object.keys(raw).length === 0 ? '(none โ using defaults)' : JSON.stringify(raw)}`);
|
|
415
429
|
console.log('');
|
|
416
430
|
console.log('Change with: claude-token-saver mode <keywords...>');
|
|
@@ -425,7 +439,7 @@ async function main() {
|
|
|
425
439
|
}
|
|
426
440
|
const eff = statuslineDefaults();
|
|
427
441
|
console.log(`Updated: ${applied.join(', ')}`);
|
|
428
|
-
console.log(`Now: icon=${eff.icon} verbose=${eff.verbose} timer=${eff.timer} color=${eff.color}
|
|
442
|
+
console.log(`Now: icon=${eff.icon} verbose=${eff.verbose} timer=${eff.timer} color=${eff.color} window=${eff.windowLabel} language=${userLanguage()}`);
|
|
429
443
|
console.log('Statusline picks up the change on the next refresh (~1s).');
|
|
430
444
|
return;
|
|
431
445
|
}
|
package/package.json
CHANGED
package/src/config.js
CHANGED
|
@@ -36,6 +36,7 @@ export function saveConfig(cfg) {
|
|
|
36
36
|
|
|
37
37
|
// Each keyword maps to a single statusline option toggle.
|
|
38
38
|
// Orthogonal โ `mode icon verbose` flips both without resetting the rest.
|
|
39
|
+
// Statusline-only toggles. Stored under `cfg.statusline`.
|
|
39
40
|
const KEYWORDS = {
|
|
40
41
|
icon: { key: 'icon', value: true },
|
|
41
42
|
text: { key: 'icon', value: false },
|
|
@@ -45,12 +46,16 @@ const KEYWORDS = {
|
|
|
45
46
|
'no-timer': { key: 'timer', value: false },
|
|
46
47
|
color: { key: 'color', value: true },
|
|
47
48
|
'no-color': { key: 'color', value: false },
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// Output language for `last`/`history`/advice. Stored at top level
|
|
52
|
+
// (`cfg.language`) because it has nothing to do with statusline rendering โ
|
|
53
|
+
// the chips themselves stay symbolic regardless.
|
|
54
|
+
const LANG_KEYWORDS = {
|
|
55
|
+
en: 'en',
|
|
56
|
+
english: 'en',
|
|
57
|
+
ko: 'ko',
|
|
58
|
+
korean: 'ko',
|
|
54
59
|
};
|
|
55
60
|
|
|
56
61
|
// Window preset accepts forms like:
|
|
@@ -71,13 +76,15 @@ function parseWindow(word) {
|
|
|
71
76
|
return null;
|
|
72
77
|
}
|
|
73
78
|
|
|
74
|
-
export const VALID_KEYWORDS = Object.keys(KEYWORDS)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
export const VALID_KEYWORDS = Object.keys(KEYWORDS)
|
|
80
|
+
.concat(Object.keys(LANG_KEYWORDS))
|
|
81
|
+
.concat([
|
|
82
|
+
'<N>h (e.g. 1h, 6h, 24h)',
|
|
83
|
+
'<N>d (e.g. 1d, 7d, 30d)',
|
|
84
|
+
'lang=en | lang=ko',
|
|
85
|
+
'reset',
|
|
86
|
+
'default',
|
|
87
|
+
]);
|
|
81
88
|
|
|
82
89
|
/**
|
|
83
90
|
* Apply user-supplied mode keywords to the persisted config.
|
|
@@ -94,16 +101,25 @@ export function applyMode(words) {
|
|
|
94
101
|
const lower = String(w).toLowerCase();
|
|
95
102
|
if (lower === 'reset' || lower === 'default') {
|
|
96
103
|
cfg.statusline = {};
|
|
104
|
+
delete cfg.language;
|
|
97
105
|
applied.push(lower);
|
|
98
106
|
continue;
|
|
99
107
|
}
|
|
100
108
|
const langMatch = lower.match(/^lang(?:uage)?=(en|english|ko|korean)$/);
|
|
101
109
|
if (langMatch) {
|
|
102
110
|
const v = langMatch[1].startsWith('k') ? 'ko' : 'en';
|
|
103
|
-
cfg.
|
|
111
|
+
cfg.language = v;
|
|
112
|
+
// Migrate any legacy value that lived under cfg.statusline.language.
|
|
113
|
+
if (cfg.statusline) delete cfg.statusline.language;
|
|
104
114
|
applied.push(`lang=${v}`);
|
|
105
115
|
continue;
|
|
106
116
|
}
|
|
117
|
+
if (LANG_KEYWORDS[lower]) {
|
|
118
|
+
cfg.language = LANG_KEYWORDS[lower];
|
|
119
|
+
if (cfg.statusline) delete cfg.statusline.language;
|
|
120
|
+
applied.push(`lang=${cfg.language}`);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
107
123
|
const hours = parseWindow(lower);
|
|
108
124
|
if (hours !== null && hours > 0) {
|
|
109
125
|
cfg.statusline.windowHours = hours;
|
|
@@ -150,7 +166,6 @@ export function statuslineDefaults() {
|
|
|
150
166
|
verbose: s.verbose !== false,
|
|
151
167
|
timer: s.timer !== false,
|
|
152
168
|
color: s.color !== false,
|
|
153
|
-
language: s.language === 'ko' ? 'ko' : 'en',
|
|
154
169
|
windowHours,
|
|
155
170
|
windowLabel: formatWindow(windowHours),
|
|
156
171
|
};
|
|
@@ -158,9 +173,13 @@ export function statuslineDefaults() {
|
|
|
158
173
|
|
|
159
174
|
// Resolve the user's preferred output language for advice/history/last.
|
|
160
175
|
// Returns 'en' or 'ko'; defaults to 'en' for first-time users.
|
|
176
|
+
// Reads `cfg.language` (current location) with a fallback to the legacy
|
|
177
|
+
// `cfg.statusline.language` slot so configs from earlier 2.9.x installs
|
|
178
|
+
// keep working.
|
|
161
179
|
export function userLanguage() {
|
|
162
|
-
const
|
|
163
|
-
|
|
180
|
+
const cfg = loadConfig();
|
|
181
|
+
const v = cfg.language || (cfg.statusline && cfg.statusline.language);
|
|
182
|
+
return v === 'ko' ? 'ko' : 'en';
|
|
164
183
|
}
|
|
165
184
|
|
|
166
185
|
/**
|