claude-token-saver 3.26.0 โ†’ 3.26.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -62,6 +62,7 @@ By run (newest first):
62
62
  | ๐Ÿšจ **No surprise rate limits** | Warns when the 5H/7D window hits 90%; `handoff` backs up your work |
63
63
  | ๐Ÿง  **Cache waste detection** | Hit rate, TTL, 1M-context detection โ€” spikes diagnosed with issue codes |
64
64
  | ๐Ÿ‡ฐ๐Ÿ‡ท **Korean writing guidance** | Offered at install time, defaulting to your locale ([below](#-korean-writing-guidance)) |
65
+ | ๐Ÿ“„ **Document conversion** | pptx/xlsx/pdf/docx become Markdown before the model reads them, so unreadable bytes never reach the context window ([below](#-doc2md--attached-documents-become-markdown-before-the-model-reads-them)) |
65
66
 
66
67
  ## Not a router โ€” 60 seconds
67
68
 
@@ -163,6 +164,9 @@ Run these in your shell (inside Claude Code, the `/claude-token-saver` Skill is
163
164
  | `claude-token-saver korean on\|off\|status` | Inject Korean writing guidance at session start and install the write-time check (below) |
164
165
  | `claude-token-saver korean lint block\|warn\|off` | How the write-time check handles findings |
165
166
  | `claude-token-saver korean lint scope all\|prose` | Check every text file, or documents only |
167
+ | `claude-token-saver doc2md on\|off` | Convert attached documents to Markdown before the model reads them (below) |
168
+ | `claude-token-saver doc2md <file>` | Convert one file by hand. Diagnostic: it prints the refusal reason instead of swallowing it |
169
+ | `claude-token-saver mode ttl=5m\|1h\|auto` | Pin the cache TTL bucket. The default `auto` trusts the measured split, then falls back to gateway detection |
166
170
  | `claude-token-saver --version` | Print the installed version |
167
171
  | `claude-token-saver update-check` | Is a newer version out? (`--refresh` to ask now, `--dismiss` to mute this version's offer) |
168
172
  | `claude-token-saver upgrade` | Install the latest release with the package manager that installed this copy (`--print` shows the command only) |
@@ -374,6 +378,45 @@ Installs with nobody attached โ€” npm `postinstall`, CI, piped stdin โ€” skip th
374
378
  > The guidance text comes from [fluent-korean](https://github.com/snflkd/fluent-korean). Copyright (c) 2026 snflkd, MIT License.
375
379
  > The wording is unmodified; only the output-style frontmatter was removed. The full license ships with the package at `presets/korean-style/LICENSE-fluent-korean`.
376
380
 
381
+ ## ๐Ÿ“„ doc2md โ€” attached documents become Markdown before the model reads them
382
+
383
+ `Read` a pptx, xlsx, pdf or docx and the raw bytes go into the context window, where the model cannot read them. This intercepts that `Read`, converts the file once, and hands over the Markdown instead.
384
+
385
+ ```bash
386
+ pip install "markitdown[pptx,pdf,xlsx,docx]" # the converter is a Python package
387
+ claude-token-saver doc2md on # register the Read hook
388
+ claude-token-saver doc2md report.pptx # convert by hand and see the result
389
+ ```
390
+
391
+ Conversion is [markitdown](https://github.com/microsoft/markitdown). Slide numbers, heading levels, tables, speaker notes and per-sheet headings all survive, and non-Latin text comes through intact.
392
+
393
+ Several things it deliberately does not do:
394
+
395
+ - **Images are not converted.** markitdown returns nothing for them, and OCR misread resource names in testing (`c5.xlarge` as `c.xlarge`). In a document where those names *are* the content, wrong text is worse than none. The model reads images natively anyway.
396
+ - **A missing markitdown never fails silently.** The install command is shown once, then the original `Read` proceeds untouched. Repeating the notice on every read would be its own nuisance; saying nothing is how a broken converter hides.
397
+ - **Conversions never land in your project.** They go under the tool's own state directory with mode `0700`, so there is nothing to add to `.gitignore`. Filenames matching payroll/contract/secret patterns are skipped entirely.
398
+ - **Zip bombs are refused.** pptx/xlsx/docx are zip containers: the declared sizes are checked first, and since those are written by whoever built the file, the real decompressed bytes are counted against a ceiling too.
399
+ - **Spreadsheets are capped by rows, not bytes.** Conversion time tracks row count (measured: a 6.3MB PDF in 0.9s, a 5.8MB workbook in 47.75s). Past 50,000 rows only the head is converted, and **the truncation and the true row count are both stated** in what the model is told.
400
+
401
+ `claude-token-saver doc2md --clean` empties the conversion cache; `doc2md off` removes the hook. Removal filters for this tool's own entry, so anything else you registered under `PreToolUse` stays.
402
+
403
+ ## ๐ŸŒ Behind a gateway (Bedrock / Vertex)
404
+
405
+ A gateway reports the cache-creation total but never the 5m/1h split. That left the tool unable to tell "nothing cached yet" from "this provider does not say", and the fallback assumed an hour โ€” for a window that is really five minutes on Bedrock, overstating it twelvefold.
406
+
407
+ Since v3.26.0 the gateway is detected from the model ids in the transcript, which fixes:
408
+
409
+ - The countdown falls back to 5 minutes, labelled `5m?`. Three grades of certainty get three labels: measured (`5m`), inferred (`5m?`), unknown (`?`).
410
+ - In a 5-minute bucket the countdown colour follows absolute time rather than a percentage. 30% of five minutes is 90 seconds, and green there promised comfort that was not there.
411
+ - The `โš  5m TTL` warning finally reaches these users โ€” with different advice, since no subscription plan changes a gateway's TTL.
412
+ - `Extra cost if 5m-only` is only asked of sessions that have 1h writes to lose. Elsewhere the arithmetically honest `+$0` read as an endorsement of the bucket you are already stuck in.
413
+ - Delegated runs dropped for an unpriceable model id show as `๐Ÿ”€ N unresolved` instead of nothing, which used to be indistinguishable from never having delegated.
414
+ - Environment variables set to a `foundation-model` ARN now resolve. An opaque `application-inference-profile` id still does not: guessing at it is how wrong prices enter the ledger.
415
+
416
+ If the detection is wrong, pin it with `claude-token-saver mode ttl=5m` (or `ttl=1h`). An explicit value outranks the measurement.
417
+
418
+ One related non-bug: if your session model is already sonnet, a sonnet-delegation (T1) rule can never save anything, because there is no price gap to capture. That is correct, but `route-scan rules` displayed it identically to "no delegations yet", so it now says outright that the rule does not apply at the current default model.
419
+
377
420
  ## Spike issue codes
378
421
 
379
422
  | Code | Meaning |
@@ -454,6 +497,12 @@ Also update `statusLine.command` in `~/.claude/settings.json` to `claude-token-s
454
497
 
455
498
  ## Release notes
456
499
 
500
+ ### v3.26.0 (2026-09-04)
501
+ - **Attached documents are converted to Markdown before the model reads them.** Reading a pptx/xlsx/pdf/docx put unreadable bytes into the context window. `doc2md on` registers a `Read` hook that converts the file once, caches it outside your project, and points the model at the Markdown. A missing converter is announced once and then gets out of the way, zip bombs are refused, and workbooks past 50,000 rows are converted head-first with the truncation stated. See [doc2md](#-doc2md--attached-documents-become-markdown-before-the-model-reads-them).
502
+ - **TTL display fixed for Bedrock/Vertex sessions.** Gateways never report the per-bucket split, and the fallback assumed an hour โ€” twelvefold too long for a 5-minute-only backend. The gateway is now detected from the model ids, the fallback follows that evidence, and the label reads `5m?` to mark it as inferred. Pin it manually with `mode ttl=5m` if the detection is wrong.
503
+ - **Delegated runs are no longer discarded in silence.** Runs excluded for an unpriceable model id surface as `๐Ÿ”€ N unresolved` on the statusline; previously that was indistinguishable from never having delegated, so an entire tier of rules could report zero with no way to find out why. Environment variables set to a `foundation-model` ARN now resolve as well.
504
+ - **The Korean guidance stopped contradicting itself.** The injected scope claimed code comments while the vendored text disclaimed them twice, leaving the model nothing to decide on. The vendored wording is untouched; the block now states which side wins. The em dash in the attribution line โ€” a mark that guidance itself forbids โ€” became a colon.
505
+
457
506
  ### v3.25.0 (2026-09-04)
458
507
  - **The statusline now shows which version is running** โ€” until now the version lived only in the table report's footer, so "which version am I on" meant running a full report. A `--version` flag was added alongside it.
459
508
  - **A new release asks at session start** โ€” a statusline cannot open a dialog, so telling and asking are split. The statusline only reports (`โฌ† v3.24.0 โ†’ 3.25.0`); the SessionStart hook injects a line telling the model to ask the user whether to upgrade. On yes it runs `claude-token-saver upgrade`, which uses the package manager that installed this copy; on no, `update-check --dismiss` mutes that version until a newer one ships.
package/README.md CHANGED
@@ -62,6 +62,7 @@ $ claude-token-saver route-scan savings # ๋ชจ๋“  ๊ธˆ์•ก์„ ๋ฃฐ ๋‹จ์œ„๊นŒ์ง€
62
62
  | ๐Ÿšจ **ํ•œ๋„ ์ดˆ๊ณผ ์˜ˆ๋ฐฉ** | 5์‹œ๊ฐ„ยท7์ผ rate-limit ์œˆ๋„๊ฐ€ 90%์— ๋‹ฟ์œผ๋ฉด ๊ฒฝ๊ณ ํ•˜๊ณ , `handoff`๋กœ ์ž‘์—…์„ ๋ฐฑ์—…ํ•ฉ๋‹ˆ๋‹ค |
63
63
  | ๐Ÿง  **์บ์‹œ ๋‚ญ๋น„ ๊ฐ์ง€** | ํžˆํŠธ์œจยทTTLยท1M ์ปจํ…์ŠคํŠธ๋ฅผ ๊ฐ์ง€ํ•ด ํ† ํฐ ๊ธ‰์ฆ ์›์ธ์„ ์ฝ”๋“œ๋กœ ์ง„๋‹จํ•ฉ๋‹ˆ๋‹ค |
64
64
  | ๐Ÿ‡ฐ๐Ÿ‡ท **ํ•œ๊ตญ์–ด ๋ฌธ์ฒด ๊ต์ •** | ํ•œ๊ตญ์–ด ํ™˜๊ฒฝ์ด๋ฉด ์ž๋™์œผ๋กœ ์ผœ์ง‘๋‹ˆ๋‹ค ([์•„๋ž˜](#-ํ•œ๊ตญ์–ด-๋ฌธ์ฒด-์ง€์นจ)) |
65
+ | ๐Ÿ“„ **๋ฌธ์„œ ์ž๋™ ๋ณ€ํ™˜** | pptxยทxlsxยทpdfยทdocx ๋ฅผ ์ฝ๊ธฐ ์ „์— Markdown ์œผ๋กœ ๋ฐ”๊ฟ” ์ฝ์ง€ ๋ชปํ•˜๋Š” ๋ฐ”์ดํŠธ๊ฐ€ ์ปจํ…์ŠคํŠธ์— ์˜ฌ๋ผ๊ฐ€์ง€ ์•Š๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค ([์•„๋ž˜](#-doc2md-์ฒจ๋ถ€-๋ฌธ์„œ๋ฅผ-์ฝ๊ธฐ-์ „์—-markdown-์œผ๋กœ-๋ฐ”๊ฟ‰๋‹ˆ๋‹ค)) |
65
66
 
66
67
  ## ๋ผ์šฐํ„ฐ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค: 60์ดˆ ์„ค๋ช…
67
68
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-token-saver",
3
- "version": "3.26.0",
3
+ "version": "3.26.1",
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": {