sprag-cli 3.42.0 → 3.42.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Subcommand: compact-window — audit / pin Claude Code's `autoCompactWindow`.
3
- * claude-token-saver compact-window # status
4
- * claude-token-saver compact-window set --global # pin 500k in ~/.claude/settings.json
5
- * claude-token-saver compact-window set --project # pin 500k in <root>/.claude/settings.json
6
- * claude-token-saver compact-window set --global --value 600k
7
- * claude-token-saver compact-window off | on # toggle the statusline warning
3
+ * sprag compact-window # status
4
+ * sprag compact-window set --global # pin 500k in ~/.claude/settings.json
5
+ * sprag compact-window set --project # pin 500k in <root>/.claude/settings.json
6
+ * sprag compact-window set --global --value 600k
7
+ * sprag compact-window off | on # toggle the statusline warning
8
8
  *
9
9
  * Scope is deliberately explicit for `set`: writing a global settings.json is
10
10
  * not something to guess at, and the non-TTY hook environment cannot prompt.
@@ -80,14 +80,14 @@ export async function run({ args, hasFlag }) {
80
80
  console.log(ko
81
81
  ? ` 그 전까지 모든 요청이 전체 컨텍스트를 재과금합니다. 1M은 너무 크니 ${fmt(s.recommendedMin)}~${fmt(s.recommendedMax)} 범위를 권장합니다 (기본값 ${fmt(s.recommended)}, --value로 조절). 1M 창 자체는 그대로 두고 압축 시점만 앞당깁니다.`
82
82
  : ` Until then every request re-bills the whole context. 1M is too large — pick something in ${fmt(s.recommendedMin)}–${fmt(s.recommendedMax)} (default ${fmt(s.recommended)}, override with --value). The 1M window itself stays.`);
83
- console.log(`\n claude-token-saver compact-window set --global (~/.claude/settings.json, ${fmt(s.recommended)})`);
84
- console.log(` claude-token-saver compact-window set --project (<root>/.claude/settings.json, ${fmt(s.recommended)})`);
85
- console.log(` claude-token-saver compact-window set --global --value ${fmt(s.recommendedMax)}`);
83
+ console.log(`\n sprag compact-window set --global (~/.claude/settings.json, ${fmt(s.recommended)})`);
84
+ console.log(` sprag compact-window set --project (<root>/.claude/settings.json, ${fmt(s.recommended)})`);
85
+ console.log(` sprag compact-window set --global --value ${fmt(s.recommendedMax)}`);
86
86
  console.log(ko ? ' (적용 범위는 사용자에게 먼저 확인할 것)' : ' (confirm the scope with the user first)');
87
87
  return;
88
88
  }
89
89
 
90
90
  console.error(`Unknown compact-window subcommand: ${sub}`);
91
- console.error('Usage: claude-token-saver compact-window [status|set --global|--project [--value 500k]|off|on]');
91
+ console.error('Usage: sprag compact-window [status|set --global|--project [--value 500k]|off|on]');
92
92
  process.exit(1);
93
93
  }
@@ -25,13 +25,13 @@ import { join } from 'node:path';
25
25
  import os from 'node:os';
26
26
  import { debug } from '../debug.js';
27
27
 
28
- const REPO = 'rootstudioyaml/claude-token-saver';
28
+ const REPO = 'rootstudioyaml/sprag';
29
29
  const ISSUES_URL = `https://github.com/${REPO}/issues`;
30
30
 
31
31
  // Anonymous submission endpoint (Google Form). A Google Form's formResponse
32
32
  // URL accepts unauthenticated POSTs, which is exactly the property a
33
33
  // login-free, GitHub-blocked-network path needs. Responses land in the
34
- // maintainer's "claude-token-saver 피드백 (Feedback)" form (published
34
+ // maintainer's "sprag 피드백 (Feedback)" form (published
35
35
  // 2026-09-13, responder access: anyone with the link).
36
36
  // id — the /d/e/<id>/ segment of the form URL
37
37
  // message — entry.NNNN field id of the message question
@@ -49,7 +49,7 @@ export async function run({ hasFlag }) {
49
49
  chosen = ko ? 'ko' : 'en';
50
50
  }
51
51
  setUserLanguage(chosen);
