Skip to content

Releases: DFKHelper/token-goat

v2.6.12

Choose a tag to compare

@Zelys-DFKH Zelys-DFKH released this 10 Jul 07:24

Full Changelog: v2.6.11...v2.6.12

v2.6.11

Choose a tag to compare

@Zelys-DFKH Zelys-DFKH released this 10 Jul 03:36

See CHANGELOG.md for full details.

Highlights

  • Indexer/worker critical-path fixes: BOM handling on the worker's real shipping path, index exit-code correctness, embedding pipeline memoization, unchanged-file skip on bulk index, embed-freshness gate, folded-path SQL indexes (full-table-scan fix), and a cross-process retry-count persistence fix.
  • Multi-line string masking fix across the C#, PHP, Kotlin, and PowerShell language adapters.
  • Session/hooks correctness: harness-detection priority fix, build-command cache fingerprinting, curl re-download existence check, Grok session-id fallback, overflow-guard coverage on symbol/refs/skeleton/outline, multi-file cat deny, cross-agent false-deny fix, task-output size gating, and scoped git status/diff recall-dedup.
  • Gemini bridge deny-contract verified against its own hook docs (previously assumed, now tested).
  • New Windows CI job, unified env pins between pre-push and CI, and a real tarball smoke test gating npm publish.
  • token-goat stats (bare command) now renders with the same rich TTY header/KPI section as --full.

v2.6.10

Choose a tag to compare

@Zelys-DFKH Zelys-DFKH released this 09 Jul 21:05

Added

  • Salesforce Apex and metadata-XML symbol indexing. New regex adapters index .cls/.trigger Apex source (classes, interfaces, triggers, methods) and Salesforce metadata XML (.object, .field-meta.xml, .validationRule-meta.xml, .permissionset-meta.xml, .profile-meta.xml, .md-meta.xml, and related suffixes) for CustomObject, CustomField, ValidationRule, PermissionSet, Profile, and CustomMetadata symbols. Metadata files above 512 KB, and all .profile-meta.xml files, are excluded from embeddings to avoid low-signal vector noise. Contributed by @krzysztofwojt.

Fixed

  • token-goat symbol returned an empty body preview for Salesforce metadata symbols. Fixed by mirroring token-goat read's disk-reconstruction fallback in runSymbol. Also replaced a 19-branch if/else if dispatch chain for non-tree-sitter language extraction with a lookup table, so adding a new regex adapter is one map entry instead of a new branch.

Full changelog: https://github.com/DFKHelper/token-goat/blob/main/CHANGELOG.md#2610---2026-07-09

v2.6.9

Choose a tag to compare

@Zelys-DFKH Zelys-DFKH released this 09 Jul 07:32

Fixes 16 bugs found and verified across three rounds of independent bugcheck plus a Codex CLI peer review, spanning the core symbol resolver, SQL/JS path case-folding, MCP tool classification, and Windows hook invocation across the Gemini/OpenClaw/OpenCode bridges.

See CHANGELOG.md for the full list.

v2.6.8

Choose a tag to compare

@Zelys-DFKH Zelys-DFKH released this 08 Jul 02:57

Fixed

  • Overflow-guard hint for line-range reads suggested wrong syntax (:: instead of @). Fixed by updating the hint text to use the correct separator (file.py@100-150).
  • skeleton/outline --min-lines with a non-numeric value silently returned zero symbols instead of erroring. Now validated with requireNonNegativeInt like other numeric flags.
  • parseDiffHunks misattributed a deleted file's hunk to the previous file. currentFile is now reset on +++ /dev/null.
  • extractMarkdownHeadings advertised sections inside fenced code blocks as real headings. Now skips fence content via eachUnfencedLine, matching its sibling extractors.
  • The Codex CLI and pi bridges had the same bare-PATH single-point-of-failure the Copilot CLI bridge was fixed for. Both now resolve the token-goat entry via process.execPath and a baked-in entry path instead of depending on PATH resolution, with a PATH-based fallback for older cached installs.

Full changelog: https://github.com/DFKHelper/token-goat/blob/main/CHANGELOG.md#268---2026-07-07

v2.6.7

Choose a tag to compare

@Zelys-DFKH Zelys-DFKH released this 08 Jul 01:22

