token-goat 2.6.15 → 2.6.17

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
@@ -19,7 +19,7 @@ permalink: /
19
19
 
20
20
  Token-Goat sits silently between your AI and your tools. Re-read a file? It gets a one-line hint and a narrow-slice suggestion instead of the full file again. Grab a screenshot? A 100 KB copy reaches the model instead of 10 MB. Run `pytest`, `npm install`, `docker build`, or `cargo`? The thousands of progress bars and passing-test names are stripped to the failures before the output even reaches the context window. Open a PDF, a large Markdown doc, or a CSV? The hook intercepts it — heading tree, page count, or column preview — so the model never pays for the full file. Run `gh run watch` or `next dev` a second time? Prior output is recalled rather than re-run. Compact a long session? It gets a clean structured manifest of edited files and key symbols so nothing important is forgotten. Sessions drop 40–90%+ in cost. You change nothing about how you work.
21
21
 
22
- Works with **Claude Code**, **Gemini CLI**, **Codex CLI**, **Aider**, **Cursor**, **Cline**, **Windsurf**, **Copilot CLI**, and OpenCode, plus **pi** ([pi-coding-agent](https://github.com/earendil-works/pi-mono)).
22
+ Works with **Claude Code**, **Gemini CLI**, **Qwen Code**, **Codex CLI**, **Aider**, **Cursor**, **Cline**, **Windsurf**, **Copilot CLI**, **Grok CLI** (xAI Grok Build), and OpenCode, plus **pi** ([pi-coding-agent](https://github.com/earendil-works/pi-mono)).
23
23
 
24
24
  **Ask your AI to install it fully (give it this GitHub link), or install in one command:**
25
25
 
@@ -103,11 +103,16 @@ The fastest way to reduce AI token costs is fixing these five, not writing short
103
103
  | Large CSV or TSV file (≥10 KB) read in full | Column headers, row count, and 3 sample rows shown; `token-goat csv-query` projects columns and/or filters rows instead of a full read; `duckdb` query suggestion for very large tabular data |
104
104
  | WebFetch returns a page's full raw HTML | HTML-to-text extraction strips markup/scripts/styles before the model ever sees it — readable prose instead of a wall of tags |
105
105
  | Large WebVTT/SRT transcript (≥10 KB) read in full | Duration, cue count, and detected speakers shown; `token-goat transcript-outline` gives a skimmable speaker/time overview and `token-goat transcript` slices by speaker/time range/pattern instead of a full read |
106
-
107
106
  | Large TXT or log file (≥20 KB) read in full | Line count + first/last 5 lines shown; `.log`/`.out` files bias toward `--tail 100 --grep`; general catch-all for any file ≥100 KB |
108
107
  | Subagent reads a 47–86 KB recon dump (or greps a 73 KB transcript) and overflows its window | `pre_read` denies a full Read at or above `large_read_redirect_bytes` (512 KB base, tightened by context pressure to as low as ~92 KB once the session is nearly full — the case that matters most for an already-strained subagent), and a `content`-mode Grep over one oversized file, redirecting both to surgical reads or a windowed `offset`/`limit` |
109
108
  | Subagent overflows at "hello" with no idea why | `token-goat baseline` (`--subagent` for the terser variant a fresh subagent gets) prints a project map — file count, languages, top symbols, recent files — as quick orientation instead of an `ls -R`/full-repo read |
110
109
  | MCP screenshot call lands 10 MB image in context because no file path was passed | `pre_screenshot` denies chrome-devtools and playwright screenshot calls without a `filePath`/`file_path` argument; redirects the model to re-issue with one, so the saved file flows through image-shrink (~39K tokens raw → ~8K compressed) |
110
+ | `claude-in-chrome`'s `computer`/`browser_batch` return a raw, full-resolution base64 screenshot in-band, with no destination-file option to redirect through image-shrink | Inline screenshot blocks are shrunk via the same image-shrink pipeline in place, and a repeated `Tab Context:` listing (appended to nearly every call, often unchanged) collapses to a placeholder once seen unchanged this session |
111
+ | Agent tool spawns a subagent with no orientation and no reuse hints | A `PreToolUse` handler appends a compact briefing pack to the prompt: a one-line project-map summary, 2-3 recent cached-output IDs, and a surgical-read reminder (~300 tokens) |
112
+ | Subagent's own final report runs long and gets discarded once the parent moves on | Agent tool results ≥8000 characters get a recall pointer appended (`token-goat recall`); the original report always reaches the parent untouched |
113
+ | Large MCP tool result (≥2 KB) is a homogeneous array of objects, e.g. a list/search result | Deterministic structural compression: table-ified into one header row + tab-delimited rows, with columns constant across every row hoisted into a single `constant:` line instead of repeated per row; only applied when it saves ≥15%. Full original always recoverable via `token-goat bash-output <id>` (labeled `[token-goat: compressed, full via mcp-output <id>]`). Disable with `TOKEN_GOAT_MCP_COMPRESS=0` |
114
+ | GitHub MCP tool result (`list_pull_requests`, `list_issues`, `search_code`, `get_file_contents`, `pull_request_read`, …) carries dozens of boilerplate fields per object | GitHub compression pack strips `_links`, `node_id`, `gravatar_id`, `site_admin`, and every `*_url` field (`avatar_url`, `html_url`, `events_url`, `gists_url`, `followers_url`, …) except `download_url`/`git_url`/`clone_url`/`ssh_url`, before handing the shrunk JSON to the same table-ifying pass — same `TOKEN_GOAT_MCP_COMPRESS=0` opt-out and full-recovery-by-id guarantee |
115
+ | Browser-automation MCP tool result (claude-in-chrome's `read_console_messages`/`read_network_requests`, chrome-devtools-mcp's `list_console_messages`/`list_network_requests`) carries verbose CDP plumbing per entry | Browser compression pack strips console `stackTrace` frames and network `requestHeaders`/`responseHeaders`/`timing`/`initiator`/`securityDetails`/cookie fields, keeping `url`/`method`/`status`/`resourceType`/`mimeType`/`reqid` and the actual log text, before the same table-ifying pass runs — same opt-out and full-recovery-by-id guarantee |
111
116
  | `curl -v` dumps TLS handshake + all request/response headers | Verbose lines stripped; request line, HTTP status, content-type, and body kept — typically 70–90% smaller |
112
117
  | `jest --verbose` / `vitest --verbose` emits one `✓` line per passing test | Consecutive passing-test lines collapsed to a count per file; failures kept verbatim, ~95% smaller on passing suites |
113
118
  | `go test -v` emits `--- PASS: TestName (Ns)` for every passing test | PASS lines collapsed to a count per package; FAIL lines and panic output kept, ~90% smaller on clean runs |
@@ -287,6 +292,14 @@ token-goat install --gemini
287
292
 
288
293
  This writes hook entries into `~/.gemini/settings.json` using Gemini CLI's `BeforeTool` / `AfterTool` / `PreCompress` event names. Token-goat translates between Gemini's snake_case tool names (`run_shell_command`, `read_file`, `grep_search`, etc.) and its internal format automatically. Image shrinking, session hints, post-edit indexing, compact assist, and bash output compression all work. To remove: `token-goat uninstall --gemini`.
289
294
 
295
+ ### Qwen Code users
296
+
297
+ ```
298
+ token-goat install --qwen
299
+ ```
300
+
301
+ This writes hook entries into `~/.qwen/settings.json`. Unlike Gemini CLI (its own ancestor, with a custom `BeforeTool`/`AfterTool`/`PreCompress` event/matcher scheme), Qwen Code's hooks system diverged and now mirrors Claude Code's own natively — `PreToolUse`/`PostToolUse`/`PreCompact`/`UserPromptSubmit`/`SubagentStop` event names and snake_case stdin JSON — so token-goat wires all five events with no wire-format translation needed. Qwen Code's own tool-name taxonomy is only partially documented, so token-goat uses a catch-all matcher per event rather than an incomplete per-tool list. Image shrinking, session hints, post-edit indexing, compact assist, and bash output compression all work. This bridge was built from QwenLM/qwen-code's published docs, not dogfooded against a live Qwen Code install — if hooks aren't firing, `token-goat doctor` and the settings.json contents are the first things to check. To remove: `token-goat uninstall --qwen`.
302
+
290
303
  ### opencode users
291
304
 
292
305
  ```
@@ -339,6 +352,18 @@ No ambient environment variable documents "this process is running under Copilot
339
352
 
340
353
  **If Copilot CLI starts denying every tool call with `Denied by preToolUse hook ... (hook errored)`:** this is Copilot's own fail-closed behavior for a `preToolUse` hook that crashes, exits non-zero, or returns unparseable output -- it isn't limited to token-goat's own tool calls, since a fail-closed `preToolUse` hook blocks the whole session. Copilot caches hook configs at session start, so **renaming or reinstalling the hook mid-session has no effect** -- the only recovery is: run `token-goat install --copilot` (or `token-goat doctor`, which now checks the installed hook end-to-end and calls out a stale node-binary path from an nvm/fnm/volta upgrade specifically), then **fully restart Copilot CLI**.
341
354
 
355
+ ### Grok CLI (xAI Grok Build) users
356
+
357
+ Grok Build already reads Claude Code's `~/.claude/settings.json` as a "Harness Compatibility" source out of the box (confirmed against grok 0.2.93 and its own [hooks doc](https://github.com/xai-org/grok-build/blob/main/crates/codegen/xai-grok-pager/docs/user-guide/10-hooks.md)), so `token-goat install` alone already gets most of the integration working — image shrinking, session hints, post-edit indexing, and bash output compression all fire. The one gap: Grok's own `PreToolUse` hook contract documents only `{"decision":"allow"}` / `{"decision":"deny","reason":"..."}`, never token-goat's harness-independent `{"decision":"block","reason":"..."}` shape (unlike Gemini CLI, whose docs explicitly confirm `"block"` as an accepted alias for `"deny"`), so re-read denial and oversized-first-read redirects don't reliably block on the Claude Code compat path alone.
358
+
359
+ ```
360
+ token-goat install --grok
361
+ ```
362
+
363
+ The `--grok` flag patches Claude Code and additionally writes a standalone hook config at `~/.grok/hooks/token-goat.json` (global scope only — Grok's own project-scoped `<project>/.grok/hooks/*.json` requires a separate manual `/hooks-trust` grant this bridge can't perform for you) plus the shim it points at, `~/.grok/hooks/token-goat-shim.js`. The shim's only job is translating that one response shape: a token-goat `{"decision":"block",...}` deny becomes Grok's documented `{"decision":"deny",...}` (with exit code 2, matching Grok's own "explicit deny" convention), and every other event's response is forwarded through unmodified — Grok already sends the raw camelCase wire payload (`toolName`/`toolInput`/`sessionId`) token-goat's built-in `grok` harness detection (`GROK_SESSION_ID`, set on every hook subprocess Grok spawns) already normalizes correctly.
364
+
365
+ To remove: `token-goat uninstall --grok`.
366
+
342
367
  ### Cline, Windsurf, Cursor, and other AI tool CLIs
343
368
 
344
369
  No separate install step needed. Token-goat compresses the terminal output of these tools automatically as soon as they appear on your PATH. Run `token-goat doctor` to confirm they are detected — the "Third-party AI tools" section will show `detected — bash output compression active`.
@@ -376,14 +401,17 @@ To upgrade cleanly:
376
401
  | `token-goat symbol <name>` | Jump to a symbol definition. |
377
402
  | `token-goat read "file::symbol"` | Pull one function or class, not the whole file. Supports qualified lookups (`read "file.py::Class.method"`) and line ranges: `read "file.py@10-40"` for lines 10 to 40 inclusive, or `read "file.py@42"` for one line. Line ranges read straight from disk, so they work on any file, including paths outside an indexed project. `--force-refresh` reparses the file from disk and updates the index before querying — for files touched by git operations, external tools, or direct filesystem writes that bypass the normal post-edit indexing hook. |
378
403
  | `token-goat replace <file>` | Replace one string in a file using `--old-from`/`--new-from` or `--old-b64`/`--new-b64`; `--all` replaces every match. |
404
+ | `token-goat write-file <dest>` | Write exact bytes to a file, sidestepping shell-escaping trouble with backticks, quotes, `$vars`, and CRLF. `--from <source>` copies bytes from a source file; `--b64 <payload>` decodes a base64 payload; with neither, reads from stdin. |
379
405
  | `token-goat section "doc.md::Heading"` | Pull one Markdown section by heading. A miss that is an unambiguous prefix of exactly one heading auto-redirects with a `(redirected from: …)` marker (and a `redirectedFrom` field under `--json`). Disambiguate duplicates with `"doc.md::Heading#2"`. |
380
406
  | `token-goat skill-section "<name>::<heading>"` | Extract a named section from an installed skill without reading the full skill file. |
381
407
  | `token-goat skeleton "file"` | Show all signatures in a file without bodies — typically 70–90% fewer tokens than a full read. `--force-refresh` reparses from disk first, bypassing a stale index. `--stats` adds a per-symbol reference count and doc-coverage flag, computed live from the index. |
382
408
  | `token-goat outline "file"` | List top-level symbols with line ranges and docstring hints — one-glance file map. `--force-refresh` reparses from disk first, bypassing a stale index. `--stats` adds a per-symbol reference count and doc-coverage flag, computed live from the index. |
409
+ | `token-goat yaml-outline <file>` | Structural summary of a YAML document (array shape / object key types) instead of a raw Read. Multi-document streams (`---`-separated) outline as an array of documents. |
410
+ | `token-goat yaml-query <file> <path>` | Extract one value or a projected/filtered subset from a YAML document by dot-path instead of a raw Read (same grammar as `json-query`: `[n]` index, `[*]` wildcard, `[field=value]` filter — e.g. `items[status=active].name`). `--head <n>` caps a projected/filtered result. |
383
411
  | `token-goat brief "file::symbol"` | Bundle a symbol's body, resolved callers (grouped by enclosing function), and its containing doc section into one round-trip instead of three separate `read`/`callers`/`section` calls. `--limit <n>` caps the callers shown (default 20; the true caller count is reported even when truncated). |
384
412
  | `token-goat scope "file:line"` | Show symbols in scope at a given line — avoids reading the whole file to understand locals. |
385
413
  | `token-goat exports "file"` | List public (exported) symbols with types and docstring hints. |
386
- | `token-goat refs "<name>"` | Show all files and line numbers where a symbol is referenced. Pass a comma-separated spec (`a,b,c` or `file::a,b`) to merge several symbols' references into one call, each group headed by its symbol name. |
414
+ | `token-goat refs "<name>"` | Show all files and line numbers where a symbol is referenced. Pass a comma-separated spec (`a,b,c` or `file::a,b`) to merge several symbols' references into one call, each group headed by its symbol name. `--top <n>` groups references by file (count only) and shows just the top N by reference count with an elision note, instead of a per-line dump — for high-fanout symbols referenced in hundreds of places. |
387
415
  | `token-goat callers <symbol>` | Show which functions call a given symbol, grouped by caller with file, caller name, and every invoking line. Complements `refs`, which shows raw reference sites without grouping by enclosing function. |
388
416
  | `token-goat call-chain <symbol>` | Trace every caller layer from a symbol back to the entry points — one step deeper than `callers`. Use when you need to know what reaches a function across the whole call graph, not only who invokes it directly. Pairs with `impact` for the downstream direction. |
389
417
  | `token-goat impact <symbol>` | Walk the call-reference graph forward (breadth-first) and list every function that depends on a symbol, with hop depth; module-scope callers are surfaced as `(module scope) <file>` entries. Run before a refactor to size up the blast radius without starting a build. |
@@ -391,6 +419,7 @@ To upgrade cleanly:
391
419
  | `token-goat ask "<question>"` *(experimental)* | Retrieves relevant slices via full-text (BM25) search over the symbol index — not semantic/embedding search — and lists them as pointer-citations plus `token-goat read` commands. Set `TOKEN_GOAT_ASK_BACKEND=claude` or `TOKEN_GOAT_ASK_BACKEND=codex` to synthesize a short answer via that CLI (whatever model it defaults to; token-goat does not force Haiku or any particular tier); with the env var unset, or the named CLI missing from PATH, `ask` degrades to printing the retrieved pointers with no network call. `--top N` caps the number of FTS hits (default 8); `--json` for structured output. Answers are not cached — each call re-retrieves and re-synthesizes from scratch. |
392
420
  | `token-goat changed [<ref>]` | List symbols that changed since a git ref, without reading the full diff. |
393
421
  | `token-goat blame "file::symbol"` | Git blame narrowed to a specific symbol's lines — no whole-file blame needed. |
422
+ | `token-goat log "file::symbol" [ref]` | Git commit history scoped to one symbol's line range via git's own `-L` line-range history, instead of a raw `git log -- file` dump of every commit that touched the whole file. `--max-count <n>` caps commits shown (default 20); `--json` for structured output. |
394
423
  | `token-goat types ["file"]` | List type definitions (TypedDict, Protocol, dataclass, Pydantic models) in a file or across the project. |
395
424
  | `token-goat imports "file"` | Show the import graph for a file one level deep. |
396
425
  | `token-goat find "<query>"` | Unified search: exact/fuzzy symbol match + semantic, merged and ranked by confidence. |
@@ -400,9 +429,10 @@ To upgrade cleanly:
400
429
  | `token-goat coverage-gaps` | Find callables in non-test source files that never appear in a test file's reference records. Useful for spotting untested surface area before a refactor or release. `--top N` caps output; `--json` for structured output. |
401
430
  | `token-goat recent [N]` | Show the N most recently edited/accessed files with their symbols. |
402
431
  | `token-goat grep "<pattern>" [paths...]` | Built-in fallback regex search over files (no `rg` shell-out, no caching) — session-aware dedup for raw `rg`/`grep` Bash calls is a separate hook, not this command. Accepts zero or more paths: omit to walk cwd, or pass several to search them together with hits merged in argument order under one `--max-lines` cap. `-C, --context <n>` shows `n` lines before and after each match. |
403
- | `token-goat semantic "<query>"` | Find code by meaning, not by filename: embedding-vector similarity search over indexed file chunks, falling back to full-text search (BM25) over symbol names/bodies if no vector index exists yet (e.g. optional embedding deps unavailable, or `indexing.embeddings_enabled` is off). `--limit <n>` caps result count. |
432
+ | `token-goat semantic "<query>"` | Find code by meaning, not by filename: embedding-vector similarity search over indexed file chunks, falling back to full-text search (BM25) over symbol names/bodies if no vector index exists yet (e.g. optional embedding deps unavailable, or `indexing.embeddings_enabled` is off). Covers extracted text from PDF/DOCX/PPTX/XLSX files alongside source code, so a query can surface a spec PDF, design doc, deck, or spreadsheet, not just code. `--limit <n>` caps result count. |
404
433
  | `token-goat map` | Get a compact orientation of the repo. Add `--compact` to fit a fixed 2000-token budget. |
405
434
  | `token-goat arch` | Project-wide import graph summary: hub modules (most imported), entry points (nothing imports them), and circular chains. Complements `token-goat deps <file>` for per-file depth. |
435
+ | `token-goat index [path]` | Parse all git-tracked files and (re)build the symbol index from scratch. Runs automatically on install and incrementally via the background worker after edits — use this to force a full rebuild (e.g. after a `.tokengoatignore` change). `--walk` indexes a bounded directory walk instead when `path` isn't a git repo. |
406
436
  | `token-goat ignores` | List active skip patterns for the current project — built-in skip dirs and suffixes, plus any patterns from `.tokengoatignore`. |
407
437
  | `token-goat gdrive-sections <file-id>` | List the heading outline of a Google Doc without fetching the body. |
408
438
  | `token-goat stats` | See how many tokens you have saved. Shows total events / bytes saved / tokens saved. Add `--full` for the per-source, per-command, and per-day breakdown. |
@@ -410,12 +440,16 @@ To upgrade cleanly:
410
440
  | `token-goat context-stats [--project <path>]` | Report estimated token overhead from `CLAUDE.md` files and `MEMORY.md` in a project. `--json` for structured output; `--fix` prunes dead-link and duplicate entries from `MEMORY.md` and writes the file (destructive — inspect the report first). |
411
441
  | `token-goat memory [--project <path>] [--analyze\|--fix] [--yes]` | Find duplicate/overlapping content across the `CLAUDE.md` files loaded for a project, plus near-duplicate sibling auto-memory files. `--analyze` (default) is report-only. `--fix` removes exact-duplicate lines within a file (the only mechanical, judgment-free fix); duplicate headings and cross-file overlaps are reported as advisory only and never auto-applied. See [Memory analysis and cleanup](#memory-analysis-and-cleanup) below. |
412
442
  | `token-goat waste [--project <path>] [--transcript <path>] [--top <n>] [--json]` | Session spend-ledger: parses the current project's Claude Code session transcript and reports token cost by tool, by file, the top N most expensive individual tool calls, files read once and never referenced again, and Bash commands run repeatedly without hitting token-goat's own bash-output cache. See [Session waste ledger](#session-waste-ledger) below. |
443
+ | `token-goat mcp-audit [--project <path>] [--json]` | MCP server schema cost report: scans .mcp.json for installed MCP servers, estimates per-server token costs from cached tool calls, correlates schema complexity against real call frequency. Outputs as markdown table or JSON. |
444
+ | `token-goat recall "<query>" [--type bash\|web\|mcp] [--limit <n>] [--json]` | Full-text search across every cached bash-output, web-output, and mcp-output entry at once — one command instead of remembering which cache type holds a prior result. Ranked by relevance (BM25 via SQLite FTS5). `--type` narrows to one cache type; `--limit` caps results (default 10). Each hit shows its cache type, id, the exact recall command (`bash-output <id>` / `web-output <id>` / `mcp-output <id>`), and a content snippet. See [Cross-cache recall](#cross-cache-recall) below. |
445
+ | `token-goat hint-stats [--json] [--reset] [--mark-effective <cat>] [--mark-ineffective <cat>]` | Per-category efficacy report for token-goat's discretionary hint hooks: how often each hint category was emitted, how often the agent actually followed its specific suggestion within the next few tool calls, and whether the category is currently auto-suppressed. `--reset` clears all tracked data; `--mark-effective`/`--mark-ineffective <category>` record a manual vote as a supplement to the automatic signal. See [Hint efficacy tracking](#hint-efficacy-tracking) below. |
413
446
  | `token-goat history` | Show current session access history: bash commands and URLs fetched. |
414
447
  | `token-goat bash-output <id>` | Retrieve a cached Bash output by ID instead of re-running the command. Large outputs return a head(30)+tail(80) view by default; pass `--head N`/`--tail N` large enough to cover the full output, or narrow with `--grep PATTERN` (cap `--grep` to the first N hits with `--max-matches N`). Read a file directly with `--file <path>` (e.g. a background task's `tasks/<id>.output`); add `--transcript` to parse that file as a subagent JSONL transcript, keeping only assistant text blocks in order before the slicers apply. |
415
448
  | `token-goat bash-history` | List cached Bash outputs (newest first) with their IDs, byte sizes, and exit codes. |
416
449
  | `token-goat compress --cmd '<command>'` | Preview what the Bash compression hook would do to any command — runs it, applies the matching filter, and prints the compressed view. |
417
450
  | `token-goat web-output <id>` | Retrieve a cached WebFetch response body by ID — same head+tail default and `--head`/`--tail`/`--grep`/`--max-matches` slicers as `bash-output`. |
418
451
  | `token-goat web-history` | List cached WebFetch responses (newest first) with their IDs, byte sizes, status codes, and URL previews. |
452
+ | `token-goat mcp-history` | List cached MCP tool result entries (newest first) with their IDs and byte sizes — same role as `bash-history`/`web-history` for the `mcp-output` cache. |
419
453
  | `token-goat skill-body <name>` | Retrieve a cached Skill body by name without re-invoking the skill (which would replay side effects). Prints the full body; `-c`/`--compact` prints the compact slice instead. No head/tail/grep slicers. |
420
454
  | `token-goat skill-history` | List cached Skill bodies (newest first) with their IDs, byte sizes, truncation status, and skill names. |
421
455
  | `token-goat skill-compact [name]` | Cache the compact slice for a skill so later `skill-body --compact` calls are instant, and print a confirmation. Resolves an installed skill by name (falling back to `~/.claude/skills/<name>/SKILL.md` when it was never loaded this session), or pass `--path <file>` to compact a skill straight from a file without name resolution. |
@@ -426,7 +460,7 @@ To upgrade cleanly:
426
460
  | `token-goat skill-diff "<name>"` | Unified diff between the two most recent cached versions of a skill — tracks skill updates across sessions. |
427
461
  | `token-goat compact-hint --session-id <id>` | Inspect the compaction manifest for a session. Add `--trigger auto` to preview the pressure-aware budget the live PreCompact hook would use. |
428
462
  | `token-goat resume <session_id>` | Emit a single post-compact recovery packet — top skills, last two Bash outputs, top edited-file diffs, and `git diff --stat`, capped at ~2000 tokens. Replaces 5-10 round-trips. |
429
- | `token-goat config list / get / set / validate` | Inspect or edit `config.toml` from the CLI. `validate` reports unknown keys with did-you-mean suggestions. |
463
+ | `token-goat config list / get / set / validate` | Inspect or edit `config.toml` from the CLI. `validate` reports unknown keys with did-you-mean suggestions. A project-root `.token-goat.toml` layers on top of the global config, overriding hint thresholds, indexing settings, etc. for that project only; `config get`/`config set` report which layer a value resolved from. |
430
464
  | `token-goat config-get <file> <key>` | Look up one key from a config-shaped file (TOML/INI `key = value`, or YAML) without reading the whole thing. On a `.md` file, a leading `---`-fenced YAML frontmatter block (Jekyll/Hugo/SKILL.md style) is checked first and takes precedence over the TOML/INI fallback; a `.md` file with no frontmatter, or an unclosed fence, falls through to the normal lookup unchanged. |
431
465
  | `token-goat pdf-extract <file>` | Extract plain text from a PDF instead of a raw Read. `--pages <spec>` narrows to a page range (e.g. `1-5` or `3`); `--head`/`--tail`/`--grep`/`--max-matches`/`--section` slice the extracted text the same way `bash-output`/`web-output` do. `--layout` heuristically reconstructs column-aware reading order from text-item coordinates instead of raw content-stream order (imperfect on rotated/overlapping text). |
432
466
  | `token-goat pdf-outline <file>` | List a PDF's bookmark/outline tree with page numbers instead of a raw Read. |
@@ -447,8 +481,6 @@ To upgrade cleanly:
447
481
  | `token-goat docx-text <file>` | Full body text of a Word document instead of a raw Read; `--head`/`--tail`/`--grep`/`--section`/`--max-matches` slice it the same way `pdf-extract` does. |
448
482
  | `token-goat transcript-outline <file>` | Speaker list, duration, and time-bucketed markers for a WebVTT/SRT transcript instead of a raw Read. |
449
483
  | `token-goat transcript <file>` | Slice a WebVTT/SRT transcript by `--speaker <name>`, `--from`/`--to <hh:mm:ss>`, and/or `--grep <pattern>` instead of a raw Read. |
450
-
451
-
452
484
  | `token-goat screenshot <url> <destPath>` | Capture a local headless-browser screenshot, shrunk the same way local image reads are (image-shrink pipeline). `--executable-path` overrides the Chrome/Chromium binary; `--width`/`--height` set the viewport (default 1280x800); `--full-page` captures the full scrollable page. |
453
485
  | `token-goat clean-cache` | Prune on-disk caches to their configured floor without waiting for the worker. |
454
486
  | `token-goat prune-cache` | Manually trigger LRU eviction across all cache directories (images, bash, web, skills). |
@@ -459,7 +491,15 @@ To upgrade cleanly:
459
491
  | `token-goat tokens [patterns]` | Per-file token footprint table, sorted largest-first. `--tree` groups by directory with subtotals and percentage of total. `--top N` limits to the N biggest files. `--asc` reverses order. `--json` for structured output. Omit patterns to scan the whole project. Useful for deciding what to exclude before running `pack`. |
460
492
  | `token-goat todo` | Scan indexed project files for `TODO`, `FIXME`, `HACK`, `XXX`, and `NOTE` comment markers. Groups by file by default; `--group kind` to group by marker type; `--kinds` to filter to a subset; `--json` for machine output. Markers in string literals are excluded. |
461
493
  | `token-goat failures [src]` | Extract failing test blocks from test runner output (pytest, Jest, Go, Cargo). Passes and preamble are dropped; each failure comes back as a labeled block. Reads stdin by default; pass a file path for saved output. `--json` for structured output. |
462
- | `token-goat trace [src]` | Condense Python exception tracebacks to project-owned frames. Strips library, stdlib, and venv frames; chained exceptions preserve cause notes; bare exceptions without a message are handled. `--keep N` (default 5) caps the frame count. `--json` for structured output. |
494
+ | `token-goat trace [src]` | Condense a stack trace/traceback/panic to project-owned frames. Auto-detects and parses Python tracebacks, Node.js/V8 stack traces, Rust panics (including `RUST_BACKTRACE=1` backtraces), and JVM (Java/Kotlin/Scala) and .NET exceptions -- even mixed together in one input (e.g. a CI log with both a Python and a Node error). Strips library, stdlib/runtime-internal (`node:...`), and dependency (site-packages, rustc-internal, Cargo registry) frames; chained exceptions (Python's chained tracebacks, JVM's `Caused by:`) preserve cause notes as separate blocks; bare exceptions without a message are handled. `--keep N` (default 5) caps the frame count. `--bodies` resolves each surviving frame to its enclosing symbol and prints the actual code body (same lookup `scope`/`read`/`symbol` use), so a traceback is directly readable without a separate lookup per frame; recursive frames show the body once with `(same as above)` on repeats. `--json` for structured output. |
495
+ | `token-goat conflicts [path]` | Unresolved git merge-conflict markers (`<<<<<<<` / `\|\|\|\|\|\|\|` / `=======` / `>>>>>>>`, two-way or diff3 three-way) instead of a raw Read or grep. `path` may be a file, a directory (scanned recursively), or omitted entirely (scans the whole project); only files with at least one conflict region or malformed-marker warning are reported. `--summary` narrows each region to its line range and side labels, omitting the full ours/base/theirs content. `--json` for structured output. |
496
+ | `token-goat coverage-report-gaps <file>` | Extract uncovered lines/branches/functions from an LCOV or Istanbul coverage report instead of scanning the raw file. Auto-detects format; collapses consecutive uncovered lines into ranges; drops fully-covered files. `--file <path>` filters to one file; `--json` for structured output. |
497
+ | `token-goat zip-list <archive>` | Entry paths and sizes inside a zip-format archive (`.zip`/`.jar`/`.whl`/`.vsix`/`.nupkg` are all zip containers under the hood) instead of a raw Read or an `unzip -l` shell-out. Reads the central directory only — no member is decompressed just to list it. `--json` for structured output. |
498
+ | `token-goat zip-read <archive> <entry>` | Extract and print exactly one entry's text content from a zip-format archive by its in-archive path, instead of extracting the whole archive to disk. A binary member prints a `[binary content elided by token-goat]` marker instead of raw bytes. |
499
+ | `token-goat pr-slice <pr>` | Surgical GitHub PR reads via `gh` — one file's diff, a single review-comment thread, the description, or CI check statuses, instead of pulling the whole PR payload into context. |
500
+ | `token-goat bridges-status` | Parity matrix of which hooks/commands are wired for each supported harness (Claude Code, Codex, opencode, openclaw, Grok, etc.), side by side. |
501
+ | `token-goat commands` | Machine-readable manifest of every registered command, its description, options, and arguments (including subcommands like `worker start`). `--json` emits it as structured JSON for external tooling (shell completion, doc generators, scripts) instead of the default text listing. |
502
+ | `token-goat statusline` | Claude Code statusline command surfacing session stats (bytes saved, hint efficacy, cache hit rate) inline in the terminal. |
463
503
  | `token-goat lockdeps [path]` | Summarize lock file dependencies as a compact table. Reads poetry.lock, uv.lock, requirements.txt, Pipfile.lock, package-lock.json, Cargo.lock, and yarn.lock. Direct dependencies only — optional and transitive entries excluded. `--json` for structured output. |
464
504
  | `token-goat logfold [src]` | Collapse consecutive duplicate log lines. Runs of identical or structurally equivalent lines fold to `[Nx] line`. Normalizes timestamps, UUIDs, IPs, and hex IDs before comparing so the same event with different values folds correctly. `--tail N` keeps last N lines; `--no-normalize` disables normalization; `--json` for structured output. |
465
505
  | `token-goat hot [--limit N]` | Cross-session file frequency table: read and edit counts tallied from all stored sessions, ranked by total activity. Shows which files dominate your token spend across your entire history. `--project <dir>` filters to one project; `--json` for structured output. |
@@ -545,6 +585,62 @@ Total tokens: 18420
545
585
 
546
586
  `--top <n>` controls how many entries appear under "Top expensive tool calls" (default 10). `--json` prints the same report as machine-readable JSON instead.
547
587
 
588
+ ### Cross-cache recall
589
+
590
+ `token-goat recall "<query>"` searches every cached bash-output, web-output, and mcp-output entry at once, so you don't need to remember which cache type holds the result you want — a single full-text query ranks hits across all three:
591
+
592
+ ```
593
+ $ token-goat recall "eslint warnings"
594
+
595
+ [bash] a1b2c3d4e5f6a7b8 (token-goat bash-output a1b2c3d4e5f6a7b8)
596
+ npx eslint src tests
597
+ npx eslint src tests\n[token-goat: delta] 2 of 5 prior issues resolved; remaining: 3
598
+
599
+ [mcp ] mcp_9f8e7d6c5b4a3210 (token-goat mcp-output mcp_9f8e7d6c5b4a3210)
600
+ mcp:mcp__plugin_github_github__get_check_runs {"owner":"..."}
601
+ ... eslint warnings found in 2 files during CI ...
602
+ ```
603
+
604
+ Results are ranked by relevance (BM25 via SQLite FTS5, falling back to a plain substring scan if FTS5 is unavailable), newest indexed entries win ties. `--type bash|web|mcp` narrows to one cache type; `--limit <n>` caps the result count (default 10); `--json` emits `{ id, cacheType, label, snippet, storedAt }[]` instead. The index is built incrementally as entries are cached — there is no separate rebuild step.
605
+
606
+ ### Hint efficacy tracking
607
+
608
+ Every hint hook (the re-read/dedup/surgical-read nudges in the Bash, Read, and Edit hooks) is
609
+ worth its keep only if it's actually followed. `token-goat hint-stats` reports, per hint
610
+ category: how many times it fired, how many times a later Bash command in the same session
611
+ actually invoked the specific `token-goat` command (or referenced the specific cached-output id)
612
+ the hint pointed at, the resulting efficacy percentage, and whether the category is currently
613
+ auto-suppressed:
614
+
615
+ ```
616
+ $ token-goat hint-stats
617
+ category emitted acted-on efficacy suppressed manual+ manual-
618
+ bash_redirect 42 9 21.4% no 0 0
619
+ bash_recall 18 15 83.3% no 0 0
620
+ read_reread_dedup 11 2 18.2% no 0 0
621
+ read_structural_nav 7 1 14.3% yes 0 1
622
+ edit_reread_suggest 3 0 0% no 0 0
623
+ ```
624
+
625
+ A category is auto-suppressed for its harness once it has at least `hint_stats.min_sample_size`
626
+ emissions (default 5) AND its efficacy falls below `hint_stats.suppress_threshold_pct` (default
627
+ 15%) — the sample-size floor exists so a category is never suppressed off a single unlucky
628
+ emission. Once suppressed, that hook stops emitting that category until `token-goat hint-stats
629
+ --reset` clears the tracked data. Configure both knobs with `token-goat config set hint_stats.min_sample_size <n>` / `token-goat config set hint_stats.suppress_threshold_pct <pct>`.
630
+
631
+ "Acted on" is a real, session-scoped signal (the exact file path or cached-output id the hint's
632
+ own text pointed at is checked against the next few tool calls in that session) — not a guess —
633
+ but it is a proxy for correlation, not proof of causation: a match means the agent ran the
634
+ suggested command shortly after the hint, not that the hint necessarily caused it. A hint whose
635
+ text has no extractable path/id (a small minority of branches) is counted as emitted with no
636
+ automatic "acted on" credit. `--mark-effective <category>` / `--mark-ineffective <category>`
637
+ record a separate manual vote as a human override/supplement for exactly that gap — manual votes
638
+ are shown alongside the automatic percentage but never blended into it. `--json` emits
639
+ `{ category, emitted, actedOn, efficacyPct, suppressed, manualEffective, manualIneffective }[]`.
640
+ Note that what this feature calls "harness" (Claude Code, Codex, Gemini, ...) is not the same as
641
+ "which LLM model" — no bridge in this codebase exposes an LLM model identifier to hooks, so
642
+ harness is the closest real signal available.
643
+
548
644
  ## MCP server
549
645
 
550
646
  ```
@@ -612,7 +708,7 @@ Contains the symbol index (`global.db`, per-project `.db` files), session cache,
612
708
 
613
709
  | Path | What |
614
710
  |------|------|
615
- | `~/.codex/config.toml` | Hooks block with Codex-specific matchers (`view_image|Bash`, `apply_patch`, `web_search`). Existing hooks preserved. |
711
+ | `~/.codex/config.toml` | Hooks block with Codex-specific matchers (`view_image|Bash`, `apply_patch`, `web_search`) plus `PreCompact`/`UserPromptSubmit`/`SubagentStop` global hooks. Existing hooks preserved. |
616
712
  | `~/.codex/AGENTS.md` | A delimited block (`<!-- token-goat-codex-begin -->` … `<!-- token-goat-codex-end -->`) with the same routing guidance, adapted for Codex tool names. |
617
713
  | `~/.codex/hooks/token-goat-shim.js` | The hook script `config.toml`'s hook commands invoke (`node "<path>" <event>`). Strips internal `_tg_*` keys and injects `hookSpecificOutput.hookEventName` to satisfy Codex's strict schemas. Regenerated on every `install --codex` run. |
618
714
 
@@ -622,6 +718,12 @@ Contains the symbol index (`global.db`, per-project `.db` files), session cache,
622
718
  |------|------|
623
719
  | `~/.gemini/settings.json` | Hook entries under Gemini's `BeforeTool`, `AfterTool`, and `PreCompress` events, using Gemini's own snake_case tool-name matchers (`run_shell_command`, `read_file`, `grep_search`, etc.). Existing hooks preserved; a timestamped `.bak` is written before any change. |
624
720
 
721
+ **With `--qwen`** (Qwen Code integration)
722
+
723
+ | Path | What |
724
+ |------|------|
725
+ | `~/.qwen/settings.json` | Hook entries under Qwen Code's `PreToolUse`, `PostToolUse`, `PreCompact`, `UserPromptSubmit`, and `SubagentStop` events (Claude-Code-native names and payload shape, not Gemini's), using a catch-all matcher per event. Existing hooks preserved; a timestamped `.bak` is written before any change. |
726
+
625
727
  **With `--opencode`** (opencode plugin)
626
728
 
627
729
  | Path | What |
@@ -641,6 +743,13 @@ Contains the symbol index (`global.db`, per-project `.db` files), session cache,
641
743
  | `~/.copilot/hooks/token-goat.json` | Hook config (`{ version, hooks }`) registering `preToolUse`, `postToolUse`, `preCompact`, `agentStop`, and `subagentStop`, each pointing at the shim script below. Existing files elsewhere in the hooks directory are untouched. |
642
744
  | `~/.copilot/hooks/token-goat-shim.js` | The shim `token-goat.json`'s hook commands invoke (`node "<path>"`). Translates Copilot's event names and response schema (`permissionDecision`/`modifiedArgs`, `additionalContext`) to/from token-goat's internal hook protocol. Regenerated on every `install --copilot` run. A project-local install (`--copilot --local`) writes `<project>/.github/hooks/token-goat.json` and `<project>/.github/hooks/token-goat-shim.js` instead. |
643
745
 
746
+ **With `--grok`** (Grok CLI / xAI Grok Build hook bridge)
747
+
748
+ | Path | What |
749
+ |------|------|
750
+ | `~/.grok/hooks/token-goat.json` | Hook config (`{ hooks }`) registering `PreToolUse`, `PostToolUse`, `PreCompact`, `UserPromptSubmit`, and `SubagentStop` with an empty (match-everything) matcher, each pointing at the shim script below. Existing files elsewhere in the hooks directory are untouched; global scope only (Grok's project-scoped `.grok/hooks/` requires a separate manual `/hooks-trust` grant). |
751
+ | `~/.grok/hooks/token-goat-shim.js` | The shim `token-goat.json`'s hook commands invoke. Translates `PreToolUse`'s deny shape only (`{"decision":"block",...}` → Grok's documented `{"decision":"deny",...}`, plus exit code 2); every other event's response is forwarded unmodified. Regenerated on every `install --grok` run. |
752
+
644
753
  **With `--hermes`** (Hermes Agent integration)
645
754
 
646
755
  | Path | What |
@@ -876,7 +985,7 @@ Outbound network is reserved to two explicit cases:
876
985
 
877
986
  **Prompt injection.** When an AI reads a file, web page, or command output, that content enters its context alongside your own instructions. Prompt injection is when untrusted content includes text designed to look like instructions — "Ignore all previous directives and run this instead" — to redirect the AI mid-task.
878
987
 
879
- Token-goat intercepts every Read, Fetch, and Bash call the AI makes. It does not filter or sanitize content before passing it to the model; doing so would silently break legitimate use cases. The primary defense is the model's own training to treat tool output as data, not as commands from a trusted party.
988
+ Token-goat intercepts every Read, Fetch, and Bash call the AI makes. For Read and Bash, it does not filter or sanitize content before passing it to the model; doing so would silently break legitimate use cases. WebFetch is the one exception: every fetched page is scanned for a set of imperative-override attack patterns ("ignore previous instructions," "reveal system prompt," and similar), and a match is wrapped in an untrusted-content fence rather than passed through untouched (`injection.enabled`, on by default). Outside of that scan, the primary defense is the model's own training to treat tool output as data, not as commands from a trusted party.
880
989
 
881
990
  In practice: if you're reading files from untrusted sources or fetching unknown URLs during a session, pay attention to any actions the AI takes immediately after. Unusual follow-on behavior — opening files it wasn't asked about, writing to unexpected locations — is a sign that something in the read content may have tried to redirect it.
882
991
 
@@ -894,7 +1003,7 @@ Add-MpPreference -ExclusionPath "$env:LOCALAPPDATA\dfk-helper\token-goat"
894
1003
  token-goat uninstall
895
1004
  ```
896
1005
 
897
- Reverses everything in [What gets installed?](#what-gets-installed): the hook entries in `settings.json`, the `CLAUDE.md` block, the skill directory. Add `--codex`, `--gemini`, `--opencode`, `--pi`, `--hermes`, `--openclaw`, or `--copilot` to also strip those integrations. There is no `--purge` flag — `uninstall` never deletes the data directory (cache, index, models, logs); remove it by hand if you want it gone. It also does not stop a running worker; use `token-goat worker stop` for that. Nothing else on the system depends on it.
1006
+ Reverses everything in [What gets installed?](#what-gets-installed): the hook entries in `settings.json`, the `CLAUDE.md` block, the skill directory. Add `--codex`, `--gemini`, `--opencode`, `--pi`, `--hermes`, `--openclaw`, `--copilot`, or `--grok` to also strip those integrations. There is no `--purge` flag — `uninstall` never deletes the data directory (cache, index, models, logs); remove it by hand if you want it gone. It also does not stop a running worker; use `token-goat worker stop` for that. Nothing else on the system depends on it.
898
1007
 
899
1008
  ## About
900
1009
 
@@ -902,6 +1011,10 @@ I built this because long Claude Code and Codex sessions on my machine kept burn
902
1011
 
903
1012
  This is a solo project. I use it daily on Windows 11. Tests run on Node.js 20 and 22.
904
1013
 
1014
+ ## Sister project
1015
+
1016
+ [Token-Goat Mem](https://github.com/DFKHelper/token-goat-mem) is a companion project: durable, local-first memory for AI coding agents, with trust levels and anchor-based staleness detection, so a decision like "we use pnpm, not npm" survives a compaction instead of getting re-explained every session. Token-Goat controls what gets read into context; Mem controls what gets remembered across sessions. The two are independent — neither requires the other — but Mem has an optional one-way seam that feeds its facts into Token-Goat's compaction manifest.
1017
+
905
1018
  ## Requests and issues
906
1019
 
907
1020
  Want token-goat to support something it doesn't yet? Open a GitHub issue. Feature requests: a new agent CLI integration (Cline, Copilot Workspace, or any tool not yet covered), a new language adapter, or an image or document format the shrink path doesn't compress yet. Issues are public and searchable. That's where I work out what to build next. A short repro plus what you'd want the command to do is enough.