Docs / How it works

How hooks intercept tool calls

Updated

TL;DR — `tokenade install` adds hooks to your agent's config. Before a tool runs, a hook rewrites shell commands to `tokenade wrap '…'` and stages compact reads; after it runs, PostToolUse hooks fold the result. Hooks never block the agent, and `TOKENADE_HOOK_DISABLED=1` turns them off.

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:

  1. hooks, or a plugin bridge for agents that load plugins;
  2. the shell wrapper (tokenade wrap, and the shell-init aliases);
  3. the MCP proxy (mcp-wrap);
  4. 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.

EventJob
PreToolUseRewrite or serve shell commands, reads, searches, web calls and subagent launches before they run; keep a copy of a file before an edit
PostToolUseDeliver 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
UserPromptSubmitAdd the style note
SessionStartPoint at the code index, show recorded dead ends
PreCompactReset per-conversation state before compaction
SubagentStopNote 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 read does;
  • hand over a downscaled copy of a large image (long edge over 1024 px by default; TOKENADE_IMAGE_MAX_EDGE=0 keeps 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

AgentMechanism
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 CodeA tokenade.ts plugin in the agent's plugin directory
Gemini CLI, Qwen CodeBeforeTool 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

HowScope
TOKENADE_HOOK_DISABLED=1 in the environmentEvery hook, for that process
TOKENADE_HOOK_DISABLED=1 <cmd> as a command prefixOne command
tokenade raw <cmd>One command, also sets the variable
tokenade install --no-hookInstall without hooks
tokenade uninstallRemove 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 health points 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 healthcheck reports it and tokenade install restores it.