token-goat 2.9.28 → 2.9.30
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 +36 -40
- package/SECURITY.md +28 -10
- package/THIRD_PARTY_NOTICES.md +40 -3
- package/dist/native/linux-arm64/tg-hook +0 -0
- package/dist/native/linux-x64/tg-hook +0 -0
- package/dist/ort-wasm-simd-threaded.mjs +59 -0
- package/dist/token-goat-chunk-3CHUNJ2O.mjs +53 -0
- package/dist/token-goat-chunk-3Z5S4KGM.mjs +918 -0
- package/dist/token-goat-chunk-4FVIAHSI.mjs +211 -0
- package/dist/{token-goat-chunk-66LODAUT.mjs → token-goat-chunk-4JJS54TR.mjs} +4 -3
- package/dist/token-goat-chunk-4LCCNRTG.mjs +313 -0
- package/dist/token-goat-chunk-54K3EUV3.mjs +35 -0
- package/dist/token-goat-chunk-56EIMS3E.mjs +159 -0
- package/dist/token-goat-chunk-5BCIJXMO.mjs +609 -0
- package/dist/token-goat-chunk-5KDMCMF2.mjs +362 -0
- package/dist/token-goat-chunk-5RG5SBL6.mjs +221 -0
- package/dist/{token-goat-chunk-RRNZMM3A.mjs → token-goat-chunk-5Y6ZYL6U.mjs} +21 -2
- package/dist/{token-goat-chunk-NILVK7XM.mjs → token-goat-chunk-64FBPDTK.mjs} +12 -6
- package/dist/{token-goat-chunk-LEG3JNJ6.mjs → token-goat-chunk-664RTTUV.mjs} +31 -15
- package/dist/token-goat-chunk-67TQJ76B.mjs +57 -0
- package/dist/token-goat-chunk-6QMAS7AB.mjs +42 -0
- package/dist/token-goat-chunk-7BXSNBY5.mjs +253 -0
- package/dist/{token-goat-chunk-F7QZRIWM.mjs → token-goat-chunk-7F2UBPD3.mjs} +42 -35
- package/dist/{token-goat-chunk-CC2PYJM7.mjs → token-goat-chunk-7IN2MKDS.mjs} +718 -595
- package/dist/token-goat-chunk-7NADEDKJ.mjs +124 -0
- package/dist/{token-goat-chunk-6SGLIPQB.mjs → token-goat-chunk-A3CK6N5Z.mjs} +621 -72
- package/dist/{token-goat-chunk-HXNAC4ZF.mjs → token-goat-chunk-AFLYLHDH.mjs} +48 -33
- package/dist/token-goat-chunk-AM5V6GSX.mjs +367 -0
- package/dist/{token-goat-chunk-I7CB3X4K.mjs → token-goat-chunk-APGZXSPS.mjs} +44 -148
- package/dist/{token-goat-chunk-BJBRGPBX.mjs → token-goat-chunk-ARDNEC2U.mjs} +11 -7
- package/dist/token-goat-chunk-ATCPY7EQ.mjs +134 -0
- package/dist/token-goat-chunk-B2RZZCSS.mjs +354 -0
- package/dist/{token-goat-chunk-QM76S6YS.mjs → token-goat-chunk-B45VMIIH.mjs} +6 -5
- package/dist/token-goat-chunk-BPGCUMR7.mjs +30 -0
- package/dist/{token-goat-chunk-GGLEE35R.mjs → token-goat-chunk-C63JQV5K.mjs} +49 -10
- package/dist/{token-goat-chunk-RJH64KQH.mjs → token-goat-chunk-COBQGL5S.mjs} +2661 -2440
- package/dist/token-goat-chunk-COTXZHTS.mjs +39 -0
- package/dist/token-goat-chunk-CYCEYAEO.mjs +265 -0
- package/dist/token-goat-chunk-CZ3LUXYZ.mjs +4115 -0
- package/dist/token-goat-chunk-DZX2YDPT.mjs +15 -0
- package/dist/token-goat-chunk-E3OQX2XT.mjs +824 -0
- package/dist/token-goat-chunk-EFHMMIGP.mjs +68 -0
- package/dist/token-goat-chunk-ETBHVDB6.mjs +328 -0
- package/dist/token-goat-chunk-EVMZJ27Z.mjs +147 -0
- package/dist/token-goat-chunk-EXKGNHEG.mjs +2096 -0
- package/dist/{token-goat-chunk-6Z5ULNE5.mjs → token-goat-chunk-FBNQNSJK.mjs} +2490 -4957
- package/dist/{token-goat-chunk-NMTKNYGF.mjs → token-goat-chunk-FNFBKLRD.mjs} +74 -9
- package/dist/{token-goat-chunk-XI2VFAV6.mjs → token-goat-chunk-FZ3NEW5O.mjs} +33 -19
- package/dist/token-goat-chunk-G5PJ7AGM.mjs +36 -0
- package/dist/{token-goat-chunk-VE27HPIF.mjs → token-goat-chunk-GFBSN7BD.mjs} +30 -398
- package/dist/{token-goat-chunk-L45ZQRT7.mjs → token-goat-chunk-GOLEOXZP.mjs} +780 -786
- package/dist/token-goat-chunk-H2K3QP6H.mjs +24 -0
- package/dist/token-goat-chunk-H2PHHGM5.mjs +188 -0
- package/dist/token-goat-chunk-HAVAOB3S.mjs +87 -0
- package/dist/token-goat-chunk-HG45AF2B.mjs +2228 -0
- package/dist/{token-goat-chunk-CBMY2FGI.mjs → token-goat-chunk-HOJLCGDP.mjs} +17113 -15554
- package/dist/{token-goat-chunk-HUDC5GS5.mjs → token-goat-chunk-HYBFA5X3.mjs} +120 -19
- package/dist/token-goat-chunk-IVALLT3S.mjs +48 -0
- package/dist/token-goat-chunk-IVE6U7KV.mjs +53 -0
- package/dist/{token-goat-chunk-UBUKHVYW.mjs → token-goat-chunk-IVKIZWAB.mjs} +3 -3
- package/dist/{token-goat-chunk-4JMWPWCS.mjs → token-goat-chunk-JB6QN6VF.mjs} +6 -4
- package/dist/{token-goat-chunk-Q4S3UQGO.mjs → token-goat-chunk-JDHE26RP.mjs} +10 -3
- package/dist/{token-goat-chunk-7R2XYKC5.mjs → token-goat-chunk-JDU3EXSU.mjs} +14 -10
- package/dist/token-goat-chunk-JDWCRD6M.mjs +253 -0
- package/dist/{token-goat-chunk-XBESNWEX.mjs → token-goat-chunk-JN4XMLSD.mjs} +7 -4
- package/dist/token-goat-chunk-JTQQGXZH.mjs +733 -0
- package/dist/token-goat-chunk-KKUFXAPD.mjs +25 -0
- package/dist/token-goat-chunk-KQNZDCBD.mjs +47 -0
- package/dist/{token-goat-chunk-4RN64ZND.mjs → token-goat-chunk-KWPNJBDH.mjs} +28 -3
- package/dist/token-goat-chunk-LOBGHXPB.mjs +242 -0
- package/dist/token-goat-chunk-MKPF4CL5.mjs +37 -0
- package/dist/token-goat-chunk-MNWKPRAL.mjs +13 -0
- package/dist/{token-goat-chunk-YWSP6IU7.mjs → token-goat-chunk-N2NMER56.mjs} +25 -15
- package/dist/token-goat-chunk-NYKZLXMK.mjs +218 -0
- package/dist/token-goat-chunk-OJBNYTJP.mjs +3087 -0
- package/dist/token-goat-chunk-P4QMM4WK.mjs +295 -0
- package/dist/token-goat-chunk-PD5VKH46.mjs +184 -0
- package/dist/token-goat-chunk-PEPTHRFF.mjs +129 -0
- package/dist/{token-goat-chunk-VWZKZPSR.mjs → token-goat-chunk-PU7V3FD6.mjs} +8752 -11098
- package/dist/token-goat-chunk-PY533T7F.mjs +46 -0
- package/dist/token-goat-chunk-Q5VTGRH7.mjs +761 -0
- package/dist/{token-goat-chunk-IHKZ3QNA.mjs → token-goat-chunk-QCLDAQTS.mjs} +33 -19
- package/dist/{token-goat-chunk-LKSXAMJB.mjs → token-goat-chunk-QSBRTGM2.mjs} +9 -2
- package/dist/{token-goat-chunk-4STDIGYC.mjs → token-goat-chunk-RC35RBUL.mjs} +7 -5
- package/dist/{token-goat-chunk-D5ICEPSB.mjs → token-goat-chunk-RHXKCZX3.mjs} +887 -507
- package/dist/{token-goat-chunk-RSS3TLXU.mjs → token-goat-chunk-RZRTDST7.mjs} +17 -7
- package/dist/{token-goat-chunk-MAMQPC43.mjs → token-goat-chunk-SJHWVNDQ.mjs} +15 -21
- package/dist/token-goat-chunk-SMVRN2HU.mjs +188 -0
- package/dist/{token-goat-chunk-EL7M26WP.mjs → token-goat-chunk-SQSSNQPE.mjs} +2100 -1442
- package/dist/{token-goat-chunk-OZRSREKR.mjs → token-goat-chunk-T4FK7VOV.mjs} +3 -3
- package/dist/token-goat-chunk-U4N3BN2W.mjs +92 -0
- package/dist/token-goat-chunk-UA5V6P3P.mjs +122 -0
- package/dist/{token-goat-chunk-XKY4VKJ4.mjs → token-goat-chunk-UQ5UK2T7.mjs} +15 -4
- package/dist/token-goat-chunk-USILZ3T3.mjs +53 -0
- package/dist/token-goat-chunk-VES7EL7O.mjs +205 -0
- package/dist/{token-goat-chunk-M56BWPBN.mjs → token-goat-chunk-VL3YIFHZ.mjs} +550 -49
- package/dist/{token-goat-chunk-IZXKVT4A.mjs → token-goat-chunk-VPBBTSJR.mjs} +362 -128
- package/dist/{token-goat-chunk-F2ARFHLJ.mjs → token-goat-chunk-W3QCJS6G.mjs} +10 -2
- package/dist/{token-goat-chunk-FSTWAOW6.mjs → token-goat-chunk-WY3L4DVT.mjs} +11 -5
- package/dist/{token-goat-chunk-OSUFN2FV.mjs → token-goat-chunk-XB5KKOCG.mjs} +5 -25
- package/dist/token-goat-chunk-XKI4SEMX.mjs +66 -0
- package/dist/token-goat-chunk-XU4P6Z24.mjs +133 -0
- package/dist/{token-goat-chunk-6CCQDAYY.mjs → token-goat-chunk-Y776AENC.mjs} +138 -33
- package/dist/token-goat-chunk-YARZFCZS.mjs +359 -0
- package/dist/{token-goat-chunk-EEIDFMEM.mjs → token-goat-chunk-YZAAZU2S.mjs} +12 -3
- package/dist/{token-goat-chunk-E3K3BTEQ.mjs → token-goat-chunk-Z44YO3QZ.mjs} +12 -6
- package/dist/token-goat-chunk-Z57YODA2.mjs +35 -0
- package/dist/{token-goat-chunk-DA43OE7L.mjs → token-goat-chunk-ZCDTCVIS.mjs} +49 -30
- package/dist/token-goat-chunk-ZEJVMUQH.mjs +48 -0
- package/dist/{token-goat-chunk-BGHSSJUA.mjs → token-goat-chunk-ZFOBKUWH.mjs} +1 -1
- package/dist/token-goat-chunk-ZMBL6UVV.mjs +110 -0
- package/dist/{token-goat-chunk-SJEKA7Y2.mjs → token-goat-chunk-ZQSJMO2R.mjs} +381 -201
- package/dist/token-goat-hook-client.cjs +539 -0
- package/dist/token-goat-hook-client.mjs +26 -0
- package/dist/token-goat-hook.mjs +48 -28
- package/dist/token-goat.core.mjs +10 -45
- package/docs/C4_RUNTIME_ARCHITECTURE.md +3 -3
- package/docs/cli.md +82 -47
- package/docs/install.md +58 -23
- package/docs/security.md +7 -7
- package/package.json +17 -7
- package/scripts/verify-native-dist.mjs +386 -0
- package/dist/token-goat-chunk-4JJBFT7V.mjs +0 -20
- package/dist/token-goat-chunk-5NNYIUGV.mjs +0 -143
- package/dist/token-goat-chunk-6DQNNFJ6.mjs +0 -294
- package/dist/token-goat-chunk-7MAFDRVR.mjs +0 -47
- package/dist/token-goat-chunk-BCN2YQC6.mjs +0 -32
- package/dist/token-goat-chunk-D7GHQKQD.mjs +0 -30
- package/dist/token-goat-chunk-GMOUBOX4.mjs +0 -386
- package/dist/token-goat-chunk-IFORDBGC.mjs +0 -192
- package/dist/token-goat-chunk-JXK2HQXS.mjs +0 -318
- package/dist/token-goat-chunk-L7SDVGBT.mjs +0 -430
- package/dist/token-goat-chunk-MMLMALWK.mjs +0 -1381
- package/dist/token-goat-chunk-MVSWBNMD.mjs +0 -1985
package/docs/install.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Install guide"
|
|
3
|
-
description: "How to install, wire it into Claude Code, Codex, Gemini, Qwen, Kimi, opencode, OpenClaw, pi, Copilot, Grok, Cline or Cursor, and what lands on your machine."
|
|
3
|
+
description: "How to install, wire it into Claude Code, Codex, Gemini, Qwen, Kimi, opencode, OpenClaw, pi, Copilot, Grok, Antigravity, Cline or Cursor, and what lands on your machine."
|
|
4
4
|
image: /token-goat/assets/goat-social.png
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -128,7 +128,19 @@ This writes hook entries into `~/.qwen/settings.json`. Unlike Gemini CLI (its ow
|
|
|
128
128
|
token-goat install --kimi
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
-
This writes `[[hooks]]` entries into `~/.kimi-code/config.toml` (or `$KIMI_CODE_HOME/config.toml`), covering Kimi Code's `PreToolUse`, `PostToolUse`, `PreCompact`, `UserPromptSubmit`, `SubagentStop`, and `SessionStart` events. Kimi Code sends a Claude-Code-shaped snake_case payload on stdin, but it reads a different response: only a top-level `message` and `hookSpecificOutput.permissionDecision` / `permissionDecisionReason`. So the install also writes a small shim at `~/.kimi-code/hooks/token-goat-shim.
|
|
131
|
+
This writes `[[hooks]]` entries into `~/.kimi-code/config.toml` (or `$KIMI_CODE_HOME/config.toml`), covering Kimi Code's `PreToolUse`, `PostToolUse`, `PreCompact`, `UserPromptSubmit`, `SubagentStop`, and `SessionStart` events. Kimi Code sends a Claude-Code-shaped snake_case payload on stdin, but it reads a different response: only a top-level `message` and `hookSpecificOutput.permissionDecision` / `permissionDecisionReason`. So the install also writes a small shim at `~/.kimi-code/hooks/token-goat-shim.cjs` that translates token-goat's answer into that contract, turns a hint into `message`, and writes nothing at all for a no-op. Image shrinking, session hints, post-edit indexing, compact assist, and bash output compression all work. `Notification` and `Stop` are not wired, because token-goat has no handler for them. Input and output rewriting are not wired either: Kimi Code offers no channel to replace a tool's input or its result. This bridge was built from MoonshotAI/kimi-code's own source and docs, not tested against a live Kimi Code install, so if hooks are not firing, `token-goat doctor` and the `config.toml` contents are the first things to check. To remove: `token-goat uninstall --kimi`.
|
|
132
|
+
|
|
133
|
+
### Antigravity CLI users
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
token-goat install --antigravity
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
This adds token-goat to Google's Antigravity CLI (`agy`) as a plugin: a folder at `~/.gemini/config/plugins/token-goat/` holding a `plugin.json`, a `hooks.json`, and on Windows a one-line launcher, `token-goat-hook.cmd`. agy turns plugins on by default, so nothing else needs changing. token-goat does not edit `~/.gemini/config/hooks.json`, which other tools write to, or `~/.gemini/config/config.json`, so if you turned the plugin off there it stays off.
|
|
140
|
+
|
|
141
|
+
It wires agy's `PreToolUse` and `PostToolUse` events. agy's tool names (`view_file`, `run_command`, `grep_search`, `find_by_name`, `replace_file_content`, `write_to_file` and others) and their argument names are translated to token-goat's own, so repeat-read hints, repeat-read denial, bash output handling and post-edit indexing see agy's calls. A pass answers `{}`, not `"allow"`, because in agy `"allow"` approves the tool call without asking you. agy has no session-start or pre-compaction event token-goat can use, so those are not wired.
|
|
142
|
+
|
|
143
|
+
The hooks were checked loading and running under agy 1.2.11 on Windows, and the payloads they read were captured from real agy tool calls. Whether agy acts on every answer (a hint, a rewritten command, a rewritten result) has not been checked in a live session yet, so if something seems not to take effect, check first that `~/.gemini/config/plugins/token-goat/hooks.json` is there and that the plugin is not turned off in `~/.gemini/config/config.json`. To remove: `token-goat uninstall --antigravity`, which deletes the plugin folder and any `~/.gemini` folders the install created, if they are empty.
|
|
132
144
|
|
|
133
145
|
### opencode users
|
|
134
146
|
|
|
@@ -136,7 +148,7 @@ This writes `[[hooks]]` entries into `~/.kimi-code/config.toml` (or `$KIMI_CODE_
|
|
|
136
148
|
token-goat install --opencode
|
|
137
149
|
```
|
|
138
150
|
|
|
139
|
-
The `--opencode` flag
|
|
151
|
+
The `--opencode` flag drops a TypeScript bridge plugin into opencode's plugins directory. Image shrinking, post-edit indexing, compact assist, and rewritten tool results (prompt-injection fencing, secret redaction, and output compression replace the raw result, the same protection Claude Code sessions get) work. So do repeat-search denial for `websearch`, repeat-load denial for `skill`, and the subagent prompt briefing for `task` — all three tool ids and their argument keys were verified against opencode's own source at the installed release's tag. Session hints don't — opencode's plugin API has no way to inject context before a tool read.
|
|
140
152
|
|
|
141
153
|
### openclaw users
|
|
142
154
|
|
|
@@ -166,7 +178,7 @@ What works: **bash output compression** (the bash command is rewritten in `tool_
|
|
|
166
178
|
npx token-goat install --pi --local
|
|
167
179
|
```
|
|
168
180
|
|
|
169
|
-
This writes `.pi/extensions/token-goat.ts` in the current project only. Remove it by deleting that file.
|
|
181
|
+
This writes `.pi/extensions/token-goat.ts` in the current project only. `-p`/`--project` does the same as `--local`. Remove it with `npx token-goat uninstall --pi --local`, or by deleting that file.
|
|
170
182
|
|
|
171
183
|
### Copilot CLI users
|
|
172
184
|
|
|
@@ -174,15 +186,23 @@ This writes `.pi/extensions/token-goat.ts` in the current project only. Remove i
|
|
|
174
186
|
token-goat install --copilot
|
|
175
187
|
```
|
|
176
188
|
|
|
177
|
-
The `--copilot` flag patches Claude Code and registers a Copilot CLI hook config: `~/.copilot/hooks/token-goat.json` (a `{ version, hooks }` file registering `sessionStart`, `preToolUse`, `postToolUse`, `preCompact`, `agentStop`, `subagentStop`, and `userPromptSubmitted`, per Copilot's own [hooks reference](https://docs.github.com/en/copilot/reference/hooks-reference)) plus the shim script it points at, `~/.copilot/hooks/token-goat-shim.
|
|
189
|
+
The `--copilot` flag patches Claude Code and registers a Copilot CLI hook config: `~/.copilot/hooks/token-goat.json` (a `{ version, hooks }` file registering `sessionStart`, `preToolUse`, `postToolUse`, `postToolUseFailure`, `preCompact`, `agentStop`, `subagentStart`, `subagentStop`, and `userPromptSubmitted`, per Copilot's own [hooks reference](https://docs.github.com/en/copilot/reference/hooks-reference)) plus the shim script it points at, `~/.copilot/hooks/token-goat-shim.cjs`. Unlike Codex, Copilot's event names and response schema (`permissionDecision`/`modifiedArgs` for `preToolUse`, `modifiedResult`/`additionalContext` for `postToolUse`, `decision`/`reason` for `agentStop`/`subagentStop`) genuinely differ from Claude Code's, so the shim translates rather than passes through.
|
|
178
190
|
|
|
179
|
-
What works: **the command-routing reminder** (`sessionStart` returns `additionalContext`, so Copilot is told token-goat exists before it picks its first read tool — this is the one channel that lands ahead of that decision), **bash output compression and re-read denial** (`preToolUse` returns `modifiedArgs` or `permissionDecision: "deny"`), **background-shell output compression** (`postToolUse` returns `modifiedResult`), **image shrinking** (`preToolUse` on a `view` call returns `modifiedArgs` carrying the full original arguments with `path` swapped to a materialized shrunk copy — Copilot replaces the tool call's arguments wholesale with `modifiedArgs`, so the rewrite must carry them all), **post-edit indexing** (a `postToolUse` side effect; it needs no response channel), and **stop-hallucination logging** (`agentStop`/`subagentStop` map a token-goat `deny` onto `decision: "block"`, everything else onto `decision: "allow"`). `
|
|
191
|
+
What works: **the command-routing reminder** (`sessionStart` returns `additionalContext`, so Copilot is told token-goat exists before it picks its first read tool — this is the one channel that lands ahead of that decision), **bash output compression and re-read denial** (`preToolUse` returns `modifiedArgs` or `permissionDecision: "deny"`), **background-shell output compression** (`postToolUse` returns `modifiedResult`), **image shrinking** (`preToolUse` on a `view` call returns `modifiedArgs` carrying the full original arguments with `path` swapped to a materialized shrunk copy — Copilot replaces the tool call's arguments wholesale with `modifiedArgs`, so the rewrite must carry them all), **post-edit indexing** (a `postToolUse` side effect; it needs no response channel), and **stop-hallucination logging** (`agentStop`/`subagentStop` map a token-goat `deny` onto `decision: "block"`, everything else onto `decision: "allow"`). **A subagent's session briefing** goes to the subagent itself: `subagentStart` answers with it, so it is no longer added to the parent's `task` call and left in the parent conversation. A long subagent report is compacted on `subagentStop` (long code blocks trimmed to their ends, repeated blocks folded) with a pointer to the full copy, which `token-goat mcp-output <id> --full` prints. After upgrading, run `token-goat install --copilot` again to add the `subagentStart` hook; until then the briefing keeps arriving the old way. **Prompt hints and the compaction manifest** reach the model through `userPromptSubmitted`: Copilot CLI 1.0.88 appends the returned `additionalContext` to the prompt inside a `<system_reminder>` block. `preCompact` itself ignores a returned `additionalContext`, so token-goat saves the manifest when compaction starts and hands it back with your next prompt. Copilot's built-in tool names are remapped onto token-goat's internal names where a clear match exists (`view`→Read, `edit`→Edit, `create`→Write, `bash`/`powershell`→Bash, `read_bash`/`read_powershell`→BashOutput, `web_fetch`→WebFetch, `grep`→Grep, `glob`→Glob). MCP-server tool calls, which Copilot names `<server>-<tool>` rather than `mcp__<server>__<tool>`, are translated too, but only when the name matches Copilot's own cached tool list exactly — never guessed from the name's shape, because a server name can itself contain a hyphen and a wrong guess would make the read-only MCP dedup path deny an ordinary built-in call. With no cache to match against, nothing is translated. `memory`, `ask_user`, `write_bash`/`write_powershell` (which send keystrokes to a running shell, not commands), and `stop_bash`/`list_bash` pass through unmapped and simply no-op. `task`, Copilot's subagent tool, is not remapped either, but it is handled under its own name: a `task` spawn gets the same prompt briefing, duplicate-spawn advisory, and recall pointer on a long report that a Claude Code `Agent` spawn gets. The once-per-session unrestricted-spawn advisory is the one exception: it is suppressed under Copilot, because its `subagent_type` advice describes Claude Code's Task schema, which Copilot's `task` tool does not use.
|
|
180
192
|
|
|
181
193
|
**Why the background-shell compression matters most on Copilot.** Copilot runs shell commands in the background: a build or a test suite is started once, and the model then checks on it repeatedly while it runs. Each check hands back everything the command has printed since it started, from the first line. So the second check re-sends the whole first check, the third re-sends the first two, and a check ten minutes into a slow build re-sends the same output for the tenth time. The model has already read all of it and pays again for every word, every time. Token-goat sends the first check through untouched, then returns only the new part on each later check, with one line saying that is what it is; a check that found nothing new comes back as a single short line instead of the whole output again. Measured through the installed hook: a second check of 5,200 characters came back as about 1,250, and a third check that added nothing came back as 60 — roughly a quarter of the cost for the second look and about one percent for the third, improving the longer the command runs. Nothing is lost, because what is cut is what was already sent. It only shortens a check when the new output genuinely continues the last one seen; anything else passes straight through, so the worst case is a saving that does not happen rather than a wrong answer.
|
|
182
194
|
|
|
183
|
-
No ambient environment variable documents "this process is running under Copilot CLI" the way Codex/opencode set one, so the shim sets `TOKEN_GOAT_HARNESS_OVERRIDE=copilot_cli` itself before calling `token-goat hook` (same workaround `--pi` uses). Install also writes a token-goat routing block into `~/.copilot/copilot-instructions.md` (the same delimited-block gate written to `~/.claude/CLAUDE.md` and `~/.codex/AGENTS.md`), merged idempotently so any hand-written content outside the markers is preserved byte-for-byte. If you set `COPILOT_HOME`, install follows it — hooks go to `$COPILOT_HOME/hooks
|
|
195
|
+
No ambient environment variable documents "this process is running under Copilot CLI" the way Codex/opencode set one, so the shim sets `TOKEN_GOAT_HARNESS_OVERRIDE=copilot_cli` itself before calling `token-goat hook` (same workaround `--pi` uses). Install also writes a token-goat routing block into `~/.copilot/copilot-instructions.md` (the same delimited-block gate written to `~/.claude/CLAUDE.md` and `~/.codex/AGENTS.md`), merged idempotently so any hand-written content outside the markers is preserved byte-for-byte. If you set `COPILOT_HOME`, install follows it — hooks go to `$COPILOT_HOME/hooks/`, the routing block to `$COPILOT_HOME/copilot-instructions.md` and the MCP server entry to `$COPILOT_HOME/mcp-config.json`, matching where Copilot CLI actually reads them. The MCP entry (`mcpServers.token-goat`, in the shape `copilot mcp add` writes) registers token-goat's MCP server with Copilot, so `copilot mcp list` shows it; every other server in that file is kept as it was. A project install (`--local`) does not touch it, because Copilot reads that file only at user scope. To install for one project instead of user scope: `token-goat install --copilot --local`, or `-p`/`--project` in place of `--local` (writes `.github/hooks/token-goat.json` and `.github/copilot-instructions.md` in the current project). `.github/hooks/token-goat.json` holds absolute paths to node and token-goat on your machine, so do not commit it or the `token-goat-shim.cjs` and `token-goat-shim.js` next to it: list them in `.git/info/exclude` (just for you) or `.gitignore`. Install prints this reminder. To remove: `token-goat uninstall --copilot`.
|
|
196
|
+
|
|
197
|
+
**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**. The same happens when something stops the native hook client `tg-hook` from starting after it was installed, such as an application-control policy (Smart App Control, App Control for Business, AppLocker) or an antivirus quarantining the copy: `doctor` then reports that the client fails its self-test, or that it no longer exists when the antivirus removed it. `token-goat install --copilot` copies the client again and tests it; one that still cannot run is left out and the entries are written as plain Node commands, after which Copilot needs the same full restart. If the client passes that test and is blocked again later, set `TOKEN_GOAT_NATIVE_HOOKS=0` (or `native = "off"` under `[hooks]` in the global config) before running `install`, which writes the Node commands whatever the client does.
|
|
184
198
|
|
|
185
|
-
**
|
|
199
|
+
**Status line.** Copilot CLI runs a status line command the same way Claude Code does, and `token-goat statusline` works as one. Install does not set it, because `~/.copilot/settings.json` holds only one status line and yours may already be in use. To use it, add this to `~/.copilot/settings.json` (or `$COPILOT_HOME/settings.json`), merged with what is already there:
|
|
200
|
+
|
|
201
|
+
```json
|
|
202
|
+
{ "statusLine": { "type": "command", "command": "token-goat statusline" } }
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
It shows the project, the model, the context percentage Copilot's own footer shows, whether the index is up to date, and the tokens token-goat saved today.
|
|
186
206
|
|
|
187
207
|
### VS Code (Copilot agent) users
|
|
188
208
|
|
|
@@ -190,7 +210,7 @@ No ambient environment variable documents "this process is running under Copilot
|
|
|
190
210
|
token-goat install --vscode
|
|
191
211
|
```
|
|
192
212
|
|
|
193
|
-
This installs into the **current project**: the MCP entry goes to `.vscode/mcp.json` (a timestamped `.bak` is written before any change to an existing file), the agent hooks to `.github/hooks/` (`token-goat.json` plus the `token-goat-shim.
|
|
213
|
+
This installs into the **current project**: the MCP entry goes to `.vscode/mcp.json` (a timestamped `.bak` is written before any change to an existing file), the agent hooks to `.github/hooks/` (`token-goat.json` plus the `token-goat-shim.cjs` it runs), and the routing guidance to `.github/copilot-instructions.md`. Run it once in each project you want token-goat in. VS Code's Copilot agent reads hooks from that folder, so token-goat sees the agent's built-in tool calls: `read_file`, `view_image`, `list_dir`, `grep_search`, `file_search`, `create_file`, `replace_string_in_file`, `insert_edit_into_file`, `edit_notebook_file`, `run_in_terminal`, `multi_replace_string_in_file`, `apply_patch`, `fetch_webpage`, `runSubagent` and `get_terminal_output`. The hooks file also registers `SubagentStart`, so a subagent's session briefing reaches the subagent itself rather than the parent's history (run `token-goat install --vscode` again after upgrading to add it). Both `.vscode/mcp.json` and `.github/hooks/token-goat.json` hold absolute paths to node and token-goat on your machine, so do not commit them or the `token-goat-shim.js` next to them: list them in `.git/info/exclude` (just for you) or `.gitignore`. Install prints this reminder.
|
|
194
214
|
|
|
195
215
|
`--vscode` is the one integration that installs into the project rather than user scope by default, and the reason is a limitation of VS Code itself. VS Code resolves an agent hook's working directory from the hook **file's** own location: the folder of the workspace that contains it, or the workspace's first folder when no workspace contains it. A user-scope hooks file lives in `~/.copilot/hooks/`, which is inside no workspace folder, so it always runs with the **first** folder of a multi-root workspace as its working directory — and since token-goat confines every pre-approval hook to that directory, read hints, image shrinking and edit interception silently do nothing for every other folder. A project-scope hooks file is inside its own folder, so each folder gets its own.
|
|
196
216
|
|
|
@@ -217,7 +237,7 @@ Two steps in Visual Studio after installing:
|
|
|
217
237
|
1. Tools > Options: turn on "Enable custom instructions to be loaded from .github/copilot-instructions.md files and added to requests". Without it, Visual Studio ignores the routing block.
|
|
218
238
|
2. In Copilot Chat agent mode, open the Tools picker and tick the token-goat tools. New MCP tools start disabled. Visual Studio 18.7 and later also asks you to trust the server when its command or arguments change, for example after a reinstall.
|
|
219
239
|
|
|
220
|
-
Both `.mcp.json` files are also read by Claude Code, under a different key (`mcpServers`), and Claude Code stops with an error on a `.mcp.json` that has no `mcpServers` key. So token-goat writes its entry under `servers` and, when the file has no `mcpServers` key yet, adds an empty one. It registers nothing for Claude Code and leaves your own `mcpServers` entries as they were. A timestamped `.bak` is written before any change to an existing `.mcp.json`. Visual Studio also reads `.vscode/mcp.json`, so if `token-goat install --vscode` (project scope, the default) put token-goat there too, Visual Studio lists the server twice. The install prints a note when that happens, and `token-goat doctor` warns about it; keep one of the two. If `--vscode` (project scope) or `--copilot --local` already put a token-goat block in `.github/copilot-instructions.md`, the Visual Studio block shrinks to a short addendum rather than repeating it, and grows back to the full text when that other block is removed.
|
|
240
|
+
Both `.mcp.json` files are also read by Claude Code, under a different key (`mcpServers`), and Claude Code stops with an error on a `.mcp.json` that has no `mcpServers` key. So token-goat writes its entry under `servers` and, when the file has no `mcpServers` key yet, adds an empty one. It registers nothing for Claude Code and leaves your own `mcpServers` entries as they were. A timestamped `.bak` is written before any change to an existing `.mcp.json`. Visual Studio also reads `.vscode/mcp.json`, so if `token-goat install --vscode` (project scope, the default) put token-goat there too, Visual Studio lists the server twice. The install prints a note when that happens, and `token-goat doctor` warns about it; keep one of the two. If `--vscode` (project scope) or `--copilot --local` (or `-p`) already put a token-goat block in `.github/copilot-instructions.md`, the Visual Studio block shrinks to a short addendum rather than repeating it, and grows back to the full text when that other block is removed.
|
|
221
241
|
|
|
222
242
|
`token-goat doctor` reports the entry and warns when its node or token-goat path no longer exists. To remove: `token-goat uninstall --visualstudio` (add `-p` for the project install). It removes only token-goat's entry and block.
|
|
223
243
|
|
|
@@ -255,7 +275,7 @@ Grok Build already reads Claude Code's `~/.claude/settings.json` as a "Harness C
|
|
|
255
275
|
token-goat install --grok
|
|
256
276
|
```
|
|
257
277
|
|
|
258
|
-
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.
|
|
278
|
+
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.cjs`. 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. That normalization maps every tool id registered in the grok 0.2.93 binary itself — both shell-tool spellings (`run_terminal_command` and `run_terminal_cmd`), `web_fetch`, `web_search`, `glob`, and the `hashline_*`/`*_concise` read/edit/grep variants — onto token-goat's internal tool names, so hooks fire regardless of which id a given Grok build sends.
|
|
259
279
|
|
|
260
280
|
To remove: `token-goat uninstall --grok`.
|
|
261
281
|
|
|
@@ -265,7 +285,7 @@ No separate install step needed. Token-goat compresses the terminal output of th
|
|
|
265
285
|
|
|
266
286
|
Filters are built in for: **Cline** (`cline` / `claude-dev`), **Windsurf** (`windsurf`, including Cascade AI patterns), **Cursor** (`cursor` — this passive terminal filter is separate from the `--cursor` MCP bridge in [Cursor users](#cursor-users) above; it needs no install step), **GitHub Copilot CLI** (`gh copilot explain/suggest` and the standalone `copilot` binary — this passive output filter is separate from the `--copilot` hook bridge above; it works with no install step and covers Copilot CLI's own terminal chrome, not the hook-driven read/index integrations), **Aider** (`aider`), **Continue** (`continue`), **OpenCode** (`opencode`). Each filter strips version banners, spinner/thinking lines, token-usage boilerplate, and tool-call progress noise while keeping the AI response body, error signals, and any user-approval prompts verbatim.
|
|
267
287
|
|
|
268
|
-
Windsurf gets terminal-output compression only — not the read/index hook integration Claude Code, Codex, Copilot CLI, Gemini, Qwen, Kimi, VS Code, Visual Studio and Grok get above. Windsurf's Cascade agent hooks (`cascadeHooksJson`) are configured on Windsurf's own servers, per team, not from a file on your machine, so there is no local hook config for token-goat to install into. There is no `--windsurf` flag, and none is planned unless that changes.
|
|
288
|
+
Windsurf gets terminal-output compression only — not the read/index hook integration Claude Code, Codex, Copilot CLI, Gemini, Qwen, Kimi, Antigravity, VS Code, Visual Studio and Grok get above. Windsurf's Cascade agent hooks (`cascadeHooksJson`) are configured on Windsurf's own servers, per team, not from a file on your machine, so there is no local hook config for token-goat to install into. There is no `--windsurf` flag, and none is planned unless that changes.
|
|
269
289
|
|
|
270
290
|
### JetBrains IDEs (WebStorm, IntelliJ, PyCharm, Rider, PhpStorm) users
|
|
271
291
|
|
|
@@ -284,9 +304,9 @@ There is no auto-update mechanism — token-goat never schedules or runs anythin
|
|
|
284
304
|
|
|
285
305
|
### Upgrading from the Python version
|
|
286
306
|
|
|
287
|
-
The old Python package (`pip install token-goat`) wrote hook entries into `settings.json` with commands containing `token_goat` (underscore), invoking Python directly: something like `pythonw.exe -m token_goat.cli hook pre_tool_use`. The npm package invokes a generated shim instead (`"<node>" "~/.claude/hooks/token-goat-shim.
|
|
307
|
+
The old Python package (`pip install token-goat`) wrote hook entries into `settings.json` with commands containing `token_goat` (underscore), invoking Python directly: something like `pythonw.exe -m token_goat.cli hook pre_tool_use`. The npm package invokes a generated shim instead (`"<node>" "~/.claude/hooks/token-goat-shim.cjs" pre_tool_use "<entry>"`).
|
|
288
308
|
|
|
289
|
-
Both `install` and `uninstall` recognize the
|
|
309
|
+
Both `install` and `uninstall` recognize every command spelling token-goat has ever written as its own: the current shim and native `tg-hook` forms, and the older `token_goat`, `tokenwise`, `token-goat-hook` and pre-shim `token-goat hook` spellings, so you do not need to hand-edit `settings.json`. Installing replaces a stale entry in place rather than leaving a dead one beside the new one, and uninstalling removes it. An entry counts as the current native client only when it has the shape `install` writes today (a `tg-hook` binary, its `--harness` and `--event` flags, and the Node command after `--`); any other `tg-hook` spelling is treated as an old entry and replaced.
|
|
290
310
|
|
|
291
311
|
To upgrade cleanly:
|
|
292
312
|
|
|
@@ -386,19 +406,25 @@ MATLAB, OpenEdge ABL and Salesforce metadata share their file extensions with ot
|
|
|
386
406
|
|
|
387
407
|
`token-goat install` writes the following on your machine — nothing else, anywhere. Every entry is reversed by `token-goat uninstall`. Integrations for other harnesses are additive on the way out as well as in, so a plain uninstall does not touch one you installed with `--codex`, `--copilot`, or a sibling flag: rather than undo something you did not ask about, it names each one still present and the flag that removes it. Run `token-goat doctor` at any time to see which of these are currently present.
|
|
388
408
|
|
|
389
|
-
A bare `token-goat install` (no other flag) installs the Claude Code integration below. Passing a harness flag
|
|
409
|
+
A bare `token-goat install` (no other flag) installs the Claude Code integration below. Passing a harness flag (`--vscode`, `--codex`, `--gemini`, and so on) installs only that harness's own files, listed in its own section further down: it never also touches `~/.claude/` on the side. To have the Claude Code integration as well, run a bare `token-goat install` too. Several harness flags in one command install each of those harnesses. The one exception is `--hermes`, which delegates to `claude -p` and so genuinely needs the Claude Code hooks below; it installs them the same way a bare `install` does.
|
|
390
410
|
|
|
391
411
|
**Claude Code integration** (`~/.claude/`; written by a bare `install`, or by `--hermes`)
|
|
392
412
|
|
|
393
413
|
| Path | What |
|
|
394
414
|
|------|------|
|
|
395
415
|
| `~/.claude/settings.json` | Hook entries for `SessionStart`, `PreToolUse` (Read/Grep/Bash, Drive/WebFetch), `PostToolUse` (Edit/Write/MultiEdit, Read/Grep/Glob, Bash, WebFetch, Skill), and `PreCompact`. Hook entries only: install writes nothing under `permissions`, so it never grants the agent unprompted execution of anything. Existing hooks are preserved; a timestamped `.bak` is written before any change.<br><br>The `PreToolUse` and `PostToolUse` matchers are narrowed to exactly the tools token-goat handles (plus `^mcp__`), generated from the live hook registry rather than a fixed list, so they can't fall out of date as handlers change. Claude Code starts a new process per matcher hit and most of that cost is process startup, so a catch-all matcher would make every unrelated tool call — `TodoWrite`, `TaskUpdate`, and friends — pay for a hook that has nothing to do. |
|
|
396
|
-
| `~/.claude/hooks/token-goat-shim.
|
|
416
|
+
| `~/.claude/hooks/token-goat-shim.cjs` | The hook script those `settings.json` commands invoke (`"<node>" "<shim>" <event> "<entry>"`). It imports the hook library in-process instead of spawning a second process, and naming the node binary directly skips the npm bin wrapper — on Windows a `cmd.exe` layer every hook would otherwise pay for. Measured 480 ms → 324 ms per hook call. Regenerated on every `install` run. Always written here even for a `--project` install, since the command bakes in machine-specific absolute paths; a project-scope `settings.json` just points at this one. The `.cjs` extension keeps Node from loading it as an ES module when a package.json above it says `"type": "module"`. A small `token-goat-shim.js` beside it hands off to the `.cjs` file, for sessions started before the rename that still run the old path. |
|
|
397
417
|
| `~/.claude/CLAUDE.md` | A delimited block (`<!-- token-goat-begin -->` … `<!-- token-goat-end -->`) telling the agent to prefer `token-goat read` / `symbol` / `section` over `Read` / `Grep`. Any existing content is preserved; a timestamped `.bak` is written before any change. |
|
|
398
418
|
| `~/.claude/skills/token-goat/SKILL.md` | The token-goat skill — the same routing guidance in skill form. A timestamped `.bak` is written before any change. |
|
|
399
419
|
|
|
420
|
+
**With `-p`/`--project`**, the hooks go to `<project>/.claude/settings.json`, the routing block to `<project>/CLAUDE.md`, and the skill to `<project>/.claude/skills/token-goat/SKILL.md`, so nothing under `~/.claude/` changes except the shared hook script above, which both scopes use. `token-goat uninstall -p` removes exactly those project files (a `CLAUDE.md` that install created and that now holds nothing else is deleted; your own content in it stays) and leaves the user-wide block and skill alone. Run it from the project root: the project scope is the directory you run the command in.
|
|
421
|
+
|
|
400
422
|
**Background worker.** token-goat does not register any persistent OS-level autostart entry — no Windows registry `Run` key, no systemd user unit, no XDG `.desktop` entry, and no macOS launchd `.plist`. The worker that drains the reindex queue is started manually as a detached child process: `token-goat worker start` launches `node <npm-prefix>/lib/node_modules/token-goat/dist/token-goat.mjs --worker-daemon` and returns immediately, and the child keeps running independent of the parent shell. `token-goat worker status` reports whether it's running; `token-goat worker stop` kills it. If it crashes or is killed while the machine stays up, the next edit hook detects it's gone and respawns it automatically (checked on every edit, rate-limited to roughly once every 5 minutes). It does not survive a reboot or logout, though — re-run `token-goat worker start` after either.
|
|
401
423
|
|
|
424
|
+
**Hook server.** The first hook call also starts up to three hook servers in the background: plain detached `node` processes, not OS services, that answer later hook calls and read-only commands so each call skips starting Node. A read-only command a server has taken waits for its answer however long it runs, rather than starting a second copy beside it. Each listens on a named pipe (Windows) or a Unix socket with mode 0600 (elsewhere), never on a network port, and answers only a caller that proves it holds the random key in `hook-server.key` in the data directory, a file readable only by you. `hook-server.spawn-<slot>`, `hook-server.disabled` and `hook-server.failed` beside it are small marker files: a start rate limit, a record that the config turned the server off, and the reason the last start failed. A server exits after 30 minutes idle, after an upgrade replaces the build it loaded, when `server = false` under `[hooks]` in the global config or `TOKEN_GOAT_HOOK_SERVER=0` turns it off, and within two seconds of its key file being deleted. `uninstall` and `uninstall --purge` stop every running server before touching anything else. `token-goat capabilities` lists it under "Listens for other processes on this machine".
|
|
425
|
+
|
|
426
|
+
**Native hook client.** On Windows and Linux (x64 and arm64), `install` puts a small native program, `tg-hook`, in front of each hook command it writes, for every harness it wires. `tg-hook` hands the call to the hook server and prints its answer, which saves starting Node on every call. When the server cannot answer (it is off, not running yet, or busy), `tg-hook` runs the ordinary Node hook command it wraps, with the same input, so a hook never fails because the server is away. The command after `--` in each entry is exactly the Node command `install` writes without it. On Windows the hook entries name a copy of the binary kept in the data directory under `native\<id>\tg-hook.exe`, not the one inside the npm package, so an upgrade can replace the package while a hook call is still running. `install` refreshes that copy, and moves a running one aside to be removed by a later install. `uninstall` removes the hook entries but leaves that copy in place with the rest of token-goat's data, because a project-scope install in another repository may point at the same copy and `uninstall` cannot see it; delete the `native` folder under the data directory once no install uses it. `install` writes the native form only when the binary for this platform is present and passes its own self-test (`tg-hook --selftest`); otherwise it writes the Node command alone, which is always the case on macOS, where no binary ships. A Windows binary ships only when the release signed it with Authenticode; a release built without the signing certificate carries none, Windows then gets the Node command as macOS does, and `doctor` says this build ships no native hook client for the platform. Linux release binaries carry build provenance attestations; how to check both is under [Verifying what you installed](../SECURITY.md#verifying-what-you-installed). To turn the native client off, set `native = "off"` under `[hooks]` in the global config, or `TOKEN_GOAT_NATIVE_HOOKS=0`, and run `install` again; the variable wins over the config, and a project's `.token-goat.toml` cannot set this key. `token-goat doctor` prints one `Native hooks` line per harness and scope, for example `Native hooks (Codex): native, <path>, self-test passed; last 7 days: 1 served natively, 0 fell back, 0 through Node`: the form wired (native, Node, or mixed), the binary and its self-test result, and over the last seven days how many hook calls the server answered, how many fell back to the Node command and why, and how many ran the Node command directly. An entry written by an older build is flagged as outdated with the `install` command that rewrites it, and an entry whose binary no longer exists is reported as broken, since those events fail rather than fall back. The fallback to Node runs inside `tg-hook`, so it cannot help when `tg-hook` itself is stopped from starting after install, by an antivirus quarantining it or an application-control policy (Smart App Control, App Control for Business, AppLocker) refusing it. Most harnesses then carry on without token-goat's hooks, and Copilot CLI denies every tool call. `doctor` reports either case as a failure; run `install` again, which writes the Node command for a client that still cannot run, and turn the native client off as above if the block comes back.
|
|
427
|
+
|
|
402
428
|
There is no auto-update mechanism. Updating token-goat is always a manual `npm install -g token-goat@latest`.
|
|
403
429
|
|
|
404
430
|
**Data directory** (created on first run)
|
|
@@ -421,7 +447,7 @@ Three things follow, and they are worth knowing before you decide. It never leav
|
|
|
421
447
|
|------|------|
|
|
422
448
|
| `~/.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. |
|
|
423
449
|
| `~/.codex/AGENTS.md` | A delimited block (`<!-- token-goat-codex-begin -->` … `<!-- token-goat-codex-end -->`) with the same routing guidance, adapted for Codex tool names. |
|
|
424
|
-
| `~/.codex/hooks/token-goat-shim.
|
|
450
|
+
| `~/.codex/hooks/token-goat-shim.cjs` | 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. The `.cjs` extension keeps Node from loading it as an ES module when a package.json above it says `"type": "module"`. A small `token-goat-shim.js` beside it hands off to the `.cjs` file, for sessions started before the rename that still run the old path. |
|
|
425
451
|
|
|
426
452
|
**With `--gemini`** (Gemini CLI integration)
|
|
427
453
|
|
|
@@ -440,15 +466,23 @@ Three things follow, and they are worth knowing before you decide. It never leav
|
|
|
440
466
|
| Path | What |
|
|
441
467
|
|------|------|
|
|
442
468
|
| `~/.kimi-code/config.toml` | `[[hooks]]` entries for Kimi Code's `PreToolUse`, `PostToolUse`, `PreCompact`, `UserPromptSubmit`, `SubagentStop`, and `SessionStart` events. Each entry carries only `event` and `command`, the keys Kimi Code's strict schema accepts. Existing hooks and other config keys preserved; a timestamped `.bak` is written before any change. |
|
|
443
|
-
| `~/.kimi-code/hooks/token-goat-shim.
|
|
469
|
+
| `~/.kimi-code/hooks/token-goat-shim.cjs` | The hook script those commands invoke. Rewrites a token-goat block into `hookSpecificOutput.permissionDecision` and a hint into a top-level `message`, and writes empty stdout for a no-op. Regenerated on every `install --kimi` run. The `.cjs` extension keeps Node from loading it as an ES module when a package.json above it says `"type": "module"`. A small `token-goat-shim.js` beside it hands off to the `.cjs` file, for sessions started before the rename that still run the old path. |
|
|
444
470
|
| `~/.kimi-code/AGENTS.md` | A delimited block (`<!-- token-goat-kimi-begin -->` ... `<!-- token-goat-kimi-end -->`) with the routing guidance, adapted for Kimi Code tool names. |
|
|
445
471
|
| `~/.kimi-code/skills/token-goat/SKILL.md` | The same guidance as a Kimi Code skill. |
|
|
446
472
|
|
|
473
|
+
**With `--antigravity`** (Antigravity CLI integration)
|
|
474
|
+
|
|
475
|
+
| Path | What |
|
|
476
|
+
|------|------|
|
|
477
|
+
| `~/.gemini/config/plugins/token-goat/plugin.json` | `{"name": "token-goat"}`, the marker agy needs before it treats the folder as a plugin. Written only if missing. |
|
|
478
|
+
| `~/.gemini/config/plugins/token-goat/hooks.json` | A `token-goat` entry with `PreToolUse` and `PostToolUse` hooks, catch-all matcher, 30-second timeout. Other entries in the file are kept. |
|
|
479
|
+
| `~/.gemini/config/plugins/token-goat/token-goat-hook.cmd` | Windows only. A one-line launcher the hooks call as `.\token-goat-hook.cmd <event>`: agy runs plugin hooks from the plugin folder, and on Windows it neither finds a bare name there nor passes a quoted path through intact. Rewritten on each `install --antigravity` run. |
|
|
480
|
+
|
|
447
481
|
**With `--opencode`** (opencode plugin)
|
|
448
482
|
|
|
449
483
|
| Path | What |
|
|
450
484
|
|------|------|
|
|
451
|
-
| `~/.config/opencode/plugins/token-goat.ts` (
|
|
485
|
+
| `~/.config/opencode/plugins/token-goat.ts` on every platform, Windows included (`$XDG_CONFIG_HOME/opencode/plugins/token-goat.ts` when that is set) | TypeScript bridge plugin. Fires on `tool.execute.before`, `tool.execute.after`, and `experimental.session.compacting`. Covers image shrinking, post-edit indexing, and compact assist. |
|
|
452
486
|
|
|
453
487
|
**With `--pi`** (pi extension)
|
|
454
488
|
|
|
@@ -461,15 +495,16 @@ Three things follow, and they are worth knowing before you decide. It never leav
|
|
|
461
495
|
| Path | What |
|
|
462
496
|
|------|------|
|
|
463
497
|
| `~/.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. |
|
|
464
|
-
| `~/.copilot/hooks/token-goat-shim.
|
|
465
|
-
| `~/.copilot/
|
|
498
|
+
| `~/.copilot/hooks/token-goat-shim.cjs` | 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` or `--copilot -p`) writes `<project>/.github/hooks/token-goat.json` and `<project>/.github/hooks/token-goat-shim.cjs` instead. The `.cjs` extension keeps Node from loading it as an ES module in a repository whose package.json says `"type": "module"`. A two-line `token-goat-shim.js` beside it hands off to the `.cjs` file, for Copilot sessions started before the rename that still run the old path. |
|
|
499
|
+
| `~/.copilot/mcp-config.json` | The `mcpServers.token-goat` entry (`{ tools, type: "local", command, args }`, the shape `copilot mcp add` writes) that registers `token-goat mcp-serve` with Copilot CLI. Other servers in the file are kept. User scope only; follows `COPILOT_HOME`. |
|
|
500
|
+
| `~/.copilot/copilot-instructions.md` | A delimited block (`<!-- token-goat-begin -->` … `<!-- token-goat-end -->`) with the same routing gate written to `~/.claude/CLAUDE.md` and `~/.codex/AGENTS.md`, naming Copilot CLI's own `view`/`grep`/`glob` tools in the conflict-resolution clause. Merged idempotently — everything outside the markers is preserved byte-for-byte. A project-local install (`--copilot --local` or `--copilot -p`) writes `<project>/.github/copilot-instructions.md` instead. |
|
|
466
501
|
|
|
467
502
|
**With `--grok`** (Grok CLI / xAI Grok Build hook bridge)
|
|
468
503
|
|
|
469
504
|
| Path | What |
|
|
470
505
|
|------|------|
|
|
471
506
|
| `~/.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). |
|
|
472
|
-
| `~/.grok/hooks/token-goat-shim.
|
|
507
|
+
| `~/.grok/hooks/token-goat-shim.cjs` | 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. The `.cjs` extension keeps Node from loading it as an ES module when a package.json above it says `"type": "module"`. A small `token-goat-shim.js` beside it hands off to the `.cjs` file, for sessions started before the rename that still run the old path. |
|
|
473
508
|
|
|
474
509
|
**With `--vscode`** (VS Code MCP configuration; **project scope by default** — the only integration that inverts the usual default, because VS Code pins a user-scope hook to the first folder of a multi-root workspace — with `--user` for the old every-project install)
|
|
475
510
|
|
|
@@ -477,7 +512,7 @@ Three things follow, and they are worth knowing before you decide. It never leav
|
|
|
477
512
|
|------|------|
|
|
478
513
|
| `<project>/.vscode/mcp.json` — or `%APPDATA%\Code\User\mcp.json` (Windows) / `~/Library/Application Support/Code/User/mcp.json` (macOS) / `~/.config/Code/User/mcp.json` (Linux) with `--user` | Merges the `token-goat` stdio entry under VS Code's `servers` root key, preserving unrelated servers and settings. `--user` refuses to write when the project scope already has a token-goat-managed entry, to avoid a duplicate registration; the reverse direction is a migration instead, and removes the user-scope install. |
|
|
479
514
|
| `<project>/.github/copilot-instructions.md` (`~/.copilot/instructions/token-goat.instructions.md` with `--user`) | A delimited VS Code routing block that documents supported MCP selection and what the agent hooks can and cannot do with built-in file reads. The user-scope file is a personal instructions file with `applyTo: '**'`, so VS Code applies it in every workspace; install creates it with that frontmatter if it is missing and otherwise merges the block in, and uninstall deletes it again when nothing else is left in it. A user-scope install never writes into the folder you run it from. |
|
|
480
|
-
| `<project>/.github/hooks/token-goat.json`, `token-goat-shim.js`, `token-goat.owners` (`~/.copilot/hooks/` with `--user`) | VS Code agent hooks, shared with `--copilot`; the owners file records which of the two installs still uses them. |
|
|
515
|
+
| `<project>/.github/hooks/token-goat.json`, `token-goat-shim.cjs`, `token-goat-shim.js`, `token-goat.owners` (`~/.copilot/hooks/` with `--user`) | VS Code agent hooks, shared with `--copilot`; the owners file records which of the two installs still uses them. |
|
|
481
516
|
|
|
482
517
|
**With `--visualstudio`** (Visual Studio MCP configuration; user scope by default, `-p`/`--project` for the solution folder)
|
|
483
518
|
|
package/docs/security.md
CHANGED
|
@@ -15,24 +15,24 @@ Outbound network is reserved to these explicit cases:
|
|
|
15
15
|
- Google Drive API calls, only if you already authorized Drive in Claude Code. Token-goat never prompts for its own auth.
|
|
16
16
|
- Image fetches from URLs: either explicit via `token-goat fetch-image <url>`, or when the AI agent issues a WebFetch call that returns image content — the hook intercepts and shrinks the image. The URL always originates from the agent's work, not from token-goat itself.
|
|
17
17
|
- `token-goat screenshot <url>` navigates a headless browser to the URL you give it, subject to the target restrictions described below.
|
|
18
|
-
- The first `token-goat semantic` run on a machine downloads the embedding model from `huggingface.co`, pinned to an immutable commit rather than a mutable branch and checked against a recorded SHA-256 and byte length before it is used,
|
|
18
|
+
- The first `token-goat semantic` run on a machine downloads the embedding model from `huggingface.co`, pinned to an immutable commit rather than a mutable branch and checked against a recorded SHA-256 and byte length before it is used. Unless `onnxruntime-node` is installed, the same first run also downloads the inference runtime: the `onnxruntime-web` 1.30.0 tarball from `registry.npmjs.org` (33 MB), itself checked against a recorded SHA-256 and byte length, from which only the 14 MB `ort-wasm-simd-threaded.wasm` is kept, checked against a digest of its own. The JavaScript that loads it ships inside token-goat and is checked against its recorded digest before it runs. Nothing is installed and no install script runs. Subsequent runs use the local cache, re-verify it, and make no network call. Setting `TOKEN_GOAT_MODEL_CACHE_DIR` adds one more place to look before the network: a directory you name that outlives any single data root, which is how a continuous-integration job stops refetching the weights once per worker. A file taken from there is checked against the same recorded digest as a downloaded one and dropped from the shared directory if it fails, and an entry that is not a plain file of the expected size is passed over without being read at all, so a tampered copy costs a download and cannot substitute different weights, stall the read, or fill the disk. Token-goat also writes there, and treats the directory as somebody else's: it creates its temporary file exclusively rather than through whatever is already sitting at that name, and removes only what it created. Point it at a directory you control all the same, since nothing token-goat does can stop another writer filling it with entries that will simply be rejected. It is an environment variable only, so no project config file can point it anywhere. Skip the download entirely by setting `indexing.embeddings_enabled = false` (it is on by default), in which case `semantic` falls back to full-text search.
|
|
19
19
|
- The first optical-character read of an image downloads the language data (about 4 MB; English `eng` by default, plus any additional opt-in languages configured via `image_shrink.ocr_lang`, `TOKEN_GOAT_OCR_LANG`, or `--lang` among 16 pinned models) from `cdn.jsdelivr.net`, at a fixed version path with precomputed SHA-256 integrity verification against the decompressed traineddata payload. Subsequent reads use the local cache. This happens for an explicit `token-goat image-text`, and also for the automatic text extraction the image-shrink hook performs when the agent reads a screenshot; turn the automatic one off with `image_shrink.ocr_enabled = false`.
|
|
20
20
|
|
|
21
21
|
**One switch for all of it.** Set `network.offline = true` (env `TOKEN_GOAT_OFFLINE`) and every one of the paths above refuses instead of connecting, saying so rather than failing quietly. Anything already cached keeps working: a machine that has the embedding model still runs `semantic`, and one that has the language data still reads text out of images. This is one of the settings a per-project config file may not touch, so cloning a repository cannot switch it back off.
|
|
22
22
|
|
|
23
|
-
**A repository cannot reconfigure the security controls.** A project-root `.token-goat.toml` layers on top of your global config, which is what it is for: hint thresholds, indexing settings, compression tuning. But that file arrives with the repository, so whoever wrote the repository wrote it. Seven whole sections are therefore off limits to it, and come from your global config or the environment only: `injection` (prompt-injection fencing), `webfetch` (the fetch allow and deny lists), `gdrive` (the Google Drive integration), `mcp` (root confinement and the allowed-roots list), `network` (offline mode), `redaction` (the secret-redaction rules), and `screenshot` (the headless browser).
|
|
23
|
+
**A repository cannot reconfigure the security controls.** A project-root `.token-goat.toml` layers on top of your global config, which is what it is for: hint thresholds, indexing settings, compression tuning. But that file arrives with the repository, so whoever wrote the repository wrote it. Seven whole sections are therefore off limits to it, and come from your global config or the environment only: `injection` (prompt-injection fencing), `webfetch` (the fetch allow and deny lists), `gdrive` (the Google Drive integration), `mcp` (root confinement and the allowed-roots list), `network` (offline mode), `redaction` (the secret-redaction rules), and `screenshot` (the headless browser). Twenty individual keys inside otherwise-overridable sections are locked the same way. Seven decide what gets indexed at all: `indexing.cross_project_symbols`, `indexing.skip_dirs`, `indexing.skip_files`, `indexing.skip_minified`, `indexing.large_file_skip_kb`, `indexing.large_file_symbol_only_kb` and `indexing.max_chunks_per_file`, which matter because an unindexed file answers `symbol`, `read` and `semantic` in the same words a name that never existed does. Five more are the switches that decide whether a large file arrives folded rather than whole: `hints.fold_code_bodies`, `hints.fold_comment_blocks`, `hints.fold_prose_paragraphs`, `hints.outline_large_documents` and `hints.skeleton_large_sources`. Five more each guard one thing: `image_shrink.max_image_pixels`, the decompression-bomb cap; `worker.blocked_roots`, the folders you have kept out of the index; `compact_assist.summary_budget_chars`, the length target token-goat hands to whoever writes your compaction summary, which a repository must not be able to set low enough to erase the session; `semantic.max_distance`, the relevance floor for `semantic`, which a repository must not be able to set low enough that its own code stops matching while the command goes on answering from keyword search as though nothing were missing; and `semantic.weak_distance`, the line past which `semantic` warns that its closest match is weak, which a repository must not be able to raise until every poor hit reads as confident. Two more govern the shared database: `indexing.max_db_size_mb` and `indexing.auto_reclaim_embeddings`, which prevent a repository from manipulating global database disk caps or forcing vector purging across projects. One more is `hooks.native`, which decides whether `install` writes the native hook client into the hook configs of every harness on the machine, so a project's file has no say in it. A project file that sets one of them is ignored, and token-goat prints a line naming what it dropped. Everything else stays project-overridable.
|
|
24
24
|
|
|
25
|
-
**The lock covers the config file, not the environment.** These settings still read a `TOKEN_GOAT_*` environment variable, and a repository has ways to set one: a `.envrc` for direnv, a `terminal.integrated.env.*` block in a committed `.vscode/settings.json`, a `containerEnv` entry in a devcontainer. Refusing environment overrides would break the operator who exports a variable in their own shell, which is the legitimate case and the common one, so token-goat reports instead of refusing: `token-goat doctor` prints a `Security config overrides` line naming every locked security setting the environment is currently deciding, and the variable to unset. It covers all twenty-
|
|
25
|
+
**The lock covers the config file, not the environment.** These settings still read a `TOKEN_GOAT_*` environment variable, and a repository has ways to set one: a `.envrc` for direnv, a `terminal.integrated.env.*` block in a committed `.vscode/settings.json`, a `containerEnv` entry in a devcontainer. Refusing environment overrides would break the operator who exports a variable in their own shell, which is the legitimate case and the common one, so token-goat reports instead of refusing: `token-goat doctor` prints a `Security config overrides` line naming every locked security setting the environment is currently deciding, and the variable to unset. It covers all twenty-three locked keys that read an environment variable, and it derives that set from the same two tables that define what a project config may not write, rather than from a list kept alongside them. Settings with a safe side (booleans) are reported when the environment holds them open; settings without one (lists, sizes) are reported whenever the environment supplies a value at all, since there is nothing to compare against. A default install, where nothing is set, prints a single ok line.
|
|
26
26
|
|
|
27
27
|
**Security reports.** See [SECURITY.md](../SECURITY.md). Email `token-goat@dfkhelper.com`; do not file as a GitHub issue. Reports are acknowledged within 7 days; coordinated disclosure with a 90-day default window.
|
|
28
28
|
|
|
29
|
-
**Dependency advisories.** `npm audit` on the published package is empty, for a default install as well as for `npm install --omit=optional`. That took removing the package the findings all came through: `@xenova/transformers`, which supplied the embedding half of `semantic` and carried a critical `protobufjs` advisory plus five more that had no forward patch. It is gone entirely now — the tokenizer and the ONNX runner are token-goat's own code
|
|
29
|
+
**Dependency advisories.** `npm audit` on the published package is empty, for a default install as well as for `npm install --omit=optional`. That took removing the package the findings all came through: `@xenova/transformers`, which supplied the embedding half of `semantic` and carried a critical `protobufjs` advisory plus five more that had no forward patch. It is gone entirely now — the tokenizer and the ONNX runner are token-goat's own code. By default they run on the WebAssembly build of ONNX Runtime, whose JavaScript is bundled into token-goat and whose binary is the pinned download described above, so a default install adds no package for it. If you install the native build, token-goat uses it instead:
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
npm install -g onnxruntime-node #
|
|
32
|
+
npm install -g onnxruntime-node # optional; about 288 MB installed. Drop -g if token-goat is a project dependency
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
That command is the one
|
|
35
|
+
That command is the one place an advisory can still reach: `onnxruntime-node` releases before 1.30.0 pull an `adm-zip` below 0.6.0, which carries [one high advisory](https://github.com/advisories/GHSA-xcpc-8h2w-3j85) that npm reports twice. It is reachable only from that package's own install script, unpacking the binary it just downloaded. The full accounting — including the override that clears it, why co-installing a fixed `adm-zip` does not, and what the old package cost — is under [Dependency advisories](../SECURITY.md#dependency-advisories).
|
|
36
36
|
|
|
37
37
|
**Verifying what you installed.** Every published version is built and pushed by one pinned workflow when a GitHub release is published, with npm provenance, so `npm audit signatures` verifies the tarball against the commit that produced it. Details in [Verifying what you installed](../SECURITY.md#verifying-what-you-installed).
|
|
38
38
|
|
|
@@ -66,7 +66,7 @@ Note what that flag does and does not cover. It stops a caller traversing *out o
|
|
|
66
66
|
|
|
67
67
|
**Where cached content lives, and who can read it.** Cached command output, fetched pages, MCP results, session state and the source index all sit under one data directory (`~/.local/share/token-goat` on Linux, `~/Library/Application Support/token-goat` on macOS, `%LOCALAPPDATA%\dfk-helper\token-goat` on Windows). On POSIX that directory is created owner-only (mode 0700), and an existing one is tightened on the next run, so other local users on a shared build host cannot read it. Windows uses inherited ACLs instead. Individual JSON blobs are additionally written 0600.
|
|
68
68
|
|
|
69
|
-
**Confining `symbol` to one project.** `token-goat symbol` is the one read command that answers from the machine-wide index (`global.db`) rather than the current project, so by default `symbol <name>` and `symbol --grep .` return matching symbols, bodies included, from every project ever indexed on the host. That is deliberate and useful on a personal machine: it is how you find a helper you wrote in another repo. On a shared build host, or under an agent you have confined to one directory, it is a read channel that the directory sandbox does not close, because the answer comes out of the index instead of the filesystem. Set `indexing.cross_project_symbols = false` (env `TOKEN_GOAT_CROSS_PROJECT_SYMBOLS`) and `symbol` only answers from the project it is run in. `--project` and `--file` pointing outside that project are refused rather than honored, so the setting cannot be stepped around from inside the confined process. Every other read command (`read`, `refs`, `callers`, `types`, `dead`, `find`, `semantic`)
|
|
69
|
+
**Confining `symbol` to one project.** `token-goat symbol` is the one read command that answers from the machine-wide index (`global.db`) rather than the current project, so by default `symbol <name>` and `symbol --grep .` return matching symbols, bodies included, from every project ever indexed on the host. That is deliberate and useful on a personal machine: it is how you find a helper you wrote in another repo. On a shared build host, or under an agent you have confined to one directory, it is a read channel that the directory sandbox does not close, because the answer comes out of the index instead of the filesystem. Set `indexing.cross_project_symbols = false` (env `TOKEN_GOAT_CROSS_PROJECT_SYMBOLS`) and `symbol` only answers from the project it is run in. `--project` and `--file` pointing outside that project are refused rather than honored, so the setting cannot be stepped around from inside the confined process. Every other read command (`read`, `refs`, `callers`, `types`, `dead`, `find`, `semantic`, `search`) answers only for the project it runs in, and a root named to read another project's indexed code, whether through `search --project` or the `projectRoot` of an MCP call, is refused the same way unless `mcp.allowed_roots` lists it. Because the permissive setting is the default and says nothing about itself, `token-goat doctor` prints a `Security symbol scope` line stating which way it is currently set, and names the switch when lookups are unconfined.
|
|
70
70
|
|
|
71
71
|
**Redacting credentials this build has never heard of.** Before anything is written to disk or handed back to the model, token-goat redacts the credential shapes it recognises — 19 patterns covering AWS, GitHub, Slack, Stripe, OpenAI, Anthropic, Google, npm and Azure keys, private key blocks, JWTs, bearer and basic auth headers, presigned URL signatures, and credentials embedded in a URL. Two settings cover what a fixed list cannot. `redaction.custom_patterns` (env `TOKEN_GOAT_REDACTION_CUSTOM_PATTERNS`, one pattern per line) is a list of your own regular expressions, redacted as `[REDACTED:custom]` — for an in-house token prefix, an employee number, an internal account id. A pattern that does not compile is skipped and named by `token-goat doctor` rather than failing silently, because a redaction rule you believe is running and which is not is worse than none at all. `redaction.strict` (env `TOKEN_GOAT_REDACTION_STRICT`, off by default) additionally redacts long high-entropy strings that match nothing known: the shape of a credential nobody wrote a rule for. It is a heuristic, and it says so — it needs three of the four character classes and genuine randomness, which spares git SHAs and hex digests, but it will sometimes redact a base64 blob that was not a secret. Both are settings a per-project config file may not touch, so a checked-in `.token-goat.toml` cannot weaken redaction; an environment variable still can, which is what the `Security config overrides` line above exists to surface.
|
|
72
72
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "token-goat",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.30",
|
|
4
4
|
"description": "Surgical token-reduction companion for Claude Code and other AI coding agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/token-goat.mjs",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"scripts": {
|
|
20
20
|
"build": "node esbuild.config.mjs",
|
|
21
|
+
"build:native": "node scripts/build-native.mjs",
|
|
21
22
|
"sbom": "npm sbom --sbom-format cyclonedx --omit=dev",
|
|
22
23
|
"notices": "node scripts/generate-third-party-notices.mjs",
|
|
23
24
|
"notices:check": "node scripts/generate-third-party-notices.mjs --check",
|
|
@@ -26,21 +27,28 @@
|
|
|
26
27
|
"typecheck:tests": "tsc -p tsconfig.tests.json --noEmit",
|
|
27
28
|
"test": "vitest run",
|
|
28
29
|
"model:warm": "tsx scripts/warm-model-cache.ts",
|
|
30
|
+
"eval:hints": "tsx scripts/eval-hints.ts",
|
|
31
|
+
"eval:retrieval": "tsx scripts/eval-retrieval.ts",
|
|
29
32
|
"test:guards": "vitest run tests/guards",
|
|
30
33
|
"test:matrix": "vitest run tests/command_matrix_e2e",
|
|
31
34
|
"test:watch": "vitest",
|
|
32
35
|
"test:vscode-extension": "npm --prefix vscode-extension test",
|
|
33
|
-
"lint": "eslint src tests scripts vscode-extension/src vscode-extension/tests",
|
|
36
|
+
"lint": "eslint src tests scripts evals vscode-extension/src vscode-extension/tests",
|
|
34
37
|
"typecheck:vscode-extension": "npm --prefix vscode-extension run compile",
|
|
35
38
|
"typecheck:vscode-extension:tests": "npm --prefix vscode-extension run typecheck:tests",
|
|
36
39
|
"dev": "tsx src/main.ts",
|
|
40
|
+
"sync": "node scripts/post-merge.mjs",
|
|
37
41
|
"prepare": "node scripts/install-git-hooks.mjs",
|
|
42
|
+
"prepack": "node scripts/verify-native-dist.mjs --pack dist/native",
|
|
38
43
|
"parser:fingerprint": "node scripts/parser-fingerprint.mjs",
|
|
39
44
|
"parser:fingerprint:check": "node scripts/parser-fingerprint.mjs --check",
|
|
45
|
+
"skill:canonical": "node scripts/generate-canonical-skill.mjs",
|
|
46
|
+
"skill:canonical:check": "node scripts/generate-canonical-skill.mjs --check",
|
|
40
47
|
"schema:copilot": "node scripts/extract_harness_schema.mjs auto --harness copilot_cli --out schemas/copilot_cli.hooks.json",
|
|
41
48
|
"schema:copilot:check": "node scripts/extract_harness_schema.mjs auto --harness copilot_cli --out schemas/copilot_cli.hooks.json --check",
|
|
42
49
|
"docs:arch": "node scripts/sync-arch-docs.mjs",
|
|
43
|
-
"docs:arch:check": "node scripts/sync-arch-docs.mjs --check"
|
|
50
|
+
"docs:arch:check": "node scripts/sync-arch-docs.mjs --check",
|
|
51
|
+
"adoption": "node scripts/adoption-baseline.mjs"
|
|
44
52
|
},
|
|
45
53
|
"contributors": [
|
|
46
54
|
{
|
|
@@ -67,7 +75,8 @@
|
|
|
67
75
|
"docs/C4_RUNTIME_ARCHITECTURE.md",
|
|
68
76
|
"LICENSE",
|
|
69
77
|
"THIRD_PARTY_NOTICES.md",
|
|
70
|
-
"scripts/install-git-hooks.mjs"
|
|
78
|
+
"scripts/install-git-hooks.mjs",
|
|
79
|
+
"scripts/verify-native-dist.mjs"
|
|
71
80
|
],
|
|
72
81
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
73
82
|
"engines": {
|
|
@@ -80,7 +89,6 @@
|
|
|
80
89
|
"@eslint/js": "^10.0.1",
|
|
81
90
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
82
91
|
"@types/better-sqlite3": "^9.6.0",
|
|
83
|
-
"@types/jpeg-js": "^0.3.0",
|
|
84
92
|
"@types/node": "^26.2.0",
|
|
85
93
|
"@types/omggif": "^1.0.5",
|
|
86
94
|
"@xenova/transformers": "^2.17.2",
|
|
@@ -98,12 +106,14 @@
|
|
|
98
106
|
"lefthook": "^2.1.10",
|
|
99
107
|
"omggif": "^1.0.10",
|
|
100
108
|
"onnxruntime-node": "^1.27.0",
|
|
109
|
+
"onnxruntime-web": "1.30.0",
|
|
101
110
|
"sharp": "^0.35.3",
|
|
102
111
|
"smol-toml": "^1.8.0",
|
|
103
112
|
"tsx": "^4.23.12",
|
|
104
113
|
"typescript": "^6.0.3",
|
|
105
114
|
"typescript-eslint": "^8.67.0",
|
|
106
|
-
"
|
|
115
|
+
"vite": "^8.3.0",
|
|
116
|
+
"vitest": "^5.0.1",
|
|
107
117
|
"zod": "^4.4.3"
|
|
108
118
|
},
|
|
109
119
|
"optionalDependencies": {
|
|
@@ -130,7 +140,7 @@
|
|
|
130
140
|
"uuid": "^14.0.1",
|
|
131
141
|
"sharp": "$sharp",
|
|
132
142
|
"unzipper": "^0.12.5",
|
|
133
|
-
"adm-zip": "^0.6.
|
|
143
|
+
"adm-zip": "^0.6.1",
|
|
134
144
|
"fast-uri": "^3.1.6",
|
|
135
145
|
"qs": "^6.16.0",
|
|
136
146
|
"tesseract.js-core": "6.1.2"
|