token-goat 2.9.29 → 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.
Files changed (131) hide show
  1. package/README.md +34 -40
  2. package/SECURITY.md +28 -10
  3. package/THIRD_PARTY_NOTICES.md +40 -3
  4. package/dist/native/linux-arm64/tg-hook +0 -0
  5. package/dist/native/linux-x64/tg-hook +0 -0
  6. package/dist/ort-wasm-simd-threaded.mjs +59 -0
  7. package/dist/token-goat-chunk-3CHUNJ2O.mjs +53 -0
  8. package/dist/token-goat-chunk-3Z5S4KGM.mjs +918 -0
  9. package/dist/token-goat-chunk-4FVIAHSI.mjs +211 -0
  10. package/dist/{token-goat-chunk-PGTH2U4C.mjs → token-goat-chunk-4JJS54TR.mjs} +4 -3
  11. package/dist/token-goat-chunk-4LCCNRTG.mjs +313 -0
  12. package/dist/{token-goat-chunk-L7H3U27L.mjs → token-goat-chunk-54K3EUV3.mjs} +1 -1
  13. package/dist/token-goat-chunk-56EIMS3E.mjs +159 -0
  14. package/dist/token-goat-chunk-5BCIJXMO.mjs +609 -0
  15. package/dist/token-goat-chunk-5KDMCMF2.mjs +362 -0
  16. package/dist/token-goat-chunk-5RG5SBL6.mjs +221 -0
  17. package/dist/{token-goat-chunk-RRNZMM3A.mjs → token-goat-chunk-5Y6ZYL6U.mjs} +21 -2
  18. package/dist/{token-goat-chunk-GLXRTTLE.mjs → token-goat-chunk-64FBPDTK.mjs} +12 -8
  19. package/dist/{token-goat-chunk-G23DWHV4.mjs → token-goat-chunk-664RTTUV.mjs} +28 -15
  20. package/dist/token-goat-chunk-67TQJ76B.mjs +57 -0
  21. package/dist/token-goat-chunk-6QMAS7AB.mjs +42 -0
  22. package/dist/token-goat-chunk-7BXSNBY5.mjs +253 -0
  23. package/dist/{token-goat-chunk-IVWI2OCK.mjs → token-goat-chunk-7F2UBPD3.mjs} +40 -11
  24. package/dist/{token-goat-chunk-TGOXNAHW.mjs → token-goat-chunk-7IN2MKDS.mjs} +682 -501
  25. package/dist/token-goat-chunk-7NADEDKJ.mjs +124 -0
  26. package/dist/{token-goat-chunk-KOPIR3KZ.mjs → token-goat-chunk-A3CK6N5Z.mjs} +618 -72
  27. package/dist/{token-goat-chunk-O6I2XU4P.mjs → token-goat-chunk-AFLYLHDH.mjs} +44 -31
  28. package/dist/{token-goat-chunk-TCQANXYC.mjs → token-goat-chunk-AM5V6GSX.mjs} +18 -2
  29. package/dist/{token-goat-chunk-E4ZOJIZK.mjs → token-goat-chunk-APGZXSPS.mjs} +39 -146
  30. package/dist/{token-goat-chunk-D4ETHJD6.mjs → token-goat-chunk-ARDNEC2U.mjs} +9 -7
  31. package/dist/token-goat-chunk-ATCPY7EQ.mjs +134 -0
  32. package/dist/token-goat-chunk-B2RZZCSS.mjs +354 -0
  33. package/dist/{token-goat-chunk-BGYOZ6DO.mjs → token-goat-chunk-B45VMIIH.mjs} +6 -7
  34. package/dist/token-goat-chunk-BPGCUMR7.mjs +30 -0
  35. package/dist/{token-goat-chunk-TDUT2CL6.mjs → token-goat-chunk-C63JQV5K.mjs} +45 -6
  36. package/dist/{token-goat-chunk-ZER6EAXZ.mjs → token-goat-chunk-COBQGL5S.mjs} +2661 -2440
  37. package/dist/token-goat-chunk-COTXZHTS.mjs +39 -0
  38. package/dist/{token-goat-chunk-RQGGMPCR.mjs → token-goat-chunk-CYCEYAEO.mjs} +76 -16
  39. package/dist/token-goat-chunk-CZ3LUXYZ.mjs +4115 -0
  40. package/dist/{token-goat-chunk-ASLWOQ3I.mjs → token-goat-chunk-DZX2YDPT.mjs} +2 -1
  41. package/dist/token-goat-chunk-E3OQX2XT.mjs +824 -0
  42. package/dist/token-goat-chunk-EFHMMIGP.mjs +68 -0
  43. package/dist/token-goat-chunk-ETBHVDB6.mjs +328 -0
  44. package/dist/token-goat-chunk-EVMZJ27Z.mjs +147 -0
  45. package/dist/token-goat-chunk-EXKGNHEG.mjs +2096 -0
  46. package/dist/{token-goat-chunk-RTMVLHWX.mjs → token-goat-chunk-FBNQNSJK.mjs} +2555 -5127
  47. package/dist/{token-goat-chunk-NMTKNYGF.mjs → token-goat-chunk-FNFBKLRD.mjs} +74 -9
  48. package/dist/{token-goat-chunk-RLP6J7WR.mjs → token-goat-chunk-FZ3NEW5O.mjs} +33 -19
  49. package/dist/token-goat-chunk-G5PJ7AGM.mjs +36 -0
  50. package/dist/{token-goat-chunk-DNRPXHYH.mjs → token-goat-chunk-GFBSN7BD.mjs} +29 -401
  51. package/dist/{token-goat-chunk-XYWPOSCN.mjs → token-goat-chunk-GOLEOXZP.mjs} +763 -211
  52. package/dist/token-goat-chunk-H2K3QP6H.mjs +24 -0
  53. package/dist/token-goat-chunk-H2PHHGM5.mjs +188 -0
  54. package/dist/token-goat-chunk-HAVAOB3S.mjs +87 -0
  55. package/dist/token-goat-chunk-HG45AF2B.mjs +2228 -0
  56. package/dist/{token-goat-chunk-HUYUHODZ.mjs → token-goat-chunk-HOJLCGDP.mjs} +12965 -11748
  57. package/dist/{token-goat-chunk-435UQTKD.mjs → token-goat-chunk-HYBFA5X3.mjs} +118 -19
  58. package/dist/token-goat-chunk-IVALLT3S.mjs +48 -0
  59. package/dist/{token-goat-chunk-UXSXQQIY.mjs → token-goat-chunk-IVKIZWAB.mjs} +3 -3
  60. package/dist/{token-goat-chunk-52NSDWYY.mjs → token-goat-chunk-JB6QN6VF.mjs} +6 -4
  61. package/dist/{token-goat-chunk-HNFZZHFW.mjs → token-goat-chunk-JDHE26RP.mjs} +10 -3
  62. package/dist/{token-goat-chunk-FTP4U4QA.mjs → token-goat-chunk-JDU3EXSU.mjs} +12 -11
  63. package/dist/token-goat-chunk-JDWCRD6M.mjs +253 -0
  64. package/dist/{token-goat-chunk-6AK46ZT7.mjs → token-goat-chunk-JN4XMLSD.mjs} +5 -1
  65. package/dist/token-goat-chunk-JTQQGXZH.mjs +733 -0
  66. package/dist/token-goat-chunk-KKUFXAPD.mjs +25 -0
  67. package/dist/token-goat-chunk-KQNZDCBD.mjs +47 -0
  68. package/dist/{token-goat-chunk-2WOUYWLM.mjs → token-goat-chunk-KWPNJBDH.mjs} +27 -3
  69. package/dist/{token-goat-chunk-DPNLUJWB.mjs → token-goat-chunk-LOBGHXPB.mjs} +30 -8
  70. package/dist/token-goat-chunk-MKPF4CL5.mjs +37 -0
  71. package/dist/token-goat-chunk-MNWKPRAL.mjs +13 -0
  72. package/dist/{token-goat-chunk-DNSPXQXQ.mjs → token-goat-chunk-N2NMER56.mjs} +25 -15
  73. package/dist/token-goat-chunk-NYKZLXMK.mjs +218 -0
  74. package/dist/token-goat-chunk-OJBNYTJP.mjs +3087 -0
  75. package/dist/token-goat-chunk-P4QMM4WK.mjs +295 -0
  76. package/dist/token-goat-chunk-PD5VKH46.mjs +184 -0
  77. package/dist/token-goat-chunk-PEPTHRFF.mjs +129 -0
  78. package/dist/{token-goat-chunk-NMBWLRHW.mjs → token-goat-chunk-PU7V3FD6.mjs} +8721 -11104
  79. package/dist/token-goat-chunk-PY533T7F.mjs +46 -0
  80. package/dist/token-goat-chunk-Q5VTGRH7.mjs +761 -0
  81. package/dist/{token-goat-chunk-67BNIKKO.mjs → token-goat-chunk-QCLDAQTS.mjs} +31 -20
  82. package/dist/{token-goat-chunk-SE6E4BKJ.mjs → token-goat-chunk-QSBRTGM2.mjs} +9 -2
  83. package/dist/{token-goat-chunk-VZQEWRVH.mjs → token-goat-chunk-RC35RBUL.mjs} +4 -4
  84. package/dist/{token-goat-chunk-VMFWNHGR.mjs → token-goat-chunk-RHXKCZX3.mjs} +873 -504
  85. package/dist/{token-goat-chunk-PYSUADX4.mjs → token-goat-chunk-RZRTDST7.mjs} +17 -7
  86. package/dist/{token-goat-chunk-ONXH6NZ5.mjs → token-goat-chunk-SJHWVNDQ.mjs} +15 -21
  87. package/dist/token-goat-chunk-SMVRN2HU.mjs +188 -0
  88. package/dist/{token-goat-chunk-QO3LXVVR.mjs → token-goat-chunk-SQSSNQPE.mjs} +2295 -1718
  89. package/dist/{token-goat-chunk-2AWQ2R5X.mjs → token-goat-chunk-T4FK7VOV.mjs} +2 -2
  90. package/dist/token-goat-chunk-U4N3BN2W.mjs +92 -0
  91. package/dist/token-goat-chunk-UA5V6P3P.mjs +122 -0
  92. package/dist/{token-goat-chunk-UA5BKWWQ.mjs → token-goat-chunk-UQ5UK2T7.mjs} +15 -4
  93. package/dist/token-goat-chunk-USILZ3T3.mjs +53 -0
  94. package/dist/{token-goat-chunk-MELOKFDJ.mjs → token-goat-chunk-VES7EL7O.mjs} +7 -1
  95. package/dist/{token-goat-chunk-7CPMDFGB.mjs → token-goat-chunk-VL3YIFHZ.mjs} +389 -14
  96. package/dist/{token-goat-chunk-E5TK5DNO.mjs → token-goat-chunk-VPBBTSJR.mjs} +356 -129
  97. package/dist/{token-goat-chunk-YOOVFPTP.mjs → token-goat-chunk-W3QCJS6G.mjs} +10 -2
  98. package/dist/{token-goat-chunk-LZNBQTDK.mjs → token-goat-chunk-WY3L4DVT.mjs} +11 -7
  99. package/dist/token-goat-chunk-XKI4SEMX.mjs +66 -0
  100. package/dist/token-goat-chunk-XU4P6Z24.mjs +133 -0
  101. package/dist/{token-goat-chunk-H5J3C56Q.mjs → token-goat-chunk-Y776AENC.mjs} +112 -26
  102. package/dist/token-goat-chunk-YARZFCZS.mjs +359 -0
  103. package/dist/{token-goat-chunk-S4VSXURL.mjs → token-goat-chunk-Z44YO3QZ.mjs} +4 -0
  104. package/dist/token-goat-chunk-Z57YODA2.mjs +35 -0
  105. package/dist/{token-goat-chunk-PQ53BSCF.mjs → token-goat-chunk-ZCDTCVIS.mjs} +48 -29
  106. package/dist/token-goat-chunk-ZEJVMUQH.mjs +48 -0
  107. package/dist/{token-goat-chunk-BGHSSJUA.mjs → token-goat-chunk-ZFOBKUWH.mjs} +1 -1
  108. package/dist/token-goat-chunk-ZMBL6UVV.mjs +110 -0
  109. package/dist/{token-goat-chunk-PKRWMHVP.mjs → token-goat-chunk-ZQSJMO2R.mjs} +338 -170
  110. package/dist/token-goat-hook-client.cjs +87 -23
  111. package/dist/token-goat-hook-client.mjs +3 -3
  112. package/dist/token-goat-hook.mjs +46 -30
  113. package/dist/token-goat.core.mjs +6 -6
  114. package/docs/C4_RUNTIME_ARCHITECTURE.md +1 -1
  115. package/docs/cli.md +80 -46
  116. package/docs/install.md +47 -14
  117. package/docs/security.md +7 -7
  118. package/package.json +17 -7
  119. package/scripts/verify-native-dist.mjs +386 -0
  120. package/dist/token-goat-chunk-2NNUA2LR.mjs +0 -143
  121. package/dist/token-goat-chunk-44BM7DDQ.mjs +0 -294
  122. package/dist/token-goat-chunk-C5YPNZKQ.mjs +0 -318
  123. package/dist/token-goat-chunk-CIQ2FTY3.mjs +0 -1990
  124. package/dist/token-goat-chunk-EUSDXRXU.mjs +0 -1429
  125. package/dist/token-goat-chunk-G7IWXCFF.mjs +0 -456
  126. package/dist/token-goat-chunk-JTKCQMQA.mjs +0 -418
  127. package/dist/token-goat-chunk-ORNFMIER.mjs +0 -295
  128. package/dist/token-goat-chunk-VQ6F6T7X.mjs +0 -36
  129. package/dist/token-goat-chunk-YAGLESS3.mjs +0 -23
  130. package/dist/token-goat-chunk-YKSRAWUU.mjs +0 -33
  131. package/dist/token-goat-chunk-Z6KBMOBI.mjs +0 -53
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
 
