Wrapping agents
caveman wrap <agent> starts a coding agent with provider base URLs pointed at the local proxy. It changes the child process environment, not the agent binary or config files.
Most coding agents already support a provider base URL override. wrap knows which setting each registered agent reads. It does not patch the agent, intercept its binary, or translate protocols.
Start, then wrap
You can start the proxy first, then wrap an agent in another shell:
caveman start
caveman wrap claudecaveman start launches the proxy on 127.0.0.1:8787. caveman wrap claude then starts Claude Code with the right environment. For Claude that includes ANTHROPIC_BASE_URL; for OpenAI-protocol agents it uses OPENAI_BASE_URL. The agent still speaks its native protocol.
The agent registry drives it
Which variables get set comes from the registry under public/agents: one profile per agent plus a draft-07 JSON Schema. There are five profiles today: aider, claude, codex, gemini, and opencode.
Each profile names the agent's binaries, its wire protocol, and how to inject the base URL. The injection method is one of two:
env— set literal environment variables, with values that may use templates like{{cave_base_url}},{{cave_api_key}},{{cave_proxy_url}}, and{{cave_org_id}}. A variable that renders empty is omitted, so an empty auth token is never set.config-env-content— render a mode-selected inline JSON config and set it as a single env var. This is howopencodeis wrapped (viaOPENCODE_CONFIG_CONTENT) without ever touching the user's own config file.
The wire protocol is one of anthropic-messages, openai-chat, openai-responses, or gemini-generatecontent.
Adding an agent is a data change
A new coding agent is one JSON file in the registry — no CLI code changes. The compiler validates it fail-closed: an unknown wire_protocol or injection.method fails the build rather than guessing. See the agent registry docs.
Only native protocols
wrap only uses wire protocols the proxy speaks natively — anthropic-messages, openai-chat, openai-responses, and gemini-generatecontent. There is no protocol translation in the wrap path. An agent is wrappable when it speaks one of these and exposes a base-URL override; if it does, pointing it at the proxy is enough, and its requests reach the provider in the same shape they always had.
No code change, byte-safe in transit
Wrapping changes only the agent's base URL through its own configuration. The proxy is byte-safe: in record mode and on any transform error it forwards the original bytes unchanged, and every spend row it records is inferred, never verified.