token-goat 2.9.2 → 2.9.3

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.
Files changed (26) hide show
  1. package/README.md +20 -49
  2. package/dist/{token-goat-chunk-Q4LOQY44.mjs → token-goat-chunk-2VVXTAGD.mjs} +137 -12
  3. package/dist/{token-goat-chunk-LEBYARO3.mjs → token-goat-chunk-3UBORD6Z.mjs} +9 -6
  4. package/dist/{token-goat-chunk-LJ3CHCTT.mjs → token-goat-chunk-3XVGPLDS.mjs} +3492 -46
  5. package/dist/{token-goat-chunk-KKIB7O3Z.mjs → token-goat-chunk-6FQMEMWX.mjs} +418 -105
  6. package/dist/{token-goat-chunk-FXAPKVRG.mjs → token-goat-chunk-7A7SBE6R.mjs} +26 -5
  7. package/dist/token-goat-chunk-A37V4PBF.mjs +56 -0
  8. package/dist/{token-goat-chunk-VCNW7BGU.mjs → token-goat-chunk-A4VBNWSL.mjs} +20 -3
  9. package/dist/{token-goat-chunk-G6XLWJWI.mjs → token-goat-chunk-E3K3BTEQ.mjs} +5 -2
  10. package/dist/{token-goat-chunk-AO2QD2AG.mjs → token-goat-chunk-EEIDFMEM.mjs} +4 -0
  11. package/dist/{token-goat-chunk-324QOJYZ.mjs → token-goat-chunk-EVC4TOLE.mjs} +4 -1
  12. package/dist/{token-goat-chunk-WN5T5EW5.mjs → token-goat-chunk-FQD3OB5W.mjs} +98 -2
  13. package/dist/token-goat-chunk-HC5NMGPD.mjs +23 -0
  14. package/dist/{token-goat-chunk-UZ2NFOOZ.mjs → token-goat-chunk-KKHKXUVS.mjs} +154 -8
  15. package/dist/{token-goat-chunk-NY4HYRSK.mjs → token-goat-chunk-LLNA42NI.mjs} +10 -12
  16. package/dist/{token-goat-chunk-5CVKO3DA.mjs → token-goat-chunk-LYWIRYCF.mjs} +5 -2
  17. package/dist/{token-goat-chunk-CGWACYYZ.mjs → token-goat-chunk-OKJX2JWW.mjs} +6 -1
  18. package/dist/{token-goat-chunk-R4SR7MQY.mjs → token-goat-chunk-PXWBHSFB.mjs} +2 -2
  19. package/dist/{token-goat-chunk-JMUBXBG7.mjs → token-goat-chunk-XSSQFI4C.mjs} +7 -7
  20. package/dist/token-goat-hook.mjs +12 -7
  21. package/dist/token-goat.core.mjs +10 -7
  22. package/docs/cli.md +53 -0
  23. package/docs/security.md +6 -2
  24. package/package.json +8 -2
  25. package/dist/token-goat-chunk-AEX54RUZ.mjs +0 -11
  26. package/dist/token-goat-chunk-ZVN5WHTO.mjs +0 -23
package/README.md CHANGED
@@ -150,7 +150,7 @@ The fastest way to reduce AI token costs is fixing these five, not writing short
150
150
  | Manifest git-history section loses signal on clean main | Inline git diffs + skip git log when on clean main branch; session-awareness improves manifest hygiene |
151
151
  | Skill body lost after compaction but recovery too verbose | Recovery hint deduped skills by content_sha (same skill loaded twice = one entry); inline skill checklist |
152
152
  | Recovery hints omit critical paths when space is tight | Skip bash snippet when recall available |
153
- | AVIF format not supported despite better compression | AVIF image-shrink via sharp (when libvips is built with libaom); WebP fallback; codec auto-detection in docker |
153
+ | AVIF format not supported despite better compression | Still open. The image engine is pure TypeScript and decodes PNG, JPEG, GIF, and BMP; AVIF would need a decoder written, and an AVIF file is passed through untouched today |
154
154
  | Token-savings invisible until you run `stats` | Token-savings benchmark (slow-marked test suite) locks in measured wins; `token-goat stats` reports net-positive impact |