Fixed

  • token-goat stats showed events as happening "tomorrow" once UTC crossed midnight, ahead of the local calendar day. summarize()'s day-bucket key and the rich stats renderer's header date were both derived via toISOString(), which always renders in UTC -- so any event recorded in the evening in a negative-UTC-offset zone (where UTC has already rolled to the next day) got bucketed and displayed under tomorrow's date. Both now derive the calendar day from local Date getters via a shared toLocalDateKey helper; skill-history's timestamp column got the same local-time treatment via a new formatLocalTimestamp helper. See src/stats.ts, src/render/stats_renderer.ts, and src/cli.ts; regression-tested in tests/stats.test.ts against a fixed UTC-5 timezone so the day-boundary crossing is deterministic regardless of the host machine's real timezone.
  • The Copilot CLI hook shim's inner call still depended on PATH resolution, unlike its already-hardened outer command. The outer hook command invokes the shim via a baked process.execPath, but the shim's own inner token-goat hook <event> call shelled out to a bare token-goat (shell: true), which depends on the npm global bin being on whatever PATH Copilot spawns the hook subprocess with -- and Copilot's preToolUse fails closed on a non-zero exit or crash, denying every tool call for the rest of the session with no mid-session recovery (Copilot caches hook configs at startup, so renaming/reinstalling the config has no effect until a full restart). token-goat install --copilot now bakes the running token-goat entry's absolute path into the generated hook command as a third argument, and the shim invokes it directly via process.execPath for the inner call too, falling back to the old PATH-based lookup only when that argument is absent (an older cached config). Every generated hook entry also now sets an explicit timeoutSec: 60, doubling Copilot's own 30s default as headroom for a cold first invocation (bundle load + DB open) on the four events that lack preToolUse's documented fail-open-on-timeout carve-out -- per GitHub's hooks reference, a preToolUse timeout itself already fails open, so this is not what causes the deny-all class, just cheap insurance for the other events. token-goat doctor gained a checkCopilotCli check that runs the exact installed preToolUse command end-to-end with a synthetic payload (through a shell, the same path Copilot uses) and separately verifies the baked node binary still exists on disk, since an nvm/fnm/volta node upgrade can silently make it stale. See src/bridges/copilot_cli.ts, src/bridges/copilot_cli_install.ts, src/cli_doctor.ts, and README.md (documents the rename-and-restart recovery path); regression-tested in tests/install_copilot_cli.test.ts and tests/cli_doctor.test.ts.

Full Changelog: https://github.com/DFKHelper/token-goat/blob/main/CHANGELOG.md

v2.6.6

Choose a tag to compare

@Zelys-DFKH Zelys-DFKH released this 08 Jul 00:14

Fixed

  • Three indexer bugs found by a Fable bugcheck: PowerShell block comments could be opened mid-line by a <# sitting inside a # line comment; token-goat read/brief couldn't resolve a symbol whose indexed name literally contains a dot (TOML sections, CSS selectors); the SQL/Protobuf block-comment stripper could close a comment against its own opening asterisk.
  • Copilot CLI recorded zero read/edit activity in any session. The view/edit/create tools send the file path under path, but every token-goat handler these tools reach only looks for file_path. The shim now adds file_path alongside the original key.

Full changelog: https://github.com/DFKHelper/token-goat/blob/main/CHANGELOG.md#266---2026-07-07

v2.6.5

Choose a tag to compare

@Zelys-DFKH Zelys-DFKH released this 07 Jul 15:22

Added

  • Copilot CLI hook bridge (--copilot on install/uninstall) — a Node shim translates token-goat's generic hook JSON into Copilot CLI's preToolUse/postToolUse/preCompact/agentStop wire shapes
  • token-goat mcp-serve — an MCP server over stdio exposing read, symbol, section, outline, skeleton, and semantic as real MCP tools, for harnesses that support MCP but not hook interception

Fixed

  • stripCstyleComments/stripHashComments weren't quote-aware, letting a stray comment marker inside a string literal swallow real code
  • BanditFilter buffered issue lines out of order, scrambling or leaking source-context lines
  • go_test's OK_PKG_RE missed (cached) packages, undercounting pass totals
  • C#'s CONSTRUCTOR_RE required an explicit access modifier, dropping implicitly-private constructors from the index
  • PowerShell adapter counted braces inside <# #> block-comment prose, desyncing brace depth and dropping subsequent top-level symbols
  • 11 additional correctness bugs across hooks, git/pytest output parsing, session tracking, Kotlin/markdown parsing, and cache eviction (see CHANGELOG)

Full changelog: https://github.com/DFKHelper/token-goat/blob/main/CHANGELOG.md#265---2026-07-07

v2.6.4

Choose a tag to compare

@Zelys-DFKH Zelys-DFKH released this 06 Jul 22:52

