claude-token-saver 2.9.0 โ†’ 2.9.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.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 59:51 ยท ๐Ÿ“ฆ Ctx 200k ยท ๐Ÿ’ฐ Cache saved $221 ยท last 1d
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
- Risk chips lead when something's wrong:
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
- ## Skill โ€” mention a chip, it activates
65
+ ## When a warning chip appears โ€” Skill workflow
66
+
67
+ The Claude Code Skill registered at install time bridges "warning chip โ†’ remediation":
62
68
 
63
- The Claude Code Skill registered at install time auto-activates whenever you mention chip wording in chat ("cache hit rate", "1M context", "5H cap"). It runs `claude-token-saver last` to surface the most recent warning + remediation, then points you at `history` / `handoff` for follow-up. (v2.6.0 folded the legacy `/token-monitor` slash command into this Skill โ€” older installs are cleaned up automatically the next time you run `claude-token-saver install`.)
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.
73
+
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,11 @@ Node.js โ‰ฅ 18 ยท macOS / Windows / Linux / WSL ยท zero dependencies.
178
191
 
179
192
  ## Release notes
180
193
 
194
+ ### v2.9.1 (2026-04-27)
195
+ - Fix the README statusline sample so it matches actual output (includes the `โœฆ current` / `๐Ÿ“… weekly` window segments that were missing).
196
+ - Add a 4-step "When a warning chip appears" Skill workflow โ€” spot the chip โ†’ mention its wording to Claude โ†’ Skill runs `last` โ†’ apply remediation.
197
+ - 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.
198
+
181
199
  ### v2.9.0 (2026-04-27)
182
200
  - **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
201
  - 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 59:51 ยท ๐Ÿ“ฆ Ctx 200k ยท ๐Ÿ’ฐ Cache saved $221 ยท last 1d
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
- ํ‘œ์‹œ๋˜๋Š” ๊ฒฝ๊ณ  ์นฉ โ€” `๐Ÿšจ 5H/7D NN%`, `โš  1M ON`, `โš  Input spike`, `โš  Cache miss`, `โš  5m TTL`, `โš  Rebuild churn`, `โš  Output heavy`, `โš  Call surge`.
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
- ## Skill โ€” ์นฉ์„ ์–ธ๊ธ‰ํ•˜๋ฉด ์ž๋™ ํ™œ์„ฑํ™”
65
+ ## ๊ฒฝ๊ณ  ์นฉ์ด ๋–ด์„ ๋•Œ โ€” Skill ์›Œํฌํ”Œ๋กœ
66
+
67
+ ์„ค์น˜ ์‹œ ํ•จ๊ป˜ ๋“ฑ๋ก๋˜๋Š” Claude Code Skill์ด "๊ฒฝ๊ณ  ์นฉ โ†’ ์ฒ˜๋ฐฉ"์˜ ๋‹ค๋ฆฌ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
62
68
 
63
- ์„ค์น˜ ์‹œ ํ•จ๊ป˜ ๋“ฑ๋ก๋˜๋Š” Claude Code Skill ๋•๋ถ„์— ๋Œ€ํ™” ์ค‘ "cache hit rate", "1M context", "5H cap" ๊ฐ™์€ ์นฉ ๋‹จ์–ด๋ฅผ ์–ธ๊ธ‰ํ•˜๋ฉด Claude๊ฐ€ ์ž๋™์œผ๋กœ `claude-token-saver last`๋ฅผ ์‹คํ–‰ํ•ด ๊ฐ€์žฅ ์ตœ๊ทผ ๊ฒฝ๊ณ ์™€ ์ฒ˜๋ฐฉ์„ ๋ณด์—ฌ์ฃผ๊ณ , ํ•„์š” ์‹œ `history` / `handoff`๋กœ ํ›„์† ์กฐ์น˜๋ฅผ ์•ˆ๋‚ดํ•ฉ๋‹ˆ๋‹ค. (v2.6.0์—์„œ ๋ ˆ๊ฑฐ์‹œ `/token-monitor` ์Šฌ๋ž˜์‹œ ์ปค๋งจ๋“œ๋Š” Skill๋กœ ํก์ˆ˜๋์Šต๋‹ˆ๋‹ค โ€” ์ด์ „ ๋ฒ„์ „ ์‚ฌ์šฉ์ž๋Š” `claude-token-saver install`์„ ํ•œ ๋ฒˆ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋ฉด ์ž๋™ ์ •๋ฆฌ๋ฉ๋‹ˆ๋‹ค.)
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 ์ง์ „ ๋ฐฑ์—…)๋ฅผ ์ง์ ‘ ์‹คํ–‰ํ•ด๋„ ๊ฐ™์€ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
73
+
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,11 @@ Node.js โ‰ฅ 18 ยท macOS / Linux / Windows / WSL ยท ์˜์กด์„ฑ 0.
138
151
 