155
155
  | Hook crash leaves agent waiting for response | Every way the shim can fail prints `{}` and exits 0, leaving the tool call to proceed untouched: an event name it does not know, stdin it cannot read or parse, an in-process load that throws, a token-goat child that exits non-zero or prints nothing, and a catch around the whole run |
156
156
  | Concurrent edits lose update counts mid-session | Session CAS + mtime-based retry prevent lost edits in manifest |
@@ -188,13 +188,13 @@ Numbers below come from synthetic-fixture benchmarks in the test suite. Each row
188
188
 
189
189
  | Source | Improvement | Measured impact | Where |
190
190
  |--------|-------------|-----------------|-------|
191
- | Image shrink | WebP encoder beats JPEG on screenshot-shaped images | ~39% smaller than the same image at JPEG quality 85 | `src/image_shrink.ts` (codec selection) |
191
+ | Image shrink | Every still is encoded both ways and the smaller file wins, rather than one codec being assumed | 2560x1440 screenshot-shaped PNG: 2,782,963 -> 259,475 bytes (91% smaller) | `src/image_shrink.ts` (codec selection) |
192
192
  | Repomap output | `--compact` trims the top-symbols list to 10 (vs 30) and drops the recent-files section and per-symbol locations | Denser overview for the same byte budget | `src/baseline.ts` (`buildProjectMap`, `token-goat map --compact`) |
193
193
  | DB reindex | Batched single transaction + composite indexes on `(file_id, kind)` | 100 files / 10K rows: 84 s → 1 s (~80× faster) | `src/parser.ts`, `src/db.ts` (index migration) |
194
194
  | Hook cold-start | Lazy import of heavy modules; unknown events short-circuit | 86 ms → 30 ms (~65% faster); unknown-event dispatch <1 ms | `src/hooks_cli.ts` |
195
195
  | Symbol start_line | TypeScript decorators captured in symbol span | One `token-goat read` returns the decorator + signature + body; no re-read | `src/parser.ts` (TypeScript adapter) |
196
196
  | Section extraction | Setext headings, h5/h6, anchor IDs, and `__frontmatter__` | `token-goat section` resolves more headings without falling back to a full file read | `src/parser.ts` (Markdown adapter) |
197
- | Image cache | Repeat Read of an unchanged image serves the stored re-encode, keyed on path + size + mtime, instead of running `sharp` again | Skips the re-encode entirely on a hit; the same bytes reach the model, so the reported saving is identical either way | `src/image_shrink.ts` (`findCachedShrink`) |
197
+ | Image cache | Repeat Read of an unchanged image serves the stored re-encode, keyed on path + size + mtime, instead of re-encoding it again | Skips the re-encode entirely on a hit; the same bytes reach the model, so the reported saving is identical either way | `src/image_shrink.ts` (`findCachedShrink`) |
198
198
  | Monorepo defaults | Reindex batch 500 → 2000; compact `min_events` 5 → 3 | Fewer worker wakeups; compact manifests fire on shorter sessions | `src/config.ts` defaults |
199
199
  | Miss suggestions | `read` / `section` print "Did you mean…?" on a miss; `section` also auto-redirects on an unambiguous heading-prefix match | Keeps agents on the surgical-read path instead of falling back to full-file `Read` | `src/read_commands.ts` |
200
200
 
@@ -208,14 +208,17 @@ Concrete before/after for the four interception points. Token counts use the ~4-
208
208
  $ ls -lh screenshot.png
209
209
  -rw-r--r-- 1 user user 1.2M screenshot.png
210
210
 
211
- # Without token-goat: Claude reads the 1.2 MB PNG.
212
- # With token-goat: hook re-encodes as WebP and substitutes the cached copy.
211
+ # Without token-goat: Claude reads the whole PNG.
212
+ # With token-goat: the pre-read hook substitutes a downscaled re-encode.
213
213
 
