Why I built my coding-agent tooling as a local proxy instead of hooks
Description and use
The author built Torana, a local proxy between coding agents and model providers, to enable cross-tool optimization, secret checking, token tracking, and old-output trimming without maintaining per-tool hook versions. Plugins are compiled to WebAssembly and run only after permission review.
Problem
The author wanted to optimize coding agent requests, check them for secrets, track token usage, and trim old tool output, but built per-tool hook extensions that required maintaining multiple versions that break when tools change.
Outcome
A single local proxy can serve all coding agents, enabling secret checking, token tracking, and old-output trimming without maintaining per-tool versions; plugins are compiled to WebAssembly and run only after permission review.
Workflow
- Pick a coding agent tool (e.g., Claude Code or Codex CLI)
- Build on that tool's hooks/config/plugins, which requires maintaining multiple versions that break when tools change
- Move the optimization layer to a single local proxy (Torana) that sits between the agent and the model provider
- Point the agent at the proxy via an environment variable such as ANTHROPIC_BASE_URL=$(torana endpoint anthropic)
- Write plugins in Go or Rust that see all agent traffic; plugins are compiled to WebAssembly and run only after the user reviews their permissions
- For tools whose API differs (e.g., Anthropic Messages vs OpenAI Chat Completions vs Responses), have the proxy understand each format before anything can be built on top
Evidence
What if a small local model checked them for secrets first? What if I could see where my tokens actually go? What if old tool output could be trimmed before it's sent again?
The sensible move was to pick one tool like Claude Code or Codex CLI, build on that tool's hooks, and call it a day. In true side project fashion, that's not what happened.
Torana is a local proxy that sits between the agent and the model provider.
ANTHROPIC_BASE_URL='$(torana endpoint anthropic)' claude
Since the proxy sees every request, anything built there works for Claude Code, Codex, OpenCode or Pi. The catch: they don't all speak the same API. Anthropic Messages, OpenAI Chat Completions and Responses all look different, so the proxy has to understand each format before anything can be built on top of it.
Plugins are compiled to WebAssembly, and you can write them in Go or Rust. A plugin that sees all your agent traffic shouldn't run just because it's installed, so nothing runs until you've reviewed its permissions and approved it.
Codex, for example, needs its HTTP/SSE mode instead of websockets for plugins to see the responses.
- Record date: 2026-10-22T17:11:27.562Z