139
152
  ## ๋ฆด๋ฆฌ์Šค ๋…ธํŠธ
140
153
 
154
+ ### v2.9.1 (2026-04-27)
155
+ - README์˜ statusline ์˜ˆ์‹œ๋ฅผ ์‹ค์ œ ์ถœ๋ ฅ(`โœฆ current` / `๐Ÿ“… weekly` ์œˆ๋„ ์„ธ๊ทธ๋จผํŠธ ํฌํ•จ)์œผ๋กœ ์ •์ •.
156
+ - "๊ฒฝ๊ณ  ์นฉ์ด ๋–ด์„ ๋•Œ" Skill ์›Œํฌํ”Œ๋กœ 4๋‹จ๊ณ„ ๊ฐ€์ด๋“œ ์ถ”๊ฐ€ โ€” ์นฉ ๋ฐœ๊ฒฌ โ†’ Claude์—๊ฒŒ ์นฉ ๋ฌธ๊ตฌ ๊ทธ๋Œ€๋กœ ๋งํ•˜๊ธฐ โ†’ Skill์ด `last` ์‹คํ–‰ โ†’ ์ฒ˜๋ฐฉ ์ ์šฉ.
157
+ - `language` ์„ค์ • ์œ„์น˜๋ฅผ `cfg.statusline` ํ•˜์œ„์—์„œ top-level `cfg.language`๋กœ ์ด๋™(statusline ํ† ๊ธ€์ด ์•„๋‹ˆ๋ฏ€๋กœ). ๊ตฌ๋ฒ„์ „ ์œ„์น˜๋„ fallback์œผ๋กœ ๊ณ„์† ์ฝ์–ด ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์€ ์ž๋™. `mode` ์ถœ๋ ฅ๋„ statusline / output language๋ฅผ ๋ถ„๋ฆฌํ•ด์„œ ํ‘œ์‹œ.
158
+
141
159
  ### v2.9.0 (2026-04-27)
142
160
  - **์ถœ๋ ฅ ์–ธ์–ด ์ „ํ™˜ ์ถ”๊ฐ€** โ€” `last` / `history` / ์ฒ˜๋ฐฉ ๋ฉ”์‹œ์ง€๊ฐ€ ํ•œ ๋ฒˆ์— ํ•œ ์–ธ์–ด๋งŒ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์€ ์˜์–ด, `claude-token-saver mode ko`๋กœ ํ•œ๊ตญ์–ด ์ „ํ™˜ (statusline ์นฉ์€ ์˜ํ–ฅ ์—†์Œ).
143
161
  - ๊ธฐ์กด history ํŒŒ์ผ์€ ์ด์ค‘์–ธ์–ด๋กœ ๋ณด๊ด€๋˜๋ฉฐ, ํ‘œ์‹œํ•  ๋•Œ ์„ ํƒํ•œ ์–ธ์–ด๋งŒ ํ•„ํ„ฐ๋ง๋ฉ๋‹ˆ๋‹ค.