@@ -130,6 +130,18 @@ token-goat install --kimi
130
130
 
131
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
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.
144
+
133
145
  ### opencode users
134
146
 
135
147
  ```
@@ -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.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.
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"`). `preCompact` and `userPromptSubmitted` are notification-only on real Copilot CLI, per its docs: Copilot never reads a response body for either, so token-goat's compaction manifest and prompt-context hints have no surfacing channel there. The shim still calls through for both so token-goat's internal side effects keep running, but nothing gets injected back into the agent. 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 it rides the `postToolUse` `additionalContext` channel Copilot discards, and its `subagent_type` advice describes Claude Code's Task schema, which Copilot's `task` tool does not use.
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/` and the routing block to `$COPILOT_HOME/copilot-instructions.md`, matching where Copilot CLI actually reads them. To install for one project instead of user scope: `token-goat install --copilot --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`.
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.
198
+
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:
184
200
 
185
- **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**.
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.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`, and `run_in_terminal`. 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.
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
 
@@ -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
 
@@ -286,7 +306,7 @@ There is no auto-update mechanism — token-goat never schedules or runs anythin
286
306
 
287
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 older command spellings — `token_goat`, `tokenwise`, `tg-hook`, `token-goat-hook`, and the pre-shim `token-goat hook` — 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.
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
 
