claude-token-saver 3.31.0 → 3.35.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.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  # claude-token-saver
8
8
 
9
- **아낀 돈을 두 줄로 보여 줍니다.** 비싼 모델이 반복하던 쉬운 작업을 싼 모델로 내려보내고, 모델이 읽지 못하는 문서를 Markdown 으로 바꿉니다. 두 절감액 모두 추정이 아니라 원장 기록이고, 더 많이 아낀 쪽이 첫 줄을 차지합니다. 의존성 0, 설치 한 줄.
9
+ **아낀 돈을 두 줄로 보여 줍니다.** 비싼 모델이 반복하던 쉬운 작업을 싼 모델로 내려보내고, 모델이 읽지 못하는 문서를 Markdown 으로 바꿉니다. 두 절감액 모두 추정이 아니라 원장 기록입니다. 의존성 0, 설치 한 줄.
10
10
 
11
11
  ![statusline 예시. 첫 줄은 라우팅 절감액, 둘째 줄은 문서 변환 절감액, 셋째 줄은 진단 칩입니다](./docs/statusline.png)
12
12
 
@@ -14,18 +14,22 @@
14
14
  npm i -g claude-token-saver
15
15
  ```
16
16
 
17
+ 숫자 세 개가 이 도구의 전부입니다.
18
+
19
+ - **비용 −18.6%**: Harness 5원칙 도입 전후 실측 ([근거](#실제-효과-도입-전후-리포트))
20
+ - **문서 한 건에 51만 토큰**: 30MB 발표자료를 XML 대신 Markdown 으로 읽었을 때 ([근거](#-doc2md-문서를-읽기-전에-markdown-으로-바꿉니다))
21
+ - **라우팅 절감액은 실행 단위 원장**: 추정치가 아니라 위임 한 건 한 건의 차액 기록 ([근거](#-절감액은-추정이-아니라-원장-기록입니다))
22
+
17
23
  ## 네 가지가 함께 돌아갑니다
18
24
 
19
25
  | | 하는 일 | 효과 |
20
26
  |---|---|---|
21
27
  | 🔀 **라우팅** | 반복되는 쉬운 작업을 더 싼 모델에 위임 | 절감액을 원장에 실측 기록 |
22
- | 📄 **문서 변환** | pptx·xlsx·pdf·docx·fig 를 읽기 전에 Markdown 으로 변환 | 발표자료 한 건에 **51만 토큰** 절약 ([아래](#-doc2md-문서를-읽기-전에-markdown-으로-바꿉니다)) |
23
- | 🅷 **Harness** | 증거 없는 완료 보고·검증 생략 차단 (5원칙) | **비용 −18.6%** ([실측](#실제-효과-도입-전후-리포트)) |
28
+ | 📄 **문서 변환** | pptx·xlsx·pdf·docx·fig 를 읽기 전에 Markdown 으로 변환 | 발표자료 한 건에 **51만 토큰** 절약 |
29
+ | 🅷 **Harness** | 증거 없는 완료 보고·검증 생략 차단 (5원칙) | **비용 −18.6%** |
24
30
  | ⚙️ **Ratchet** | 한 번 겪은 에러를 룰로 고정 | 같은 실수 재발 차단 |
25
31
 
26
- 설치 한 번이면 넷 다 적용됩니다. 실측 −18.6%는 Harness와 ratchet의 몫이고, 라우팅과 문서 변환 절감액은 그 위에 얹힙니다.
27
-
28
- 두 절감액은 성격이 달라서 한 숫자로 합치지 않습니다. 라우팅은 "같은 일을 더 싼 모델이 했다"이고, 문서 변환은 "읽을 수 없던 파일을 읽었고 그 과정에서 원본을 통째로 밀어 넣지 않았다"입니다. statusline 은 둘을 각각의 줄로 보여 주고, 금액이 큰 쪽을 위에 놓습니다.
32
+ 설치 한 번이면 넷 다 적용됩니다. 실측 −18.6%는 Harness와 ratchet의 몫이고, 라우팅과 문서 변환 절감액은 그 위에 얹힙니다. 두 절감액은 성격이 달라서 한 숫자로 합치지 않고, statusline 이 각각의 줄로 보여 주며 금액이 큰 쪽을 위에 놓습니다.
29
33
 
30
34
  ## 🔀 절감액은 추정이 아니라 원장 기록입니다
31
35
 
@@ -53,7 +57,7 @@ $ claude-token-saver route-scan savings # 모든 금액을 룰 단위까지
53
57
  룰: T2|paste|-Users-me-projects-my-app
54
58
  ```
55
59
 
56
- **집계에서 빼는 것들** — 정직한 숫자가 작은 숫자보다 낫기 때문입니다.
60
+ **집계에서 빼는 것들**: 정직한 숫자가 작은 숫자보다 낫기 때문입니다.
57
61
 
58
62
  - 등록된 룰이 담당하지 않는 위임(`Explore`, 직접 만든 에이전트, 플러그인 에이전트): 이 도구가 라우팅한 결과가 아닙니다.
59
63
  - 가격표가 인식하지 못하는 모델명: 틀린 금액을 쓰느니 그 실행을 뺍니다.
@@ -113,13 +117,36 @@ npm i -g claude-token-saver
113
117
 
114
118
  > ⚠️ sudo로 글로벌 설치를 하면 Skill이 사용자 계정이 아니라 root의 `~/.claude`에 등록되는 함정이 있습니다. nvm이나 fnm, Volta를 사용해 사용자 영역에 설치하기를 권장합니다.
115
119
 
120
+ ### 설치하면 켜지는 기능과 직접 켜야 하는 기능
121
+
122
+ 설치 시점에 비용이 들지 않는 기능은 전부 자동으로 켜집니다. 수동으로 남겨 둔 항목은 Claude Code 자체의 설정을 바꾸거나, 적용 범위를 사람이 정해 주어야 하는 것들뿐입니다.
123
+
124
+ | 기능 | 설치 직후 상태 | 끄는 방법 |
125
+ |---|---|---|
126
+ | statusline (진단 칩·절감 원장) | 켜짐 | `claude-token-saver uninstall` |
127
+ | `/claude-token-saver` Skill | 켜짐 | 위와 같습니다 |
128
+ | SessionStart 훅 (route-scan 재분석) | 켜짐 | 위와 같습니다 |
129
+ | UserPromptSubmit 훅 (brief 주입) | 켜짐 | 위와 같습니다 |
130
+ | 최초 route-scan (최근 14일 로그 분석) | 설치 중 즉시 1회 실행 | 해당 없습니다 |
131
+ | 🅷 Harness 5원칙 (`~/.claude/CLAUDE.md`) | 켜짐 (터미널에서는 내용을 보여 주고 한 번 묻습니다) | `harness uninit --global` · `CTS_NO_HARNESS=1` |
132
+ | doc2md 훅 (Read·Edit·Write·프롬프트) | 켜짐 | `doc2md off` · `CTS_NO_DOC2MD=1` |
133
+ | doc2md 변환기(markitdown venv) | 터미널에서 설치 여부를 묻고, 비대화형 설치에서는 명령만 안내합니다 | `doc2md install-converter` 로 나중에 설치 |
134
+ | 한국어 문체 지침 | 시스템 로케일이 한국어면 켜짐 (터미널에서는 묻습니다) | `korean off` · `CTS_NO_KOREAN=1` |
135
+ | compact-window 경고 칩 | 켜짐 | `compact-window off` |
136
+ | 업데이트 안내 칩 | 켜짐 | `CTS_NO_UPDATE_CHECK=1` |
137
+ | **compact-window 값 고정** (`autoCompactWindow` 500k) | **꺼짐 — 직접 실행해야 합니다** | `compact-window set --global` 또는 `--project` |
138
+ | **모델 피팅 룰 승인** (`ratchet-model.md` 위임 룰) | **후보만 제안합니다** | `route-scan rules` 로 확인하고 승인·삭제 |
139
+ | `handoff` (한도 임박 시 작업 백업) | 필요할 때 직접 실행하는 명령입니다 | 해당 없습니다 |
140
+
141
+ `compact-window set` 은 Claude Code 의 `settings.json` 에 값을 적고, 전역과 프로젝트 중 어디에 적을지는 사람이 정해야 하므로 자동으로 실행하지 않습니다. 모델 피팅 룰도 같은 이유로 승인 단계를 남겨 두었습니다. 어떤 작업을 더 싼 티어에 맡길지는 사용자의 판단이 필요합니다.
142
+
116
143
  ## statusline 읽는 법
117
144
 
118
145
  절감 원장에 기록이 쌓이면 statusline이 **두 줄로** 출력됩니다. 첫째 줄에는 라우팅 절감액만 표시하고, 둘째 줄에는 진단 칩을 표시합니다.
119
146
 
120
147
  ```
121
148
  🔀 Routing saved $2.09 | fable→sonnet 1× $0.72 · opus→haiku 1× $0.57
122
- ⚠ 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
149
+ ⚠ 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
123
150
  ```
124
151
 
125
152
  원장이 비어 있으면, 다시 말해 아직 실측된 위임이 없으면 첫째 줄을 그리지 않고 종전처럼 한 줄로 출력합니다. 일부 환경(구버전 macOS Claude Code)에서 첫째 줄만 표시된다면 `--single-line` 옵션으로 한 줄 레이아웃을 유지하십시오.
@@ -130,9 +157,11 @@ npm i -g claude-token-saver
130
157
  | `🤖` | 현재 모델 |
