claude-token-saver 3.30.1 โ†’ 3.34.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/README.en.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/claude-token-saver.svg)](https://www.npmjs.com/package/claude-token-saver)
4
4
 
5
+ ๐ŸŒ **[Project page](https://rootstudioyaml.github.io/claude-token-saver/)**
6
+
5
7
  # claude-token-saver
6
8
 
7
9
  **Shows what it saved, on two lines.** It moves the easy work your expensive model keeps repeating onto cheaper ones, and turns documents the model cannot read into Markdown. Both figures are ledger entries rather than estimates, and whichever saved more takes the top line. Zero dependencies, one-line install.
@@ -112,13 +114,36 @@ Outside a terminal โ€” npm `postinstall`, CI, piped stdin โ€” the question is sk
112
114
 
113
115
  > โš ๏ธ Avoid `sudo` global installs โ€” the Skill lands in root's `~/.claude` instead of yours. Use nvm/fnm/Volta or `npm config set prefix ~/.npm-global`.
114
116
 
117
+ ### What the install turns on, and what stays manual
118
+
119
+ Everything that costs nothing until it is needed is on after a plain install. The only manual items are the ones that change Claude Code's own settings or need a human to pick a scope.
120
+
121
+ | Feature | After install | How to turn it off |
122
+ |---|---|---|
123
+ | statusline (diagnostic chips, savings ledger) | on | `claude-token-saver uninstall` |
124
+ | `/claude-token-saver` Skill | on | same |
125
+ | SessionStart hook (route-scan refresh) | on | same |
126
+ | UserPromptSubmit hook (brief injection) | on | same |
127
+ | First route-scan (last 14 days of logs) | runs once during the install | n/a |
128
+ | ๐Ÿ…ท Harness 5 principles (`~/.claude/CLAUDE.md`) | on (shown and confirmed once at a terminal) | `harness uninit --global`, `CTS_NO_HARNESS=1` |
129
+ | doc2md hooks (Read, Edit/Write, prompt) | on | `doc2md off`, `CTS_NO_DOC2MD=1` |
130
+ | doc2md converter (markitdown venv) | offered at a terminal; an unattended install prints the command | install later with `doc2md install-converter` |
131
+ | Korean writing guidance | on when the locale is Korean (asked at a terminal) | `korean off`, `CTS_NO_KOREAN=1` |
132
+ | compact-window warning chip | on | `compact-window off` |
133
+ | Update-available chip | on | `CTS_NO_UPDATE_CHECK=1` |
134
+ | **Pinning compact-window** (`autoCompactWindow` 500k) | **off โ€” run it yourself** | `compact-window set --global` or `--project` |
135
+ | **Model-fitting rules** (`ratchet-model.md` delegations) | **candidates are proposed only** | review and approve with `route-scan rules` |
136
+ | `handoff` (back up work before a cap) | an on-demand command | n/a |
137
+
138
+ `compact-window set` writes into Claude Code's `settings.json` and a human has to choose global or project scope, so it is never run for you. Model-fitting rules keep an approval step for the same reason: which work belongs on a cheaper tier is your call.
139
+
115
140
  ## Reading the statusline
116
141
 
117
142
  Once the savings ledger has entries it renders as **two rows** โ€” routing savings on row 1, diagnostics on row 2.
118
143
 
119
144
  ```
120
145
  ๐Ÿ”€ Routing saved $2.09 | fableโ†’sonnet 1ร— $0.72 ยท opusโ†’haiku 1ร— $0.57
121
- โš  Ctx 200k+ ยท ๐Ÿ…ท 5/5 ยท ๐Ÿค– Opus 5 ยท ๐Ÿง  Cache hit 98.8% ยท โณ Cache expires 59:46 ยท โœฆ current โ–ˆโ–ˆโ–ˆโ–“โ–‘โ–‘ 62% ๐Ÿ”„ 21:33 ยท ๐Ÿ“… weekly โ–ˆโ–ˆโ–’โ–‘โ–‘โ–‘ 38% ๐Ÿ”„ Tue 19:33 ยท ๐Ÿ“ฆ Ctx 47% of 1M ยท ๐Ÿ’ฐ Cache saved $1.0K ยท last 1d
146
+ โš  Ctx 500k+ ยท ๐Ÿ…ท 5/5 ยท ๐Ÿค– Opus 5 ยท ๐Ÿง  Cache hit 98.8% ยท โณ Cache expires 59:46 ยท โœฆ current โ–ˆโ–ˆโ–ˆโ–“โ–‘โ–‘ 62% ๐Ÿ”„ 21:33 ยท ๐Ÿ“… weekly โ–ˆโ–ˆโ–’โ–‘โ–‘โ–‘ 38% ๐Ÿ”„ Tue 19:33 ยท ๐Ÿ“ฆ Ctx 47% of 1M ยท ๐Ÿ’ฐ Cache saved $1.0K ยท last 1d
122
147
  ```
123
148
 
124
149
  With an empty ledger (no measured delegation yet) row 1 is not drawn and the layout stays single-line. If your build renders only the first row (some macOS Claude Code versions), pass `--single-line`.
@@ -142,7 +167,7 @@ When something is wrong, a **warning chip leads the line**:
142
167
  ๐Ÿšจ 5H โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–“ 94% ๐Ÿ”„ 12:36 ยท ๐Ÿ…ท 5/5 ยท ๐Ÿค– Opus 4.8 ยท ๐Ÿง  Cache hit 72.1% ยท โš  Cache miss ยท ๐Ÿ“… weekly โ–“โ–‘โ–‘โ–‘โ–‘โ–‘ 12% ๐Ÿ”„ Sun 14:26 ยท ๐Ÿ“ฆ Ctx 200k ยท last 1d
143
168
  ```
144
169
 
145
- Chips โ€” `๐Ÿšจ 5H/7D NN%` (cap imminent) ยท `โš  Ctx 200k+` (a single request actually exceeded 200k) ยท `โš  Cache miss` ยท `โš  Input spike` ยท `โš  Output heavy` ยท `โš  Call surge` ยท `โš  Rebuild churn` ยท `โš  5m TTL`. When both windows cross 90% at once, the sooner-resetting one is promoted to ๐Ÿšจ and the other stays visible as a red segment (v2.16.0+).
170
+ Chips โ€” `๐Ÿšจ 5H/7D NN%` (cap imminent) ยท `โš  Ctx 500k+` (a single request actually exceeded 500k) ยท `โš  Cache miss` ยท `โš  Input spike` ยท `โš  Output heavy` ยท `โš  Call surge` ยท `โš  Rebuild churn` ยท `โš  5m TTL`. When both windows cross 90% at once, the sooner-resetting one is promoted to ๐Ÿšจ and the other stays visible as a red segment (v2.16.0+).
146
171
 
147
172
  ### When a chip appears
148
173
 
@@ -175,7 +200,7 @@ Run these in your shell (inside Claude Code, the `/claude-token-saver` Skill is
175
200
  | `claude-token-saver install` | Manually register Skill + statusline |
176
201
  | `claude-token-saver uninstall [--purge]` | Remove the hooks, statusline and skill it registered. Recorded savings are kept unless `--purge` is given |
177
202
 
178
- Switch output language with `mode ko` / `mode en` (English default; statusline chips stay symbolic).
203
+ The output language is decided once, at install time: a terminal install proposes the system locale and asks whether to use Korean, while an unattended install records what the locale says. Once recorded it is never asked again, not even on an upgrade. Change it later with `mode ko` / `mode en`, or pin it for a scripted install with `CTS_LANG=ko` / `CTS_LANG=en`. Statusline chips stay symbolic either way.
179
204
 
180
205
  <details>
181
206
  <summary>All CLI options</summary>
@@ -214,6 +239,7 @@ Bootstrap five engineering principles (Ratchet ยท Evidence ยท PEV ยท Structured
214
239
  claude-token-saver harness init # this project
215
240
  claude-token-saver harness init --global # ~/.claude/CLAUDE.md โ€” every project
216
241
  claude-token-saver harness check # current score (global fallback honored)
242
+ claude-token-saver harness analyze # run the transcript analysis manually (no hook needed); refreshes harness-state.json
217
243
  claude-token-saver harness promote <N> --project|--global # warning #N โ†’ ratchet rule (scope required)
218
244
  claude-token-saver harness promote "<rule text>" --project|--global # register your own hand-written rules the same way
219
245
  claude-token-saver harness pull # register the package's curated ratchet rules into your global ratchet (opt-in, dedupes)
@@ -222,7 +248,8 @@ claude-token-saver harness off | on # toggle the ๐Ÿ…ท chip
222
248
  ```
223
249
 
224
250
  - `promote` **requires** `--project`/`--global` in non-TTY contexts (scripts, LLM calls) โ€” a scope choice is never silently made for the caller.
225
- - `pull` registers the **author-curated ratchet rules** bundled with the package (`presets/ratchet-rules.md` โ€” only general-purpose rules promoted from real recurring mistakes) into your global ratchet (`~/.claude/ratchet.md`). `install`/`init` never auto-inject anything; `pull` is always opt-in and idempotent. Drop any rule you dislike with `harness rm`.
251
+ - `pull` registers the **author-curated ratchet rules** bundled with the package (`presets/ratchet-rules.json` โ€” only general-purpose rules promoted from real recurring mistakes) into your global ratchet (`~/.claude/ratchet.md`). `install`/`init` never auto-inject anything; `pull` is always opt-in and idempotent. Drop any rule you dislike with `harness rm`.
252
+ - `seed` offers the same presets **one at a time**. Where `pull` registers the whole ratchet set in one go, `seed` covers the model-fitting presets too and asks about each of them in the first session after an install or upgrade ([below](#-seed-delegation-that-works-from-the-first-session)).
226
253
  - ๐Ÿ…ทโš  runtime warnings (`ratchet?` `no-evidence` `PEV-skip`) expire after 30 minutes, subdirectory sessions match their project correctly, and PEV-skip counts only mutating tools (Edit/Write/Bash) so read-only research sessions don't trip it (v2.16.0+).
227
254
 
228
255
  <details>
@@ -304,6 +331,32 @@ For environments the learner cannot reach, write the mapping yourself in `<userD
304
331
 
305
332
  That file holds internal identifiers in plain text โ€” do not commit it. On a direct-API machine it is never created and behaviour is unchanged.
306
333
 
334
+ ## ๐ŸŒฑ seed: delegation that works from the first session
335
+
336
+ The model-fitting ratchet (`ratchet-model.md`) **starts empty.** A rule exists only after route-scan has seen the same kind of work recur in your own logs and you have approved that candidate. So a fresh install delegates nothing, and keeps delegating nothing for days โ€” precisely the stretch where the savings would matter most.
337
+
338
+ `seed` fills that gap from presets bundled with the package.
339
+
340
+ | Presets | What they cover | File |
341
+ |---|---|---|
342
+ | 9 model-fitting | running commands, lookup, status checks, questions about pasted logs, read-and-summarize โ€” each with a T2 (haiku) and a T1 (sonnet) rule | `presets/model-rules.json` |
343
+ | 6 ratchet | general-purpose rules promoted from mistakes that actually recurred | `presets/ratchet-rules.json` |
344
+
345
+ **How they get registered:** in the first session after an install or upgrade, the SessionStart hook hands the pending presets to the model, which walks the user through them **one at a time**. Each answer runs one of these immediately:
346
+
347
+ ```bash
348
+ claude-token-saver seed # pending presets + recorded answers
349
+ claude-token-saver seed accept <id> --global|--project # register one (scope required)
350
+ claude-token-saver seed accept all --global # when the user says "register them all"
351
+ claude-token-saver seed skip <id> # decline โ€” never offered again
352
+ claude-token-saver seed reset # clear the answers and offer everything again
353
+ ```
354
+
355
+ - **Nothing is written without a yes to that specific rule.** A declined rule stays declined across upgrades; a later release only surfaces the presets it actually added.
356
+ - A preset is withheld when you already approved a rule of the same shape (same tier and category).
357
+ - A seeded rule **does not pass someone else's statistics off as yours.** It is recorded as `preset (curated)` until a scan measures real firings and delegations, and then those numbers replace it. If its delegated error rate crosses the threshold it gets the same review flag as any other rule.
358
+ - The scope must be stated as `--global` or `--project`. The hook environment is non-TTY, so the CLI cannot ask โ€” the model confirms with the user and passes the flag.
359
+
307
360
  ## ๐Ÿ‡ฐ๐Ÿ‡ท Korean writing guidance
308
361
 
309
362
  Injects guidance that corrects how Claude writes Korean (dropped sentence parts, noun-stopped sentences, translationese, em-dash overuse) **once per session.**
@@ -613,6 +666,24 @@ Also update `statusLine.command` in `~/.claude/settings.json` to `claude-token-s
613
666
 
614
667
  ## Release notes
615
668
 
669
+ ### v3.34.0 (2026-09-10)
670
+ - **The output language is chosen at install time.** With nothing recorded it used to fall back to English in silence, so a Korean user read English reports until they happened to find `mode ko`. A terminal install now proposes the system locale and asks whether to use Korean; an unattended install records what the locale says. Once recorded it is never asked again, and a scripted install can pin it with `CTS_LANG=ko|en`.
671
+ - **Fixed a locale-detection defect.** An explicit `LANG=en_US.UTF-8` was overruled on macOS, where detection went on to read the system locale (`AppleLocale`) and answered "Korean". A POSIX locale variable that is set now counts as the answer; the system locale is consulted only when all of them are empty, which is the macOS GUI-shell case the fallback was for.
672
+ - Language is the first step of the install, so the harness, doc2md and seed notices below it all print in the chosen language.
673
+
674
+ ### v3.33.0 (2026-09-10)
675
+ - **`seed`: delegation works from the first session.** The model-fitting ratchet started empty, so a fresh install delegated nothing for days โ€” until enough of the user's own history accumulated and a candidate was approved. The package now bundles **9 model-fitting presets** (`presets/model-rules.json`) and **6 ratchet presets** (`presets/ratchet-rules.json`), and the SessionStart hook hands the pending ones to the model in the first session after an install or upgrade so it can ask about them **one at a time**.
676
+ - **Answers are recorded for good.** A declined preset is not re-offered after an upgrade; only presets a later release actually added show up. A preset is withheld entirely when a rule of the same tier and category is already registered. Commands: `seed`, `seed accept <id> --global|--project`, `seed skip <id>`, `seed reset`.
677
+ - **A seeded rule does not report someone else's statistics as yours.** It reads `preset (curated)` until a scan measures real firings and delegations, then those numbers take over. Its delegated error rate gets the same review flag as any other rule.
678
+ - **Ratchet presets are bilingual now.** `presets/ratchet-rules.md` became `presets/ratchet-rules.json` with both languages per rule: the text is injected into the model's context, so a Korean-only rule pulled an English session's answers into Korean. Ids come from the Korean text, so revising an English wording keeps the user's answer.
679
+ - **One template for rule sentences.** route-scan and seed both compose through `modelRuleBaseText()`, so a reworded rule cannot mean two different things depending on which producer wrote it.
680
+
681
+ ### v3.32.0 (2026-09-10)
682
+ - **The context warning moved from 200k to 500k.** A brand-new session clears 200k from the system prompt plus a couple of file reads, so `โš  Ctx 200k+` was on almost permanently and therefore said nothing. The chip is now `โš  Ctx 500k+` and fires only when a single request really carried more than 500k input tokens. The `๐Ÿ“ฆ Ctx` segment also waits for 500k before turning yellow โ€” being on a 1M window is no longer a warning by itself.
683
+ - **Old history still resolves.** The legacy `โš  Ctx 200k+` chip and the old detail string (`Single-request context exceeded 200k`) are still parsed.
684
+ - **doc2md is enabled by the install.** Registering the hooks is two entries in `settings.json` and costs nothing until a document appears, yet until now only people who found `doc2md on` themselves benefited. The converter (a markitdown venv) takes minutes to build, so it is offered at a terminal and merely printed as a command on an unattended install. Opt out with `doc2md off` or `CTS_NO_DOC2MD=1`.
685
+ - **Documented which features the install turns on and which stay manual.** The only manual ones left are `compact-window set` (writes Claude Code settings and needs an explicit scope) and approving model-fitting rules.
686
+
616
687
  ### v3.27.0 (2026-09-04)
617
688
  - **A document path in the prompt is finally caught.** The 3.26.x `PreToolUse(Read)` hook never reached the formats it was written for: Claude Code refuses pptx/xlsx/docx as binary *before* running any hook. Measured โ€” a `.pdf` Read fires the hook, a `.pptx` Read in the same session leaves no hook log entry. Interception now also happens at `UserPromptSubmit`, which sees the raw prompt: paths there are converted and the conversion is handed back as context. `@path`, quoted and relative forms all count.
618
689
  - **A session-start note was added.** It tells the model two things it cannot work out alone: that a binary-file refusal is answered by `doc2md <path>`, and that if the user attached a document, they should be asked for a path next time. An attachment bills its entire contents into the context, and no hook event receives attachment content, so there is nothing the tool itself can do about it.
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/claude-token-saver.svg)](https://www.npmjs.com/package/claude-token-saver)
4
4
 
5
+ ๐ŸŒ **[ํ”„๋กœ์ ํŠธ ์†Œ๊ฐœ ํŽ˜์ด์ง€](https://rootstudioyaml.github.io/claude-token-saver/)**
6
+
5
7
  # claude-token-saver
6
8
 
7
9
  **์•„๋‚€ ๋ˆ์„ ๋‘ ์ค„๋กœ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค.** ๋น„์‹ผ ๋ชจ๋ธ์ด ๋ฐ˜๋ณตํ•˜๋˜ ์‰ฌ์šด ์ž‘์—…์„ ์‹ผ ๋ชจ๋ธ๋กœ ๋‚ด๋ ค๋ณด๋‚ด๊ณ , ๋ชจ๋ธ์ด ์ฝ์ง€ ๋ชปํ•˜๋Š” ๋ฌธ์„œ๋ฅผ Markdown ์œผ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค. ๋‘ ์ ˆ๊ฐ์•ก ๋ชจ๋‘ ์ถ”์ •์ด ์•„๋‹ˆ๋ผ ์›์žฅ ๊ธฐ๋ก์ด๊ณ , ๋” ๋งŽ์ด ์•„๋‚€ ์ชฝ์ด ์ฒซ ์ค„์„ ์ฐจ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์˜์กด์„ฑ 0, ์„ค์น˜ ํ•œ ์ค„.
@@ -111,13 +113,36 @@ npm i -g claude-token-saver
111
113
 
112
114
  > โš ๏ธ sudo๋กœ ๊ธ€๋กœ๋ฒŒ ์„ค์น˜๋ฅผ ํ•˜๋ฉด Skill์ด ์‚ฌ์šฉ์ž ๊ณ„์ •์ด ์•„๋‹ˆ๋ผ root์˜ `~/.claude`์— ๋“ฑ๋ก๋˜๋Š” ํ•จ์ •์ด ์žˆ์Šต๋‹ˆ๋‹ค. nvm์ด๋‚˜ fnm, Volta๋ฅผ ์‚ฌ์šฉํ•ด ์‚ฌ์šฉ์ž ์˜์—ญ์— ์„ค์น˜ํ•˜๊ธฐ๋ฅผ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
113
115
 
116
+ ### ์„ค์น˜ํ•˜๋ฉด ์ผœ์ง€๋Š” ๊ธฐ๋Šฅ๊ณผ ์ง์ ‘ ์ผœ์•ผ ํ•˜๋Š” ๊ธฐ๋Šฅ
117
+
118
+ ์„ค์น˜ ์‹œ์ ์— ๋น„์šฉ์ด ๋“ค์ง€ ์•Š๋Š” ๊ธฐ๋Šฅ์€ ์ „๋ถ€ ์ž๋™์œผ๋กœ ์ผœ์ง‘๋‹ˆ๋‹ค. ์ˆ˜๋™์œผ๋กœ ๋‚จ๊ฒจ ๋‘” ํ•ญ๋ชฉ์€ Claude Code ์ž์ฒด์˜ ์„ค์ •์„ ๋ฐ”๊พธ๊ฑฐ๋‚˜, ์ ์šฉ ๋ฒ”์œ„๋ฅผ ์‚ฌ๋žŒ์ด ์ •ํ•ด ์ฃผ์–ด์•ผ ํ•˜๋Š” ๊ฒƒ๋“ค๋ฟ์ž…๋‹ˆ๋‹ค.
119
+
120
+ | ๊ธฐ๋Šฅ | ์„ค์น˜ ์งํ›„ ์ƒํƒœ | ๋„๋Š” ๋ฐฉ๋ฒ• |
121
+ |---|---|---|
122
+ | statusline (์ง„๋‹จ ์นฉยท์ ˆ๊ฐ ์›์žฅ) | ์ผœ์ง | `claude-token-saver uninstall` |
123
+ | `/claude-token-saver` Skill | ์ผœ์ง | ์œ„์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค |
124
+ | SessionStart ํ›… (route-scan ์žฌ๋ถ„์„) | ์ผœ์ง | ์œ„์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค |
125
+ | UserPromptSubmit ํ›… (brief ์ฃผ์ž…) | ์ผœ์ง | ์œ„์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค |
126
+ | ์ตœ์ดˆ route-scan (์ตœ๊ทผ 14์ผ ๋กœ๊ทธ ๋ถ„์„) | ์„ค์น˜ ์ค‘ ์ฆ‰์‹œ 1ํšŒ ์‹คํ–‰ | ํ•ด๋‹น ์—†์Šต๋‹ˆ๋‹ค |
127
+ | ๐Ÿ…ท Harness 5์›์น™ (`~/.claude/CLAUDE.md`) | ์ผœ์ง (ํ„ฐ๋ฏธ๋„์—์„œ๋Š” ๋‚ด์šฉ์„ ๋ณด์—ฌ ์ฃผ๊ณ  ํ•œ ๋ฒˆ ๋ฌป์Šต๋‹ˆ๋‹ค) | `harness uninit --global` ยท `CTS_NO_HARNESS=1` |
128
+ | doc2md ํ›… (ReadยทEditยทWriteยทํ”„๋กฌํ”„ํŠธ) | ์ผœ์ง | `doc2md off` ยท `CTS_NO_DOC2MD=1` |
129
+ | doc2md ๋ณ€ํ™˜๊ธฐ(markitdown venv) | ํ„ฐ๋ฏธ๋„์—์„œ ์„ค์น˜ ์—ฌ๋ถ€๋ฅผ ๋ฌป๊ณ , ๋น„๋Œ€ํ™”ํ˜• ์„ค์น˜์—์„œ๋Š” ๋ช…๋ น๋งŒ ์•ˆ๋‚ดํ•ฉ๋‹ˆ๋‹ค | `doc2md install-converter` ๋กœ ๋‚˜์ค‘์— ์„ค์น˜ |
130
+ | ํ•œ๊ตญ์–ด ๋ฌธ์ฒด ์ง€์นจ | ์‹œ์Šคํ…œ ๋กœ์ผ€์ผ์ด ํ•œ๊ตญ์–ด๋ฉด ์ผœ์ง (ํ„ฐ๋ฏธ๋„์—์„œ๋Š” ๋ฌป์Šต๋‹ˆ๋‹ค) | `korean off` ยท `CTS_NO_KOREAN=1` |
131
+ | compact-window ๊ฒฝ๊ณ  ์นฉ | ์ผœ์ง | `compact-window off` |
132
+ | ์—…๋ฐ์ดํŠธ ์•ˆ๋‚ด ์นฉ | ์ผœ์ง | `CTS_NO_UPDATE_CHECK=1` |
133
+ | **compact-window ๊ฐ’ ๊ณ ์ •** (`autoCompactWindow` 500k) | **๊บผ์ง โ€” ์ง์ ‘ ์‹คํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค** | `compact-window set --global` ๋˜๋Š” `--project` |
134
+ | **๋ชจ๋ธ ํ”ผํŒ… ๋ฃฐ ์Šน์ธ** (`ratchet-model.md` ์œ„์ž„ ๋ฃฐ) | **ํ›„๋ณด๋งŒ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค** | `route-scan rules` ๋กœ ํ™•์ธํ•˜๊ณ  ์Šน์ธยท์‚ญ์ œ |
135
+ | `handoff` (ํ•œ๋„ ์ž„๋ฐ• ์‹œ ์ž‘์—… ๋ฐฑ์—…) | ํ•„์š”ํ•  ๋•Œ ์ง์ ‘ ์‹คํ–‰ํ•˜๋Š” ๋ช…๋ น์ž…๋‹ˆ๋‹ค | ํ•ด๋‹น ์—†์Šต๋‹ˆ๋‹ค |
136
+
137
+ `compact-window set` ์€ Claude Code ์˜ `settings.json` ์— ๊ฐ’์„ ์ ๊ณ , ์ „์—ญ๊ณผ ํ”„๋กœ์ ํŠธ ์ค‘ ์–ด๋””์— ์ ์„์ง€๋Š” ์‚ฌ๋žŒ์ด ์ •ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์ž๋™์œผ๋กœ ์‹คํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ชจ๋ธ ํ”ผํŒ… ๋ฃฐ๋„ ๊ฐ™์€ ์ด์œ ๋กœ ์Šน์ธ ๋‹จ๊ณ„๋ฅผ ๋‚จ๊ฒจ ๋‘์—ˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ค ์ž‘์—…์„ ๋” ์‹ผ ํ‹ฐ์–ด์— ๋งก๊ธธ์ง€๋Š” ์‚ฌ์šฉ์ž์˜ ํŒ๋‹จ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
138
+
114
139
  ## statusline ์ฝ๋Š” ๋ฒ•
115
140
 
116
141
  ์ ˆ๊ฐ ์›์žฅ์— ๊ธฐ๋ก์ด ์Œ“์ด๋ฉด statusline์ด **๋‘ ์ค„๋กœ** ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค. ์ฒซ์งธ ์ค„์—๋Š” ๋ผ์šฐํŒ… ์ ˆ๊ฐ์•ก๋งŒ ํ‘œ์‹œํ•˜๊ณ , ๋‘˜์งธ ์ค„์—๋Š” ์ง„๋‹จ ์นฉ์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
117
142
 
118
143
  ```
119
144
  ๐Ÿ”€ Routing saved $2.09 | fableโ†’sonnet 1ร— $0.72 ยท opusโ†’haiku 1ร— $0.57
120
- โš  Ctx 200k+ ยท ๐Ÿ…ท 5/5 ยท ๐Ÿค– Opus 5 ยท ๐Ÿง  Cache hit 98.8% ยท โณ Cache expires 59:46 ยท โœฆ current โ–ˆโ–ˆโ–ˆโ–“โ–‘โ–‘ 62% ๐Ÿ”„ 21:33 ยท ๐Ÿ“… weekly โ–ˆโ–ˆโ–’โ–‘โ–‘โ–‘ 38% ๐Ÿ”„ Tue 19:33 ยท ๐Ÿ“ฆ Ctx 47% of 1M ยท ๐Ÿ’ฐ Cache saved $1.0K ยท last 1d
145
+ โš  Ctx 500k+ ยท ๐Ÿ…ท 5/5 ยท ๐Ÿค– Opus 5 ยท ๐Ÿง  Cache hit 98.8% ยท โณ Cache expires 59:46 ยท โœฆ current โ–ˆโ–ˆโ–ˆโ–“โ–‘โ–‘ 62% ๐Ÿ”„ 21:33 ยท ๐Ÿ“… weekly โ–ˆโ–ˆโ–’โ–‘โ–‘โ–‘ 38% ๐Ÿ”„ Tue 19:33 ยท ๐Ÿ“ฆ Ctx 47% of 1M ยท ๐Ÿ’ฐ Cache saved $1.0K ยท last 1d
121
146
  ```
122
147
 
123
148
  ์›์žฅ์ด ๋น„์–ด ์žˆ์œผ๋ฉด, ๋‹ค์‹œ ๋งํ•ด ์•„์ง ์‹ค์ธก๋œ ์œ„์ž„์ด ์—†์œผ๋ฉด ์ฒซ์งธ ์ค„์„ ๊ทธ๋ฆฌ์ง€ ์•Š๊ณ  ์ข…์ „์ฒ˜๋Ÿผ ํ•œ ์ค„๋กœ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ถ€ ํ™˜๊ฒฝ(๊ตฌ๋ฒ„์ „ macOS Claude Code)์—์„œ ์ฒซ์งธ ์ค„๋งŒ ํ‘œ์‹œ๋œ๋‹ค๋ฉด `--single-line` ์˜ต์…˜์œผ๋กœ ํ•œ ์ค„ ๋ ˆ์ด์•„์›ƒ์„ ์œ ์ง€ํ•˜์‹ญ์‹œ์˜ค.
@@ -141,7 +166,7 @@ npm i -g claude-token-saver
141
166
  ๐Ÿšจ 5H โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–“ 94% ๐Ÿ”„ 12:36 ยท ๐Ÿ…ท 5/5 ยท ๐Ÿค– Opus 4.8 ยท ๐Ÿง  Cache hit 72.1% ยท โš  Cache miss ยท ๐Ÿ“… weekly โ–“โ–‘โ–‘โ–‘โ–‘โ–‘ 12% ๐Ÿ”„ Sun 14:26 ยท ๐Ÿ“ฆ Ctx 200k ยท last 1d
142
167
  ```
143
168
 
144
- ์นฉ์˜ ์ข…๋ฅ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. `๐Ÿšจ 5H/7D NN%`(ํ•œ๋„ ์ž„๋ฐ•) ยท `โš  Ctx 200k+`(๋‹จ์ผ ์š”์ฒญ์ด ์‹ค์ œ๋กœ 200k๋ฅผ ์ดˆ๊ณผ) ยท `โš  Cache miss` ยท `โš  Input spike` ยท `โš  Output heavy` ยท `โš  Call surge` ยท `โš  Rebuild churn` ยท `โš  5m TTL`. ๋‘ ์œˆ๋„๊ฐ€ ๋™์‹œ์— 90%๋ฅผ ๋„˜์œผ๋ฉด ๋ฆฌ์…‹์ด ๋” ์ž„๋ฐ•ํ•œ ์ชฝ์„ ๐Ÿšจ๋กœ ์˜ฌ๋ฆฌ๊ณ , ๋‚˜๋จธ์ง€ ํ•˜๋‚˜๋Š” ๋นจ๊ฐ„ ์„ธ๊ทธ๋จผํŠธ๋กœ ๊ณ„์† ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค (v2.16.0 ์ด์ƒ).
169
+ ์นฉ์˜ ์ข…๋ฅ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. `๐Ÿšจ 5H/7D NN%`(ํ•œ๋„ ์ž„๋ฐ•) ยท `โš  Ctx 500k+`(๋‹จ์ผ ์š”์ฒญ์ด ์‹ค์ œ๋กœ 500k๋ฅผ ์ดˆ๊ณผ) ยท `โš  Cache miss` ยท `โš  Input spike` ยท `โš  Output heavy` ยท `โš  Call surge` ยท `โš  Rebuild churn` ยท `โš  5m TTL`. ๋‘ ์œˆ๋„๊ฐ€ ๋™์‹œ์— 90%๋ฅผ ๋„˜์œผ๋ฉด ๋ฆฌ์…‹์ด ๋” ์ž„๋ฐ•ํ•œ ์ชฝ์„ ๐Ÿšจ๋กœ ์˜ฌ๋ฆฌ๊ณ , ๋‚˜๋จธ์ง€ ํ•˜๋‚˜๋Š” ๋นจ๊ฐ„ ์„ธ๊ทธ๋จผํŠธ๋กœ ๊ณ„์† ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค (v2.16.0 ์ด์ƒ).
145
170
 
146
171
  ### ๊ฒฝ๊ณ  ์นฉ์ด ๋–ด์„ ๋•Œ
147
172
 
@@ -174,7 +199,7 @@ Claude Code ์•ˆ์—์„œ `/claude-token-saver` Skill์„ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜, ์นฉ์— ์ 
174
199
  | `claude-token-saver install` | Skillยทstatusline ์ˆ˜๋™ ๋“ฑ๋ก |
175
200
  | `claude-token-saver uninstall [--purge]` | ๋“ฑ๋กํ•œ ํ›…ยทstatuslineยทSkill ์ œ๊ฑฐ. ๊ธฐ๋ก๋œ ์ ˆ๊ฐ์•ก์€ ๋‚จ๊ธฐ๋ฉฐ, `--purge` ๋ฅผ ๋ถ™์ด๋ฉด ์ƒํƒœ ๋””๋ ‰ํ„ฐ๋ฆฌ๊นŒ์ง€ ์ง€์›๋‹ˆ๋‹ค |
176
201
 
177
- ์ถœ๋ ฅ ์–ธ์–ด๋Š” `mode ko`์™€ `mode en`์œผ๋กœ ์ „ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ ์˜์–ด์ด๋ฉฐ, statusline์˜ ์นฉ์€ ์–ธ์ œ๋‚˜ ๊ธฐํ˜ธ๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์ „์ฒด ์˜ต์…˜์€ [์˜๋ฌธ README](./README.en.md#options)๋ฅผ ์ฐธ๊ณ ํ•˜์‹ญ์‹œ์˜ค.
202
+ ์ถœ๋ ฅ ์–ธ์–ด๋Š” ์„ค์น˜ํ•  ๋•Œ ํ•œ ๋ฒˆ ์ •ํ•ฉ๋‹ˆ๋‹ค. ํ„ฐ๋ฏธ๋„์—์„œ ์„ค์น˜ํ•˜๋ฉด ์‹œ์Šคํ…œ ๋กœ์ผ€์ผ์„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ œ์‹œํ•˜๊ณ  ํ•œ๊ตญ์–ด๋ฅผ ์“ธ์ง€ ๋ฌผ์–ด๋ณด๋ฉฐ, ๋น„๋Œ€ํ™”ํ˜• ์„ค์น˜์—์„œ๋Š” ๋กœ์ผ€์ผ ํŒ์ •์„ ๊ทธ๋Œ€๋กœ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ํ•œ ๋ฒˆ ๊ธฐ๋ก๋˜๋ฉด ์—…๊ทธ๋ ˆ์ด๋“œํ•ด๋„ ๋‹ค์‹œ ๋ฌป์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‚˜์ค‘์— ๋ฐ”๊ฟ€ ๋•Œ๋Š” `mode ko`๋‚˜ `mode en`์„ ์“ฐ๊ณ , ์Šคํฌ๋ฆฝํŠธ์—์„œ ์„ค์น˜ํ•  ๋•Œ๋Š” `CTS_LANG=ko` ๋˜๋Š” `CTS_LANG=en`์œผ๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. statusline์˜ ์นฉ์€ ์–ธ์ œ๋‚˜ ๊ธฐํ˜ธ๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์ „์ฒด ์˜ต์…˜์€ [์˜๋ฌธ README](./README.en.md#options)๋ฅผ ์ฐธ๊ณ ํ•˜์‹ญ์‹œ์˜ค.
178
203
 
179
204
  ## โฌ† ์—…๋ฐ์ดํŠธ ์•ˆ๋‚ด
180
205
 
@@ -194,6 +219,7 @@ statusline์€ ๋Œ€ํ™” ์ƒ์ž๋ฅผ ๋„์šธ ์ˆ˜ ์—†๊ณ , 300๋ฐ€๋ฆฌ์ดˆ๋งˆ๋‹ค ๋‹ค์‹œ ๊ทธ
194
219
  claude-token-saver harness init # ์ด ํ”„๋กœ์ ํŠธ์— ์…‹์—…
195
220
  claude-token-saver harness init --global # ~/.claude/CLAUDE.md, ๋ชจ๋“  ํ”„๋กœ์ ํŠธ์— ์ ์šฉ
196
221
  claude-token-saver harness check # ํ˜„์žฌ ์ ์ˆ˜ (๊ธ€๋กœ๋ฒŒ fallback ์ธ์ •)
222
+ claude-token-saver harness analyze # ํ›… ์—†์ด๋„ ์ˆ˜๋™์œผ๋กœ ์ „์‚ฌ ๋ถ„์„์„ ์‹คํ–‰ํ•ด harness-state.json ๊ฐฑ์‹ 
197
223
  claude-token-saver harness promote <N> --project|--global # ๊ฒฝ๊ณ  #N โ†’ ratchet ๋ฃฐ (์Šค์ฝ”ํ”„ ํ•„์ˆ˜)
198
224
  claude-token-saver harness promote "<๋ฃฐ ํ…์ŠคํŠธ>" --project|--global # ๋‚ด๊ฐ€ ์ง์ ‘ ์ •์˜ํ•œ ๋ฃฐ๋„ ๊ฐ™์€ ๋ช…๋ น์œผ๋กœ ๋“ฑ๋ก
199
225
  claude-token-saver harness pull # ํŒจํ‚ค์ง€ ๋™๋ด‰ ํ๋ ˆ์ด์…˜ ๋ฃฐ โ†’ ๋‚ด ๊ธ€๋กœ๋ฒŒ ๋žซ์ณ‡์— ๋“ฑ๋ก (opt-in, ์ค‘๋ณต ์Šคํ‚ต)
@@ -202,7 +228,8 @@ claude-token-saver harness off | on # ๐Ÿ…ท ํ‘œ์‹œ ํ† ๊ธ€
202
228
  ```
203
229
 
204
230
  - `promote`๋Š” non-TTY ํ™˜๊ฒฝ(์Šคํฌ๋ฆฝํŠธ๋‚˜ LLM ํ˜ธ์ถœ)์—์„œ `--project` ๋˜๋Š” `--global` ํ”Œ๋ž˜๊ทธ๊ฐ€ **๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.** ์ ์šฉ ๋ฒ”์œ„๊ฐ€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฌป์ง€ ์•Š์€ ์ฑ„ ๊ฒฐ์ •๋˜๋Š” ์‚ฌ๊ณ ๋ฅผ ๋ง‰๊ธฐ ์œ„ํ•œ ์„ค๊ณ„์ž…๋‹ˆ๋‹ค.
205
- - `pull`์€ ํŒจํ‚ค์ง€์— ๋™๋ด‰๋œ **์ œ์ž‘์ž ํ๋ ˆ์ด์…˜ ๋žซ์ณ‡ ๋ฃฐ**(`presets/ratchet-rules.md` โ€” ์‹ค์ œ ๋ฐ˜๋ณต ์‚ฌ๊ณ ์—์„œ ์Šน๊ฒฉ๋œ ๋ฒ”์šฉ ๋ฃฐ๋งŒ)์„ ๋‚ด ๊ธ€๋กœ๋ฒŒ ๋žซ์ณ‡(`~/.claude/ratchet.md`)์— ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ์„ค์น˜(`install`)๋‚˜ `init`์€ ์•„๋ฌด๊ฒƒ๋„ ์ž๋™ ์ฃผ์ž…ํ•˜์ง€ ์•Š์œผ๋ฉฐ, `pull`์€ ํ•ญ์ƒ opt-in์ด๊ณ  ์žฌ์‹คํ–‰ํ•ด๋„ ์ค‘๋ณต์ด ์—†์Šต๋‹ˆ๋‹ค(๋ฉฑ๋“ฑ). ๋งˆ์Œ์— ์•ˆ ๋“œ๋Š” ๋ฃฐ์€ `harness rm`์œผ๋กœ ์ œ๊ฑฐํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
231
+ - `pull`์€ ํŒจํ‚ค์ง€์— ๋™๋ด‰๋œ **์ œ์ž‘์ž ํ๋ ˆ์ด์…˜ ๋žซ์ณ‡ ๋ฃฐ**(`presets/ratchet-rules.json` โ€” ์‹ค์ œ ๋ฐ˜๋ณต ์‚ฌ๊ณ ์—์„œ ์Šน๊ฒฉ๋œ ๋ฒ”์šฉ ๋ฃฐ๋งŒ)์„ ๋‚ด ๊ธ€๋กœ๋ฒŒ ๋žซ์ณ‡(`~/.claude/ratchet.md`)์— ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ์„ค์น˜(`install`)๋‚˜ `init`์€ ์•„๋ฌด๊ฒƒ๋„ ์ž๋™ ์ฃผ์ž…ํ•˜์ง€ ์•Š์œผ๋ฉฐ, `pull`์€ ํ•ญ์ƒ opt-in์ด๊ณ  ์žฌ์‹คํ–‰ํ•ด๋„ ์ค‘๋ณต์ด ์—†์Šต๋‹ˆ๋‹ค(๋ฉฑ๋“ฑ). ๋งˆ์Œ์— ์•ˆ ๋“œ๋Š” ๋ฃฐ์€ `harness rm`์œผ๋กœ ์ œ๊ฑฐํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
232
+ - `seed`๋Š” ๊ฐ™์€ ํ”„๋ฆฌ์…‹์„ **ํ•œ ๊ฑด์”ฉ** ๋ฌผ์–ด๋ณด๋Š” ๊ฒฝ๋กœ์ž…๋‹ˆ๋‹ค. `pull`์ด ๋žซ์ณ‡ ๋ฃฐ ์ „์ฒด๋ฅผ ํ•œ ๋ฒˆ์— ๋“ฑ๋กํ•˜๋Š” ๋ช…๋ น์ธ ๋ฐ ๋ฐ˜ํ•ด, `seed`๋Š” ๋ชจ๋ธ ํ”ผํŒ… ํ”„๋ฆฌ์…‹๊นŒ์ง€ ํฌํ•จํ•ด ์„ค์น˜ยท์—…๊ทธ๋ ˆ์ด๋“œ ํ›„ ์ฒซ ์„ธ์…˜์—์„œ ํ•œ ๊ฑด์”ฉ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค ([์•„๋ž˜](#-seed-์„ค์น˜-์งํ›„๋ถ€ํ„ฐ-์œ„์ž„์ด-๊ฑธ๋ฆฌ๊ฒŒ-ํ•˜๋Š”-์‹œ์ž‘-๋ฃฐ)).
206
233
  - ๐Ÿ…ทโš  ๋Ÿฐํƒ€์ž„ ๊ฒฝ๊ณ (`ratchet?` `no-evidence` `PEV-skip`)๋Š” 30๋ถ„ ํ›„ ์ž๋™ ๋งŒ๋ฃŒ๋˜๊ณ , ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ ์„ธ์…˜๋„ ํ”„๋กœ์ ํŠธ์— ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋งค์นญ๋ฉ๋‹ˆ๋‹ค. PEV-skip์€ ๋ณ€๊ฒฝ์„ฑ ๋„๊ตฌ(Edit/Write/Bash)๋งŒ ์นด์šดํŠธํ•ด ์ฝ๊ธฐ ์œ„์ฃผ ์„ธ์…˜์—์„œ๋Š” ๋ฐœ๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค (v2.16.0+).
207
234
 
208
235
  <details>
@@ -294,6 +321,32 @@ v3.10.0๋ถ€ํ„ฐ๋Š” ํ”„๋กœํŒŒ์ผ ID๋ฅผ ์—ญํ• (mainยทopusยทsonnetยทhaiku)๋กœ ๋˜๋Œ
294
321
 
295
322
  ์ด ํŒŒ์ผ์—๋Š” ์‚ฌ๋‚ด ์‹๋ณ„์ž๊ฐ€ ํ‰๋ฌธ์œผ๋กœ ๋‚จ์œผ๋ฏ€๋กœ ์ €์žฅ์†Œ์— ์ปค๋ฐ‹ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ๊ฒŒ์ดํŠธ์›จ์ด๋ฅผ ์“ฐ์ง€ ์•Š๋Š” ํ™˜๊ฒฝ์—์„œ๋Š” ํŒŒ์ผ์ด ์•„์˜ˆ ๋งŒ๋“ค์–ด์ง€์ง€ ์•Š๊ณ  ๊ธฐ์กด ๋™์ž‘์ด ๊ทธ๋Œ€๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.
296
323
 
324
+ ## ๐ŸŒฑ seed: ์„ค์น˜ ์งํ›„๋ถ€ํ„ฐ ์œ„์ž„์ด ๊ฑธ๋ฆฌ๊ฒŒ ํ•˜๋Š” ์‹œ์ž‘ ๋ฃฐ
325
+
326
+ ๋ชจ๋ธ ํ”ผํŒ… ๋žซ์ณ‡(`ratchet-model.md`)์€ **๋นˆ ํŒŒ์ผ๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.** route-scan์ด ์‚ฌ์šฉ์ž์˜ ๋กœ๊ทธ์—์„œ ๊ฐ™์€ ์œ ํ˜•์˜ ์ž‘์—…์„ ์—ฌ๋Ÿฌ ๋ฒˆ ๊ด€์ธกํ•˜๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ๊ทธ ํ›„๋ณด๋ฅผ ์Šน์ธํ•ด์•ผ ๋ฃฐ์ด ์ƒ๊น๋‹ˆ๋‹ค. ์ฆ‰ ๊ฐ“ ์„ค์น˜ํ•œ ์ƒํƒœ์—์„œ๋Š” ์œ„์ž„์ด ํ•œ ๊ฑด๋„ ๊ฑธ๋ฆฌ์ง€ ์•Š๊ณ , ๊ทธ ์ƒํƒœ๊ฐ€ ๋ฉฐ์น  ์ด์–ด์ง‘๋‹ˆ๋‹ค. ์ •์ž‘ ์ ˆ๊ฐ ํšจ๊ณผ๊ฐ€ ๊ฐ€์žฅ ํด ์‹œ๊ธฐ์ž…๋‹ˆ๋‹ค.
327
+
328
+ `seed`๋Š” ํŒจํ‚ค์ง€์— ๋™๋ด‰๋œ ํ”„๋ฆฌ์…‹์œผ๋กœ ๊ทธ ๊ณต๋ฐฑ์„ ๋ฉ”์›๋‹ˆ๋‹ค.
329
+
330
+ | ํ”„๋ฆฌ์…‹ | ๋‚ด์šฉ | ํŒŒ์ผ |
331
+ |---|---|---|
332
+ | ๋ชจ๋ธ ํ”ผํŒ… 9๊ฑด | ๋ช…๋ น ์‹คํ–‰ยทํƒ์ƒ‰ยท์ƒํƒœ ํ™•์ธยท๋ถ™์—ฌ๋„ฃ์€ ๋กœ๊ทธ ์งˆ๋ฌธยท์ฝ๊ธฐ ์š”์•ฝ, ๊ฐ ์œ ํ˜•์˜ T2(haiku)์™€ T1(sonnet) ๋ฃฐ | `presets/model-rules.json` |
333
+ | ๋žซ์ณ‡ 6๊ฑด | ์‹ค์ œ ๋ฐ˜๋ณต ์‚ฌ๊ณ ์—์„œ ์Šน๊ฒฉ๋œ ๋ฒ”์šฉ ๋ฃฐ | `presets/ratchet-rules.json` |
334
+
335
+ **๋“ฑ๋ก ์ ˆ์ฐจ:** ์„ค์น˜๋‚˜ ์—…๊ทธ๋ ˆ์ด๋“œ ํ›„ ์ฒซ ์„ธ์…˜์—์„œ SessionStart ํ›…์ด ๋Œ€๊ธฐ ์ค‘์ธ ํ”„๋ฆฌ์…‹์„ ๋ชจ๋ธ์—๊ฒŒ ์ „๋‹ฌํ•˜๊ณ , ๋ชจ๋ธ์ด **ํ•œ ๊ฑด์”ฉ ์ˆœ์„œ๋Œ€๋กœ** ๋“ฑ๋ก ์—ฌ๋ถ€๋ฅผ ๋ฌป์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ตํ•˜๋ฉด ๊ทธ ์ž๋ฆฌ์—์„œ ์•„๋ž˜ ๋ช…๋ น์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
336
+
337
+ ```bash
338
+ claude-token-saver seed # ๋Œ€๊ธฐ ์ค‘์ธ ํ”„๋ฆฌ์…‹๊ณผ ์‘๋‹ต ๊ธฐ๋ก
339
+ claude-token-saver seed accept <id> --global|--project # ํ•œ ๊ฑด ๋“ฑ๋ก (์ ์šฉ ๋ฒ”์œ„ ํ•„์ˆ˜)
340
+ claude-token-saver seed accept all --global # ์‚ฌ์šฉ์ž๊ฐ€ "์ „๋ถ€ ๋“ฑ๋ก"์ด๋ผ๊ณ  ๋‹ตํ•œ ๊ฒฝ์šฐ
341
+ claude-token-saver seed skip <id> # ๊ฑฐ์ ˆ โ€” ๋‹ค์‹œ ๋ฌป์ง€ ์•Š์Šต๋‹ˆ๋‹ค
342
+ claude-token-saver seed reset # ์‘๋‹ต ๊ธฐ๋ก์„ ์ง€์›Œ ์ „์ฒด๋ฅผ ๋‹ค์‹œ ์ œ์•ˆ ๋Œ€์ƒ์œผ๋กœ
343
+ ```
344
+
345
+ - **์Šน์ธ ์—†์ด๋Š” ์•„๋ฌด๊ฒƒ๋„ ๊ธฐ๋ก๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.** ๊ฑฐ์ ˆํ•œ ๋ฃฐ์€ ์—…๊ทธ๋ ˆ์ด๋“œ ํ›„์—๋„ ๋‹ค์‹œ ๋ฌป์ง€ ์•Š๊ณ , ์ƒˆ ๋ฆด๋ฆฌ์Šค์—์„œ ์ถ”๊ฐ€๋œ ํ”„๋ฆฌ์…‹๋งŒ ๋‹ค์Œ ์„ธ์…˜์— ์ œ์•ˆ๋ฉ๋‹ˆ๋‹ค.
346
+ - ์‚ฌ์šฉ์ž๊ฐ€ ์ด๋ฏธ ๊ฐ™์€ ์œ ํ˜•(๊ฐ™์€ ํ‹ฐ์–ดยท์นดํ…Œ๊ณ ๋ฆฌ)์˜ ๋ฃฐ์„ ์ง์ ‘ ์Šน์ธํ•ด ๋‘์—ˆ๋‹ค๋ฉด ๊ทธ ํ”„๋ฆฌ์…‹์€ ์ œ์•ˆํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
347
+ - ํ”„๋ฆฌ์…‹์œผ๋กœ ๋“ฑ๋กํ•œ ๋ฃฐ์€ **๋‚จ์˜ ํ†ต๊ณ„๋ฅผ ๋‚ด ๊ฒƒ์ฒ˜๋Ÿผ ํ‘œ์‹œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.** ๋“ฑ๋ก ์งํ›„์—๋Š” `preset (curated)`๋กœ ์ ํžˆ๊ณ , ์ดํ›„ ์Šค์บ”์—์„œ ์‹ค์ œ ๋ฐœํ™”์™€ ์œ„์ž„ ๊ฒฐ๊ณผ๊ฐ€ ์ธก์ •๋˜๋ฉด ๊ทธ ์ˆ˜์น˜๋กœ ๋Œ€์ฒด๋ฉ๋‹ˆ๋‹ค. ์œ„์ž„ ์—๋Ÿฌ์œจ์ด ๊ธฐ์ค€์„ ๋„˜์œผ๋ฉด ๋‹ค๋ฅธ ๋ฃฐ๊ณผ ๋˜‘๊ฐ™์ด ์žฌ๊ฒ€ํ†  ํ”Œ๋ž˜๊ทธ๊ฐ€ ๋ถ™์Šต๋‹ˆ๋‹ค.
348
+ - ์ ์šฉ ๋ฒ”์œ„๋Š” `--global`๊ณผ `--project` ์ค‘ ๋ฐ˜๋“œ์‹œ ๋ช…์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ›… ํ™˜๊ฒฝ์€ non-TTY๋ผ CLI๊ฐ€ ์ง์ ‘ ๋ฌผ์„ ์ˆ˜ ์—†์œผ๋ฏ€๋กœ, ๋ชจ๋ธ์ด ์‚ฌ์šฉ์ž์—๊ฒŒ ํ™•์ธํ•œ ๋’ค ํ”Œ๋ž˜๊ทธ๋ฅผ ๋ถ™์—ฌ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
349
+
297
350
  ## ๐Ÿ‡ฐ๐Ÿ‡ท ํ•œ๊ตญ์–ด ๋ฌธ์ฒด ์ง€์นจ
298
351
 
299
352
  Claude๊ฐ€ ํ•œ๊ตญ์–ด๋กœ ์“ธ ๋•Œ ๋‚˜ํƒ€๋‚˜๋Š” ๋ฌธ์ฒด ๊ฒฐํ•จ(๋ฌธ์žฅ ์„ฑ๋ถ„ ์ƒ๋žต, ๋ช…์‚ฌํ˜• ์ข…๊ฒฐ, ๋ฒˆ์—ญ์ฒด, ์— ๋Œ€์‹œ ๋‚จ์šฉ)์„ ๊ต์ •ํ•˜๋Š” ์ง€์นจ์„ **์„ธ์…˜ ์‹œ์ž‘ ์‹œ ํ•œ ๋ฒˆ ์ฃผ์ž…ํ•ฉ๋‹ˆ๋‹ค.**
@@ -585,6 +638,24 @@ npm uninstall -g claude-cache-monitor && npm i -g claude-token-saver
585
638
 
586
639
  ## ๋ฆด๋ฆฌ์Šค ๋…ธํŠธ
587
640
 
641
+ ### v3.34.0 (2026-09-10)
642
+ - **์ถœ๋ ฅ ์–ธ์–ด๋ฅผ ์„ค์น˜ํ•  ๋•Œ ์ •ํ•ฉ๋‹ˆ๋‹ค.** ์ง€๊ธˆ๊นŒ์ง€๋Š” ๊ธฐ๋ก์ด ์—†์œผ๋ฉด ์กฐ์šฉํžˆ ์˜์–ด๋กœ ๋–จ์–ด์ ธ์„œ, ํ•œ๊ตญ์–ด ์‚ฌ์šฉ์ž๋Š” `mode ko`๋ฅผ ์šฐ์—ฐํžˆ ๋ฐœ๊ฒฌํ•  ๋•Œ๊นŒ์ง€ ์˜์–ด ๋ฆฌํฌํŠธ๋ฅผ ์ฝ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ํ„ฐ๋ฏธ๋„ ์„ค์น˜์—์„œ๋Š” ์‹œ์Šคํ…œ ๋กœ์ผ€์ผ์„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ œ์‹œํ•˜๊ณ  ํ•œ๊ตญ์–ด๋ฅผ ์“ธ์ง€ ๋ฌผ์–ด๋ณด๋ฉฐ, ๋น„๋Œ€ํ™”ํ˜• ์„ค์น˜์—์„œ๋Š” ๋กœ์ผ€์ผ ํŒ์ •์„ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ํ•œ ๋ฒˆ ๊ธฐ๋ก๋˜๋ฉด ์—…๊ทธ๋ ˆ์ด๋“œํ•ด๋„ ๋‹ค์‹œ ๋ฌป์ง€ ์•Š๊ณ , ์Šคํฌ๋ฆฝํŠธ ์„ค์น˜๋Š” `CTS_LANG=ko|en`์œผ๋กœ ๊ณ ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
643
+ - **๋กœ์ผ€์ผ ํŒ์ •์˜ ๊ฒฐํ•จ์„ ๊ณ ์ณค์Šต๋‹ˆ๋‹ค.** `LANG=en_US.UTF-8`์ด ์ง€์ •๋ผ ์žˆ์–ด๋„ macOS์—์„œ๋Š” ์‹œ์Šคํ…œ ๋กœ์ผ€์ผ(`AppleLocale`)๊นŒ์ง€ ์ฝ์–ด ํ•œ๊ตญ์–ด๋กœ ํŒ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ POSIX ๋กœ์ผ€์ผ ๋ณ€์ˆ˜๊ฐ€ ๊ฐ’์„ ๊ฐ–๊ณ  ์žˆ์œผ๋ฉด ๊ทธ ๊ฐ’์„ ๋‹ต์œผ๋กœ ๋ฐ›์•„๋“ค์ด๊ณ , ๋ณ€์ˆ˜๊ฐ€ ๋ชจ๋‘ ๋น„์–ด ์žˆ์„ ๋•Œ์—๋งŒ ์‹œ์Šคํ…œ ๋กœ์ผ€์ผ์„ ๋ด…๋‹ˆ๋‹ค. ์ด ๋Œ€๋น„์ฑ…์€ `LANG`์ด ๋น„์–ด ์žˆ๋Š” macOS GUI ์…ธ์„ ์œ„ํ•œ ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค.
644
+ - ์–ธ์–ด๋Š” ์„ค์น˜ ์ ˆ์ฐจ์˜ ์ฒซ ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค. ๊ทธ ์•„๋ž˜์˜ harnessยทdoc2mdยทseed ์•ˆ๋‚ด๊ฐ€ ๋ชจ๋‘ ์„ ํƒํ•œ ์–ธ์–ด๋กœ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.
645
+
646
+ ### v3.33.0 (2026-09-10)
647
+ - **`seed`: ์„ค์น˜ ์งํ›„๋ถ€ํ„ฐ ์œ„์ž„์ด ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค.** ๋ชจ๋ธ ํ”ผํŒ… ๋žซ์ณ‡์€ ๋นˆ ํŒŒ์ผ๋กœ ์‹œ์ž‘ํ•ด์„œ, ์‚ฌ์šฉ์ž ๋กœ๊ทธ์— ๊ฐ™์€ ์œ ํ˜•์˜ ์ž‘์—…์ด ์Œ“์ด๊ณ  ํ›„๋ณด๋ฅผ ์Šน์ธํ•  ๋•Œ๊นŒ์ง€ ๋ฉฐ์น ๊ฐ„ ์œ„์ž„์ด ํ•œ ๊ฑด๋„ ๊ฑธ๋ฆฌ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ด์ œ ํŒจํ‚ค์ง€์— **๋ชจ๋ธ ํ”ผํŒ… ํ”„๋ฆฌ์…‹ 9๊ฑด**(`presets/model-rules.json`)๊ณผ **๋žซ์ณ‡ ํ”„๋ฆฌ์…‹ 6๊ฑด**(`presets/ratchet-rules.json`)์„ ๋™๋ด‰ํ•˜๊ณ , ์„ค์น˜ยท์—…๊ทธ๋ ˆ์ด๋“œ ํ›„ ์ฒซ ์„ธ์…˜์—์„œ SessionStart ํ›…์ด ์ด๋ฅผ ๋ชจ๋ธ์—๊ฒŒ ์ „๋‹ฌํ•ด **ํ•œ ๊ฑด์”ฉ** ๋“ฑ๋ก ์—ฌ๋ถ€๋ฅผ ๋ฌป์Šต๋‹ˆ๋‹ค.
648
+ - **์‘๋‹ต์€ ์˜๊ตฌ ๊ธฐ๋ก๋ฉ๋‹ˆ๋‹ค.** ๊ฑฐ์ ˆํ•œ ํ”„๋ฆฌ์…‹์€ ์—…๊ทธ๋ ˆ์ด๋“œ ํ›„์—๋„ ๋‹ค์‹œ ๋ฌป์ง€ ์•Š๊ณ , ์ƒˆ ๋ฆด๋ฆฌ์Šค์—์„œ ์ถ”๊ฐ€๋œ ํ•ญ๋ชฉ๋งŒ ์ œ์•ˆ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ ๊ฐ™์€ ํ‹ฐ์–ดยท์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋ฃฐ์„ ์Šน์ธํ•ด ๋‘์—ˆ๋‹ค๋ฉด ๊ทธ ํ”„๋ฆฌ์…‹์€ ์ œ์•ˆ ๋Œ€์ƒ์—์„œ ๋น ์ง‘๋‹ˆ๋‹ค. ๋ช…๋ น: `seed` ยท `seed accept <id> --global|--project` ยท `seed skip <id>` ยท `seed reset`.
649
+ - **ํ”„๋ฆฌ์…‹ ๋ฃฐ์€ ๋‚จ์˜ ํ†ต๊ณ„๋ฅผ ๋‚ด ๊ฒƒ์ฒ˜๋Ÿผ ์ ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.** ๋“ฑ๋ก ์งํ›„์—๋Š” `preset (curated)`๋กœ ํ‘œ๊ธฐํ•˜๊ณ , ์ดํ›„ ์Šค์บ”์ด ์‹ค์ œ ๋ฐœํ™”ยท์œ„์ž„ ๊ฒฐ๊ณผ๋ฅผ ์ธก์ •ํ•˜๋ฉด ๊ทธ ์ˆ˜์น˜๋กœ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค. ์œ„์ž„ ์—๋Ÿฌ์œจ์ด ๊ธฐ์ค€์„ ๋„˜์œผ๋ฉด ๋‹ค๋ฅธ ๋ฃฐ๊ณผ ๋™์ผํ•˜๊ฒŒ ์žฌ๊ฒ€ํ†  ํ”Œ๋ž˜๊ทธ๊ฐ€ ๋ถ™์Šต๋‹ˆ๋‹ค.
650
+ - **๋žซ์ณ‡ ํ”„๋ฆฌ์…‹์„ ์–‘๊ตญ์–ด๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.** `presets/ratchet-rules.md`๋ฅผ `presets/ratchet-rules.json`์œผ๋กœ ๋ฐ”๊พธ๊ณ  ๋ฃฐ๋งˆ๋‹ค ํ•œ๊ตญ์–ด์™€ ์˜์–ด๋ฅผ ํ•จ๊ป˜ ๋‹ด์•˜์Šต๋‹ˆ๋‹ค. ๋ฃฐ ํ…์ŠคํŠธ๋Š” ๋ชจ๋ธ ์ปจํ…์ŠคํŠธ์— ์ฃผ์ž…๋˜๋ฏ€๋กœ, ํ•œ๊ตญ์–ด๋งŒ ์žˆ์œผ๋ฉด ์˜์–ด ์„ธ์…˜์˜ ์‘๋‹ต๊นŒ์ง€ ํ•œ๊ตญ์–ด๋กœ ๋Œ๋ ค๊ฐ‘๋‹ˆ๋‹ค. ์‹๋ณ„์ž๋Š” ํ•œ๊ตญ์–ด ์›๋ฌธ์—์„œ ๋ฝ‘์•„ ์˜์–ด ๋ฌธ์žฅ์„ ๋‹ค๋“ฌ์–ด๋„ ์‚ฌ์šฉ์ž์˜ ์‘๋‹ต์ด ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.
651
+ - **๋ฃฐ ๋ฌธ์žฅ ํ…œํ”Œ๋ฆฟ์„ ํ•œ ๊ณณ์œผ๋กœ ํ•ฉ์ณค์Šต๋‹ˆ๋‹ค.** route-scan๊ณผ seed๊ฐ€ ๊ฐ™์€ `modelRuleBaseText()`๋ฅผ ์“ฐ๋ฏ€๋กœ, ๋ฌธ๊ตฌ๋ฅผ ๊ณ ์น  ๋•Œ ๋‘ ์ƒ์‚ฐ์ž์˜ ํ‘œํ˜„์ด ๊ฐˆ๋ผ์งˆ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
652
+
653
+ ### v3.32.0 (2026-09-10)
654
+ - **์ปจํ…์ŠคํŠธ ๊ฒฝ๊ณ  ๊ธฐ์ค€์„ 200k ์—์„œ 500k ๋กœ ์˜ฌ๋ ธ์Šต๋‹ˆ๋‹ค.** ์„ค์น˜ ์งํ›„์˜ ์ƒˆ ์„ธ์…˜๋„ ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ์™€ ํŒŒ์ผ ๋ช‡ ๊ฐœ๋งŒ ์ฝ์œผ๋ฉด 200k ๋ฅผ ๋„˜๊ธฐ๋ฏ€๋กœ, `โš  Ctx 200k+` ๋Š” ๊ฑฐ์˜ ํ•ญ์ƒ ๋–  ์žˆ๋Š” ์นฉ์ด์—ˆ๊ณ  ๊ทธ๋งŒํผ ์•„๋ฌด ์ •๋ณด๋„ ์ฃผ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์นฉ์€ `โš  Ctx 500k+` ๋กœ ๋ฐ”๋€Œ์—ˆ๊ณ , ๋‹จ์ผ ์š”์ฒญ์ด ์‹ค์ œ๋กœ 500k ๋ฅผ ๋„˜๊ธธ ๋•Œ๋งŒ ๋œน๋‹ˆ๋‹ค. `๐Ÿ“ฆ Ctx` ์„ธ๊ทธ๋จผํŠธ๋„ 500k ๋ฅผ ๋„˜๊ฒจ์•ผ ๋…ธ๋ž€์ƒ‰์œผ๋กœ ๋ฐ”๋€๋‹ˆ๋‹ค. 1M ์œˆ๋„๋ฅผ ์“ฐ๊ณ  ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค ์ž์ฒด๋Š” ๋” ์ด์ƒ ๊ฒฝ๊ณ ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.
655
+ - **์˜ˆ์ „ ํžˆ์Šคํ† ๋ฆฌ๋Š” ๊ทธ๋Œ€๋กœ ์ฝํž™๋‹ˆ๋‹ค.** `โš  Ctx 200k+` ์นฉ๊ณผ ๊ตฌ ๋””ํ…Œ์ผ ๋ฌธ๊ตฌ(`Single-request context exceeded 200k`)๋„ ๊ณ„์† ํ•ด์„ํ•ฉ๋‹ˆ๋‹ค.
656
+ - **doc2md ๋ฅผ ์„ค์น˜ ๋•Œ ์ž๋™์œผ๋กœ ์ผญ๋‹ˆ๋‹ค.** ํ›… ๋“ฑ๋ก์€ `settings.json` ํ•ญ๋ชฉ ๋‘ ๊ฐœ์ผ ๋ฟ์ด๊ณ  ๋ฌธ์„œ๋ฅผ ์ฝ์ง€ ์•Š์œผ๋ฉด ๋น„์šฉ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋ฐ, ๊ทธ๋™์•ˆ์€ `doc2md on` ์„ ์ง์ ‘ ์ฐพ์•„๋‚ธ ์‚ฌ๋žŒ๋งŒ ์ผ์Šต๋‹ˆ๋‹ค. ๋ณ€ํ™˜๊ธฐ(markitdown venv)๋Š” ์„ค์น˜์— ๋ช‡ ๋ถ„์ด ๊ฑธ๋ฆฌ๋ฏ€๋กœ ํ„ฐ๋ฏธ๋„์—์„œ๋งŒ ๋ฌผ์–ด๋ณด๊ณ , ๋น„๋Œ€ํ™”ํ˜• ์„ค์น˜์—์„œ๋Š” ๋ช…๋ น๋งŒ ์•ˆ๋‚ดํ•ฉ๋‹ˆ๋‹ค. ๋„๋ ค๋ฉด `doc2md off` ๋˜๋Š” `CTS_NO_DOC2MD=1` ์„ ์“ฐ์‹ญ์‹œ์˜ค.
657
+ - **์„ค์น˜ ์งํ›„ ์ผœ์ง€๋Š” ๊ธฐ๋Šฅ๊ณผ ์ง์ ‘ ์ผœ์•ผ ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๋ฌธ์„œ์— ํ‘œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.** ์ˆ˜๋™์œผ๋กœ ๋‚จ์€ ํ•ญ๋ชฉ์€ `compact-window set`(Claude Code ์„ค์ •์— ๊ฐ’์„ ์ ๊ณ  ์ ์šฉ ๋ฒ”์œ„๋ฅผ ์‚ฌ๋žŒ์ด ์ •ํ•ด์•ผ ํ•จ)๊ณผ ๋ชจ๋ธ ํ”ผํŒ… ๋ฃฐ ์Šน์ธ๋ฟ์ž…๋‹ˆ๋‹ค.
658
+
588
659
  ### v3.27.0 (2026-09-04)
589
660
  - **๋ฌธ์„œ ๊ฒฝ๋กœ๋ฅผ ํ”„๋กฌํ”„ํŠธ์— ์ ์œผ๋ฉด ์ด์ œ ์‹ค์ œ๋กœ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค.** 3.26.x ์˜ `PreToolUse(Read)` ํ›…์€ ์ •์ž‘ ๋ชฉํ‘œํ•œ ํ˜•์‹์— ๋‹ฟ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. Claude Code ๊ฐ€ pptxยทxlsxยทdocx ๋ฅผ ์ด์ง„ ํŒŒ์ผ์ด๋ผ๋ฉฐ ํ›…๋ณด๋‹ค ๋จผ์ € ๊ฑฐ๋ถ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(์‹ค์ธก: `.pdf` Read ๋Š” ํ›…์ด ์‹คํ–‰๋˜๊ณ  `.pptx` Read ๋Š” ํ›… ๊ธฐ๋ก์ด ๋‚จ์ง€ ์•Š์Šต๋‹ˆ๋‹ค). ๊ฐœ์ž… ์ง€์ ์„ `UserPromptSubmit` ์œผ๋กœ ๋„“ํ˜€, ํ”„๋กฌํ”„ํŠธ์— ์ ํžŒ ๊ฒฝ๋กœ๋ฅผ ๋ณ€ํ™˜ํ•œ ๋’ค ๋ณ€ํ™˜๋ณธ ๊ฒฝ๋กœ๋ฅผ ์ปจํ…์ŠคํŠธ๋กœ ๋„ฃ์Šต๋‹ˆ๋‹ค. `@๊ฒฝ๋กœ`ยท๋”ฐ์˜ดํ‘œยท์ƒ๋Œ€ ๊ฒฝ๋กœ๋ฅผ ๋ชจ๋‘ ์ธ์‹ํ•ฉ๋‹ˆ๋‹ค.
590
661
  - **์„ธ์…˜ ์‹œ์ž‘ ์•ˆ๋‚ด๋ฌธ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.** ๋‘ ๊ฐ€์ง€๋ฅผ ๋ชจ๋ธ์—๊ฒŒ ์•Œ๋ฆฝ๋‹ˆ๋‹ค. `Read` ๊ฐ€ ์ด์ง„ ํŒŒ์ผ์ด๋ผ๋ฉฐ ๊ฑฐ๋ถ€ํ•˜๋ฉด `doc2md <๊ฒฝ๋กœ>` ๋ฅผ ์‹คํ–‰ํ•  ๊ฒƒ, ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ๋ฌธ์„œ๋ฅผ ์ง์ ‘ ์ฒจ๋ถ€ํ–ˆ์œผ๋ฉด ๋‹ค์Œ๋ถ€ํ„ฐ ๊ฒฝ๋กœ๋กœ ๋‹ฌ๋ผ๊ณ  ์•ˆ๋‚ดํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ฒจ๋ถ€๋Š” ๋‚ด์šฉ ์ „์ฒด๊ฐ€ ์ปจํ…์ŠคํŠธ์— ์‹ค๋ ค ํ† ํฐ์„ ํฌ๊ฒŒ ์“ฐ๋Š”๋ฐ, ์–ด๋–ค ํ›… ์ด๋ฒคํŠธ๋„ ์ฒจ๋ถ€ ๋‚ด์šฉ์„ ๋ฐ›์ง€ ๋ชปํ•ด ๋„๊ตฌ๊ฐ€ ๊ฐœ์ž…ํ•  ๋ฐฉ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค.
package/bin/cli.js CHANGED
@@ -87,9 +87,43 @@ function readUpdateChip() {
87
87
  const KNOWN_SUBCOMMANDS = new Set([
88
88
  'last', 'brief', 'history', 'handoff', 'install', 'uninstall', 'mode', 'korean',
89
89
  'doc2md', 'harness', 'route-scan', 'compact-window', 'update-check', 'upgrade',
90
+ 'seed',
90
91
  ]);
91
92
 
93
+ const USAGE = `claude-token-saver โ€” Claude Code token usage, cache health, and model routing
94
+
95
+ Usage:
96
+ claude-token-saver default report (last 30 days)
97
+ claude-token-saver --days 7 last 7 days
98
+ claude-token-saver --format json JSON output
99
+ claude-token-saver --format csv CSV output
100
+ claude-token-saver --project myproj filter by project
101
+ claude-token-saver route-scan detect recurring easy work โ†’ delegation candidates
102
+ claude-token-saver install set up skill/hooks/statusline
103
+ claude-token-saver install --yes take the defaults without asking
104
+ claude-token-saver uninstall remove everything install added
105
+ claude-token-saver harness check score the harness setup in CLAUDE.md
106
+ claude-token-saver harness analyze run the harness transcript analysis manually
107
+ claude-token-saver last most recent warning + how to handle it
108
+ claude-token-saver history recent warning transitions
109
+ claude-token-saver handoff write a session handoff file
110
+ claude-token-saver upgrade install the latest release
111
+ claude-token-saver --install-hook install cache-monitor PostToolUse hook
112
+ claude-token-saver --uninstall-hook remove that hook
113
+ claude-token-saver --statusline one-line output for Claude Code statusline
114
+ --verbose / --no-color / --icon / --no-timer / --single-line
115
+
116
+ Run any subcommand with --help for its own options where available.
117
+ `;
118
+
92
119
  async function main() {
120
+ // Help must never fall through to the default report โ€” that runs a full
121
+ // 30-day scan, which is the opposite of what someone asking for help wants.
122
+ if (hasFlag('--help') || hasFlag('-h') || args[0] === 'help') {
123
+ process.stdout.write(USAGE);
124
+ return;
125
+ }
126
+
93
127
  // A hook invocation names a subcommand and expects either silence or that
94
128
  // subcommand's own protocol on stdout. If this build does not have the
95
129
  // subcommand โ€” an older global install against a newer settings.json, which
@@ -191,6 +225,13 @@ async function main() {
191
225
  return (await import('../src/commands/doc2md.js')).run({ args, hasFlag });
192
226
  }
193
227
 
228
+ // Subcommand: seed โ€” register the bundled starter rules (model-fitting
229
+ // presets + curated ratchet rules), one answer at a time.
230
+ // claude-token-saver seed | seed accept <id> --global|--project | seed skip <id>
231
+ if (args[0] === 'seed') {
232
+ return (await import('../src/commands/seed.js')).run({ args, hasFlag });
233
+ }
234
+
194
235
  // Subcommand: harness โ€” manage the project's CLAUDE.md harness rules.
195
236
  // claude-token-saver harness init # write CLAUDE.md (5 sections) + ratchet.md
196
237
  // claude-token-saver harness uninit # remove harness block from CLAUDE.md (backup kept)
@@ -466,14 +507,14 @@ async function main() {
466
507
  }
467
508
 
468
509
  // For statusline: attach a single-word chip only when there's something
469
- // actionable right now. 1M context is always shown; otherwise only fire
470
- // if the most recent session actually appears in the spike list.
510
+ // actionable right now. A context over the 500k warn line is always shown;
511
+ // otherwise only fire if the most recent session appears in the spike list.
471
512
  let spikeChip = null;
472
513
  let chipDetail = null;
473
514
  if (format === 'statusline') {
474
- if (contextWindow.size === '1M') {
515
+ if (contextWindow.overWarn) {
475
516
  spikeChip = chipForIssues([], contextWindow);
476
- chipDetail = `Single-request context exceeded 200k (max ${Math.round(contextWindow.maxContext / 1000)}k tokens)`;
517
+ chipDetail = `Single-request context exceeded 500k (max ${Math.round(contextWindow.maxContext / 1000)}k tokens)`;
477
518
  } else {
478
519
  const recentSession = sessions
479
520
  .slice()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-token-saver",
3
- "version": "3.30.1",
3
+ "version": "3.34.0",
4
4
  "description": "Route the easy work your expensive Claude model keeps repeating down to haiku/sonnet โ€” post-hoc session analysis, no realtime router, no extra LLM calls.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,115 @@
1
+ {
2
+ "note": [
3
+ "Curated tier-delegation presets bundled with the package โ€” the model-fitting",
4
+ "counterpart to presets/ratchet-rules.md. These were promoted from the author's",
5
+ "own route-scan candidates over months of real sessions, then stripped of the",
6
+ "originating examples, project paths and recurrence counts: what carries over is",
7
+ "the shape of the work (category, tier, agent, cap), not the author's transcripts.",
8
+ "Each entry is offered one at a time at session start; nothing is registered",
9
+ "without the user saying yes. Caps are the defaults a scan would calibrate to;",
10
+ "later scans refresh the stats on whatever the user accepts.",
11
+ "Rule sentences are composed at accept time from modelRuleBaseText() so that a",
12
+ "reworded template never leaves this file stale."
13
+ ],
14
+ "presets": [
15
+ {
16
+ "id": "run-t2",
17
+ "tier": "T2",
18
+ "category": "run",
19
+ "label": "๋ช…๋ น ์‹คํ–‰ (๋นŒ๋“œยทํ…Œ์ŠคํŠธยทgit)",
20
+ "labelEn": "running commands (build/test/git)",
21
+ "agent": "haiku-runner",
22
+ "example": "npm test ๋Œ๋ ค๋ด",
23
+ "exampleEn": "run npm test",
24
+ "budget": { "calls": 8, "out": 1500 }
25
+ },
26
+ {
27
+ "id": "run-t1",
28
+ "tier": "T1",
29
+ "category": "run",
30
+ "label": "๋ช…๋ น ์‹คํ–‰ (๋นŒ๋“œยทํ…Œ์ŠคํŠธยทgit)",
31
+ "labelEn": "running commands (build/test/git)",
32
+ "agent": "sonnet",
33
+ "example": "๋นŒ๋“œํ•˜๊ณ  ์‹คํŒจํ•œ ํ…Œ์ŠคํŠธ๋งŒ ๋ณด์—ฌ์ค˜",
34
+ "exampleEn": "build it and show only the failing tests",
35
+ "budget": { "calls": null, "out": 6000 }
36
+ },
37
+ {
38
+ "id": "explore-t2",
39
+ "tier": "T2",
40
+ "category": "explore",
41
+ "label": "ํƒ์ƒ‰ยท์กฐํšŒ (ํŒŒ์ผ/๊ฐ’ ์ฐพ๊ธฐ)",
42
+ "labelEn": "lookup (finding files/values)",
43
+ "agent": "haiku-explore",
44
+ "example": "์ด ์„ค์ •๊ฐ’ ์–ด๋А ํŒŒ์ผ์— ์žˆ์–ด?",
45
+ "exampleEn": "which file holds this config value?",
46
+ "budget": { "calls": 8, "out": 1500 }
47
+ },
48
+ {
49
+ "id": "explore-t1",
50
+ "tier": "T1",
51
+ "category": "explore",
52
+ "label": "ํƒ์ƒ‰ยท์กฐํšŒ (ํŒŒ์ผ/๊ฐ’ ์ฐพ๊ธฐ)",
53
+ "labelEn": "lookup (finding files/values)",
54
+ "agent": "sonnet",
55
+ "example": "์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ณณ ์ „๋ถ€ ์ฐพ์•„์ค˜",
56
+ "exampleEn": "find every caller of this function",
57
+ "budget": { "calls": null, "out": 6000 }
58
+ },
59
+ {
60
+ "id": "check-t2",
61
+ "tier": "T2",
62
+ "category": "check",
63
+ "label": "์ƒํƒœ ํ™•์ธยท๊ฒ€์ฆ",
64
+ "labelEn": "status checks / verification",
65
+ "agent": "haiku-explore",
66
+ "example": "์ง€๊ธˆ ๋ฐฐํฌ๋œ ๋ฒ„์ „์ด ๋ญ”์ง€ ํ™•์ธํ•ด์ค˜",
67
+ "exampleEn": "check which version is deployed right now",
68
+ "budget": { "calls": 8, "out": 1500 }
69
+ },
70
+ {
71
+ "id": "check-t1",
72
+ "tier": "T1",
73
+ "category": "check",
74
+ "label": "์ƒํƒœ ํ™•์ธยท๊ฒ€์ฆ",
75
+ "labelEn": "status checks / verification",
76
+ "agent": "sonnet",
77
+ "example": "๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ด ์‹ค์ œ๋กœ ์ ์šฉ๋๋Š”์ง€ ํ™•์ธํ•ด์ค˜",
78
+ "exampleEn": "verify the migration actually applied",
79
+ "budget": { "calls": null, "out": 6000 }
80
+ },
81
+ {
82
+ "id": "paste-t2",
83
+ "tier": "T2",
84
+ "category": "paste",
85
+ "label": "๋ถ™์—ฌ๋„ฃ์€ ํ™”๋ฉดยท๋กœ๊ทธ ์งˆ๋ฌธ",
86
+ "labelEn": "questions about pasted screens/logs",
87
+ "agent": "haiku-explore",
88
+ "example": "์ด ์—๋Ÿฌ ๋กœ๊ทธ๋Š” ๋ฌด์Šจ ๋œป์ด์•ผ?",
89
+ "exampleEn": "what does this error log mean?",
90
+ "budget": { "calls": 8, "out": 1500 }
91
+ },
92
+ {
93
+ "id": "paste-t1",
94
+ "tier": "T1",
95
+ "category": "paste",
96
+ "label": "๋ถ™์—ฌ๋„ฃ์€ ํ™”๋ฉดยท๋กœ๊ทธ ์งˆ๋ฌธ",
97
+ "labelEn": "questions about pasted screens/logs",
98
+ "agent": "sonnet",
99
+ "example": "์ด ์ŠคํƒํŠธ๋ ˆ์ด์Šค์—์„œ ์–ด๋А ๋ชจ๋“ˆ์ด ์ฃฝ์€ ๊ฑด์ง€ ์งš์–ด์ค˜",
100
+ "exampleEn": "point out which module failed in this stack trace",
101
+ "budget": { "calls": null, "out": 8000 }
102
+ },
103
+ {
104
+ "id": "read-t2",
105
+ "tier": "T2",
106
+ "category": "read",
107
+ "label": "์ฝ๊ธฐยท์š”์•ฝยท์„ค๋ช…",
108
+ "labelEn": "reading / summarizing / explaining",
109
+ "agent": "haiku-explore",
110
+ "example": "์ด README ์š”์•ฝํ•ด์ค˜",
111
+ "exampleEn": "summarize this README",
112
+ "budget": { "calls": 8, "out": 1900 }
113
+ }
114
+ ]
115
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "note": [
3
+ "Curated ratchet rules bundled with the package โ€” promoted from mistakes that",
4
+ "actually recurred in the author's sessions, not from theory. `harness pull`",
5
+ "registers the whole set at once; `seed` offers them one at a time and records",
6
+ "each answer. Both read this file, so there is one source for the wording.",
7
+ "Each rule carries both languages because the text is injected into the model's",
8
+ "context, where a Korean-only rule would steer an English session into Korean.",
9
+ "Ids are derived from the `ko` text (the canonical one), so a rule keeps its",
10
+ "identity โ€” and a user's 'no' โ€” when the English wording is revised."
11
+ ],
12
+ "rules": [
13
+ {
14
+ "ko": "์›น fetch/search์—์„œ robotsยทUA ์ฐจ๋‹จ('unable to fetch' ๋“ฑ)์ด ๋ฐœ์ƒํ•˜๋ฉด โ†’ curl์— ๋ธŒ๋ผ์šฐ์ € UA(Mozilla/5.0 ... Chrome/...) ํ—ค๋”๋ฅผ ๋ถ™์—ฌ ์žฌ์‹œ๋„. reddit ๋“ฑ์€ .json ์—”๋“œํฌ์ธํŠธ + UA ์กฐํ•ฉ์œผ๋กœ ์ ‘๊ทผ ๊ฐ€๋Šฅ",
15
+ "en": "When a web fetch/search is blocked by robots or user-agent checks ('unable to fetch' and similar) โ†’ retry with curl carrying a browser UA header (Mozilla/5.0 ... Chrome/...). Sites like reddit also answer on their .json endpoints with that UA"
16
+ },
17
+ {
18
+ "ko": "ratchet ๋ฃฐ promote ํ˜ธ์ถœ ์ง์ „ ์‚ฌ์šฉ์ž์—๊ฒŒ scope(project/global)๋ฅผ ๋จผ์ € ๋ฌป๋Š”๋‹ค โ€” Bash ํ™˜๊ฒฝ์€ non-TTY๋ผ CLI readline ํ”„๋กฌํ”„ํŠธ๊ฐ€ ์•ˆ ๋œจ๋ฏ€๋กœ, ํ˜ธ์ถœ์ž(LLM)๊ฐ€ ๋Œ€์‹  ๋ฌป๊ณ  --project/--global ํ”Œ๋ž˜๊ทธ๋ฅผ ๋ช…์‹œํ•ด ์‹คํ–‰",
19
+ "en": "Ask the user for the scope (project or global) before calling ratchet promote โ€” the Bash environment is non-TTY, so the CLI's readline prompt never appears; the caller (the model) has to ask and pass --project/--global explicitly"
20
+ },
21
+ {
22
+ "ko": "์ž๋™ํ™” ๋„๊ตฌ๊ฐ€ grepยท์ •๊ทœ์‹์œผ๋กœ ์ฐพ๋Š” ๋งˆ์ปค ํ…์ŠคํŠธ(ํ—ค๋”ยท์•ต์ปคยทํ‚ค์›Œ๋“œ ๋ผ์ธ)๋Š” ๋ฆฌํŒฉํ„ฐ๋งยท์••์ถ•ยท์ˆ˜์ • ๊ธˆ์ง€ โ€” ์ •ํ™• ๋งค์นญ ๊ฒ€์ถœ์€ ํ•œ ๊ธ€์ž๋งŒ ๋ฐ”๋€Œ์–ด๋„ ๊นจ์ง",
23
+ "en": "Never refactor, compress or reword marker text that an automated tool finds by grep or regex (headings, anchors, keyword lines) โ€” exact-match detection breaks on a single changed character"
24
+ },
25
+ {
26
+ "ko": "์ž๋™ํ™” ์„ค๊ณ„์—์„œ vision/screenshot ๋ฃจํ”„๊ฐ€ ๋ณด์ด๋ฉด โ†’ ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•œ ํ•จ์ˆ˜ยทAPIยทMCP tool๋ถ€ํ„ฐ ์ฐพ๋Š”๋‹ค. ํ†ต์ œ ๊ฐ€๋Šฅํ•œ ๋‚ด๋ถ€ ๋„๊ตฌ๋Š” ๋ฌด์กฐ๊ฑด API, ํ†ต์ œ ๋ถˆ๊ฐ€ ์™ธ๋ถ€ SaaS๋งŒ vision ์ฐจ์„ ์ฑ…. ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฐ”๊พผ ๋’ค์— ๋ชจ๋ธ์„ ๋‚ด๋ฆฐ๋‹ค โ€” ๊ฑฐ๊พธ๋กœ ๊ฐ€๋ฉด ํ† ํฐ ํญ๋ฐœ",
27
+ "en": "When an automation design calls for a vision/screenshot loop โ†’ look for a callable function, API or MCP tool first. Anything you control gets an API; vision is the fallback only for external SaaS you cannot change. Fix the interface before lowering the model โ€” doing it the other way round explodes the token cost"
28
+ },
29
+ {
30
+ "ko": "์ž…๋ ฅ ๋ฐ์ดํ„ฐ(ground-truth) ๋ณ€๊ฒฝ ์‹œ ๊ทธ์— ์˜์กดํ•˜๋Š” ๋ชจ๋“  ํŒŒ์ƒ ์ž์‚ฐ์„ ๋๊นŒ์ง€ ์žฌ์ƒ์„ฑํ•œ๋‹ค โ€” ์ค‘๊ฐ„ ๋‹จ๊ณ„๋ฅผ ์ƒ๋žตํ•˜๋ฉด stale ์‚ฐ์ถœ๋ฌผ์ด ์ƒˆ ์ž…๋ ฅ ์œ„์— ์–นํ˜€ ๊ฒฐ๊ณผ๊ฐ€ ๊นจ์ง",
31
+ "en": "When the ground-truth input changes, regenerate every derived asset all the way through โ€” skipping an intermediate step leaves a stale artifact sitting on top of the new input and the result breaks"
32
+ },
33
+ {
34
+ "ko": "ํƒ์ƒ‰ยท์กฐํšŒยท์ƒํƒœ ํ™•์ธยท๋ช…๋ น ์‹คํ–‰ ๊ฐ™์€ ๋‹จ์ˆœ ์š”์ฒญ์€ `model: haiku` ์„œ๋ธŒ์—์ด์ „ํŠธ๋กœ ์œ„์ž„ํ•ด ์ƒ์œ„ ๋ชจ๋ธ ํ† ํฐ์„ ์•„๋‚€๋‹ค (์ฝ๊ธฐ ์ „์šฉ preset ์—์ด์ „ํŠธ๊ฐ€ ์ด๋ฏธ ์žˆ์œผ๋ฉด ๊ทธ๊ฑธ ์“ฐ๊ณ , ์—†์œผ๋ฉด ํ‹ฐ์–ด๋งŒ ๋‚ด๋ ค์„œ ์œ„์ž„)",
35
+ "en": "Delegate simple requests โ€” lookup, status checks, running commands โ€” to a `model: haiku` subagent to keep the expensive model's tokens for real work (use an existing read-only preset agent when there is one; otherwise delegate with the tier lowered)"
36
+ }
37
+ ]
38
+ }
package/src/advice.js CHANGED
@@ -514,6 +514,8 @@ export const ISSUE_TIPS = {
514
514
  * need a fallback so history.js can still surface the right tip.
515
515
  */
516
516
  export const CHIP_TO_CODES = {
517
+ 'โš  Ctx 500k+': ['LARGE_INPUT_PER_REQUEST'],
518
+ // Legacy chip name (pre-v3.32, when the threshold was 200k).
517
519
  'โš  Ctx 200k+': ['LARGE_INPUT_PER_REQUEST'],
518
520
  // Legacy chip name (pre-v2.18) โ€” kept so `last`/`history` can still resolve
519
521
  // codes from history files written by older versions.
@@ -545,11 +547,12 @@ export const CAP_TIPS = {
545
547
  * shown to a global audience.
546
548
  */
547
549
  export function chipForIssues(issues, contextWindow) {
548
- // Fires on *actual usage* (a real request carried >210k input tokens), not
549
- // on the model merely supporting 1M โ€” current models are all 1M by default
550
- // with no price premium, so "1M ON" stopped being a meaningful alarm. The
551
- // meaningful signal is "your context genuinely exceeded 200k".
552
- if (contextWindow?.size === '1M') return 'โš  Ctx 200k+';
550
+ // Fires on *actual usage* (a real request carried more than
551
+ // CONTEXT_WARN_TOKENS), not on the model merely supporting 1M. The old 200k
552
+ // line fired on a brand-new session โ€” system prompt plus a couple of file
553
+ // reads already clears it โ€” so it warned constantly and told nobody
554
+ // anything. 500k is where the per-turn re-billing is worth interrupting for.
555
+ if (contextWindow?.overWarn) return 'โš  Ctx 500k+';
553
556
  const codes = issues.map((i) => i.code);
554
557
  if (codes.includes('LARGE_INPUT_PER_REQUEST')) return 'โš  Input spike';
555
558
  if (codes.includes('BUCKET_5M_DOMINANT') || codes.includes('BUCKET_5M_DOMINANT_GATEWAY')) return 'โš  5m TTL';
package/src/brief.js CHANGED
@@ -227,7 +227,7 @@ export async function runBrief({ sessionId, transcriptPath, now = Date.now() })
227
227
  for (const [kind, x] of fresh) {
228
228
  items.push(kind === 'route'
229
229
  ? `์ƒˆ ์œ„์ž„ ํ›„๋ณด๊ฐ€ ๊ฐ์ง€๋˜์—ˆ์Šต๋‹ˆ๋‹ค โ€” "${x.label}" ์œ ํ˜• ${x.count}ํšŒ ๋ฐ˜๋ณต(statusline์˜ route? R${x.id} ์นฉ). ๋“ฑ๋ก: claude-token-saver harness promote R${x.id} --project|--global (์ ์šฉ ๋ฒ”์œ„๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ ํ™•์ธ) / ๋ฌด์‹œ: route-scan dismiss ${x.id}`
230
- : `์Šน์ธ๋œ ์œ„์ž„ ๋ฃฐ์˜ ์ตœ๊ทผ ์—๋Ÿฌ์œจ์ด ๊ธฐ์ค€(20%)์„ ๋„˜์—ˆ์Šต๋‹ˆ๋‹ค โ€” "${x.label}" (statusline์˜ rule-health ์นฉ). ์กฐ๊ฑด ์ขํžˆ๊ธฐ/์ œ๊ฑฐ๋ฅผ ์‚ฌ์šฉ์ž์™€ ์ƒ์˜ํ•˜์„ธ์š”: claude-token-saver route-scan rules`);
230
+ : `์Šน์ธ๋œ ์œ„์ž„ ๋ฃฐ์˜ ์ตœ๊ทผ ์—๋Ÿฌ์œจ์ด ๊ธฐ์ค€(20%)์„ ๋„˜์—ˆ์Šต๋‹ˆ๋‹ค โ€” "${x.label}" (${x.healthSource === 'delegated' ? `์œ„์ž„ ์‹คํ–‰ ${x.delegatedRuns}๊ฑด ์ค‘ ์—๋Ÿฌ์œจ ${Math.round((x.delegatedErrRate || 0) * 100)}%` : `์œ ์‚ฌ ์—ํ”ผ์†Œ๋“œ ๊ธฐ์ค€ ์—๋Ÿฌ์œจ ${Math.round((x.errRate || 0) * 100)}%`}, statusline์˜ rule-health ์นฉ). ์กฐ๊ฑด ์ขํžˆ๊ธฐ/์ œ๊ฑฐ๋ฅผ ์‚ฌ์šฉ์ž์™€ ์ƒ์˜ํ•˜์„ธ์š”: claude-token-saver route-scan rules`);
231
231
  }
232
232
  s.briefed = [...briefed];
233
233
  } catch { /* caches unreadable โ€” ctx briefing above still applies */ }