214
- $ token-goat image-shrink screenshot.png
215
- out: ~74 KB WebP (94% smaller)
214
+ $ token-goat image-meta screenshot.png
215
+ Dimensions: 2560x1440
216
+ Format: png
217
+ Size: 2782963 bytes
218
+ Shrink: would save 2523488 bytes (2782963 -> 259475)
216
219
  ```
217
220
 
218
- The same image at JPEG quality 85 lands around 120 KB. WebP wins by another ~39% on screenshot-shaped content (large flat regions, sharp text edges).
221
+ `image-meta` reports what the hook would do without doing it. The 91% here is one measurement on one screenshot-shaped image; run it on your own to get yours.
219
222
 
220
223
  ### 2. Surgical read — one function, not the whole file
221
224
 
@@ -297,7 +300,7 @@ For recurring scheduler loops, the 25th, 100th, and 250th observed delivery in a
297
300
  ```
298
301
  npm install -g token-goat
299
302
  token-goat install
300
- token-goat doctor # confirms hooks and sharp are working; look for "sharp: ok"
303
+ token-goat doctor # confirms hooks are wired; reports any failure it finds
301
304
  ```
302
305
 
303
306
  Three commands. Hooks register and start working immediately: no terminal popups, no tray icon, no service to babysit. That wires up Claude Code; other agent CLIs are added with a flag (`--codex`, `--copilot`, and siblings).
@@ -308,6 +311,11 @@ Per-harness setup for Codex, Gemini, Qwen, Kimi, opencode, OpenClaw, pi, Copilot
308
311
 
309
312
  You rarely type these yourself. Installation writes a routing guide into the agent's instructions, and the agent picks the command that answers its question: a surgical read (`read`, `symbol`, `section`, `skeleton`), a search (`semantic`, `refs`), orientation in an unfamiliar repo (`map`, `arch`, `affected`), recall of output it already has (`bash-output`, `web-output`, `mcp-output`), or a bounded reader for a PDF, Word file, slide deck, workbook, SQLite database or image.
310
313
 
314
+ One command is for people working on token-goat rather than for agents: `token-goat bench` replays a
315
+ corpus of captured shell output through the real compression path and reports how much smaller the
316
+ result got, alongside a count of the lines each case is not allowed to lose. Deleting output makes
317
+ the first number look better, so the second one is what keeps the first honest.
318
+
311
319
  Every command, with its flags, its output, and the comparison workflows that chain them: **[CLI reference](docs/cli.md)**.
312
320
 
313
321
  ## MCP server
@@ -451,52 +459,15 @@ A working install returns `["PreToolUse", "PostToolUse", "PreCompact"]`. Any mis
451
459
 
452
460
  Vision models bill by pixel dimensions, not file size. Anthropic charges one token per 28×28-pixel patch of a Claude image (`⌈width/28⌉ × ⌈height/28⌉` visual tokens, per the [Claude vision docs](https://platform.claude.com/docs/en/build-with-claude/vision#evaluate-image-size)), OpenAI's GPT-5.6 models tile in 32×32-pixel patches with a 1.2x multiplier on top, and Gemini charges a flat 258 tokens under 384×384 pixels and roughly 258 tokens per 768×768 tile above that. A heavily compressed screenshot can still decode to a large pixel count, so a small file on disk is no guarantee of a cheap read.
453
461
 
454
- Token-goat shrinks an image before it reaches the model whenever either of two independent checks trips: the file is at or above 512 KB, or its longest edge exceeds 1568 pixels (`src/image_shrink.ts`). The byte check is a cheap pre-filter that skips decoding most images outright. The dimension check exists because the byte check alone misses a case: a flat-color screenshot can compress to a few hundred kilobytes on disk and still decode to a resolution well past 1568 pixels on its long edge, and vision models bill on that decoded resolution, not the compressed file. Either trigger routes the image through the same pipeline: downscale to a 1568px long edge and re-encode as WebP. The pipeline uses [`sharp`](https://sharp.pixelplumbing.com/), a Node.js image processing library that ships prebuilt native binaries for Windows, macOS, Linux, and Alpine.
462
+ Token-goat shrinks an image before it reaches the model whenever either of two independent checks trips: the file is at or above 512 KB, or its longest edge exceeds 1568 pixels (`src/image_shrink.ts`). The byte check is a cheap pre-filter that skips decoding most images outright. The dimension check exists because the byte check alone misses a case: a flat-color screenshot can compress to a few hundred kilobytes on disk and still decode to a resolution well past 1568 pixels on its long edge, and vision models bill on that decoded resolution, not the compressed file. Either trigger routes the image through the same pipeline: downscale to a 1568px long edge and re-encode. A still is encoded as both JPEG and PNG and the smaller one is kept; an animated GIF stays a GIF, resized frame by frame. If the result is not smaller than the file it came from, token-goat passes the original through unchanged rather than substituting a worse copy.
455
463
 
456
464
  How much this saves depends on the model, because Claude downscales an oversized image itself before billing and caps the cost rather than charging for every pixel it was sent. By the [published per-tier table](https://platform.claude.com/docs/en/build-with-claude/vision#evaluate-image-size), a 3840x2160 screenshot bills at 4784 visual tokens on Claude 4.7 and later, and 1560 on earlier models. Resizing it to a 1568px long edge first costs 1792 tokens: a 63% cut against the newer models, and nothing against the older ones, whose own cap is already tighter than what this pipeline produces. Other vendors cap differently, so treat 63% as the measured Claude figure rather than a universal rate.
457
465
 
458
466
  Two cases are not about cost at all. Screenshots returned to the computer-use and browser-use toolsets are rejected outright when they exceed the model's limits, rather than downscaled, so resizing before the call is what lets it succeed. A request carrying more than 20 images also applies a stricter per-image dimension limit to every image in it, which a 1568px long edge already satisfies.
459
467
 
460
- On most platforms, `npm install -g token-goat` installs sharp without additional steps. npm pulls a prebuilt binary keyed to your Node.js major version and OS — no C++ compiler, libvips, or system codec libraries required.
461
-
462
- Quick check (any platform):
463
-
464
- ```
465
- token-goat doctor
466
- ```
467
-
468
- If the `sharp` line shows `OK`, you're done.
469
-
470
- ### Image support — troubleshooting
471
-
472
- If `token-goat doctor` reports `sharp: FAIL`, the most common cause is a cached binary built against a different Node.js version. A fresh install usually fixes it:
473
-
474
- ```bash
475
- npm install -g token-goat@latest
476
- token-goat doctor
477
- ```
478
-
479
- On Alpine Linux, some ARM boards, and air-gapped environments, npm can't fetch a prebuilt binary and falls back to compiling from source. That requires `libvips` and C++ build tools:
480
-
481
- ```bash
482
- # Debian / Ubuntu / WSL
483
- sudo apt-get install -y libvips-dev build-essential
484
-
485
- # Alpine
486
- apk add --no-cache vips-dev build-base python3
487
-
488
- # Fedora / RHEL
489
- sudo dnf install -y vips-devel gcc-c++ make
490
- ```
491
-
492
- After installing the system packages:
493
-
494
- ```bash
495
- npm install -g token-goat@latest
496
- token-goat doctor
497
- ```
468
+ The pipeline is written in TypeScript and decodes PNG, JPEG, GIF, and BMP itself, so there is nothing to install and nothing to build: no native binary, no C++ compiler, no libvips, no system codec libraries, and no platform where it is unavailable. `token-goat doctor` has no image line to check because there is no image dependency that can fail.
498
469
 
499
- For platform-specific build details, see the [sharp installation docs](https://sharp.pixelplumbing.com/install).
470
+ The one thing the decoders will do is decline. A file whose header asks for more than 256 MB of pixel buffer, or that is in a variant token-goat cannot read exactly, is refused rather than guessed at, and the untouched original goes to the model. An untouched original is the right picture, so the only cost of a refusal is that the read is not shrunk.
500
471
 
501
472
  ## Stats display
502
473