131
158
  | `🅷 5/5` | harness 원칙 점수 ([Harness 모드](#-harness-모드)) |
132
159
  | `🧠` | 캐시 히트율 (85%+ 녹색) |
133
- | `⏳` | 캐시 TTL 카운트다운입니다. 만료되기 전에 메시지를 보내면 캐시가 유지됩니다 |
160
+ | `⏳` | 캐시 TTL 카운트다운입니다. 만료되기 전에 메시지를 보내면 캐시가 유지됩니다. 입력이 없을 때도 초 단위로 줄어드는 표시는 Claude Code v2.1.97 이상에서 동작합니다 (아래 [카운트다운이 멈춰 보일 때](#동작-원리--환경) 참고) |
134
161
  | `✦ current` / `📅 weekly` | 5시간 / 7일 rate-limit 윈도 사용률 + 리셋 시각 |
135
162
  | `📦` | 컨텍스트 사용률입니다(예: `Ctx 68% of 1M`). 사용률에 따라 녹색·노란색·빨간색으로 표시합니다. 최신 모델은 1M 컨텍스트가 기본이고 별도 요금이 붙지 않지만, 토큰량 자체가 턴당 비용과 5시간·7일 한도를 빠르게 소모시킵니다 |
163
+ | `💵 Sep $42` | **이번 달 1일 00시(로컬) 이후 지출 추정치**입니다. 세션 로그에 세션별 모델 단가를 적용해 합산하며, 5h/7d cap 이 없는 게이트웨이 환경에서도 항상 표시됩니다 (v3.35.0) |
164
+ | `🔑 budget` | **LiteLLM 게이트웨이 키의 예산 게이지**입니다. stdin 에 rate_limits 가 오지 않는 환경에서 키의 `max_budget` 대비 `spend` 를 `🔑 budget ▰▱ 34% $34/$100` 형태로 보여 줍니다 (v3.35.0, [아래](#-bedrockvertex-경유-환경)) |
136
165
  | `💰` | 프롬프트 캐시가 절약해 준 누적 금액입니다. 첫째 줄의 `🔀`(모델 라우팅 절감액)와는 **서로 다른 수치입니다** |
137
166
  | `v3.24.0` | 지금 실행 중인 claude-token-saver의 버전입니다. 최신이면 회색으로 줄 끝에 조용히 놓입니다 |
138
167
  | `⬆ v3.24.0 → 3.25.0` | 새 버전이 배포되어 있다는 표시입니다. 조치가 필요한 칩이므로 줄 앞쪽으로 올라옵니다 ([업데이트 안내](#-업데이트-안내)) |
@@ -143,7 +172,7 @@ npm i -g claude-token-saver
143
172
  🚨 5H █████▓ 94% 🔄 12:36 · 🅷 5/5 · 🤖 Opus 4.8 · 🧠 Cache hit 72.1% · ⚠ Cache miss · 📅 weekly ▓░░░░░ 12% 🔄 Sun 14:26 · 📦 Ctx 200k · last 1d
144
173
  ```
145
174
 
146
- 칩의 종류는 다음과 같습니다. `🚨 5H/7D NN%`(한도 임박) · `⚠ Ctx 200k+`(단일 요청이 실제로 200k를 초과) · `⚠ Cache miss` · `⚠ Input spike` · `⚠ Output heavy` · `⚠ Call surge` · `⚠ Rebuild churn` · `⚠ 5m TTL`. 두 윈도가 동시에 90%를 넘으면 리셋이 더 임박한 쪽을 🚨로 올리고, 나머지 하나는 빨간 세그먼트로 계속 표시합니다 (v2.16.0 이상).
175
+ 칩의 종류는 다음과 같습니다. `🚨 5H/7D NN%`(한도 임박) · `⚠ Ctx 500k+`(단일 요청이 실제로 500k를 초과) · `⚠ Cache miss` · `⚠ Input spike` · `⚠ Output heavy` · `⚠ Call surge` · `⚠ Rebuild churn` · `⚠ 5m TTL`. 두 윈도가 동시에 90%를 넘으면 리셋이 더 임박한 쪽을 🚨로 올리고, 나머지 하나는 빨간 세그먼트로 계속 표시합니다 (v2.16.0 이상).
147
176
 
148
177
  ### 경고 칩이 떴을 때
149
178
 
@@ -176,7 +205,7 @@ Claude Code 안에서 `/claude-token-saver` Skill을 실행하거나, 칩에 적
176
205
  | `claude-token-saver install` | Skill·statusline 수동 등록 |
177
206
  | `claude-token-saver uninstall [--purge]` | 등록한 훅·statusline·Skill 제거. 기록된 절감액은 남기며, `--purge` 를 붙이면 상태 디렉터리까지 지웁니다 |
178
207
 
179
- 출력 언어는 `mode ko`와 `mode en`으로 전환합니다. 기본값은 영어이며, statusline의 칩은 언제나 기호로 표시합니다. 전체 옵션은 [영문 README](./README.en.md#options)를 참고하십시오.
208
+ 출력 언어는 설치할 때 한 번 정합니다. 터미널에서 설치하면 시스템 로케일을 기본값으로 제시하고 한국어를 쓸지 물어보며, 비대화형 설치에서는 로케일 판정을 그대로 기록합니다. 한 번 기록되면 업그레이드해도 다시 묻지 않습니다. 나중에 바꿀 때는 `mode ko`나 `mode en`을 쓰고, 스크립트에서 설치할 때는 `CTS_LANG=ko` 또는 `CTS_LANG=en`으로 지정할 수 있습니다. statusline의 칩은 언제나 기호로 표시합니다. 전체 옵션은 [영문 README](./README.en.md#options)를 참고하십시오.
180
209
 
181
210
  ## ⬆ 업데이트 안내
182
211
 
@@ -205,7 +234,8 @@ claude-token-saver harness off | on # 🅷 표시 토글
205
234
  ```
206
235
 
207
236
  - `promote`는 non-TTY 환경(스크립트나 LLM 호출)에서 `--project` 또는 `--global` 플래그가 **반드시 필요합니다.** 적용 범위가 사용자에게 묻지 않은 채 결정되는 사고를 막기 위한 설계입니다.
208
- - `pull`은 패키지에 동봉된 **제작자 큐레이션 랫쳇 룰**(`presets/ratchet-rules.md` — 실제 반복 사고에서 승격된 범용 룰만)을 내 글로벌 랫쳇(`~/.claude/ratchet.md`)에 등록합니다. 설치(`install`)나 `init`은 아무것도 자동 주입하지 않으며, `pull`은 항상 opt-in이고 재실행해도 중복이 없습니다(멱등). 마음에 안 드는 룰은 `harness rm`으로 제거하면 됩니다.
237
+ - `pull`은 패키지에 동봉된 **제작자 큐레이션 랫쳇 룰**(`presets/ratchet-rules.json`, 실제 반복 사고에서 승격된 범용 룰만)을 내 글로벌 랫쳇(`~/.claude/ratchet.md`)에 등록합니다. 설치(`install`)나 `init`은 아무것도 자동 주입하지 않으며, `pull`은 항상 opt-in이고 재실행해도 중복이 없습니다(멱등). 마음에 안 드는 룰은 `harness rm`으로 제거하면 됩니다.
238
+ - `seed`는 같은 프리셋을 **한 건씩** 물어보는 경로입니다. `pull`이 랫쳇 룰 전체를 한 번에 등록하는 명령인 데 반해, `seed`는 모델 피팅 프리셋까지 포함해 설치·업그레이드 후 첫 세션에서 한 건씩 제안합니다 ([아래](#-seed-설치-직후부터-위임이-걸리게-하는-시작-룰)).
209
239
  - 🅷⚠ 런타임 경고(`ratchet?` `no-evidence` `PEV-skip`)는 30분 후 자동 만료되고, 하위 디렉터리 세션도 프로젝트에 올바르게 매칭됩니다. PEV-skip은 변경성 도구(Edit/Write/Bash)만 카운트해 읽기 위주 세션에서는 발동하지 않습니다 (v2.16.0+).
210
240
 
211
241
  <details>
@@ -223,7 +253,7 @@ ratchet의 가치는 **한 방향 누적**에 있습니다. 룰을 가볍게 지
223
253
 
224
254
  ## 📦 compact-window: 1M 컨텍스트의 자동 압축 지점 고정
225
255
 
226
- Claude Code는 `min(autoCompactWindow, 모델 최대 창)`에 가까워지면 대화를 자동 압축합니다. 1M 창을 쓰면 이 값이 잡혀 있지 않은 한 80만 토큰 근처까지 가서야 압축이 걸리고, 그전까지 모든 요청이 전체 컨텍스트를 통째로 재과금합니다. **1M은 너무 크니 40만~70만 범위를 권장합니다** — 큰 붙여넣기용 여유는 200k 세션의 2~3.5배로 남기면서 꼬리만 잘라냅니다.
256
+ Claude Code는 `min(autoCompactWindow, 모델 최대 창)`에 가까워지면 대화를 자동 압축합니다. 1M 창을 쓰면 이 값이 잡혀 있지 않은 한 80만 토큰 근처까지 가서야 압축이 걸리고, 그전까지 모든 요청이 전체 컨텍스트를 통째로 재과금합니다. **1M은 너무 크니 40만~70만 범위를 권장합니다.** 큰 붙여넣기용 여유는 200k 세션의 2~3.5배로 남기면서 꼬리만 잘라냅니다.
227
257
 
228
258
  **권장 범위 안이면 경고하지 않습니다.** 40만은 절감이 압축 횟수를 이기는 하한이고, 긴 세션은 그보다 여유가 더 필요한 경우가 많습니다. 미설정이거나 70만을 넘을 때만 알립니다(그보다 낮게 잡은 건 더 공격적으로 아끼겠다는 선택이라 그냥 둡니다).
229
259
 
@@ -277,11 +307,11 @@ claude-token-saver route-scan savings # 절감 원장: 어느 룰이
277
307
 
278
308
  ### 게이트웨이(Bedrock·LiteLLM) 경유 환경
279
309
 
280
- 사내 게이트웨이를 거치면 로그의 모델명 자리에 추론 프로파일 ARN이 기록됩니다. 그 문자열에는 `opus`·`haiku` 같은 단서가 없어서 예전 버전은 이것을 전부 Sonnet으로 읽었고, 그 결과 **T1(→sonnet) 위임 룰이 하나도 제안되지 않았으며 절감 집계가 0**이었습니다.
310
+ 사내 게이트웨이를 거치면 로그의 모델명 필드에 추론 프로파일 ARN이 기록됩니다. 그 문자열에는 `opus`·`haiku` 같은 단서가 없어서 예전 버전은 이것을 전부 Sonnet으로 읽었고, 그 결과 **T1(→sonnet) 위임 룰이 하나도 제안되지 않았으며 절감 집계가 0**이었습니다.
281
311
 
282
312
  v3.10.0부터는 프로파일 ID를 역할(main·opus·sonnet·haiku)로 되돌린 뒤 `ANTHROPIC_DEFAULT_*_MODEL` 환경변수가 선언한 별칭으로 치환합니다. 매핑은 부모 세션의 `Task` 호출과 서브에이전트 기록을 `toolUseId`로 조인해 스스로 학습하며, 관측이 3건 미만이거나 역할 판정이 80% 미만으로 갈리면 **추측하지 않고 `unknown`으로 두고 위임 집계에서 제외**합니다.
283
313
 
284
- 자동 학습이 닿지 않는 환경을 위한 수동 경로도 있습니다. `<userDataDir>/profile-map.json`에 아래처럼 적으면 되고, 계정 ID와 리전은 `*`로 가려도 매칭됩니다.
314
+ 자동 학습이 닿지 않는 환경에서 쓸 수 있는 수동 경로도 있습니다. `<userDataDir>/profile-map.json`에 아래처럼 적으면 되고, 계정 ID와 리전은 `*`로 가려도 매칭됩니다.
285
315
 
286
316
  ```jsonc
287
317
  {
@@ -297,6 +327,32 @@ v3.10.0부터는 프로파일 ID를 역할(main·opus·sonnet·haiku)로 되돌
297
327
 
298
328
  이 파일에는 사내 식별자가 평문으로 남으므로 저장소에 커밋하지 마십시오. 게이트웨이를 쓰지 않는 환경에서는 파일이 아예 만들어지지 않고 기존 동작이 그대로 유지됩니다.
299
329
 
330
+ ## 🌱 seed: 설치 직후부터 위임이 걸리게 하는 시작 룰
331
+
332
+ 모델 피팅 랫쳇(`ratchet-model.md`)은 **빈 파일로 시작합니다.** route-scan이 사용자의 로그에서 같은 유형의 작업을 여러 번 관측하고, 사용자가 그 후보를 승인해야 룰이 생깁니다. 즉 갓 설치한 상태에서는 위임이 한 건도 걸리지 않고, 그 상태가 며칠 이어집니다. 정작 절감 효과가 가장 클 시기입니다.
333
+
334
+ `seed`는 패키지에 동봉된 프리셋으로 그 공백을 메웁니다.
335
+
336
+ | 프리셋 | 내용 | 파일 |
337
+ |---|---|---|
338
+ | 모델 피팅 9건 | 명령 실행·탐색·상태 확인·붙여넣은 로그 질문·읽기 요약, 각 유형의 T2(haiku)와 T1(sonnet) 룰 | `presets/model-rules.json` |
339
+ | 랫쳇 6건 | 실제 반복 사고에서 승격된 범용 룰 | `presets/ratchet-rules.json` |
340
+
341
+ **등록 절차:** 설치나 업그레이드 후 첫 세션에서 SessionStart 훅이 대기 중인 프리셋을 모델에게 전달하고, 모델이 **한 건씩 순서대로** 등록 여부를 묻습니다. 사용자가 답하면 곧바로 아래 명령을 실행합니다.
342
+
343
+ ```bash
344
+ claude-token-saver seed # 대기 중인 프리셋과 응답 기록
345
+ claude-token-saver seed accept <id> --global|--project # 한 건 등록 (적용 범위 필수)
346
+ claude-token-saver seed accept all --global # 사용자가 "전부 등록"이라고 답한 경우
347
+ claude-token-saver seed skip <id> # 거절 — 다시 묻지 않습니다
348
+ claude-token-saver seed reset # 응답 기록을 지워 전체를 다시 제안 대상으로
349
+ ```
350
+
351
+ - **승인 없이는 아무것도 기록되지 않습니다.** 거절한 룰은 업그레이드 후에도 다시 묻지 않고, 새 릴리스에서 추가된 프리셋만 다음 세션에 제안됩니다.
352
+ - 사용자가 이미 같은 유형(같은 티어·카테고리)의 룰을 직접 승인해 두었다면 그 프리셋은 제안하지 않습니다.
353
+ - 프리셋으로 등록한 룰은 **남의 통계를 내 것처럼 표시하지 않습니다.** 등록 직후에는 `preset (curated)`로 적히고, 이후 스캔에서 실제 발화와 위임 결과가 측정되면 그 수치로 대체됩니다. 위임 에러율이 기준을 넘으면 다른 룰과 똑같이 재검토 플래그가 붙습니다.
354
+ - 적용 범위는 `--global`과 `--project` 중 반드시 명시해야 합니다. 훅 환경은 non-TTY라 CLI가 직접 물을 수 없으므로, 모델이 사용자에게 확인한 뒤 플래그를 붙여 실행합니다.
355
+
300
356
  ## 🇰🇷 한국어 문체 지침
301
357
 
302
358
  Claude가 한국어로 쓸 때 나타나는 문체 결함(문장 성분 생략, 명사형 종결, 번역체, 엠대시 남용)을 교정하는 지침을 **세션 시작 시 한 번 주입합니다.**
@@ -326,7 +382,7 @@ Claude Code의 output style로도 같은 일을 할 수 있지만, output style
326
382
  >
327
383
  > 다음 caption-blocks가 captions.json 단어열과 일치하는지 본다. 내레이션 재TTS 후 blocks 재생성 빠지면 옛 자막이 새 음성 위에 뜬다.
328
384
 
329
- 바뀐 지점은 세 가지입니다. 첫째, 엠대시로 이어 붙이던 절이 마침표로 끊어져 한 문장이 한 가지 사실만 전달합니다. 둘째, "확인", "대조", "렌더 깨짐" 같은 명사형 종결이 "확인한다", "본다", "뜬다"처럼 서술어로 바뀌어 무엇을 하라는 것인지가 분명해집니다. 셋째, "자막·음성 어긋나"처럼 조사가 빠진 자리에 조사가 돌아와 어떤 성분이 주어이고 목적어인지 읽는 즉시 잡힙니다.
385
+ 바뀐 지점은 세 가지입니다. 첫째, 엠대시로 이어 붙이던 절이 마침표로 끊어져 한 문장이 한 가지 사실만 전달합니다. 둘째, "확인", "대조", "렌더 깨짐" 같은 명사형 종결이 "확인한다", "본다", "뜬다"처럼 서술어로 바뀌어 무엇을 하라는 것인지가 분명해집니다. 셋째, "자막·음성 어긋나"처럼 조사가 빠졌던 지점에 조사가 돌아와 어떤 성분이 주어이고 목적어인지 읽는 즉시 잡힙니다.
330
386
 
331
387
  기술적 내용은 양쪽이 동일합니다. 지침은 판단이나 정확도가 아니라 문장의 완성도에만 관여하므로, 답이 달라지는 것이 아니라 같은 답을 다시 읽지 않아도 되는 형태로 만들어 줍니다. 슬랙처럼 사람이 스크롤하며 읽는 채널에서는 이 차이가 되묻는 횟수를 줄이고, 되묻지 않는 만큼 토큰도 아낍니다.
332
388
 
@@ -334,7 +390,7 @@ Claude Code의 output style로도 같은 일을 할 수 있지만, output style
334
390
 
335
391
  지침을 세션 시작에 한 번 넣는 것만으로는 부족했습니다. 모델은 지침을 한 번 읽고 그 뒤로 파일 수십 개를 쓰는데, 그동안 결과물을 다시 읽어 보는 단계가 없었습니다. 그래서 지침이 켜진 세션이 규약에 어긋나는 문장을 문서에 그대로 실어 보냈고, 사람이 완성본을 읽을 때에야 드러났습니다. 2026년 8월에 적용 범위 문장을 고쳐서 같은 문제를 잡으려 했지만, 문장을 고쳐도 검사 단계가 없다는 조건은 그대로였기 때문에 재발했습니다.
336
392
 
337
- v3.24.0부터 `korean on`이 PostToolUse 훅을 함께 설치합니다. 모델이 방금 쓴 파일을 열어서 기계로 판정할 수 있는 조항을 검사하고, 위반이 있으면 모델에게 되돌려 보냅니다. 파일은 이미 저장된 뒤이므로 잃는 것은 없고, 모델이 그 자리에서 고칩니다.
393
+ v3.24.0부터 `korean on`이 PostToolUse 훅을 함께 설치합니다. 모델이 방금 쓴 파일을 열어서 기계로 판정할 수 있는 조항을 검사하고, 위반이 있으면 모델에게 되돌려 보냅니다. 파일은 이미 저장된 뒤이므로 잃는 것은 없고, 모델이 즉시 고칩니다.
338
394
 
339
395
  ```bash
340
396
  claude-token-saver korean lint block # 기본값. 위반을 되돌려 보내 고치게 합니다
@@ -366,7 +422,7 @@ claude-token-saver korean lint docs/*.md # 이미 저장된 파일을 직접
366
422
 
367
423
  ### 설치할 때 물어봅니다
368
424
 
369
- 설치 과정에서 **지침의 내용과 세션당 비용, 출처를 먼저 보여 준 다음 켤지 물어봅니다.** 시스템 로캘이 한국어이면(`ko_KR` 등, macOS는 시스템 설정까지 확인) 질문의 기본값이 "켬"이 되고, 한국어 환경이 아니면 기본값이 "끔"입니다. 로캘은 답이 아니라 기본값일 뿐이므로 영어 로캘에서 한국어로 작업하는 경우에도 그 자리에서 켤 수 있습니다.
425
+ 설치 과정에서 **지침의 내용과 세션당 비용, 출처를 먼저 보여 준 다음 켤지 물어봅니다.** 시스템 로캘이 한국어이면(`ko_KR` 등, macOS는 시스템 설정까지 확인) 질문의 기본값이 "켬"이 되고, 한국어 환경이 아니면 기본값이 "끔"입니다. 로캘은 답이 아니라 기본값일 뿐이므로 영어 로캘에서 한국어로 작업하는 경우에도 설치 중에 바로 켤 수 있습니다.
370
426
 
371
427
  npm의 `postinstall`이나 CI처럼 사람이 붙어 있지 않은 설치에서는 질문을 건너뛰고 로캘 기본값을 그대로 적용합니다. 프롬프트가 멈춰 서면 설치 자체가 걸리기 때문입니다. 이때 로캘이 한국어가 아니면 **설정을 저장하지 않고 미결정으로 남겨 두므로**, 나중에 터미널에서 다시 설치하면 그때 물어봅니다. 질문 없이 기본값으로 넘기려면 `--yes`나 `--no-input`을, 기능 자체를 건너뛰려면 `CTS_NO_KOREAN=1`을 쓰십시오. **한 번이라도 직접 켜거나 끈 뒤에는 그 선택을 유지하므로, 업데이트 설치가 사용자의 결정을 되돌리지 않습니다.**
372
428
 
@@ -417,103 +473,13 @@ claude-token-saver doc2md install-converter # 설치를 미리 끝내 두고
417
473
  - **압축 폭탄은 막습니다.** pptx·xlsx·docx 는 zip 컨테이너입니다. 선언된 크기를 먼저 걸러 내고, 선언은 조작될 수 있으므로 실제 해제 바이트도 상한과 대조합니다.
418
474
  - **엑셀은 행 수로 자릅니다.** 변환 시간은 파일 크기가 아니라 행 수를 따릅니다(실측: PDF 6.3MB 0.9초, 엑셀 5.8MB 47.75초). 5만 행을 넘으면 앞부분만 변환하고, **잘랐다는 사실과 전체 행 수를 안내에 함께 적습니다.**
419
475
 
420
- ### 변환이 얼마를 아끼는지
421
-
422
- 변환본은 첫머리에 출처 주석을 답니다. 어떤 원본을 언제 변환했고 몇 토큰인지가 파일을 여는 순간 보입니다. 절감액은 스테이터스라인의 절감 줄 끝에 `📄 Doc2md saved` 로 붙습니다.
423
-
424
- 절감액의 기준은 변환기가 없을 때 실제로 하게 되는 일이고, 그 일이 형식마다 다릅니다. 두 경우 모두 2026-09-06 에 실측했습니다.
425
-
426
- **PDF 는 첨부와 비교합니다.** `claude --print --input-format stream-json` 으로 같은 한 줄 프롬프트를 첨부 있이·없이 보내고 입력 토큰을 비교했습니다. 대조군은 42,204 토큰이었고 두 번 반복해 값이 같았습니다.
427
-
428
- | 첨부 파일 | 분량 | 첨부가 더 든 토큰 | 페이지당 |
429
- |---|---|---|---|
430
- | 이력서 PDF | 7페이지 | +20,537 | 2,934 |
431
- | 이력서 PDF | 5페이지 | +12,709 | 2,542 |
432
-
433
- PDF 는 첨부하면 모델이 내용을 그대로 읽습니다. 대신 페이지마다 2,500~2,900 토큰이 붙어서, 변환본(5,531 토큰)의 서너 배가 듭니다. 계수는 두 실측치보다 낮은 페이지당 2,500 을 씁니다. 넉넉히 잡아 부풀리는 것보다 낮게 잡아 밑도는 편이 낫습니다.
434
-
435
- **pptx·xlsx·docx 는 압축을 푸는 경우와 비교합니다.** 이 형식들은 애초에 첨부로 모델에 닿지 않습니다. 같은 방식으로 docx 를 보냈더니 78 토큰만 늘었고 모델은 파일이 없다고 답했으며, `Read` 도 이진 파일이라며 거부합니다. 그래서 변환기가 없을 때 실제로 하게 되는 일은 압축을 풀고 본문 XML 을 읽는 것입니다. 태그와 스타일 속성이 글자 수의 대부분을 차지하는 그 XML 말입니다.
476
+ ### 더 깊은 내용은 별도 문서에 있습니다
436
477
 
437
- | 원본 | 본문 XML | 변환본 | 차이 |
438
- |---|---|---|---|
439
- | 발표자료 pptx (31.8MB) | 약 540,429 토큰 | 약 22,610 토큰 | 23.8배 |
440
- | 이력서 docx (189KB) | 약 79,621 토큰 | 약 1,684 토큰 | 47.3배 |
478
+ 절감액을 어떻게 실측해 산정하는지(PDF 첨부 대비, 오피스 XML 대비, `.fig` 고정 기준선), 피그마 `.fig` 변환, 문서를 수정할 때의 복사본·스크립트 절차, DRM·암호 문서 판별, Windows 지원 세부는 [docs/DOC2MD.md](./docs/DOC2MD.md)로 옮겼습니다. 요지는 세 가지입니다.
441
479
 
442
- 30MB 짜리 발표자료 하나가 XML 로는 54만 토큰입니다. 200k 컨텍스트에는 들어가지도 않습니다. 이 기준은 형식별 계수가 아니라 파일마다 실제 XML 크기를 재서 씁니다.
443
-
444
- `.xls` 는 zip 컨테이너가 아니라 재어 볼 마크업이 없으므로 절감을 0 으로 둡니다.
445
-
446
- 클라이언트 동작이 바뀌면 `scripts/doc2md-baseline.mjs` 로 첨부 쪽을 다시 재고, `src/doc2md-ledger.cjs` 의 `ATTACHMENT_BASELINE` 표에 값만 갈아 끼우면 됩니다.
447
-
448
- ### 피그마 `.fig` 도 변환합니다
449
-
450
- 기획서가 PPT 에서 피그마로 옮겨 가는 추세를 따라, `.fig` 파일도 같은 훅이 잡습니다. `.fig` 는 zip 컨테이너지만 안에 든 `canvas.fig` 가 피그마의 비공개 바이너리(kiwi 포맷)라 markitdown 이 열지 못하므로, 이 형식만 Node 파서([openfig-core](https://github.com/OpenFig-org/openfig-core), MIT)로 변환합니다. `doc2md install-converter` 가 markitdown 과 함께 도구 상태 디렉터리에 설치하며, 패키지 자체는 여전히 무의존성입니다.
451
-
452
- 변환 결과는 페이지·프레임 계층을 헤딩으로, 텍스트 노드를 본문으로 정리한 아웃라인입니다. 도형·벡터 같은 시각 요소는 나열하지 않고 개수만 남깁니다. 기획서에서 내용은 글이고, `Rectangle 173` 이 이백 줄 나오면 글이 묻히기 때문입니다. 텍스트가 하나도 없는 파일(순수 그래픽)은 빈 문서로 꾸미지 않고 변환 불가로 알립니다.
453
-
454
- 실제 파일로 검증했습니다: 피그마 커뮤니티의 Bootstrap UI kit(8.1MB, 노드 4,155개, 텍스트 1,312개)와 Tailwind kit(52MB)이 각각 0.2초 안에 71.9KB·44KB 아웃라인으로 변환됐고, 한국어 텍스트 왕복도 무손실이었습니다. `.fig` 는 두 세대가 있습니다. 요즘 익스포트는 zip 컨테이너, 옛 익스포트는 fig-kiwi 바이너리 원형인데 둘 다 처리합니다.
455
-
456
- **`.fig` 의 절감이 가장 큽니다.** 오피스 형식과 달리 `Read` 가 `.fig` 를 거부하지 않습니다. 확장자를 모르니 이진 파일을 그대로 텍스트로 읽어들이고, 컨텍스트가 토큰화된 잡음으로 찹니다. 같은 42,760 토큰 대조군으로 측정했습니다.
457
-
458
- | 파일 | 크기 | Read 가 더 쓴 토큰 | 변환본 |
459
- |---|---|---|---|
460
- | plan.fig | 26KB | +44,195 | 100 토큰 |
461
- | bootstrap-kit.fig | 8.1MB | +43,994 | 18,397 토큰 |
462
-
463
- 크기가 300배 차이인데 비용이 같습니다. Read 가 상한에서 자르기 때문인데, 바꿔 말하면 **문서 전체 값을 치르고 일부만 받습니다.** 그래서 기준선은 파일 크기와 무관한 44,000 토큰 고정입니다. 참고로 같은 방법으로 재보니 pptx 는 +317, docx 는 +185 토큰이었습니다. 거부 메시지 한 줄이 전부입니다.
464
-
465
- #### 왜 파일 크기에 비례시키지 않는가
466
-
467
- 기준선은 "변환이 없었으면 실제로 나갔을 비용"이어야 합니다. 직관으로는 파일이 클수록 더 태울 것 같지만, `Read` 도구에는 상한이 있어(기본 2,000줄, 줄당 문자 제한) 이진 파일은 그 지점에서 잘립니다. 26KB 파일조차 이미 상한을 넘기므로, 크기가 300배 차이 나는 두 파일이 201 토큰 차이로 같은 값이 나왔습니다. 8.1MB 가 통째로 들어갔다면 수백만 토큰인데, 그 돈은 200k 컨텍스트에 물리적으로 들어가지 않아 애초에 아무도 지불할 수 없습니다. 지불할 수 없는 돈을 아꼈다고 적으면 부풀리기가 됩니다.
468
-
469
- 이 원칙은 세 곳에 일관되게 적용됩니다.
470
-
471
- - **`.fig` 44,000 고정** — 실측 두 값(44,195·43,994)보다 낮게 잡습니다. 모델이 offset 을 바꿔 가며 반복 Read 하면 크기에 비례해 태울 수는 있지만, 첫 Read 에서 이진 잡음임이 드러나면 정상적인 에이전트는 더 읽지 않으므로 1회 Read 가 현실적인 대안입니다.
472
- - **PDF 페이지당 2,500** — 실측치 2,542·2,934 를 밑도는 값입니다.
473
- - **오피스 형식은 파일별 실제 XML 크기** — 이쪽은 사람이 정말 그 XML 을 읽게 되므로 비례가 맞고, 계수 대신 파일마다 잽니다.
474
-
475
- 공통 규칙: 기준선이 추정과 실측 사이에서 갈리면 항상 낮은 쪽을 택합니다. 도구를 돋보이게 하는 숫자보다 사용자가 신뢰할 수 있는 숫자가 가치 있습니다.
476
-
477
- ### 문서를 수정해야 할 때: 복사본 + 스크립트
478
-
479
- 변환은 단방향이라 변환본 .md 를 고쳐도 원본에는 반영되지 않습니다. 훅이 변환 캐시와 원본 이진 파일에 대한 Edit/Write 를 거부하면서 올바른 경로를 안내합니다. 원본을 복사하고, 복사본을 스크립트로 수정하고, 수정본을 doc2md 로 재변환해 검증하는 순서입니다.
480
-
481
- `install-converter` 가 편집 라이브러리(python-pptx·python-docx·openpyxl)를 변환기 venv 에 함께 설치하므로, "23번 슬라이드 차트를 꺾은선으로 바꿔줘" 같은 구조 편집도 에이전트가 그 자리에서 스크립트로 처리할 수 있습니다. `.fig` 는 openfig-core 가 인코더까지 제공해 텍스트 수정 후 재인코드가 됩니다.
482
-
483
- 네 형식 모두 실제로 몇 바퀴 돌려 검증했습니다(2026-09-06): docx 텍스트 치환 10건과 3회 연속 재저장, pptx 막대→꺾은선 차트 교체와 데이터 행 추가, xlsx 값 정정·행 추가, fig 텍스트 수정·재인코드·재파싱. 전 케이스에서 원본은 바이트 그대로였고, 수정본 재변환에 변경 내용이 반영됐습니다. 한 가지 주의: pptx 에서 차트 도형을 제거하면 옛 차트 XML 파트가 고아로 남습니다. PowerPoint 는 무시하지만, 깔끔히 하려면 파트와 rels 도 지우십시오. 차트·이미지 같은 시각 요소는 변환본에 잡히지 않으므로, 시각 편집의 최종 확인은 해당 프로그램에서 해야 합니다.
484
-
485
- ### DRM 으로 보호된 문서
486
-
487
- 암호와 DRM 은 다른 문제이고 해법도 다릅니다. 사내 DRM(파수·마크애니·소프트캠프 등)은 문서에 암호를 거는 것이 아니라 파일 전체를 감싸며, 벤더 에이전트가 허용한 프로그램만 평문을 봅니다. 파이썬은 거기 없으므로 디스크에 있는 것은 벤더 헤더가 붙은 암호문입니다. **암호를 입력해서 풀 수 있는 문제가 아닙니다.**
488
-
489
- 판별은 첫 바이트가 무엇을 말하는지로 갈립니다. zip 헤더면 내려받다 끊긴 파일, OLE 컨테이너면 암호 걸린 문서, 둘 다 아니면 애초에 그 형식이 아닙니다.
490
-
491
- ```
492
- ✗ bad-archive: File is not a zip file ← 다시 받으십시오
493
- ✗ encrypted: password-protected Office file ← 암호를 푼 사본을 요청하십시오
494
- ✗ drm-protected: DRM-wrapped file (FASOO) ← DRM 해제본이나 반출 승인 사본을 요청하십시오
495
- ```
496
-
497
- 벤더 이름은 어느 클라이언트로 가야 하는지 알려 주려고 맞춰 볼 뿐이고, 판별 자체는 벤더를 몰라도 성립합니다. PDF 는 공개된 DRM 보안 핸들러 이름(FOPN_foweb·EBX_HANDLER·Adobe.APS)으로 같은 판정을 합니다.
498
-
499
- ### 암호가 걸린 문서와 Windows
500
-
501
- **암호 문서는 오류가 아니라 상태로 다룹니다.** 사내에서 받는 문서 중 일부는 암호가 걸려 있습니다. 이전에는 암호 걸린 docx 를 "손상된 zip"이라고 알려서 사용자가 원인을 엉뚱한 곳에서 찾게 만들었습니다. 암호가 걸린 Office 문서는 zip 이 아니라 OLE 복합 문서로 저장되기 때문입니다. 지금은 변환 전에 판별해서 이렇게 알립니다.
502
-
503
- ```
504
- ✗ encrypted: password-protected Office file (OLE-wrapped)
505
- ✗ encrypted: password-protected PDF
506
- ```
507
-
508
- 모델에게는 암호를 푼 사본을 사용자에게 요청하라고 안내합니다. 이 도구는 암호를 묻지도 저장하지도 않습니다. 어느 경우에도 원본 `Read` 를 막지 않으므로 작업이 중단되지 않습니다. 열람은 자유롭고 인쇄만 제한된 PDF 는 암호 문서가 아니므로 그대로 변환합니다(오탐 확인 완료). 구형 `.xls` 도 원래 OLE 형식이라 암호로 오인하지 않습니다.
509
-
510
- **Windows 를 지원하며, 실제 Windows 러너에서 검증합니다.** 사내에 Windows 사용자가 있어 다음을 맞췄습니다.
511
-
512
- - 파이썬 탐색이 `py -3` 런처를 씁니다. Windows 에서는 `python3` 가 PATH 에 없는 경우가 많고, 맨 `python` 은 실행 대신 마이크로소프트 스토어를 여는 별칭 스텁일 수 있습니다. venv 기반 인터프리터도 `Scripts\python.exe` 경로로 찾습니다.
513
- - `.fig` 파서 설치가 `npm.cmd` 를 셸로 호출합니다. 그리고 패키지 지정자에서 캐럿을 뺐습니다(`openfig-core@0.4.x`). cmd.exe 에서 `^` 는 이스케이프 문자라 npm 에 닿기 전에 먹힙니다.
514
- - 백그라운드 자동 설치와 모든 하위 프로세스에 `windowsHide` 를 걸어, 프롬프트 도중에 콘솔 창이 튀어나오지 않게 했습니다.
515
-
516
- `claude-token-saver doc2md --clean` 으로 변환 캐시를 비우고, `doc2md off` 로 훅을 제거합니다. 훅 해제는 자기 항목만 골라 지우므로 `PreToolUse` 에 등록해 둔 다른 훅은 그대로 남습니다.
480
+ - 절감 기준선은 항상 실측치보다 **낮게** 잡습니다. 도구를 돋보이게 하는 숫자보다 신뢰할 수 있는 숫자가 가치 있습니다.
481
+ - `.fig` 절감이 가장 큽니다. `Read` 가 이진 파일을 거부하지 않고 그대로 읽어 회당 약 44,000 토큰을 태우기 때문입니다.
482
+ - 암호 문서와 DRM 문서는 오류가 아니라 상태로 판별해 안내합니다. 원본 `Read` 를 막지 않으므로 작업이 중단되지 않습니다.
517
483
 
518
484
  ## 🌐 Bedrock·Vertex 경유 환경
519
485
 
@@ -530,6 +496,15 @@ v3.26.0부터 트랜스크립트의 모델 ID로 게이트웨이를 감지해
530
496
 
531
497
  감지가 틀리면 `claude-token-saver mode ttl=5m`(또는 `ttl=1h`)로 직접 지정할 수 있습니다. 지정값이 실측값보다 우선합니다.
532
498
 
499
+ ### LiteLLM: 5h/7d cap 대신 키 예산을 보여 줍니다 (v3.35.0)
500
+
501
+ LiteLLM 프록시로 Bedrock 등을 쓰면 Claude Code stdin 에 `rate_limits` 가 오지 않아 `✦ current`·`📅 weekly` 게이지가 아예 없습니다. 대신 LiteLLM 은 키별 `max_budget` 과 `spend` 를 관리하므로, 그 값을 가져와 같은 지점에 예산 게이지를 그립니다.
502
+
503
+ - 감지 조건: `ANTHROPIC_BASE_URL` 이 공식 엔드포인트가 아니고, `ANTHROPIC_AUTH_TOKEN`(또는 `ANTHROPIC_API_KEY`)이 설정된 환경.
504
+ - 조회는 LiteLLM 의 `GET /key/info` 와 `GET /user/info` 로 하고, 호출 키 자신의 정보만 받습니다. 예산 출처는 실무에서 가장 많이 쓰는 **팀 멤버십 예산**(team_memberships 의 spend·max_budget)을 먼저 보고, 없으면 키 자체의 max_budget, 그다음 internal user 예산 순으로 고릅니다. 렌더는 캐시 파일만 읽으며, 갱신은 5분에 한 번 분리된 백그라운드 프로세스가 수행합니다 (update-check 와 같은 구조라 statusline 이 네트워크를 기다리지 않습니다).
505
+ - `max_budget` 이 없는 무제한 키는 게이지를 만들지 않습니다. 이 경우에도 `💵` 월 지출 세그먼트는 세션 로그 기반이라 그대로 표시됩니다.
506
+ - 상태 확인: `claude-token-saver litellm-budget` (캐시 출력) · `litellm-budget --refresh` (즉시 조회).
507
+
533
508
  세션 기본 모델이 sonnet 이면 sonnet 위임 규칙(T1)은 구조적으로 절감이 0입니다. 같은 급으로 내려보내 봐야 차액이 없기 때문이며 이는 정상 동작입니다. 다만 `route-scan rules` 가 이 경우를 "아직 위임 없음"과 같은 문구로 표시해 고장처럼 보였으므로, 이제 현재 기본 모델 기준으로 적용되지 않는다는 사실을 따로 적습니다.
534
509
 
535
510
  ## 토큰 급증 원인 코드
@@ -579,6 +554,8 @@ Node.js ≥ 18 · macOS / Linux / Windows / WSL · **의존성 0**.
579
554
 
580
555
  **IntelliJ Claude Code plugin:** statusline 위젯이 프레임을 잘못 합성해 `59:548` 같은 잔재가 보이는 버그가 있습니다(이모지 출력에서만). v2.8.5+는 `TERMINAL_EMULATOR=JetBrains-JediTerm` 감지 시 자동으로 text 모드 폴백합니다.
581
556
 
557
+ **TTL 카운트다운이 멈춰 보일 때:** 카운트다운이 입력 없이도 초 단위로 줄어들려면 Claude Code 가 statusline 명령을 주기적으로 다시 실행해야 하고, 그 주기는 `~/.claude/settings.json` 의 `statusLine.refreshInterval`(초 단위, v2.1.97 이상)이 정합니다. 이 값이 없으면 대화가 갱신될 때만 다시 그려져서 멈춘 것처럼 보입니다. 터미널마다 동작이 다르면 세 가지를 확인하십시오. ① 그 머신의 Claude Code 버전이 2.1.97 이상인지, ② 프로젝트 `.claude/settings.json` 이나 `settings.local.json` 이 `statusLine` 을 refreshInterval 없이 덮어쓰고 있지 않은지, ③ statusline 래퍼가 PATH 에서 `claude-token-saver` 를 찾지 못해 매 렌더마다 `npx` 폴백으로 수 초씩 걸리고 있지 않은지 (비로그인 셸에서 nvm 이 로드되지 않는 터미널이 여기에 해당합니다). `claude-token-saver install` 을 다시 실행하면 refreshInterval 을 5초로 복구합니다.
558
+
582
559
  **claude-cache-monitor에서 마이그레이션:**
583
560
  ```bash
584
561
  npm uninstall -g claude-cache-monitor && npm i -g claude-token-saver
@@ -588,249 +565,10 @@ npm uninstall -g claude-cache-monitor && npm i -g claude-token-saver
588
565
 
589
566
  ## 릴리스 노트
590
567
 
591
- ### v3.27.0 (2026-09-04)
592
- - **문서 경로를 프롬프트에 적으면 이제 실제로 걸립니다.** 3.26.x 의 `PreToolUse(Read)` 훅은 정작 목표한 형식에 닿지 못했습니다. Claude Code 가 pptx·xlsx·docx 를 이진 파일이라며 훅보다 먼저 거부하기 때문입니다(실측: `.pdf` Read 는 훅이 실행되고 `.pptx` Read 는 훅 기록이 남지 않습니다). 개입 지점을 `UserPromptSubmit` 으로 넓혀, 프롬프트에 적힌 경로를 변환한 뒤 변환본 경로를 컨텍스트로 넣습니다. `@경로`·따옴표·상대 경로를 모두 인식합니다.
593
- - **세션 시작 안내문을 추가했습니다.** 두 가지를 모델에게 알립니다. `Read` 가 이진 파일이라며 거부하면 `doc2md <경로>` 를 실행할 것, 그리고 사용자가 문서를 직접 첨부했으면 다음부터 경로로 달라고 안내할 것입니다. 첨부는 내용 전체가 컨텍스트에 실려 토큰을 크게 쓰는데, 어떤 훅 이벤트도 첨부 내용을 받지 못해 도구가 개입할 방법이 없습니다.
594
- - **`doc2md on` 이 훅 두 개를 함께 등록합니다.** `off` 는 자기 항목만 골라 양쪽에서 지웁니다.
595
-
596
- ### v3.26.2 (2026-09-04)
597
- - **doc2md 변환기를 도구가 직접 설치합니다.** 지금까지의 안내는 `pip install` 이었는데, 시스템 파이썬을 건드리라는 요구인 데다 실행하지 않으면 훅만 등록된 채 아무 일도 일어나지 않았습니다. `doc2md install-converter` 가 전용 venv 를 만들어 markitdown 을 넣습니다.
598
- - **`doc2md` 상태 출력에 훅 등록 여부를 함께 적습니다.** 변환기만 알려 주면 "훅은 있는데 변환기가 없다"와 "변환기는 있는데 훅이 없다"가 똑같이 아무 일도 안 하는 상태로 보여서, 어느 쪽이 빠졌는지 알 수 없었습니다.
599
- - **모르는 서브커맨드를 `--hook` 으로 부르면 아무것도 출력하지 않습니다.** 3.25.0 전역 설치본이 3.26.0 이 쓴 `settings.json` 을 만나면 `doc2md` 를 인식하지 못하고 기본 리포트로 흘러가, `Read` 할 때마다 통계 표 전문을 훅 스트림에 밀어 넣었습니다.
600
-
601
- ### v3.26.0 (2026-09-04)
602
- - **문서를 읽기 전에 Markdown 으로 변환합니다.** pptx·xlsx·pdf·docx·fig 를 그대로 `Read` 하면 모델이 읽지 못하는 바이트가 컨텍스트에 올라갑니다. `doc2md on` 으로 `Read` 훅을 등록하면 파일을 한 번 변환해 캐시에 두고 변환본을 읽게 합니다. 변환기가 없으면 안내를 한 번만 하고 원본 `Read` 를 통과시키며, 압축 폭탄은 막고, 5만 행이 넘는 엑셀은 앞부분만 변환한 뒤 잘랐다는 사실을 함께 알립니다. 자세한 내용은 [doc2md](#-doc2md-문서를-읽기-전에-markdown-으로-바꿉니다) 절을 참고하십시오.
603
- - **Bedrock·Vertex 경유 환경의 TTL 표시를 바로잡았습니다.** 게이트웨이는 버킷별 분해 값을 내려보내지 않는데, 판정 불가일 때 1시간을 기본값으로 잡고 있었습니다. 5분 버킷만 제공하는 환경에서 남은 시간이 최대 12배로 부풀어 보였습니다. 이제 모델 ID로 게이트웨이를 감지해 5분을 기본값으로 쓰고, 라벨을 `5m?` 로 적어 추정임을 밝힙니다. `mode ttl=5m` 으로 직접 지정할 수도 있습니다.
604
- - **위임 집계가 조용히 버려지지 않습니다.** 모델 ID를 해석하지 못해 제외된 위임이 있으면 statusline 에 `🔀 N unresolved` 로 알립니다. 이전에는 "위임한 적 없음"과 화면상 구별되지 않아, 집계가 통째로 사라져도 알 방법이 없었습니다. `foundation-model` ARN 으로 지정된 환경변수도 이제 해석합니다.
605
- - **한국어 지침의 적용 범위 충돌을 해소했습니다.** 주입문은 코드 주석을 검사 대상에 넣는데 벤더링한 원문은 두 번에 걸쳐 제외한다고 적고 있어서, 모델이 어느 쪽을 따를지 판단할 근거가 없었습니다. 원문은 그대로 두고 어느 쪽이 우선인지 명시하는 한 줄을 추가했습니다. 출처 표기에 들어 있던 엠대시도 지침 스스로 금지하는 표기였으므로 콜론으로 바꿨습니다.
606
-
607
- ### v3.25.0 (2026-09-04)
608
- - **statusline에 실행 중인 버전을 표시합니다.** 지금까지는 표 형식 리포트의 각주에만 버전이 있었기 때문에, 어떤 버전이 도는지 확인하려면 전체 리포트를 실행해야 했습니다. `--version` 플래그도 함께 추가했습니다.
609
- - **새 버전이 나오면 세션 시작에 물어봅니다.** statusline은 대화 상자를 띄울 수 없으므로, 알림과 질문을 나누었습니다. statusline은 `⬆ v3.24.0 → 3.25.0`으로 알리기만 하고, 실제 질문은 SessionStart 훅이 모델에게 "사용자에게 업그레이드 여부를 확인하라"고 주입해서 이루어집니다. 승낙하면 `claude-token-saver upgrade`가 설치 경로에 맞는 명령을 실행하고, 거절하면 `update-check --dismiss`가 그 버전을 더 묻지 않도록 기록합니다.
610
- - **버전 확인이 렌더를 붙잡지 않습니다.** 조회는 24시간에 한 번 분리된 백그라운드 프로세스가 수행하고, 렌더 경로는 캐시 파일만 읽습니다. 확인에 실패해도 시각을 기록하므로 오프라인에서 매 렌더마다 재시도하지 않습니다. `CTS_NO_UPDATE_CHECK=1` 또는 `NO_UPDATE_NOTIFIER`로 끌 수 있습니다.
611
-
612
- ### v3.21.0 (2026-08-22)
613
- - **설치가 무엇을 켜는지 보여 준 뒤 물어봅니다** — 지금까지는 🅷 Harness 5원칙과 한국어 문체 지침을 설치가 스스로 켰고, 사용자는 결과만 볼 수 있었습니다. 이제 harness는 다섯 원칙의 제목을, 한국어 지침은 바꾸는 내용과 세션당 비용과 출처를 먼저 출력한 다음 켤지 묻습니다. 로캘 감지는 답이 아니라 질문의 기본값으로 내려왔으므로, 영어 로캘에서 한국어로 작업하는 경우에도 그 자리에서 켤 수 있습니다.
614
- - **사람이 붙어 있지 않은 설치는 예전대로 동작합니다** — npm의 `postinstall`, CI, 파이프 입력, `CTS_NO_INPUT=1`에서는 질문을 건너뛰고 기존 기본값을 그대로 적용합니다. 프롬프트가 멈춰 서면 설치가 걸리기 때문입니다. `--yes`와 `--no-input`으로 직접 강제할 수도 있습니다. 비대화형이면서 로캘이 한국어가 아닌 경우에는 설정을 저장하지 않고 미결정으로 남겨 두므로, 나중에 터미널에서 설치하면 그때 물어봅니다.
615
- - **statusline의 한국어 지침 칩을 `가`에서 `✍️`로 바꿨습니다** — 다른 칩이 모두 이모지라서 음절 하나가 상태 표시가 아니라 잘못 섞여 들어간 글자로 보였습니다.
616
-
617
- ### v3.20.0 (2026-08-22)
618
- - **README 첫 화면을 훑어 읽을 수 있게 다시 짰습니다** — 설명 문단을 걷어내고 한 줄 요약, 스크린샷, 설치 명령을 앞에 두었습니다. 라우팅·Harness·ratchet 세 기능은 표로, 절감액 계산 방식(기준 모델 → 실행 모델 → 차액)은 도식으로 바꿨습니다. 뒤에서 같은 내용을 반복하던 "30초 요약" 표는 statusline이 추가로 잡아 주는 항목만 남겨 정리했습니다.
619
-
620
- ### v3.19.0 (2026-08-22)
621
- - **한국어 문체 지침 기능을 추가했습니다** — Claude가 한국어를 쓸 때 나타나는 문체 결함(문장 성분 생략, 명사형 종결, 번역체, 엠대시 남용)을 교정하는 지침을 세션 시작 시 한 번 주입합니다. Claude Code의 output style은 전역 슬롯 하나를 차지하고 머신마다 설정해야 하지만, 이 기능은 지침을 패키지에 담고 이미 설치된 SessionStart 훅으로 전달하므로 **CLI가 설치된 모든 프로젝트에 적용되며 output style 슬롯은 비워 둡니다.** 지침 원문은 [fluent-korean](https://github.com/snflkd/fluent-korean)(Copyright (c) 2026 snflkd, MIT)에서 가져왔고 라이선스 전문을 함께 배포합니다.
622
- - **설치와 동시에 결정됩니다** — 시스템 로캘이 한국어이면 설치 시 자동으로 켜지고, 아니면 꺼 둡니다. 직접 켜거나 끈 뒤에는 그 선택을 유지하므로 업데이트가 사용자의 결정을 되돌리지 않습니다. `CTS_NO_KOREAN=1`로 건너뛸 수 있습니다(v3.21.0부터는 설치가 묻습니다).
623
- - **README의 과장된 설명을 바로잡았습니다** — 라우팅 절감액을 "이 도구의 전부"라고 적었으나, 실측 −18.6%는 Harness와 ratchet을 도입한 효과입니다. 세 기능의 관계를 정확히 다시 썼습니다.
624
-
625
- ### v3.18.0 (2026-08-22)
626
- - **한국어 문서를 다시 다듬었습니다** — 문장 성분을 생략하지 않고 서술어로 끝맺는 형태로 본문을 고쳐 썼습니다. 의미를 지나치게 함축하던 엠대시는 콜론과 접속사로 바꾸었습니다.
627
- - **실시간 모델 라우팅이 비용을 키우는 이유를 설명에 추가했습니다** — 프롬프트 캐시가 모델별로 유지되기 때문에 세션 중간에 모델을 바꾸면 절감액이 캐시 손실로 상쇄된다는 점, 그래서 이 도구가 서브에이전트 위임만 사용한다는 점을 명시했습니다.
628
-
629
- ### v3.17.0 (2026-08-22)
630
- - **설치 한 번으로 🅷 Harness까지 적용됩니다** — 지금까지는 설치 후 `harness init`을 따로 실행해야 statusline의 🅷 점수와 ratchet 룰 전달이 동작했습니다. 이제 설치가 `~/.claude/CLAUDE.md`에 5원칙 블록을 **추가**합니다(기존 내용은 백업 후 보존, 이미 있으면 건드리지 않음). 건너뛰려면 `CTS_NO_HARNESS=1`, 되돌리려면 `harness uninit --global`.
631
- - **README 상단을 statusline 실제 스크린샷으로 교체** — 코드 블록 대신 실제 캡처를 최상단에 두고, 아래쪽에 중복으로 있던 이미지는 뺐습니다.
632
-
633
- ### v3.16.0 (2026-08-22)
634
- - **README를 라우팅 절감 중심으로 재구성** — 이 도구의 핵심이 무엇인지 첫 화면에서 바로 보이도록 `🔀 Routing saved`를 최상단에 올리고, 금액이 원장에서 어떻게 나오는지(before/after/차액)와 `route-scan savings` 실제 출력을 함께 실었습니다. 채널·홈페이지 배지는 최하단 "만든 곳"으로 내렸습니다.
635
- - **statusline 스크린샷을 현재 2줄 레이아웃으로 갱신** — 목업이 아니라 실제 출력을 캡처합니다. `npm run docs:statusline`으로 재생성할 수 있습니다(headless Chrome 사용, 의존성 추가 없음).
636
-
637
- ### v3.15.0 (2026-08-22)
638
- - **statusline 헤드라인을 누적 한 줄로 줄였습니다** — `🔀 Routing saved $2.09 | fable→sonnet 1× $0.72 · opus→haiku 1× $0.57 …`. 주간·월간 합계는 뺐습니다. 뒤에 붙는 모델 이동 내역이 누적 기준 분해인데 롤링 창 세 개와 나란히 있으면 어느 것의 내역인지 읽히지 않았습니다. 한 줄 전체가 한 시점 기준이 되면 어긋날 여지가 없습니다. 주간·월간은 `route-scan savings`에서 계속 확인할 수 있습니다.
639
- - **모델별 절감 내역은 회색으로** — 녹색은 누적 금액 하나에만 남깁니다. 구성 요소마다 같은 녹색을 반복하면 줄 전체가 한 덩어리로 시끄러워져 먼저 눈이 닿을 곳이 사라집니다.
640
-
641
- ### v3.14.0 (2026-08-22)
642
- - **statusline 헤드라인이 모델 이동을 함께 보여줍니다** — `🔀 Routing saved weekly $1.4 · monthly $2.1 · total $2.1 | fable→sonnet 1× $0.72 · opus→haiku 1× $0.57 …`. 버전 숫자는 계속 올라가고 statusline에서는 잡음이라 계열명만 남깁니다(`claude-opus-4-5-20251101-v1:0` → `opus`). 이동 목록은 **자르지 않고 전부** 표시합니다 — 금액이 `total` 옆에 붙어 있어서 일부만 보이면 합계를 잘못 말하게 됩니다. 계열 단위로 접히면 조합 수가 원래 많지 않아 줄은 짧게 유지됩니다.
643
- - **`route-scan savings` 추가** — 헤드라인 뒤에 있는 근거를 그대로 조회합니다. 모델 이동별 합계(어느 모델에서 어느 모델로 몇 회, 얼마)와 실행별 내역(날짜·금액·모델 이동·해당 룰)이 함께 나옵니다.
644
- - **기준 모델을 최고가가 아니라 '가장 많이 처리한 모델'로 정합니다** — 한 트랜스크립트에 모델이 섞이는 일이 흔한데(세션 중 모델 전환 등) 최고가를 고르면 Fable 기록 한 건이 Opus가 서른 번 처리한 카테고리의 기준을 차지해 이후 절감액을 전부 부풀렸습니다. 동수일 때만 비싼 쪽으로 기웁니다. 옛 정의로 굳은 기준은 1회 재계산됩니다.
645
- - **원장 기록을 룰 갱신 뒤로 옮겼습니다** — 앞서 기록하면 기준이 바뀐 스캔이 새 기준을 저장하면서 청구는 옛 기준으로 해, 합계가 두 번째 스캔에야 맞았습니다.
646
-
647
- ### v3.13.0 (2026-08-22)
648
- - **라우팅 절감액의 기준을 '승격 전 모델 → 위임 모델' 차액으로 바꿨습니다** — 이전에는 세션의 최상위 모델을 반사실로 잡아, 그 모델이 해당 유형을 실제로 처리한 적이 없어도 차액을 절감으로 기록했습니다. 이제 각 룰이 **승격 전 그 유형을 직접 처리하던 모델**(baseline)을 기억하고, 그 기준 대비로만 계산합니다. baseline은 한 번 정해지면 고정됩니다 — 룰이 효력을 낼수록 직접 처리 사례가 줄어 기준이 흘러내리고, 그러면 룰이 만든 절감이 스스로 작아지기 때문입니다.
649
- - **룰이 커버하지 않는 위임은 집계에서 뺐습니다** — `Explore`, 직접 만든 에이전트, 플러그인 에이전트처럼 이 도구와 무관하게 돌던 서브에이전트 실행까지 절감으로 잡히고 있었습니다. 도구가 라우팅하지 않은 작업의 절감을 도구 성과로 표시하면 안 됩니다. 원장 이벤트에 `rule`/`from`/`to`를 남겨 어느 룰이 어떤 모델 차이를 만들었는지 추적할 수 있습니다.
650
- - **원장 스키마 version 2** — 반사실 기준이 달라진 만큼 v1 항목은 마이그레이션 없이 폐기합니다(두 의미를 한 합계에 섞을 수 없습니다). 다음 `route-scan`이 귀속 가능한 절감만 다시 채웁니다.
651
- - **사내 별칭 모델명이 조용히 Sonnet으로 계산되지 않습니다** — 게이트웨이가 계열명 없는 별칭(`prod-large` 등)을 모델명으로 기록하면 가격표 기본값이 걸려 Sonnet으로 계산됐고, 그 결과 없는 절감이 생기거나 있는 절감이 지워졌습니다. 이제 비교 양쪽 모두 계열명이 남아 있는 id일 때만 집계합니다. Bedrock(`anthropic.claude-opus-4-5-v1:0`)·Vertex(`claude-opus-4-5@20251101`)·1M 접미사(`claude-sonnet-4-5[1m]`)는 그대로 인식되고, 사내 별칭은 `profile-map.json`의 `modelAliases`에 한 줄 추가하면 집계에 복귀합니다(와일드카드 가능).
652
- - `harness check`가 CLAUDE.md 크기와 `.claudeignore` 유무를 함께 보고합니다(자문 정보, 🅷 점수에는 미반영).
653
-
654
- ### v3.12.1 (2026-08-22)
655
- - **라우팅 절감 헤드라인의 가독성 정리** — 금액을 절감 녹색으로 칠하고(그 줄에서 유일하게 명확한 호재입니다), `wk`·`mo`·`all` 축약을 `weekly`·`monthly`·`total`로 풀었으며, 금액이 앞서던 순서를 뒤집어 기간이 먼저 오게 했습니다. 금액 셋이 연달아 나오면 뒤따르는 기간 표시를 찾기 전까지 한 덩어리로 읽혔습니다.
656
-
657
- ### v3.12.0 (2026-08-22)
658
- - **Routing saved가 주간·월간·누적으로 statusline 1줄째에 올라옵니다** — `🔀 Routing saved weekly $1.3 · monthly $2.0 · total $9.8`. 위임 절감 이벤트를 서브에이전트 run 단위로 원장(`delegation-ledger.json`)에 기록하고(트랜스크립트 경로 키라 재스캔이 겹쳐도 중복 집계 없음), 7일·30일·전체 합산을 표시합니다. 나머지 칩은 2줄째로 내려갑니다. 원장이 비어 있으면 기존 1줄 그대로이고, 일부 환경(macOS 구버전 Claude Code)에서 첫 줄만 보이면 `--single-line`으로 기존 레이아웃을 유지할 수 있습니다. 집계는 원장 도입 시점부터 시작합니다(소급 없음).
659
- - **`harness check`가 컨텍스트 무게도 알려줍니다** — CLAUDE.md의 요청당 대략 토큰(~4k 가이드라인 초과 시 경고)과 `.claudeignore` 유무를 표시합니다. 자문 정보일 뿐 🅷 N/5 점수에는 반영하지 않습니다.
660
- - **모델명이 내장된 ARN은 학습 없이 즉시 해석** — `foundation-model/anthropic.claude-…`와 시스템 교차 리전 프로파일(`inference-profile/us.anthropic.claude-…`)은 자원 ID가 곧 모델명인데도 `unknown`으로 떨어져, 학습 표본이 쌓이기 전의 게이트웨이 환경에서 위임·비용 집계가 통째로 빠졌습니다. 이제 즉시 기존 티어 분류로 넘깁니다. 불투명한 application-profile ID는 종전대로 오버라이드/학습 경로입니다.
661
-
662
- ### v3.11.0 (2026-08-21)
663
- - **statusline에 위임 절감 칩 추가** — `🔀 Routing saved $3.2`. 모델 위임으로 아낀 누적 비용이며, 모델 이름 바로 뒤에 놓여 줄 앞쪽에서 읽힙니다. 기존 `💰 Cache saved`(프롬프트 캐시 절감)와는 다른 수치입니다. 값이 0이거나 데이터가 없으면 칩을 아예 그리지 않아 직접 API 사용자에게는 아무것도 늘지 않습니다. statusline은 `model-rules.json`을 읽기만 하며 스캔을 돌리지 않습니다(5초마다 호출되는 자리입니다). 세그먼트 이름은 `delegated`입니다.
664
- - **역할 학습의 오분류 수정** — 서브에이전트 레코드가 부모 트랜스크립트에 `isSidechain` 없이 섞여 들어오는 경우가 있어, 그 정황 증거가 명시 증거를 이겨 haiku 프로파일이 세션 모델로 확정되곤 했습니다(실측 16건 대 1건, 합의율 정확히 80%). 이제 **명시 증거(`Task(model:)` 파라미터·에이전트 정의 frontmatter)와 정황 증거(sidechain 플래그 부재)를 분리해 집계**하고, 명시 증거가 이를 반박하면 정황 추론을 채택하지 않습니다. 확정이 안 되면 `unknown`으로 남아 집계에서 빠집니다.
665
-
666
- ### v3.10.0 (2026-08-20)
667
- - **게이트웨이(Bedrock·LiteLLM) 환경에서 모델 티어를 다시 인식합니다** — 로그의 모델명이 추론 프로파일 ARN이면 `opus`·`haiku` 단서가 없어 Sonnet으로 폴백했고, `worthDelegating()`이 `rank > target`을 요구하므로 **T1 위임이 전부 기각**됐습니다. 절감 집계는 0, 비용은 약 1.67배 과소 계상이었습니다. 이제 프로파일 ID를 역할로 학습해(부모 `Task` 호출 ↔ 서브에이전트 `toolUseId` 정확 조인) 환경변수가 선언한 별칭으로 되돌립니다. 가격표·랭크·판정 로직은 그대로입니다.
668
- - **확신이 없으면 숨기지 않고 드러냅니다** — 관측 3건 미만이거나 역할 동의율 80% 미만이면 `unknown`으로 두고 위임 집계에서 제외합니다. Sonnet으로 조용히 틀리던 기존 동작이 더 나빴습니다.
669
- - **수동 오버라이드** — `<userDataDir>/profile-map.json`의 `modelAliases`에 와일드카드 패턴으로 직접 지정할 수 있습니다. 프로파일 ID·AWS 계정 ID는 소스에 전혀 넣지 않습니다.
670
- - 게이트웨이를 쓰지 않는 환경은 **동작이 완전히 동일**합니다(파일도 만들지 않습니다).
671
-
672
- ### v3.9.2 (2026-08-01)
673
- - **LICENSE 파일 추가 (MIT)** — `package.json`에만 있고 파일이 없어서, 사내 도입 검토 시 라이선스 확인이 막히던 문제. npm 패키지에도 포함되도록 `files`에 넣었습니다.
674
- - **패키지 설명·키워드를 현재 기능에 맞게 교체** — 캐시 모니터링 시절 문구가 남아 있어 모델 위임(`model-routing`·`delegation`·`subagent`)으로 검색되지 않았습니다.
675
- - **README 상단에 60초 진입로** — 라우터가 아니라 사후 분석이라는 점과, 설치부터 내 숫자 확인까지의 명령 3줄.
676
- - **`route-scan` 최초 1회 안내** — 기능 설명 영상 링크를 딱 한 번만 출력합니다. `CTS_NO_NOTE=1`로 끕니다.
677
-
678
- ### v3.9.1 (2026-08-01)
679
- - **compact-window 권장값이 단일 40만에서 40만~70만 범위로** — 40만은 실사용에서 너무 빡빡해 압축이 잦았습니다. 이제 범위를 제안하고, **그 안(또는 그보다 낮게) 잡아둔 세션은 경고하지 않습니다.** 미설정이거나 70만 초과일 때만 `🅷⚠ compact-window?`와 브리핑이 뜹니다. `set`의 기본값도 범위 중간인 50만으로 올렸고, 원하는 값은 `--value 600k`로 지정합니다.
680
-
681
- ### v3.9.0 (2026-08-01)
682
-
683
- manifest.build의 "다들 LLM 라우터 만드는데 우리는 폐기했다"(7천 사용자·4개월 실사용 회고)와 이 도구의 설계를 대조해, 그쪽 실패 요인 중 아직 안 막혀 있던 것 4개를 메웠습니다. 자세한 대조는 [TIER_CRITERIA.md §3.9](./docs/TIER_CRITERIA.md).
684
-
685
- - **rule-health가 이제 실제 위임 결과를 봅니다** — 기존 에러율의 분모는 "비싼 모델이 직접 처리했는데 형태상 위임 가능해 보이던 에피소드"였습니다. 즉 룰이 **실제로 발동했을 때 잘 됐는지는 한 번도 재지 않았고**, 매번 실패하는 룰이 있어도 신호가 안 움직였습니다. Claude Code가 서브에이전트 실행을 `<세션>/subagents/`에 따로 남기고 그 메타의 `toolUseId`가 부모의 Task 호출과 정확히 맞물리므로, 이제 실제 위임의 성패를 직접 셉니다. 실측 5건 이상 쌓인 룰은 추정 대신 실측으로 판정하고, 경고에도 어느 쪽 근거인지 표시합니다. (저자 로그 14일: 106세션 중 4세션·18런, 조인 성공률 100%)
686
- - **룰별 절감액 표시** — 위임 실행의 토큰을 세션 모델 단가로 되돌린 차액을 14일 창으로 계산해 `route-scan rules`와 `ratchet-model.md`에 `~$` 표기로 붙입니다. 값어치 없는 룰이 눈에 보여야 정리할 수 있습니다. 위임 기록이 없는 룰은 `$0`이 아니라 `—` — 둘은 정반대를 뜻합니다.
687
- - **세션 모델 기준 상대 티어** — 기존 게이트가 "haiku인가?" 하나뿐이라, Sonnet 세션에서도 "sonnet한테 위임하라"는 T1 룰이 만들어졌습니다. 컨텍스트만 새로 쌓고 단가 차이는 0인 순손해입니다. 이제 목표 티어가 실제로 더 싼 경우에만 후보를 만듭니다 (haiku 0 · sonnet 1 · opus 2 · fable 3).
688
- - **위임 예산 문구(probe-then-commit)** — 룰은 통계로 만들어지지만 **발동은 요청 텍스트만 보고** 일어나고, 난이도는 대개 첫 도구 호출 뒤에야 드러납니다. 이 불일치는 못 없애니 오판 비용에 상한을 겁니다: 각 룰에 캘리브레이션된 상한(T2는 호출 8회·출력 p25, T1은 출력 p75)이 붙고, 넘길 것 같거나 에러가 나면 서브에이전트가 멈춰 진행분만 보고하고 메인 모델이 이어받습니다. 문구는 저장된 룰에 굽지 않고 렌더 시점에 조립하므로 **예전에 등록한 룰도 자동으로 적용**받고, promote 프리뷰와 실제 파일이 어긋날 수 없습니다.
689
-
690
- ### v3.8.2 (2026-08-01)
691
- - **압축 뒤에도 경고 티어가 안 내려가던 문제 수정** — 컨텍스트 티어를 최고치로만 기억해서, 80%에서 자동 압축이 돌아 컨텍스트가 다시 비어도 티어가 1로 남았습니다. 그 세션은 창을 다시 꽉 채워도 아무 신호를 못 받았습니다. 이제 측정치가 내려가면 티어도 같이 내려가고, 다시 차오르면 정상적으로 경고합니다.
692
- - **두 가지 창 표기 혼선 정리** — `autoCompactWindow`를 40만으로 잡으면 브리핑은 40만 기준(80%)인데 Claude Code 화면은 1M 기준(33%)이라, 같은 세션의 두 숫자가 서로 안 맞아 보였습니다. 이제 `자동 압축 창(400k)의 80%(… 화면의 1M 창 기준으로는 33%)`처럼 둘 다 적습니다.
693
- - **압축 창이 설정돼 있으면 "새 세션 시작" 권고를 하지 않습니다** — 그 지점은 압축이 자동으로 처리하는 지점이라, 대신 결정·다음 할 일을 파일에 남기라고 안내합니다.
694
-
695
- ### v3.8.1 (2026-07-31)
696
- - **1M 세션을 200k 창으로 오판하던 브리핑 버그 수정** — 세션 창을 "지금까지 본 가장 큰 요청"으로 추정해서, 1M 세션이라도 25만 토큰을 넘기 전까지는 200k로 취급했습니다. 그래서 입력 160k에서 "200k 창의 80%를 넘었습니다" 경고가 떴습니다(실제로는 16%). 이제 설정된 모델 ID로 창을 판정하고, `autoCompactWindow`가 잡혀 있으면 그 값이 실제로 세션이 넘어가는 지점이므로 그쪽을 기준으로 %를 계산합니다(문구에도 `(autoCompactWindow 기준)` 표기). 모델 ID를 못 읽는 경우에만 기존 관측치 추정으로 되돌아갑니다.
697
-
698
- ### v3.8.0 (2026-07-31)
699
- - **`compact-window` 추가 — 1M 컨텍스트에서 자동 압축 지점이 방치되던 문제** — Claude Code는 `min(autoCompactWindow, 모델 최대 창)` 근처에서 압축합니다. 1M 창을 쓰면 이 값을 안 잡는 한 80만 토큰까지 커진 뒤에야 압축이 걸리고, 그전까지 모든 요청이 전체 컨텍스트를 재과금합니다. 이제 1M 모델인데 미설정이거나 40만 초과면 statusline `🅷⚠ compact-window?` + 세션 브리핑으로 알리고, `compact-window set --global|--project`로 40만을 고정합니다. 200k 컨텍스트는 설정이 영향을 주지 않으므로 경고 대상에서 제외합니다.
700
-
701
- ### v3.7.0 (2026-07-29)
702
- - **위임 룰이 없는 서브에이전트를 가리키던 문제 수정** — 생성되는 T2 룰이 `haiku-explore`·`haiku-runner` 같은 이름을 직접 적었는데, 이 preset 에이전트들은 각자의 `~/.claude/agents/`에 있는 것이라 패키지가 배포하지 않습니다. 그래서 해당 파일이 없는 환경에서는 "존재하지 않는 에이전트로 위임하라"는 룰이 자동 생성됐습니다. 이제 기본 표현은 `model: haiku`(T1의 `model: sonnet`과 통일)이고, 에이전트 파일이 실제로 있을 때만 `haiku-explore(model: haiku)`처럼 이름을 병기합니다. 프로젝트 `.claude/agents/`도 인식합니다. 다음 `route-scan` 때 `ratchet-model.md`가 새 표현으로 다시 렌더됩니다.
703
-
704
- ### v3.6.4 (2026-07-29)
705
- - **`🅷⚠ ratchet-unloaded`가 잘못 뜨던 버그 수정** — import 여부를 CLAUDE.md 한 파일에서만 확인했습니다. 프로젝트 `CLAUDE.md`에 harness 블록이 있으면 그 파일만 보고 판정했기 때문에, `@` import가 글로벌 `~/.claude/CLAUDE.md`에 있는 흔한 조합에서는 룰이 정상 로드되는데도 경고가 떴습니다. Claude Code는 두 파일을 모두 로드하므로 이제 양쪽의 import를 합쳐서 판정하고, 어느 쪽이 들고 있는지는 `importSource`(`project`/`global`/`both`)로 알려줍니다. 두 파일 다 import가 없을 때만 경고합니다.
706
-
707
- ### v3.6.3 (2026-07-27)
708
- - **승인한 ratchet 룰이 세션에 전달되지 않던 버그 수정** — `harness promote`는 룰을 `ratchet.md`에 append했지만, 그 파일을 읽는 소비자가 어디에도 없었습니다. Claude Code는 `CLAUDE.md`(와 그것이 import하는 파일)만 로드하는데 harness 블록에 import 라인이 없었기 때문에, "승인된 룰은 다음 세션부터 자동 적용"은 사실상 미구현 상태였습니다. 이제 harness 블록이 `@.claude/ratchet.md`(project) / `@~/.claude/ratchet.md`(global)를 import합니다. `harness init`을 다시 돌리면 기존 블록도 제자리에서 갱신됩니다.
709
- - **`ratchet-model.md`도 명시적으로 import** — 모델 피팅 룰도 호스트가 알아서 읽어주길 기대하지 않고 같은 경로로 전달합니다. import가 끊기지 않도록 `harness init`이 빈 파일을 미리 만들고, 마지막 룰이 사라져도 `syncAllFiles`가 파일을 지우는 대신 비웁니다.
710
- - **`🅷⚠ ratchet-unloaded` 경고 추가** — 5개 섹션이 다 있어도 import 라인이 없으면 룰이 죽어 있는 상태라, `N/5`와 별개로 표시합니다. `harness check`도 같은 내용을 수정 명령과 함께 안내합니다.
711
- - **`harness prune` 추가 + ratchet 크기 표시** — import된 ratchet은 매 요청마다 토큰을 씁니다. `harness check`가 룰 수와 요청당 토큰을 보여주고 ~2,000 토큰을 넘으면 경고합니다. 정리는 `harness prune [--tag <t>] [--older-than <months>] [--dry-run]` — 삭제가 아니라 `ratchet-archive.md`로 이동합니다. 룰 앞에 `[태그]`를 붙여두면(`- 2026-05-08: [video] ...`) 묶어서 정리할 수 있습니다. (`@` import는 정적이라 로드 시점 필터링은 불가능합니다 — 줄일 방법은 룰 자체를 줄이는 것뿐)
712
-
713
- ### v3.6.2 (2026-07-26)
714
- - 문서 전용 릴리스 — 아래 v3.4.0~v3.5.3 릴리스 노트가 누락돼 있던 것을 복원했고, npm 패키지 페이지는 발행된 버전의 README를 보여주므로 이를 반영하기 위해 올립니다. 코드 변경 없음.
715
-
716
- ### v3.6.1 (2026-07-26)
717
- - **macOS·Windows에서 상태 파일이 갈라지던 버그 수정** — `route-scan.json` / `model-rules.json` / `brief-state.json`이 각자 복제된 경로 해석 함수를 갖고 있었고, 그 복사본들은 `XDG_CONFIG_HOME`을 리눅스에서만 인정했습니다. 그래서 macOS·Windows에서 XDG를 설정하면 `config.json`·세션 캐시만 옮겨가고 위 세 파일은 플랫폼 기본 경로에 남아, 위임 후보 브리핑과 룰이 조용히 사라졌습니다. 이제 전부 `paths.js` 한 곳에서 해석합니다. (v3.6.0에서 도입한 3-OS CI가 잡아낸 버그 — 복제본이 다시 생기지 않도록 회귀 테스트 추가)
718
- - `npm test` 스크립트가 Node 22에서 실패하던 문제 수정 (`node --test test/`의 디렉터리 인자를 Node 22가 모듈 경로로 해석).
719
-
720
- ### v3.6.0 (2026-07-26)
721
- - **statusline 재실행 비용 제거** — 세션 파싱 결과를 `(경로, mtime, size)` 키로 캐싱. 트랜스크립트는 append-only라 이 조합이 파싱 결과의 정확한 신원이 됨. 217MB/226파일 30일 창 기준 매 갱신마다 3초씩 재파싱하던 것이 변경된 파일(사실상 현재 세션 1개)만 읽는 것으로 축소. 캐시가 깨져도 항상 전체 파싱으로 폴백하므로 실패 경로 없음.
722
- - **ratchet-model.md 영문 렌더링** — 이 파일은 LLM이 지시문으로 읽기 때문에, 한글 전용 파일은 영어 세션의 응답까지 한글로 끌어당김. `language` 설정에 따라 헤더·룰 원문·rule-health 경고를 영문으로 렌더. 카테고리 라벨과 룰 원문은 스캔 시점에 양쪽 언어로 저장돼, 언어를 바꿔도 재스캔 없이 즉시 반영.
723
- - **테스트·CI 도입** — `npm test`(node:test) 22개 + GitHub Actions에서 ubuntu/macOS/Windows × Node 18/22 매트릭스. 사용자 레벨 경로 처리(XDG/APPDATA/Application Support)가 단일 OS 실행으로는 잡히지 않는 부분이라 3-OS로 돌림.
724
- - **bin/cli.js 분할** — 1,000줄 단일 파일이던 CLI를 `src/commands/*`(install, harness, route-scan, brief, handoff, history, last, mode)와 인자 파싱·stdin 페이로드 헬퍼로 분리. 동작 변경 없음.
725
-
726
- ### v3.5.3 (2026-07-22)
727
- - **rule-health: 자가수정·하네스 가드 에러 제외** — 편집 순서 가드나 자가수정 계열(`File not read yet`, `String to replace not found`, `modified since read`, `Blocked:`, Task 라이프사이클)은 모델이 스스로 회복하는 흐름의 일부지 작업 난이도 신호가 아님. v3.4.2의 권한 노이즈 정화 연장선. 모호한 `Exit code N`·`File does not exist`는 난이도 신호로 유지.
728
-
729
- ### v3.5.2 (2026-07-21)
730
- - **세션 시작 브리핑을 능동 전달** — SessionStart 훅 지시문이 조건부("전달할 때는")라 모델이 배경 정보로 흘려보낼 수 있었음. 사용자의 첫 메시지가 단순 인사여도 첫 응답 말미에 `※ [claude-token-saver]` 라벨로 요약 브리핑하도록 명시.
731
- - **brief 시딩 레이스 수정** — brief 훅이 첫 실행에서 route/rule-health 이벤트를 무조건 삼키던 것을, SessionStart가 **실제로 브리핑한 시그니처만** 삼키도록 변경(`seedSessionBriefed()`). 백그라운드 재스캔이 세션 시작 직후 끝나 새 후보가 생긴 경우, 이전에는 세션 내내 전달되지 않았지만 이제 다음 프롬프트에 브리핑됨.
732
-
733
- ### v3.5.1 (2026-07-14)
734
- - **훅 설치 시 스키마 위반 값은 덮어쓰지 않음** — `hooks.SessionStart` / `hooks.UserPromptSubmit`가 배열이 아닌 값으로 존재하면 빈 배열로 대체하던 것을, 사용자 데이터 보호 차원에서 skip + 사유 반환으로 변경. 정상 배열 병합(append·idempotent)은 회귀 없음.
735
-
736
- ### v3.5.0 (2026-07-14)
737
- - **세션별 상태 변화 브리핑 훅 (UserPromptSubmit)** — 모델은 statusline 칩을 볼 수 없어, 세션 중 상태 변화(컨텍스트 임계 돌파, 신규 route 후보, rule-health 플립)가 사용자가 묻기 전까지 설명되지 않던 공백을 메움. 프롬프트 제출마다 실행되되 **변화가 없으면 완전 침묵**(컨텍스트 비용 0).
738
- - 컨텍스트 판별·브리핑 마커 모두 session_id 단위 — 창 크기 자동 감지(200k/1M), 80%/95% 티어를 각각 1회씩만 경고.
739
- - route/rule-health는 세션 첫 이벤트에 시드해 SessionStart 브리핑과 중복 방지, 세션 중간에 새로 생긴 것만 주입.
740
- - installer가 UserPromptSubmit 훅을 idempotent하게 등록, 7일 미사용 세션 상태는 자동 정리.
741
-
742
- ### v3.4.3 (2026-07-14)
743
- - **write 우세 에피소드는 위임 후보에서 제외** — 편집 작업(Edit/Write 우세)이 범용 키워드("설명…")를 타고 read/explore로 새어 들어가던 오분류 수정. 실측에서 `Edit×5` 문서 편집이 read/T1로 잡혀 에러율 67% 노이즈를 만들었음. write 우세면 translate 키워드가 있을 때만 translate, 아니면 분류 없음(= 위임 후보 아님).
744
-
745
- ### v3.4.2 (2026-07-14)
746
- - **rule-health 분자 정화 — 권한 계열 에러 제외** — 사용자 도구 거부·auto mode classifier 거부·permission denied류는 사용자 의사와 권한 정책의 산물이지 작업 난이도 신호가 아님. 14일 전수 감사에서 `is_error` 142건 중 약 25%가 이 계열이었고, 글로벌 run/T1 룰에 24% ⚠ 플래그를 띄운 주범이었음(제외 후 18%로 해제, 실제 run/T1 에러율 23% → 8%).
747
-
748
- ### v3.4.1 (2026-07-14)
749
- - **rule-health 최소 표본 가드(`HEALTH_MIN_SAMPLE=10`)** — 표본 4건 중 에러 1건(25%)만으로 review 플래그가 뜨던 문제. 윈도 내 대상 에피소드가 10건 미만이면 에러율은 노이즈이므로 플래그를 유보.
750
-
751
- ### v3.4.0 (2026-07-14)
752
- - **행동 우선(behavior-first) 분류** — `categorize()`를 first-match 정규식에서 3단 판정으로 재작성: paste 게이트 → 도구 사용 히스토그램(`behaviorPool`)으로 후보군 축소 → 가중 키워드 스코어링. **에피소드가 실제로 실행한 도구 구성이 프롬프트 표현보다 우선**한다("테스트 통과했는지 확인해줘"가 실제로 `npx playwright test`를 돌렸다면 표현과 무관하게 run 에피소드).
753
- - ESCALATE_RE에 비가역·외부 작업 키워드 추가(제출/배포/deploy/release/merge 등) — 로그상 가벼운 run 에피소드로 보여도 위임하면 하네스의 default-safe-path 원칙이 무너짐.
754
- - rule-health 통계 키를 `tier|category|project`로 확장 — 같은 카테고리의 T2/T1 룰이 통계를 공유하며 생기던 이중 계상 제거.
755
- - ratchet-model.md 렌더: 같은 카테고리의 T2+T1 룰을 **요청 시점 판별 조건이 담긴 하나의 병합 룰**로 출력(기본 haiku → 다단계는 sonnet → 비가역은 메인 모델).
568
+ 전체 내역은 [CHANGELOG.md](./CHANGELOG.md)로 옮겼습니다. 최근 변경은 다음과 같습니다.
756
569
 
757
- ### v3.3.1 (2026-07-13)
758
- - **코드 대신 풀어쓴 설명** — `R1`, `T2` 같은 코드가 설명 없이 노출돼 처음 쓰는 사람이 알 수 없던 문제 수정. 모든 사용자 대면 출력(SessionStart 훅 브리핑, `route-scan` 후보 목록, `route-scan rules` 목록)에서 티어를 `T2 (단순 작업 — haiku급이면 충분)` 식으로 풀어쓰고, scope도 `이 프로젝트만`/`모든 프로젝트(글로벌)`로 표기. 훅 브리핑에는 "사용자에게 전달할 때 코드가 아니라 풀어쓴 설명으로 브리핑하라"는 지시 포함. (statusline 칩은 폭 제약상 `route? R1` 유지 — 의미는 세션 브리핑이 설명)
759
-
760
- ### v3.3.0 (2026-07-13)
761
- - **위임 가시화·브리핑 강화** — 모델 피팅의 전 과정이 사용자에게 보이도록:
762
- - SessionStart 훅이 후보마다 **등록 시 ratchet-model.md에 기록될 룰 원문**을 함께 주입 — 무엇이 등록될지 정확히 보고 승인.
763
- - 에러율 기준(20%) 초과로 review 상태가 된 룰은 **statusline `🅷⚠ rule-health R<N>` 칩** + 세션 시작 브리핑 양쪽으로 통지 (설계 문서에 있던 미구현 항목 구현. 우선순위: 세션 품질 경고 > rule-health > route? 후보).
764
- - ratchet-model.md 헤더에 위임 실행 시 `🔀 [claude-token-saver] 모델 피팅: "<유형>" → <agent> 위임` 한 줄을 먼저 표시하라는 지시 추가 — 어떤 도구가 토큰을 아끼는지 가시화.
765
- - README에 3.x 정체성 반영 (상단 요약에 모델 피팅 위임 추가, route-scan 섹션에 리서치 근거 접이식), model-rules.js 주석-구현 불일치 수정.
766
-
767
- ### v3.2.2 (2026-07-13)
768
- - **등록 룰 재제안 차단** — 이미 모델 피팅 룰이 있는 (티어|카테고리|프로젝트) 조합은 스캔 후보에서 자동 제외 (글로벌 룰은 전 프로젝트 커버). promote를 거치지 않고 등록된 룰(마이그레이션 등)이 후보로 되살아나던 문제 수정.
769
-
770
- ### v3.2.1 (2026-07-13)
771
- - **최초 설치 시 즉시 패턴 분석** — `install`(npm postinstall 포함)이 캐시가 없으면 기존 세션 로그를 그 자리에서 분석해, 첫 Claude Code 세션부터 티어 위임 후보가 표시됩니다 (기존에는 두 번째 세션부터).
772
-
773
- ### v3.2.0 (2026-07-13)
774
- - **티어 분류 (T0/T1/T2)** — route-scan이 이분법(easy/그외)에서 3티어로 진화. 신호에 변경성 도구 수·도구 에러 수 추가, 출력 임계값은 사용자 분포 기반 자동 보정(클램프 포함), 붙여넣은 화면·로그 질문 전용 카테고리 신설, 대화성 응답(출력 <100토큰) 제외. 기준 설계·리서치 근거는 `docs/TIER_CRITERIA.md`.
775
- - **모델 피팅 랫쳇 분리** — 승격된 위임 룰은 별도 파일(`.claude/ratchet-model.md` / `~/.claude/ratchet-model.md`)에 저장돼 사용자 룰과 파일 단위로 분리. `route-scan rules [rm <N>]`로 관리하며, 하네스 CLAUDE.md 블록이 두 파일을 함께 참조.
776
- - **로그 기반 자동 갱신 + rule-health** — 매 스캔마다 등록 룰의 반복 횟수·에러율(위임 적격 모양의 에피소드 기준)을 재계산해 파일을 재작성. 에러율 >20%면 `⚠ rule-health` 플래그로 조건 좁히기/제거를 제안.
777
- - **데이터 트리거 재스캔** — 고정 24h TTL을 폐기하고 신규 transcript 양이 재스캔을 트리거 (~5MB 즉시 / 소량 일 1회 / 무변화 스킵 / 최소 간격 1h / promote 직후 즉시 1회).
778
-
779
- ### v3.1.0 (2026-07-13)
780
- - **frugon 연계 제거** — `claude-token-saver frugon` 서브커맨드(JSONL 내보내기)를 삭제했습니다. 외부 분석기의 집계 리포트는 랫쳇 룰(조건→행동)로 변환할 수 없어 위임 파이프라인에 기여하지 못했고, 3.x의 방향은 **세션 로그 기반 티어 분류를 자체적으로 탄탄히** 가져가는 것입니다. route-scan은 영향 없이 그대로 동작합니다 (공용 파서는 `src/session-records.js`로 분리).
781
-
782
- ### v3.0.1 (2026-07-13)
783
- - **`harness pull` 재정의** — v3.0.0의 "글로벌 랫쳇 → 프로젝트 복사"는 글로벌 랫쳇이 이미 프로젝트의 상위 계층으로 항상 적용되므로 무의미해 제거. `pull`은 이제 패키지에 동봉된 **제작자 큐레이션 랫쳇 룰**(`presets/ratchet-rules.md`)을 사용자의 글로벌 랫쳇에 등록합니다 — 실제 반복 사고에서 승격된 범용 룰 6종, opt-in·멱등.
784
-
785
- ### v3.0.0 (2026-07-13)
786
- - **메이저 승격** — v2.19 frugon 연계 + v2.20 route-scan으로 "사후 토큰 모니터링 도구"에서 "반복 easy 작업을 싼 모델로 내려보내는 라우팅 계층"으로 제품 성격이 바뀌어 메이저 버전을 올립니다. Breaking change는 없습니다 (기존 명령·설정 전부 호환).
787
- - **route-scan promote 교정** — `harness promote R<N> --project`가 이제 후보가 **감지된 프로젝트**의 `.claude/ratchet.md`에 룰을 기록합니다 (이전에는 CLI를 실행한 디렉터리에 기록되는 버그). 스캔이 후보에 실제 세션 경로(`projectPath`)를 저장하며, 이 필드가 없는 구버전 캐시에서 다른 프로젝트 후보를 승격하려 하면 `route-scan --refresh`를 안내하고 중단합니다.
788
- - **`harness pull` 신설** — v3.0.1에서 재정의됨 (위 참고).
789
-
790
- ### v2.20.0 (2026-07-13)
791
- - **route-scan**: 상위 모델이 반복 처리한 easy 작업 감지 → `🅷⚠ route? R<N>` 칩 + SessionStart 훅 컨텍스트 주입 + `harness promote R<N> --project|--global`로 haiku 위임 랫쳇 룰 승격.
792
-
793
- ### v2.19.0 (2026-07-12)
794
- - **frugon 연계**: `claude-token-saver frugon` — 세션 transcript를 [frugon](https://github.com/Rodiun/frugon) 호환 JSONL로 내보내 모델 라우팅 절감 분석 (`--run`으로 즉시 분석, 캐시 가중 토큰 기본).
795
-
796
- ### v2.18.0 (2026-07-02)
797
- - **1M 컨텍스트 경고 의미 재정의** — 현재 모델(Fable 5, Opus 4.6~4.8, Sonnet 5)은 전부 1M 윈도가 기본이고 Opus 4.7부터 장기 컨텍스트 프리미엄도 없어, "1M 모드 ON = 비쌈" 프레임을 폐기했습니다. 경고는 이제 **실사용 신호**입니다: `⚠ 1M ON` → `⚠ Ctx 200k+`(단일 요청이 실제로 200k 초과), 처방도 "1M 끄기" 우선에서 "`/compact`/`/clear` + `/effort` 점검" 우선으로 재정렬. 잘못된 "200k 초과 시 장기 요금 적용" 문구 정정.
798
- - **📦 세그먼트가 실시간 사용률 표시** — Claude Code stdin의 `context_window.used_percentage`를 사용해 `📦 Ctx 68% of 1M` 형태로 렌더 (사용률 기준 녹 <70 / 황 70–89 / 적 90+). stdin이 없으면 기존 크기 추론으로 폴백하되 1M은 빨강 대신 노랑.
799
- - 구버전 히스토리 호환: `⚠ 1M ON` 칩·구 디테일 문구도 계속 해석됩니다.
800
-
801
- ### v2.17.0 (2026-07-02)
802
- - **Fable 5 가격 티어 추가** — `claude-fable-5`/`claude-mythos-5`가 Sonnet 단가($3/$15)로 폴백돼 비용이 ~3배 과소 추정되던 문제 수정. 실제 단가(입력 $10 / 출력 $50 / 캐시쓰기 5m $12.50·1h $20 / 캐시읽기 $1) 적용.
803
- - README 전면 개편 — 최상위 임팩트 요약, 세그먼트 표, harness scope 플래그 문서화, 가격 테이블 최신화.
804
-
805
- ### v2.16.0 (2026-07-02)
806
- - **statusline 버그 수정** — 두 윈도 동시 90%+ 시 하나가 사라지던 문제(cap-warn 승격분만 숨김), `--no-color` 출력의 ANSI escape 제거, 세션 데이터 없어도 cap-warn·🅷·모델 칩 유지.
807
- - **harness 경고 정확도** — 🅷⚠ 경고 30분 자동 만료(무기한 잔류 수정), 하위 디렉터리 세션 매칭, cwd 없는 상태의 전 프로젝트 누출 수정.
808
- - **PEV-skip 오탐 감소** — 변경성 도구만 카운트(Read/Grep 제외), 윈도를 어시스턴트 턴 기준으로.
809
-
810
- <details>
811
- <summary>이전 버전 (v2.8.5 ~ v2.15.0)</summary>
812
-
813
- ### v2.15.0 (2026-06-13)
814
- - **글로벌 harness init** — `harness init --global`이 `~/.claude/CLAUDE.md`(+ `~/.claude/ratchet.md`)에 5개 섹션을 설치해 모든 프로젝트에 적용. `harness check`는 글로벌을 fallback으로 인정(`🅷 5/5 (covered by global)`).
815
- - npm homepage 변경, @DeepPulseEN 채널·홈페이지 배지 추가.
816
-
817
- ### v2.13.x (2026-05-04)
818
- - "실제 효과" 섹션을 harness+ratchet 도입 전후 리포트로 재구성, statusline 스크린샷·임팩트 차트 추가, npm 메타데이터 정비, YouTube 핸들 정정.
819
-
820
- ### v2.11.0 (2026-05-02)
821
- - `harness list` / `harness rm <N>` 추가 (자동 `.bak` 백업, 삭제 전 "조건 좁히기 우선" 안내).
822
-
823
- ### v2.9.x (2026-04-27)
824
- - 출력 언어 전환(`mode ko`/`en`) 추가 — `last`/`history`/처방이 한 언어로 출력. Skill이 사용자 언어로 응답하도록 지시 추가. README에 Node.js 사전 설치 안내·Skill 워크플로 4단계 추가. `language` 설정 위치 정리.
825
-
826
- ### v2.8.6 (2026-04-27)
827
- - **Skill 자동 등록** — postinstall 훅이 Skill과 statusline을 `~/.claude`에 자동 등록.
828
-
829
- ### v2.8.5
830
- - IntelliJ plugin 프레임 합성 버그 회피 — JediTerm 감지 시 자동 text 모드.
831
-
832
- 더 이전 버전은 `git log` 참고.
833
- </details>
570
+ - **v3.35.0**: 이번 달 1일 00시 이후 지출 추정치를 `💵 Sep $42` 세그먼트로 상시 표시합니다. LiteLLM 게이트웨이 사용자는 키의 max_budget/spend 를 `🔑 budget` 게이지로 봅니다 (5h/7d cap 이 없는 Bedrock·LiteLLM 환경 대응).
571
+ - **v3.34.0**: seed 프리셋 제안, 설치 시 출력 언어 선택, 컨텍스트 경고 500k 상향. 상세는 CHANGELOG 참고.
834
572
 
835
573
  ## 라이선스
836
574