Docs / How it works
How hooks intercept tool calls
Updated
Tokenade works through hooks: small commands your agent runs before and after each tool call. Before a tool runs, a hook can rewrite it (a shell command goes through tokenade wrap); after it runs, a hook can replace its result with a compact version. You don't call anything yourself: once tokenade install has written the hooks, every session uses them.
Why hooks come first
A hook acts before a tool result is ever sent to the model, so the raw output is never paid for. That is why Tokenade prefers hooks over every other channel:
- hooks, or a plugin bridge for agents that load plugins;
- the shell wrapper (
tokenade wrap, and theshell-initaliases); - the MCP proxy (
mcp-wrap); - the LLM proxy, which can only clean up later turns.
Each agent gets the best channel it supports. See supported agents for which one yours uses.
The Claude Code hooks
tokenade install writes these entries to ~/.claude/settings.json. Each carries a _tag beginning with tokenade, which is how uninstall finds them again.
| Event | Job |
|---|---|
| PreToolUse | Rewrite or serve shell commands, reads, searches, web calls and subagent launches before they run; keep a copy of a file before an edit |
| PostToolUse | Deliver compact results for commands, reads, searches, web and MCP tools (search and MCP results need Claude Code 2.1.121 or later); re-index edited files |
| UserPromptSubmit | Add the style note |
| SessionStart | Point at the code index, show recorded dead ends |
| PreCompact | Reset per-conversation state before compaction |
| SubagentStop | Note that a subagent finished |
tokenade hooks status lists what is installed on your machine and tokenade hooks tail shows recent activity.
What happens to each tool
Shell commands
Bash(git log) becomes Bash(tokenade wrap 'git log') before it runs; PowerShell commands get tokenade wrap --shell powershell '…'. The agent sees the compacted output and the exit code of the original command. Commands that need a terminal or follow a stream are left alone, and so is any command matched by one of your own deny or ask permission rules. See output compaction.
File reads
Before a Read runs, the hook can:
- serve a short pointer when the file has not changed since the agent last read it in the session;
- strip what the model doesn't need and redact secrets;
- turn documents (PDF, Office, EPUB…) into text and describe media files instead of returning bytes, as
tokenade readdoes; - hand over a downscaled copy of a large image (long edge over 1024 px by default;
TOKENADE_IMAGE_MAX_EDGE=0keeps full size), and refuse an identical image the agent already saw.
Grep and Glob
Grep and Glob results are folded. TOKENADE_NO_GREP=1 and TOKENADE_NO_GLOB=1 turn these off.
Web
WebSearch runs locally across several engines and replaces the native result; if the engines fail or are too slow, the native tool runs instead. WebFetch is intercepted only for PDFs, other binaries and very large pages. TOKENADE_NO_WEBSEARCH=1 and TOKENADE_NO_WEBFETCH=1 turn these off. See web and search.
MCP tools and subagents
MCP results are folded after the call (TOKENADE_NO_MCP_HOOK=1 turns it off). When the agent starts a subagent through Task or Agent, the hook adds Tokenade's guidance to the subagent's prompt.
Other agents
| Agent | Mechanism |
|---|---|
| Codex | ~/.codex/hooks.json, same kind of hooks. Codex runs hooks only once approved; tokenade install marks them trusted, and the LLM proxy covers Codex until they actually run |
| Cursor | ~/.cursor/hooks.json: shell commands rewritten to tokenade wrap, MCP results folded |
| Copilot CLI | ~/.copilot/hooks/tokenade.json: tool results replaced after each call, plus session-start and prompt hooks |
| OpenCode, Kilo Code | A tokenade.ts plugin in the agent's plugin directory |
| Gemini CLI, Qwen Code | BeforeTool and AfterTool hooks in the agent's settings |
| Antigravity | ~/.gemini/config/hooks.json |
Agent-specific details are in the Agents section.
Hooks never block your agent
- Every hook command exits
0, even if Tokenade itself fails; the failure is logged and the tool call proceeds as if Tokenade were not there. - A hook that receives an oversized event returns no decision instead of guessing.
- Without an active license, shell commands are not rewritten. Secret redaction keeps running whatever the license state.
Turning hooks off
| How | Scope |
|---|---|
TOKENADE_HOOK_DISABLED=1 in the environment | Every hook, for that process |
TOKENADE_HOOK_DISABLED=1 <cmd> as a command prefix | One command |
tokenade raw <cmd> | One command, also sets the variable |
tokenade install --no-hook | Install without hooks |
tokenade uninstall | Remove everything |
If you bypass often, a one-line reminder suggests tokenade expand-ref instead.
Logs
Hook activity is written to ~/.tokenade/debug.log (rotated at 16 MiB). tokenade hooks tail [N] shows the last N records (default 20). tokenade install --no-debug-log disables the log.
Gotchas
- Claude Code runs no hooks in an interactive session in a folder whose trust prompt you haven't accepted.
tokenade healthpoints this out. - Hooks start working on the next agent session, not the one already open.
- If you replace a Tokenade hook entry by hand,
tokenade healthcheckreports it andtokenade installrestores it.