Added

  • token-goat brief "file::symbol" — symbol body + resolved callers + containing doc section in one round-trip
  • --stats on outline/skeleton — per-symbol reference count and doc-coverage flag
  • WebFetch HTML-to-text extraction, token-goat pdf-extract, token-goat csv-query, token-goat screenshot
  • tool_filters collapse for PowerShell's CommandNotFoundException noise ($_ bash pre-expansion)

Fixed

  • withFileLock could steal a lock from a still-legitimately-running holder
  • pre_compact's manifest could be silently suppressed by a future non-pass handler
  • runBrief's caller count hid its own truncation
  • runFind silently dropped matches beyond its scan limit
  • config-get rejected section headers with a trailing inline comment
  • csv-query's table formatter had no RFC 4180 quoting
  • config boolean coercion silently defaulted invalid values to false
  • dirty-reindex queue had no retry cap on a permanently stuck file
  • chunkFile mislabeled a folded chunk's kind
  • MCP dedup cache ignored state-changing input flags (clear/createIfEmpty/save_to_disk)

Removed

  • The dead session_start hook event

Full changelog: https://github.com/DFKHelper/token-goat/blob/main/CHANGELOG.md#264---2026-07-06

v2.6.3

Choose a tag to compare

@Zelys-DFKH Zelys-DFKH released this 05 Jul 23:03

[2.6.3] - 2026-07-05