package/bin/cli.js CHANGED
@@ -396,21 +396,23 @@ async function main() {
396
396
  // claude-token-saver mode icon verbose # set icon + verbose
397
397
  // claude-token-saver mode reset # clear back to defaults
398
398
  if (args[0] === 'mode') {
399
- const { applyMode, loadConfig, configPath, statuslineDefaults, VALID_KEYWORDS } =
399
+ const { applyMode, loadConfig, configPath, statuslineDefaults, userLanguage, VALID_KEYWORDS } =
400
400
  await import('../src/config.js');
401
401
  const words = args.slice(1);
402
402
  if (words.length === 0) {
403
403
  const eff = statuslineDefaults();
404
- const raw = loadConfig().statusline || {};
405
- console.log('Statusline mode (effective):');
406
- console.log(` icon: ${eff.icon}`);
407
- console.log(` verbose: ${eff.verbose}`);
408
- console.log(` timer: ${eff.timer}`);
409
- console.log(` color: ${eff.color}`);
410
- console.log(` language: ${eff.language} (advice / history / last)`);
411
- console.log(` window: ${eff.windowLabel} (${eff.windowHours}h)`);
404
+ const raw = loadConfig();
405
+ console.log('Statusline (effective):');
406
+ console.log(` icon: ${eff.icon}`);
407
+ console.log(` verbose: ${eff.verbose}`);
408
+ console.log(` timer: ${eff.timer}`);
409
+ console.log(` color: ${eff.color}`);
410
+ console.log(` window: ${eff.windowLabel} (${eff.windowHours}h)`);
412
411
  console.log('');
413
- console.log(`Stored config (${configPath()}):`);
412
+ console.log('Output language (advice / history / last):');
413
+ console.log(` language: ${userLanguage()}`);
414
+ console.log('');
415
+ console.log(`Stored config file (${configPath()}):`);
414
416
  console.log(` ${Object.keys(raw).length === 0 ? '(none โ€” using defaults)' : JSON.stringify(raw)}`);
415
417
  console.log('');
416
418
  console.log('Change with: claude-token-saver mode <keywords...>');
@@ -425,7 +427,7 @@ async function main() {
425
427
  }
426
428
  const eff = statuslineDefaults();
427
429
  console.log(`Updated: ${applied.join(', ')}`);
428
- console.log(`Now: icon=${eff.icon} verbose=${eff.verbose} timer=${eff.timer} color=${eff.color} language=${eff.language} window=${eff.windowLabel}`);
430
+ console.log(`Now: icon=${eff.icon} verbose=${eff.verbose} timer=${eff.timer} color=${eff.color} window=${eff.windowLabel} language=${userLanguage()}`);
429
431
  console.log('Statusline picks up the change on the next refresh (~1s).');
430
432
  return;
431
433
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-token-saver",
3
- "version": "2.9.0",
3
+ "version": "2.9.1",
4
4
  "description": "Save tokens on Claude Code โ€” spike diagnosis, 1M-context detection, TTL countdown, statusline. (formerly claude-cache-monitor)",
5
5
  "type": "module",
6
6
  "bin": {
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
- // Language for advice / history / `last` output. Default is `en`.
49
- // Statusline chips themselves stay symbolic (e.g. `๐Ÿšจ 5H 94%`) regardless.
50
- en: { key: 'language', value: 'en' },
51
- english: { key: 'language', value: 'en' },
52
- ko: { key: 'language', value: 'ko' },
53
- korean: { key: 'language', value: 'ko' },
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).concat([
75
- '<N>h (e.g. 1h, 6h, 24h)',
76
- '<N>d (e.g. 1d, 7d, 30d)',
77
- 'lang=en | lang=ko',
78
- 'reset',
79
- 'default',
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.statusline.language = v;
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 s = loadConfig().statusline || {};
163
- return s.language === 'ko' ? 'ko' : 'en';
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
  /**