52
- console.log(` language: set to ${chosen === 'ko' ? '한국어' : 'English'} — change it any time with \`claude-token-saver mode lang=${chosen === 'ko' ? 'en' : 'ko'}\``);
52
+ console.log(` language: set to ${chosen === 'ko' ? '한국어' : 'English'} — change it any time with \`sprag mode lang=${chosen === 'ko' ? 'en' : 'ko'}\``);
53
53
  } else if (process.env.CTS_LANG) {
54
54
  // Escape hatch for scripted installs, which cannot answer a prompt but
55
55
  // do know which language the machine's user reads.
@@ -87,8 +87,8 @@ export async function run({ hasFlag }) {
87
87
  ? ' 교체하면 토큰·캐시·상한 경고가 statusline에 표시됩니다. 기존 설정은 사라집니다.'
88
88
  : ' replacing it shows token/cache/cap warnings in the statusline; the current one is removed.');
89
89
  const replace = await confirm(lang === 'ko'
90
- ? ' claude-token-saver statusline으로 교체할까요?'
91
- : ' Replace it with the claude-token-saver statusline?', { defaultValue: false });
90
+ ? ' sprag statusline으로 교체할까요?'
91
+ : ' Replace it with the sprag statusline?', { defaultValue: false });
92
92
  if (replace) {
93
93
  const { installStatusline } = await import('../installer.js');
94
94
  s = installStatusline({ force: true });
@@ -336,8 +336,8 @@ export async function run({ hasFlag }) {
336
336
  ? ` seed: 추천 룰 ${pending.length}건이 대기 중입니다 (모델 피팅 + 랫쳇 프리셋).`
337
337
  : ` seed: ${pending.length} recommended rule(s) are waiting (model-fitting + ratchet presets).`);
338
338
  console.log(lang === 'ko'
339
- ? ' 다음 Claude Code 세션에서 한 건씩 등록할지 물어봅니다. 지금 보려면: claude-token-saver seed'
340
- : ' the next Claude Code session asks about them one at a time. See them now: claude-token-saver seed');
339
+ ? ' 다음 Claude Code 세션에서 한 건씩 등록할지 물어봅니다. 지금 보려면: sprag seed'
340
+ : ' the next Claude Code session asks about them one at a time. See them now: sprag seed');
341
341
  }
342
342
  } catch (e) {
343
343
  debug('install:seed-offer', e); // optional feature; never fail install
@@ -352,7 +352,7 @@ export async function run({ hasFlag }) {
352
352
  }
353
353
  console.log('');
354
354
  console.log(lang === 'ko'
355
- ? '버그 제보·기능 제안: https://github.com/rootstudioyaml/claude-token-saver/issues'
356
- : 'Bug reports & feature requests: https://github.com/rootstudioyaml/claude-token-saver/issues');
355
+ ? '버그 제보·기능 제안: https://github.com/rootstudioyaml/sprag/issues'
356
+ : 'Bug reports & feature requests: https://github.com/rootstudioyaml/sprag/issues');
357
357
  return;
358
358
  }
@@ -3,8 +3,8 @@
3
3
  * Designed for the auto-trigger skill so the user immediately sees
4
4
  * "what just fired and how to fix it" without having to read the whole
5
5
  * history file.
6
- * claude-token-saver last # search last 1 day
7
- * claude-token-saver last --days 7 # widen the lookback
6
+ * sprag last # search last 1 day
7
+ * sprag last --days 7 # widen the lookback
8
8
  */
9
9
 
10
10
 
@@ -113,7 +113,7 @@ export async function run({ numArg }) {
113
113
  console.log('💡 ' + (lang === 'ko' ? CAP_TIPS.ko : CAP_TIPS.en));
114
114
  console.log('');
115
115
  console.log(lang === 'ko' ? '실행:' : 'Run:');
116
- console.log(' claude-token-saver handoff');
116
+ console.log(' sprag handoff');
117
117
  return;
118
118
  }
119
119
  // Chip warning path: render full ISSUE_MESSAGES advice for each code,
@@ -121,8 +121,8 @@ export async function run({ numArg }) {
121
121
  // the history.md format).
122
122
  if (latest.codes.length === 0) {
123
123
  console.log(lang === 'ko'
124
- ? '(진단 코드 없음 — 표 뷰를 열어보세요: `claude-token-saver --days 1`)'
125
- : '(No diagnostic code attached — open the table view: `claude-token-saver --days 1`)');
124
+ ? '(진단 코드 없음 — 표 뷰를 열어보세요: `sprag --days 1`)'
125
+ : '(No diagnostic code attached — open the table view: `sprag --days 1`)');
126
126
  return;
127
127
  }