Added

  • token-goat grep now accepts multiple paths and a -C, --context <n> flag. grep <pattern> [paths...] takes zero or more paths (variadic, matching the existing pack/tokens/budget convention): zero still walks cwd, one behaves exactly as before, and two-plus are searched in argument order with all hits merged into one list before the existing --max-lines cap runs once across the combined set, never truncated per file. -C, --context <n> captures n lines before and after each match (clamped to the file's real range); JSON output includes a structured context array per hit, plain text renders it with grep's own :/- convention, and the field is entirely absent — output byte-identical to before — when -C is omitted. See src/read_commands.ts and src/cli.ts; regression-tested in tests/read_commands.test.ts.

  • token-goat config-get resolves keys from YAML frontmatter in Markdown files. A .md file's leading ----fenced frontmatter block (Jekyll/Hugo/SKILL.md-style key: value lines) previously fell into the TOML/INI fallback, which expects key = value and never matched — locating a version marker in a SKILL.md required a manual grep plus an offset/limit read instead. runConfigGet now checks for a fence pair first, before extension dispatch, and runs the existing YAML lookup against just the fenced slice; a .md file with no frontmatter, or an unclosed fence, falls through unchanged to the normal TOML/INI lookup. See src/read_commands.ts; regression-tested in tests/read_commands.test.ts.

  • token-goat read, skeleton, and outline gained a --force-refresh flag. Files touched by git operations, external tools, or direct filesystem writes bypass the normal post-edit indexing hook and were served stale symbols until the background worker's next drain cycle. --force-refresh synchronously re-parses the target file from disk and updates the index before querying, guaranteeing the result reflects current file content regardless of index staleness. See src/cli.ts and src/read_commands.ts; regression-tested in tests/read_commands.test.ts.

  • Embedding chunk boundaries now snap to symbols and headings instead of blind byte windows. A fixed-byte window could land mid-function, diluting or splitting a symbol's embedding across two chunks and degrading semantic search relevance. See src/embeddings.ts.

  • Every remaining harness now has real install/uninstall wiring: --codex, --pi (plus --pi --local for a project-only install), --gemini, --opencode, --hermes, and --openclaw. Most of these were previously documented in the README with no corresponding cli.ts command at all, or shipped a bridge file that was never referenced by install. Highlights: the pi bridge (bridges/pi.ts) and opencode bridge (bridges/opencode.ts) are real, hook-tested TypeScript templates written against each harness's actual event vocabulary; --hermes is verification-only, since Hermes delegates to Claude Code via claude -p and inherits ~/.claude/settings.json directly; --openclaw (src/bridges/openclaw.ts, openclaw_install.ts) is the first fully-implemented OpenClaw plugin writer, built against OpenClaw's documented before_tool_call/after_tool_call shape and definePluginEntry registration (not yet dogfooded against a live gateway). A single canonical detectHarness() in bridges/registry.ts replaces two previously conflicting implementations that disagreed on environment-variable names and which harnesses they recognized. See src/bridges/registry.ts, src/bridges/pi.ts, src/bridges/opencode.ts, src/bridges/openclaw.ts, and src/install.ts; regression-tested across the corresponding tests/bridges_*.test.ts and tests/install*.test.ts files.

  • Base install now writes the CLAUDE.md block and the token-goat skill, as the README always documented. Both were real in the Python-era install but silently dropped during the TypeScript port; base install had been leaving every new user without the skill or the CLAUDE.md nudge the rest of the docs assume is present. See src/install.ts; regression-tested in tests/install.test.ts — fixing this also closed a test-isolation gap where two e2e cases would otherwise have written into a real ~/.claude.

Fixed

  • Three harness bridges spoke hook protocols that didn't exist, so their integrations were complete no-ops once installed. pi's shipped bridge called token-goat hook <event> with fabricated per-tool event names ("pre-read", "post-bash", etc.); relay() silently returns "{}" for anything it doesn't recognize, so bash compression, re-read denial, image shrinking, post-edit indexing, and the compaction manifest all silently did nothing after a --pi install. openclaw's bridge subscribed to an invented session_end hook (not a real HOOK_EVENTS member) and both opencode and openclaw kept a dead Glob entry in PRE_HOOK_TOOLS with no handler behind it. Gemini's input-key remap table was keyed backwards, so it never fired, and separately never remapped list_directory's real dir_path argument to file_path at all — every list_directory call left tool_input untouched, so node_modules/large-file denies, hints, and dedup tracking silently never applied to that tool. All three bridges now use each harness's verified real event names and argument shapes. See src/bridges/pi.ts, src/bridges/openclaw.ts, src/bridges/opencode.ts, and src/hooks_cli.ts; regression-tested in the corresponding tests/bridges_*.test.ts and tests/hooks_cli.test.ts.

  • pi never resolved through detectHarness(). 'pi' was missing from HarnessName/KNOWN_HARNESS_NAMES entirely, so every pi session misdetected as 'generic' and lost harness-specific behavior (auto-compact multiplier, per-harness README claims) regardless of the bridge fixes above. See src/bridges/registry.ts.

  • Per-harness auto-compact multipliers were fully implemented and configured but never actually consulted. getContextPressure's window computation now calls getAutoTriggerMultiplier, so each harness's documented multiplier changes its effective auto-compact trigger point instead of every harness being treated identically. Verified end-to-end against the built binary at three multiplier values. See src/compact.ts.

  • Base install/uninstall and Codex/Gemini's marker-based safety checks had several gaps. installHooks/uninstallHooks never backed up settings.json before writing to it (every other bridge writer did); an existing-but-unparseable settings.json was silently clobbered instead of aborting; isCodexTokenGoatCommand/isGeminiTokenGoatCommand used a plain substring match, so an unrelated user hook whose command happened to contain the marker text could be wrongly stripped on uninstall; installHooks/isInstalled treated a leftover legacy hook entry as "already installed," silently skipping the real hook wiring on upgrade; and Codex's own shim used a snake_case hookEventName fallback instead of matching Claude Code's PascalCase convention. See src/install.ts and src/bridges/codex.ts; regression-tested in tests/install.test.ts.

  • A dozen-plus case-folding gaps let differently-cased but identical paths silently miss each other on Windows and macOS. The rest of the codebase already follows an established foldPath/isCaseInsensitiveFs pattern (parser.ts, index_prune.ts, sql_path.ts, walk_index.ts, worker.ts); this batch closed the remaining stragglers one at a time as each was found: the three read-dedup caches and manifest merge in session.ts/compact.ts, session_store.ts's concurrent-state merge, paths.ts's duplicated drive-letter lowercasing and isNodeModulesPath (previously gated on isWindows() alone, missing macOS), project.ts's temp-boundary guard and projectHash, session.ts's _fileLineRanges keys, hooks_read.ts's cross-session manifest scan and reread-count lookups, snapshots.ts's pathKey() hash input, UNC host/share segments in paths.ts, import-to-file resolution in graph_commands.ts's arch command, memory_prune.ts's duplicate-target detection, openclaw_install.ts's plugin-path membership checks, and text_commands.ts's isProjectFrame (regressed by routing through a drive-letter-only canonicalize()). See src/paths.ts, src/project.ts, src/session.ts, src/session_store.ts, src/compact.ts, src/hooks_read.ts, src/snapshots.ts, src/graph_commands.ts, src/memory_prune.ts, src/bridges/openclaw_install.ts, and src/text_commands.ts; regression-tested across the corresponding test files for each.

  • Several worker/indexing paths silently produced wrong results instead of failing loudly. Two near-simultaneous worker start calls could both pass the startup pre-check and spawn duplicate daemons (a TOCTOU race, now closed, with the dead worker_daemon.ts removed); indexFileSync counted any read failure — not just a missing file — as successfully indexed, so a transient AV/editor lock silently stored a stale SHA with no error; cmdIndex's walk had no per-file try/catch, ...

Read more