Releases: DFKHelper/token-goat
v2.2.4
Correctness and compression release.
Session recall now survives the hook process boundary
token-goat's hooks run as a fresh process per tool call, but the entire session-recall layer lived in process-local memory that died with each process, so re-read dedup and bash-output / web-output recall never fired across calls in the shipped binary. Three on-disk layers under ~/.token-goat (per-session state plus content-addressed bash/web blobs) restore the behavior, with merge-on-save, atomic writes, and age/count pruning. WebFetch responses are now actually cached for cross-process recall.
Bash-output compression, wired and filling in
The pre-bash command-rewrite mechanism is reconnected end to end, so build and test commands are compressed automatically (opt out with TOKEN_GOAT_BASH_COMPRESS=0). The first structured per-tool filters land: Jest/Vitest (a shared Node test-runner family) and pytest / go test (bespoke runners). The remaining per-tool filters port in follow-up batches.
Other fixes
token-goat config-getreturns the value from the requested section, not the first matchtruncateLineno longer overshootsmaxLineLength- the reindex queue deduplicates paths case-insensitively on Windows/macOS
- flat section ranges never end before they start
index --walkindexes a non-git folder- task-output recall hints name a working
--filecommand trimToBudgetno longer slices mid-ANSI-escape- skill compact cache filenames are colon-free and consistent across store/get/list
Full details: CHANGELOG.md
v2.2.3
2.2.3 — the surgical-read pipeline, reconnected
This is a significant correctness release. The migration off the original Python implementation to TypeScript left several core components unwired in the shipped binary while the unit test suite stayed green:
- The background indexer wrote nothing. The worker drained its dirty queue into a stub, so the
symbolstable was never populated and the real parser was tree-shaken out of the bundle — every surgical read (symbol,read,skeleton,outline,semantic) returned an empty index. refsreturned[]and its command was never registered on the CLI.semanticalways reported "no matches" because its FTS query aliased the virtual table (no such column: f, silently swallowed by acatch).token-goat index .produced an unqueryable index — it stored relative path keys no reader could match.exports,imports,find,grep, andweb-outputwere implemented but never wired into the CLI (exports/importswere also non-functional as written).config-getignored its file argument and read token-goat's own config instead.
All of these are fixed, and every surgical-read and index-backed command is now reconnected end to end.
To stop this class of failure from recurring, two structural guards were added, both driven off a single command registry so new commands are covered automatically:
- a data-driven CLI registration guard that runs in a fast (~2s, no-I/O) pre-commit tier, so an implemented-but-unregistered or unfunctional command fails before the commit lands; and
- a built-bundle command matrix that indexes a fixture and runs every registered command against the shipped
dist/token-goat.mjsat pre-push and in CI — a command broken or unreachable in the shipped artifact now fails the build.
Also in this release: serve_diff_on_reread now covers source, style, and data files (not just docs); YAML/TOML kebab-case keys are indexed; read resolves 3+ part dotted symbols to the leaf; and the architecture reference was rewritten for the TypeScript codebase.
Full details: CHANGELOG.md
v2.2.2
[2.2.2] - 2026-06-27
Added
- PowerShell system-query recall.
Get-CimInstance,Get-Process,Get-Counter,Get-Service,Get-PSDrive, andGet-WmiObjectcommands run viapowershell.exe/pwshare now registered as monitoring commands. Output is cached after the first run and atoken-goat bash-output <id> --tail 50recall hint is emitted on repeats. token-goat section/outline/symbolrepeat recall. Running the sametoken-goat section "FILE::Heading",outline FILE, orsymbol NAMEcommand a second time in a session now emits a bash-output recall hint instead of re-executing.
v2.2.1
2.2.1
v2.2.0
See CHANGELOG.md for full details.
Highlights
- Count-based hard-deny for repeated source file reads — 3rd+ read of the same source file is hard-blocked; use
token-goat read,skeleton, oroutlineinstead - Identifier grep on a single file →
token-goat symbolhint viaextractRgSymbolSearch - Section heading normalization — em/en-dashes, trailing parens, numeric prefixes all handled; full heading list shown on miss
- Markdown heading grep →
token-goat outlinehint viaextractMarkdownHeadingGrep - Session artifact re-read dedup —
tasks/*.outputandtool-results/*.txtdiff-or-deny - Python heredoc reads now caught by
extractPythonFileRead - SQL cat hooks, curl GET cache, curl -o dedup, cat JSON|jq, node require(), CSS/SCSS/LESS cat, find → fd, eza --tree/tree/ls -R → map, grep|grep chain, doc-file diff-on-reread, .md re-read denial, git diff compression
- Security hardening, Windows mkdirSync race fix, multiple CLI and embedding fixes
- 180+ filter & interception rules (was 160+)
v2.1.0
See CHANGELOG.md for details.
v2.0.3
[2.0.3] - 2026-06-26
Fixed
-
statsrecording restored end-to-end. The TypeScript rewrite had ported only the read/display side of stat recording; the write side was silently missing since 2026-06-25.recordStat()is now implemented instats.tsand wired into all four hook handlers (hooks_read.ts,hooks_bash.ts,hooks_fetch.ts,hooks_skill.ts). Recorded rows now also carry realbytes_saved/tokens_savedvalues (file size and bytes/4) instead of defaulting to zero. -
git_history.tshunk line counts overcounted. The@@ -L,N +L,N @@header N values (which include context lines) were used directly aslinesAdded/linesRemoved. The parser now counts actual +/- prefixed body lines, giving accurate per-symbol change counts. -
git_history.tshunk loop broke early on diff content starting with+++/---. A barehunkLine.startsWith('+++')guard would prematurely exit the hunk body when a file contained lines whose content began with++or--. Guard now matches exact git file-header prefixes (+++ b/,+++ /dev/null,--- a/,--- /dev/null). -
parser.tssymbol line ranges used the parent declaration node instead of the child declarator. Multi-declaratorconst x = 1, y = 2statements reported each variable's range as the whole declaration span instead of the individualvariable_declaratorchild node's span. -
parser.tsJSON property extraction missed top-level keys whose values opened a nested object on the same line. ThebraceDepthcheck captured depth after processing the line, so a key like"nested": {was recorded at depth 1 (inside the nested object) rather than depth 0 (top-level). -
embeddings.tsleft\rin chunks on Windows CRLF content.raw.split('\n')produced chunks with trailing carriage returns. Changed toraw.split(/\r?\n/). -
hooks_cli.tssuppressed non-Errorthrown values in catch blocks. Theinstanceof Errorcheck silently swallowed string errors, rejected Promises, and other thrown values. -
read_commands.tsskeleton()reported the wrong final line number when--min-lineswas active. The function used the unfiltered symbol array's last element for the total line count even after--min-lineshad reduced the set, producing a count larger than the visible output. -
Event listener leaks on stdin and
parentPort.readStdin()inhooks_cli.tsand the stdin mode ofcmdWriteFile()incli.tsregistereddata/end/errorlisteners without ever removing them, leaking listeners across invocations. Named handler refs and acleanup()call in all exit paths now prevent the leak.worker.tsparentPortmessage listener is removed when the'stop'message is received.
v2.0.2
[2.0.2] - 2026-06-26
Added
-
git diff and npm run monitoring recall patterns.
git diff HEAD,git diff, andgit diff --cachednow trigger bash-output recall hints when prior output is cached (full diffs can be many KB;git diff --statis excluded as it produces small output).npm run test,npm run build,npm run lint,npm run typecheck,npm run check, andnpm run specare now covered by monitoring recall � these invoke vitest/eslint/tsc under the hood but weren't matched by the direct-invocation patterns. -
codex and glm.sh monitoring recall patterns.
codex execand~/.claude/bin/glm.shinvocations are now tracked as monitoring commands; when prior output is cached and exceeds 2 KB, a recall pointer is injected. -
cat source-file recall hint. Repeated
cat <file>calls on source files now emit atoken-goat read 'file::Symbol'suggestion rather than a generic shell recall hint.
Fixed
- post_tool_use Bash hook was missing.
getBashOutputIdalways returned null in production because the Bash post-hook was never registered, silently disabling all monitoring and build recall hints. The hook is now wired up and bash output caching works end-to-end.
v2.0.1
[2.0.1] - 2026-06-25
Added
-
Language-agnostic read-suppression and build-tool recall pattern table.
src/hints/lang_patterns.tsadds a data-driven table covering 13 lock-file types (pre-read deny + section offer), 16 manifest/config types (section/config-get nudge on re-read), generated build-output directories (read suppression), and 12 build-tool stdout patterns (bash-output recall). The table is the single source of truth consumed by the pre-read and pre-bash hooks. -
npm-specific hook improvements.
package-lock.jsontriggers a pre-read deny with atoken-goat sectionoffer;node_modules/reads are suppressed;package.jsonre-reads emit a section/config-get nudge;npm install,npm test,npm run,npm ci, andnpm auditstdout is cached and recalled viabash-output --grep. -
TypeScript and JavaScript hook patterns.
tsconfig.jsonsection hint on re-read;.d.tsfiles indist/suppressed;tsc/tsc --watchand Vite/esbuild/webpack build output cached; vitest/jest output cached with--grep FAIL;dist/,out/,.next/,.nuxt/,build/directories suppressed;*.min.jsand*.bundle.jsfiles suppressed. -
Process-monitoring command recall hints. Pre-bash intercept for repeated monitoring commands:
gh run watch/view,gh run view --log,gh pr checks, next dev/build, vite, nuxt dev, vitest/jest watch, pytest, cargo test, go test, docker logs, nodemon, air, cargo watch, watchexec, eslint, prettier, ruff, clippy. When a prior run is cached and its output exceeds 2 KB, a recall pointer is injected instead of re-running the command. -
Large markdown file interception with heading-tree hints. Markdown files ≥ 8 KB with three or more headings are intercepted on pre-read (block: true). The hook extracts ATX H1–H3 headings (capped at 40), formats a heading tree with
#2/#3disambiguation suffixes, and injects it withtoken-goat sectionshortcuts. Well-known files (README.md, CHANGELOG.md, CONTRIBUTING.md, CLAUDE.md, CLAUDE.arch.md) receive pre-populated section shortcuts. Post-edit on markdown files injects atoken-goat sectionre-read suggestion. -
Universal large-file interception for PDF, HTML, TXT, Office, and CSV files.
src/hints/file_type_handler.tsdispatches on extension. PDF and Office binaries (.docx/.xlsx/.pptx/.odt/.ods) are fully blocked with pandoc/docx2txt extraction suggestions. HTML ≥ 50 KB is intercepted with title + heading index; minified HTML is flagged. TXT/log files ≥ 20 KB show line count plus first/last five lines with head/tail/grep offers. CSV/TSV ≥ 10 KB shows column headers, row count, and three sample rows with a DuckDB suggestion. Any file ≥ 100 KB hits a generic catch-all with byte/line count.
Fixed
-
(921ffab) parseInt radix, YAML frontmatter close regex, ANSI strip scope.
parseInt(env, 10)inask.tsprevents octal interpretation on leading-zero values.memory_prune.tstightens the frontmatter closing delimiter from bareindexOf('\n---')to/\n---(?:\n|$)/so\n---extralines no longer terminate frontmatter early.overflow_guard.tsreplaces the SGR-only localstripAnsiwith the full-coveragestripAnsiCodesfrombash_compress.ts, which handles OSC, DCS, and cursor sequences. -
(a4caffe) Falsy-zero timeout, missing maxHints guard, and hint suppressor logic.
ask.tsparseTimeoutSecs()replacesparseInt(env) || DEFAULTso a timeout of"0"is honoured rather than treated as falsy.hints.tsadds an early-return guard formaxHints <= 0.buildIndexOnlyFileHint,buildStructuredFileHint, andbuildPackageManifestHintchangehasOffset && hasLimittohasOffset || hasLimitso a read with only offset (or only limit) also suppresses the hint. Ten regression tests added.
v2.0.0 — TypeScript rewrite
Complete Python→TypeScript migration. All modules ported to TypeScript; Python source removed; package promoted from packages/token-goat-ts/ to project root. Now published to npm instead of PyPI.
Install: npm install -g token-goat
See CHANGELOG.md for the full change history.