| title | RTK Proxy | ||
|---|---|---|---|
| description | Run the RTK Proxy daemon (rtk-proxy) and point your AI agent at it so the pipeline also runs on the requests it sends to the model | ||
| sidebar |
|
rtk gain and the agent hooks work on bash output — what a command prints before your agent reads it. The RTK Proxy works one layer up, on the request your agent sends to the model: conversation history, tool results, file contents. It is a local HTTP daemon your agent talks to instead of talking to the model provider directly. The daemon binary is rtk-proxy; you drive it with rtk llm-proxy.
Claude Code ──▶ rtk-proxy ──▶ api.anthropic.com
│
├─ normalize: strip ANSI / redraws / dupes
├─ your proxy.request.tool_result rules
├─ (opt-in) cache-align
└─ record usage ──▶ rtk gain
It is local: one background process on your machine. It does four things — intercept, compress, forward, record — and does not store prompt or completion text (the opt-in CCR keeps the originals it compresses). What it compresses is in What the Proxy Compresses; its settings and endpoints are in Proxy Configuration.
Both layers are optional and independent. You can run the hooks without the proxy, the proxy without the hooks, or both — rtk gain reports them side by side.
:::note[Separate download, separate licence]
The daemon is a second binary, rtk-proxy, shipped as its own release archive (rtk-proxy-<target>). It is not inside the rtk archive, because it is licensed separately — the rtk CLI is Apache-2.0, rtk-proxy is BUSL-1.1. See Editions and licensing.
:::
Download the rtk-proxy-<target> archive for your platform from the releases page and put the binary next to rtk (anywhere on your PATH also works).
From a source checkout:
cargo build --release --manifest-path proxy/Cargo.tomlrtk looks for the daemon next to its own binary first, then on PATH. If it cannot find it, rtk llm-proxy tells you exactly where it looked.
rtk llm-proxy setup # check the daemon is present, list agents it can serve
rtk llm-proxy start # launch it in the background (no-op if already up)
rtk llm-proxy status # is it running and reachable?
rtk llm-proxy stats # usage and savings from the running daemon
rtk llm-proxy stop # ask it to shut downsetup is the one to run first: it reports which AI agents on this machine can be pointed at the proxy, and how.
You rarely need start by hand — rtk claude starts the daemon for you. See Getting your agent onto the proxy.
Two independent ways in. rtk init configures your agent once and persists it; rtk <harness> needs no configuration at all.
On a Claude Code init, RTK asks:
Set up the RTK proxy (routes Claude Code's API traffic through a local daemon)? [y/N]
Say yes and it writes env.ANTHROPIC_BASE_URL into settings.json and adds extends = "rtk:proxy" to your pipeline. Then it asks how the daemon should come back after a reboot:
| Choice | What it does |
|---|---|
| 1. SessionStart hook (default) | Registers a hook that starts the daemon when a Claude session begins |
| 2. Background service | rtk llm-proxy service install — a per-user service, independent of any agent |
| 3. Neither | Prints the export line and leaves settings.json untouched |
Declining leaves everything alone: "Skipped — enable later with rtk init -g or rtk llm-proxy start --env."
If you already have the base URL set but nothing restarting the daemon, re-running rtk init -g asks only the persistence question.
The question is only asked when the daemon can actually run: the rtk-proxy binary is installed (next to rtk or on PATH) or an rtk-proxy already answers on 127.0.0.1:8080. Otherwise init says the proxy was not offered and leaves settings.json alone. rtk init -g --uninstall removes the env.ANTHROPIC_BASE_URL this flow wrote, when it still points at the RTK daemon; a base URL aimed anywhere else is kept.
It does not do the redirection — that is the settings.json entry above. The hook is a keep-alive: when a session whose ANTHROPIC_BASE_URL points at a loopback address finds nothing listening there, it runs rtk llm-proxy start.
It reports through systemMessage, which is user-visible and never enters model context — RTK spends no tokens configuring itself. Every failure path stays silent rather than disrupting the session.
This route only exists on harnesses that have a SessionStart hook, which is why the next one matters.
rtk claudeOne command, no configuration, nothing persisted: it starts the daemon if it is not already up, points the harness at it, and execs the real binary. On Unix this is a genuine exec, so signals, stdio and the exit code behave exactly as if you had launched the harness directly.
This route needs no hook system. Not every harness has a SessionStart hook, but most offer a base-URL override — so this is how an agent without hooks still gets onto the proxy.
The daemon is agent-agnostic by design: it speaks the provider's dialect, not the agent's. A subcommand exists only where that redirection has been verified end to end, so rtk <harness> resolving is itself the signal that traffic really goes through the daemon. Today the list is:
| Subcommand | Base-URL variable |
|---|---|
rtk claude |
ANTHROPIC_BASE_URL |
A harness absent from the list is never silently unproxied — it falls through to plain passthrough. rtk llm-proxy setup reports what can be launched on this machine.
The launcher never blocks you: if the daemon cannot start, the harness launches unproxied with a warning rather than failing.
eval "$(rtk llm-proxy start --env)"Any agent launched from that shell routes through the proxy. This is choice 3 above, done manually.
Start it on a different address with --bind:
rtk llm-proxy start --bind 127.0.0.1:9090Every subcommand that talks to a running daemon (stop, status, stats) takes the same --bind flag, so you can manage a proxy that is not on the default 127.0.0.1:8080.
Two subcommands forward straight through to the daemon's own CLI:
rtk llm-proxy config <args...> # get/set runtime settings on a running proxy
rtk llm-proxy service <args...> # manage a per-user background serviceRun either with --help to see the daemon's own options; the settings themselves are listed in Proxy Configuration. service is choice 2 of the guided setup — a per-user background service that survives logins independently of any agent.
One fixed location, so the daemon's state does not depend on the shell's working directory when it was started:
| Path | Contents |
|---|---|
~/.config/rtk/llm-proxy/ |
daemon log and databases — on macOS ~/Library/Application Support/rtk/llm-proxy/, on Windows %APPDATA%\rtk\llm-proxy\ |
rtk-proxy.log |
daemon log, started fresh on every start |
rtk-proxy.db |
usage records — the file rtk gain reads |
rtk-proxy-memory.db |
originals kept by CCR (opt-in), 7 days |
Because the usage database lives at a known path, rtk gain can report proxy savings whether or not the daemon is currently running.
With the proxy running, a bare rtk gain switches to a live dashboard covering both layers. See Live dashboard and Attribution.
rtk gain # live dashboard (proxy running, interactive terminal)
rtk gain --text # force the static view
rtk gain --text --by-method # which compression method saved what