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.
- package/README.md +20 -49
- package/dist/{token-goat-chunk-Q4LOQY44.mjs → token-goat-chunk-2VVXTAGD.mjs} +137 -12
- package/dist/{token-goat-chunk-LEBYARO3.mjs → token-goat-chunk-3UBORD6Z.mjs} +9 -6
- package/dist/{token-goat-chunk-LJ3CHCTT.mjs → token-goat-chunk-3XVGPLDS.mjs} +3492 -46
- package/dist/{token-goat-chunk-KKIB7O3Z.mjs → token-goat-chunk-6FQMEMWX.mjs} +418 -105
- package/dist/{token-goat-chunk-FXAPKVRG.mjs → token-goat-chunk-7A7SBE6R.mjs} +26 -5
- package/dist/token-goat-chunk-A37V4PBF.mjs +56 -0
- package/dist/{token-goat-chunk-VCNW7BGU.mjs → token-goat-chunk-A4VBNWSL.mjs} +20 -3
- package/dist/{token-goat-chunk-G6XLWJWI.mjs → token-goat-chunk-E3K3BTEQ.mjs} +5 -2
- package/dist/{token-goat-chunk-AO2QD2AG.mjs → token-goat-chunk-EEIDFMEM.mjs} +4 -0
- package/dist/{token-goat-chunk-324QOJYZ.mjs → token-goat-chunk-EVC4TOLE.mjs} +4 -1
- package/dist/{token-goat-chunk-WN5T5EW5.mjs → token-goat-chunk-FQD3OB5W.mjs} +98 -2
- package/dist/token-goat-chunk-HC5NMGPD.mjs +23 -0
- package/dist/{token-goat-chunk-UZ2NFOOZ.mjs → token-goat-chunk-KKHKXUVS.mjs} +154 -8
- package/dist/{token-goat-chunk-NY4HYRSK.mjs → token-goat-chunk-LLNA42NI.mjs} +10 -12
- package/dist/{token-goat-chunk-5CVKO3DA.mjs → token-goat-chunk-LYWIRYCF.mjs} +5 -2
- package/dist/{token-goat-chunk-CGWACYYZ.mjs → token-goat-chunk-OKJX2JWW.mjs} +6 -1
- package/dist/{token-goat-chunk-R4SR7MQY.mjs → token-goat-chunk-PXWBHSFB.mjs} +2 -2
- package/dist/{token-goat-chunk-JMUBXBG7.mjs → token-goat-chunk-XSSQFI4C.mjs} +7 -7
- package/dist/token-goat-hook.mjs +12 -7
- package/dist/token-goat.core.mjs +10 -7
- package/docs/cli.md +53 -0
- package/docs/security.md +6 -2
- package/package.json +8 -2
- package/dist/token-goat-chunk-AEX54RUZ.mjs +0 -11
- 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 |
|
|
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 |
|
|
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
|
|
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
|
|
212
|
-
# With token-goat:
|
|
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-
|
|
215
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|