128
128
  // Pick a single language per field; fall back to EN when KO is missing.
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Subcommand: mode — persist statusline preferences so future runs pick
3
3
  * them up without flags or wrapper edits.
4
- * claude-token-saver mode # show current config
5
- * claude-token-saver mode icon verbose # set icon + verbose
6
- * claude-token-saver mode reset # clear back to defaults
4
+ * sprag mode # show current config
5
+ * sprag mode icon verbose # set icon + verbose
6
+ * sprag mode reset # clear back to defaults
7
7
  */
8
8
 
9
9
 
@@ -28,7 +28,7 @@ export async function run({ args }) {
28
28
  console.log(`Stored config file (${configPath()}):`);
29
29
  console.log(` ${Object.keys(raw).length === 0 ? '(none — using defaults)' : JSON.stringify(raw)}`);
30
30
  console.log('');
31
- console.log('Change with: claude-token-saver mode <keywords...>');
31
+ console.log('Change with: sprag mode <keywords...>');
32
32
  console.log(`Keywords: ${VALID_KEYWORDS.join(', ')}`);
33
33
  return;
34
34
  }
@@ -303,13 +303,13 @@ export async function run({ args, hasFlag, numArg }) {
303
303
  ? [
304
304
  `[sprag update] 새 버전이 나와 있습니다: v${u.current} → ${u.latest}.`,
305
305
  '사용자에게 지금 업그레이드할지 물어보고, 승낙하면 아래 명령을 실행하십시오. 묻지 않고 설치하지는 마십시오.',
306
- ' claude-token-saver upgrade # 업그레이드 실행',
306
+ ' sprag upgrade # 업그레이드 실행',
307
307
  ' sprag update-check --dismiss # 사용자가 원치 않으면 (다음 버전이 나올 때까지 다시 묻지 않습니다)',
308
308
  ].join('\n')
309
309
  : [
310
310
  `[sprag update] A newer version is available: v${u.current} → ${u.latest}.`,
311
311
  'Ask the user whether to upgrade now, and run the command below only if they agree. Do not install without asking.',
312
- ' claude-token-saver upgrade # perform the upgrade',
312
+ ' sprag upgrade # perform the upgrade',
313
313
  ' sprag update-check --dismiss # if they decline (stays quiet until a newer release)',
314
314
  ].join('\n');
315
315
  }
@@ -366,8 +366,8 @@ export async function run({ args, hasFlag, numArg }) {
366
366
  }
367
367
  if (reviewRules.length > 0) {
368
368
  lines.push(lang === 'ko'
369
- ? '[claude-token-saver rule-health] 사용자가 승인한 위임 룰 중, 위임 대상 유형의 최근 에러율이 기준(20%)을 넘어 재검토가 필요한 룰이 있습니다 — 사용자에게 브리핑하고 조건 좁히기/제거를 상의하세요:'
370
- : '[claude-token-saver rule-health] Some user-approved delegation rules now exceed the 20% error-rate threshold for their delegated category — brief the user and discuss narrowing or removing them:');
369
+ ? '[sprag rule-health] 사용자가 승인한 위임 룰 중, 위임 대상 유형의 최근 에러율이 기준(20%)을 넘어 재검토가 필요한 룰이 있습니다 — 사용자에게 브리핑하고 조건 좁히기/제거를 상의하세요:'
370
+ : '[sprag rule-health] Some user-approved delegation rules now exceed the 20% error-rate threshold for their delegated category — brief the user and discuss narrowing or removing them:');
371
371
  for (const r of reviewRules) {
372
372
  // Say WHICH signal tripped: a measured delegation failure rate is a
373
373
  // much stronger claim than the shape-based proxy, and the user's
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * Subcommand: seed — register the bundled starter rules, one answer at a time.
3
3
  *
4
- * claude-token-saver seed # what is still pending
5
- * claude-token-saver seed accept <id> --global # register one rule
6
- * claude-token-saver seed accept <id> --project # ... into this project only
7
- * claude-token-saver seed accept all --global # when the user says "all of them"
8
- * claude-token-saver seed skip <id> | skip all # never offer it again
9
- * claude-token-saver seed reset # make every preset pending again
4
+ * sprag seed # what is still pending
5
+ * sprag seed accept <id> --global # register one rule
6
+ * sprag seed accept <id> --project # ... into this project only
7
+ * sprag seed accept all --global # when the user says "all of them"
8
+ * sprag seed skip <id> | skip all # never offer it again
9
+ * sprag seed reset # make every preset pending again
10
10
  *
11
11
  * Scope is explicit on purpose, exactly as `harness promote` requires it: the
12
12
  * hook environment is non-TTY, so the model has to ask the user and pass the
@@ -36,8 +36,8 @@ export async function run({ args, hasFlag }) {
36
36
  const ids = args.slice(2).filter((a) => !a.startsWith('-'));
37
37
  if (ids.length === 0) {
38
38
  console.error(ko
39
- ? 'id를 지정하십시오 (목록: claude-token-saver seed). 전체는 `all`.'
40
- : 'Pass an id (list them with `claude-token-saver seed`), or `all`.');
39
+ ? 'id를 지정하십시오 (목록: sprag seed). 전체는 `all`.'
40
+ : 'Pass an id (list them with `sprag seed`), or `all`.');
41
41
  process.exit(1);
42
42
  }
43
43
  const pending = seed.pendingSeeds({ lang, root });
@@ -99,7 +99,7 @@ export async function run({ args, hasFlag }) {
99
99
  if (pending.length > 0) {
100
100
  console.log('');
101
101
  console.log(ko
102
- ? '등록: claude-token-saver seed accept <id> --global|--project · 거절: seed skip <id>'
103
- : 'register: claude-token-saver seed accept <id> --global|--project · decline: seed skip <id>');
102
+ ? '등록: sprag seed accept <id> --global|--project · 거절: seed skip <id>'
103
+ : 'register: sprag seed accept <id> --global|--project · decline: seed skip <id>');
104
104
  }
105
105
  }