@@ -397,9 +417,13 @@ A bare `token-goat install` (no other flag) installs the Claude Code integration
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
 
402
- **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. 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".
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.
403
427
 
404
428
  There is no auto-update mechanism. Updating token-goat is always a manual `npm install -g token-goat@latest`.
405
429
 
@@ -446,11 +470,19 @@ Three things follow, and they are worth knowing before you decide. It never leav
446
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. |
447
471
  | `~/.kimi-code/skills/token-goat/SKILL.md` | The same guidance as a Kimi Code skill. |
448
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
+
449
481
  **With `--opencode`** (opencode plugin)
450
482
 
451
483
  | Path | What |
452
484
  |------|------|
453
- | `~/.config/opencode/plugins/token-goat.ts` (Linux/macOS) or `%APPDATA%\opencode\plugins\token-goat.ts` (Windows) | TypeScript bridge plugin. Fires on `tool.execute.before`, `tool.execute.after`, and `experimental.session.compacting`. Covers image shrinking, post-edit indexing, and compact assist. |
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. |
454
486
 
455
487
  **With `--pi`** (pi extension)
456
488
 
@@ -463,8 +495,9 @@ Three things follow, and they are worth knowing before you decide. It never leav
463
495
  | Path | What |
464
496
  |------|------|
465
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. |
466
- | `~/.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`) 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. |
467
- | `~/.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`) writes `<project>/.github/copilot-instructions.md` instead. |
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. |
468
501
 
469
502
  **With `--grok`** (Grok CLI / xAI Grok Build hook bridge)
470
503
 
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, and only once `onnxruntime-node` has been installed (see below — it is not part of a default install). 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.
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). Seventeen individual keys inside otherwise-overridable sections are locked the same way. Six decide what gets indexed at all: `indexing.cross_project_symbols`, `indexing.skip_dirs`, `indexing.skip_files`, `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`. The last four are `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, and `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. 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. 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.
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-two 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.
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 over `onnxruntime-node`, which is 17 packages where the old one was 80. That runtime is opt-in and not installed by default. `semantic` still works without it, on keyword search. Both `semantic` itself and `token-goat doctor` say so, and print the one command that brings the embeddings back:
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 # drop -g if token-goat is a project dependency
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 thing here that is not clean: `onnxruntime-node` pulls 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).
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`) is already project-scoped and is unaffected. 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.
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.29",
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
- "vitest": "^4.1.11",
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.0",
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"