package/src/handoff.js CHANGED
@@ -70,7 +70,7 @@ function renderTemplate({ now, cwd, git, caps }) {
70
70
  const lines = [];
71
71
  lines.push(`# Handoff — ${ymd(now)} ${pad(now.getHours())}:${pad(now.getMinutes())}`);
72
72
  lines.push('');
73
- lines.push(`Generated by \`claude-token-saver handoff\`.`);
73
+ lines.push(`Generated by \`sprag handoff\`.`);
74
74
  lines.push('');
75
75
  lines.push('## Context');
76
76
  lines.push('');
package/src/history.js CHANGED
@@ -306,7 +306,7 @@ export function recordCapTransition(window) {
306
306
 
307
307
  /**
308
308
  * Record a handoff write — invoked by the `handoff` subcommand so
309
- * `claude-token-saver history` shows when work was backed up to a HANDOFF file.
309
+ * `sprag history` shows when work was backed up to a HANDOFF file.
310
310
  *
311
311
  * @param {string} filePath
312
312
  * @returns {boolean}
package/src/installer.js CHANGED
@@ -22,19 +22,19 @@ const STATUSLINE_REFRESH_INTERVAL = 5;
22
22
 
23
23
  const SKILL_BODY = `---
24
24
  name: claude-token-saver
25
- description: Use when the user mentions Claude Code token usage, prompt cache hit rate, TTL/expiry, the 1M context window, cache misses, output spikes, rate-limit caps (5h/7d), or anything in the statusline produced by claude-token-saver (chips like "🚨 5H 94%", "🚨 7D 92%", "⚠ Ctx 500k+", "⚠ Input spike", "⚠ Cache miss", "⚠ 5m TTL", "⚠ Rebuild churn", "⚠ Output heavy", "⚠ Call surge", "⏳ Cache expires", "💰 Cache saved", "🧠 Cache hit"). Also use when they ask to view token-usage history, want to understand a warning they just saw, or want to back up work before a session cap with \`claude-token-saver handoff\`.
25
+ description: Use when the user mentions Claude Code token usage, prompt cache hit rate, TTL/expiry, the 1M context window, cache misses, output spikes, rate-limit caps (5h/7d), or anything in the statusline produced by sprag (chips like "🚨 5H 94%", "🚨 7D 92%", "⚠ Ctx 500k+", "⚠ Input spike", "⚠ Cache miss", "⚠ 5m TTL", "⚠ Rebuild churn", "⚠ Output heavy", "⚠ Call surge", "⏳ Cache expires", "💰 Cache saved", "🧠 Cache hit"). Also use when they ask to view token-usage history, want to understand a warning they just saw, or want to back up work before a session cap with \`sprag handoff\`.
26
26
  ---
27
27
 
28
- # claude-token-saver — Claude Code Token Monitor
28
+ # sprag — Claude Code Token Monitor
29
29
 
30
- This skill helps users interpret and act on the \`claude-token-saver\` statusline
30
+ This skill helps users interpret and act on the \`sprag\` statusline
31
31
  in Claude Code. The statusline updates every ~1s and shows cache health, TTL
32
32
  countdown, savings, and (when relevant) a leading warning chip.
33
33
 
34
34
  ## Response language
35
35
 
36
36
  Respond in the user's configured output language. Run
37
- \`claude-token-saver mode\` once at the start of the session and read the
37
+ \`sprag mode\` once at the start of the session and read the
38
38
  \`Output language\` field — if it shows \`language: ko\`, write **all of your
39
39
  prose to the user in Korean** (summary, "All clear" status lines, headings,
40
40
  recommendations). If it shows \`language: en\` (the default), write in
@@ -52,7 +52,7 @@ honor that for the rest of the turn without changing the saved setting.
52
52
  "when did this start happening", or similar.
53
53
  - The user is approaching a rate-limit cap and wants to back up the current
54
54
  work so a fresh session can continue (point them at
55
- \`claude-token-saver handoff\`).
55
+ \`sprag handoff\`).
56
56
  - The user wants to see the token-usage history file or asks for a summary
57
57
  of recent warnings.
58
58
  - The user asks for a quick token report or "current state" check (the
@@ -62,16 +62,16 @@ honor that for the rest of the turn without changing the saved setting.
62
62
  ## What to do
63
63
 
64
64
  1. **Lead with the most recent warning + how to handle it.** Run
65
- \`claude-token-saver last\` first. It returns the most recent warning event
65
+ \`sprag last\` first. It returns the most recent warning event
66
66
  (chip + detail + timestamp) plus the full advice block for it. Surface that
67
67
  to the user before anything else — this is what they came for.
68
68
  2. **Identify the chip.** If the user pasted a statusline (instead of relying
69
69
  on \`last\`), pull out the leading \`⚠ ...\` chip. That maps to a specific
70
70
  issue category.
71
- 3. **Show recent history.** Run \`claude-token-saver history\` (default last 7
71
+ 3. **Show recent history.** Run \`sprag history\` (default last 7
72
72
  days) to see the chronology of warning transitions. Each entry is timestamped,
73
73
  bilingual (English line + 한국어), and includes a \`💡\` action tip inline.
74
- 4. **Drill down on the live state.** Run \`claude-token-saver --days 1\` (or
74
+ 4. **Drill down on the live state.** Run \`sprag --days 1\` (or
75
75
  another window) to render the full table view, which lists per-session
76
76
  spikes and recommended actions.
77
77
  5. **Explain the warning** in plain language. Use the chip → cause table:
@@ -94,7 +94,7 @@ honor that for the rest of the turn without changing the saved setting.
94
94
  that is expected, not a failure of this tool.
95
95
 
96
96
  6. **Suggest the next action.** For \`🚨 5H/7D\` chips, recommend running
97
- \`claude-token-saver handoff\` to back up the current work to a
97
+ \`sprag handoff\` to back up the current work to a
98
98
  \`HANDOFF-*.md\` file before the cap hits, then continue in a fresh
99
99
  session. For \`⚠ Ctx 500k+\`, recommend \`/compact\` or \`/clear\` and
100
100
  checking what is pinned into context. For
@@ -103,18 +103,18 @@ honor that for the rest of the turn without changing the saved setting.
103
103
 
104
104
  ## Useful commands
105
105
 
106
- - \`claude-token-saver last\` — most recent warning + full advice (start here).
107
- - \`claude-token-saver last --days 7\` — widen the lookback window.
108
- - \`claude-token-saver\` — full table report (default last 1 day).
109
- - \`claude-token-saver --days 7\` — wider window.
110
- - \`claude-token-saver history\` — recent warning transitions per day, with
106
+ - \`sprag last\` — most recent warning + full advice (start here).
107
+ - \`sprag last --days 7\` — widen the lookback window.
108
+ - \`sprag\` — full table report (default last 1 day).
109
+ - \`sprag --days 7\` — wider window.
110
+ - \`sprag history\` — recent warning transitions per day, with
111
111
  inline \`💡\` action tips.
112
- - \`claude-token-saver history --days 30\` — longer history.
113
- - \`claude-token-saver handoff\` — write a HANDOFF-*.md template in cwd
112
+ - \`sprag history --days 30\` — longer history.
113
+ - \`sprag handoff\` — write a HANDOFF-*.md template in cwd
114
114
  capturing git status + cap snapshot, so a fresh session can resume cleanly.
115
- - \`claude-token-saver mode\` — show statusline preferences.
116
- - \`claude-token-saver mode icon verbose 1d\` — change preferences.
117
- - \`claude-token-saver feedback "<message>"\` — file a bug report or feature
115
+ - \`sprag mode\` — show statusline preferences.
116
+ - \`sprag mode icon verbose 1d\` — change preferences.
117
+ - \`sprag feedback "<message>"\` — file a bug report or feature
118
118
  request for this tool right from the session (tries the gh CLI, then an
119
119
  anonymous no-login submission, then saves locally with a prefilled GitHub
120
120
  issue URL; \`--anonymous\` skips the gh path).
@@ -163,7 +163,7 @@ export function removeLegacyCommand() {
163
163
 
164
164
  // Registers/repairs the Claude Code statusLine entry in ~/.claude/settings.json.
165
165
  // - No statusLine yet: insert ours with refreshInterval:STATUSLINE_REFRESH_INTERVAL.
166
- // - statusLine already points at claude-token-saver: ensure that refreshInterval
166
+ // - statusLine already points at sprag: ensure that refreshInterval
167
167
  // (this is the bit that makes the TTL countdown tick every second while idle).
168
168
  // - statusLine points at a different command: leave it alone unless --force.
169
169
  export function installStatusline({ force = false } = {}) {
@@ -219,7 +219,7 @@ export function installStatusline({ force = false } = {}) {
219
219
 
220
220
  // Registers the SessionStart hook that surfaces route-scan delegation
221
221
  // candidates as session context (startup + /clear). Idempotent: skips when a
222
- // claude-token-saver route-scan hook is already present; never touches other
222
+ // sprag route-scan hook is already present; never touches other
223
223
  // hooks the user configured.
224
224
  const ROUTE_SCAN_HOOK_COMMAND = 'claude-token-saver route-scan --hook';
225
225
 
@@ -67,9 +67,13 @@ export function koreanStyleDecided(cfg = loadConfig()) {
67
67
  * locale variables, then (macOS only, where those are routinely unset) the
68
68
  * system locale.
69
69
  */
70
- export function koreanLocaleDetected({ env = process.env, platform = process.platform } = {}) {
70
+ export function koreanLocaleDetected({ env = process.env, platform = process.platform, cfg } = {}) {
71
71
  try {
72
- if (loadConfig().language === 'ko') return true;
72
+ // The saved language answer only applies to the live process environment.
73
+ // A caller that injects a synthetic `env` (tests, simulations) is asking
74
+ // about that environment, not about this machine's recorded choice.
75
+ const c = cfg !== undefined ? cfg : (env === process.env ? loadConfig() : null);
76
+ if (c && c.language === 'ko') return true;
73
77
  } catch { /* unreadable config falls through to the env checks */ }
74
78
  const posix = [env.LC_ALL, env.LC_MESSAGES, env.LANG, env.LANGUAGE].filter(
75
79
  (v) => typeof v === 'string' && v.trim() && v !== 'C' && v !== 'POSIX',
@@ -198,7 +198,7 @@ export function removeModelRule(index1) {
198
198
  export function renderModelRatchet(rules, lang = userLanguage()) {
199
199
  const ko = lang === 'ko';
200
200
  const lines = ko ? [
201
- '# Model-Fitting Ratchet (claude-token-saver 자동 관리)',
201
+ '# Model-Fitting Ratchet (sprag 자동 관리)',
202
202
  '',
203
203
  '로그 기반 티어 위임 룰. 이 파일은 route-scan이 매 스캔마다 통째로 재생성하므로',
204
204
  '직접 수정하지 마세요 — 목록/제거: `sprag route-scan rules [rm <N>]`.',
@@ -245,7 +245,7 @@ export function renderModelRatchet(rules, lang = userLanguage()) {
245
245
  '## Rules',
246
246
  '',
247
247
  ] : [
248
- '# Model-Fitting Ratchet (managed by claude-token-saver)',
248
+ '# Model-Fitting Ratchet (managed by sprag)',
249
249
  '',
250
250
  'Log-derived tier delegation rules. route-scan regenerates this file in full',
251
251
  'on every scan — do not edit it by hand. List / remove with:',