Claude Code talks to Anthropic. That is the whole product, and most days it is the right answer. But some work cannot leave the machine, some of it happens on a plane, and some of it is a loop you do not want metered. For those, you want the same editor pointed at a model that runs on your own hardware.
This is that setup. It takes one MCP call, it is reversible in one more, and the part worth knowing up front is what it refuses to touch: your existing Claude Code configuration is never read and never written.
What actually changes when you do this?
A helper binary named claude-tp is symlinked into ~/.local/bin. When you run it, it launches the official claude CLI with a settings file and an MCP config that point at ToolPiper on 127.0.0.1:9998. Your ~/.claude directory is not read, not written, and not backed up, because nothing in it is involved.
That last point is the design, not a side effect. An earlier version of this integration edited ~/.claude/settings.json directly through a 500-line writer service. It worked until it did not: stale marker files, half-written settings after a crash, and shell environment variables silently overriding whatever had been written. Your Claude Code install had become shared state that another app could break.
The replacement moves the whole integration outside ~/.claude. The settings live in a temp file created per launch and deleted when the process exits. If you want your normal Claude Code back, you type claude instead of claude-tp. There is nothing to undo because nothing was changed.
What you need
You don't need: an API key, a Docker container, Python, a config file you write by hand, or an internet connection once the model is downloaded.
You do need: a Mac with Apple Silicon, ToolPiper running with a chat model loaded, the official claude CLI on your PATH, and ~/.local/bin on your PATH. The helper checks the last one for you and tells you if it is missing.
How does the helper get the credential?
ToolPiper mints an inference bearer during install and writes it to a config file at ~/Library/Application Support/ToolPiper/claude-tp-config.json with mode 0600. The helper reads that file at launch. The bearer never appears in the command line, so it cannot be read out of ps.
Two refusals are built into the read. If the config file's permissions are wider than 0600, the helper stops and tells you to chmod it, because the file holds a credential in cleartext and something has touched it. If the bearer does not match the expected tp_ followed by 64 hex characters, it stops as well rather than sending a malformed token.
The install is idempotent. Running it again revokes the previous bearer and writes a fresh one, which is also the repair path when something has drifted.
How to tell it worked
Run the helper's own diagnostic:
claude-tp --statusIt reports four things independently: whether the symlink is valid, whether the config is readable and well-formed, whether ~/.local/bin is actually on your PATH, and whether ToolPiper answers from the helper's point of view. A green line on all four means the next claude-tp launch will reach your local model.
To see exactly what will be handed to claude without launching anything, run claude-tp --print-config. It prints the resolved settings and MCP config with the bearer redacted. That is the honest way to check what the wrapper is doing, and it is the first thing to read before filing a bug against it.
When it doesn't work
"config file missing"
Exit code 2. The install never ran, or the config was deleted. Ask Claude Code to run claude_code_install again.
"config file has unsafe permissions"
Exit code 3. Something widened the file past 0600. The error names the exact chmod to run. Re-running the install also fixes it and rotates the bearer, which is the better choice if you do not know what widened it.
"ToolPiper unreachable"
Exit code 4. ToolPiper is not running, or it is not listening where the config says. Note that the address is the IPv4 literal 127.0.0.1 and not the name localhost. macOS resolves localhost to the IPv6 address first, and ToolPiper's listener is pinned to IPv4 loopback, so a client that resolves the name gets a refused connection from a server that is running perfectly well.
"bearer rejected by ToolPiper"
Exit code 5. The token no longer matches what the server will accept, usually because the install was run again from somewhere else and rotated it. Re-run claude_code_install.
"claude not on PATH"
Exit code 6. The helper wraps the official CLI rather than replacing it, so claude has to be installed and findable first.
Nothing happens after a fresh install
Open a new terminal tab. The symlink lands in ~/.local/bin during install, and a shell that was already running may not pick it up.
Why not just set an environment variable?
Because shell configuration wins. Claude Code reads ANTHROPIC_ environment variables, and anything exported from your .zshrc would silently override the wrapper's settings on every launch. The helper strips every ANTHROPIC_ variable from the child process environment so your shell cannot shadow it.
This is the failure mode that is worst to debug, because it looks like the integration is working. The editor starts, the prompt appears, and requests quietly go somewhere else. Stripping the variables makes the wrapper's configuration the only configuration in play for that launch.
What about the tools?
Inference is one half. The helper also hands claude an MCP config, so the same launch gets ToolPiper's local tool catalog: browser automation, screen capture, transcription, system control, scraping, and the rest.
Mounting tools does not require any of this, though. If tools are all you want, one command does it and no helper is involved:
claude mcp add --transport http toolpiper http://127.0.0.1:9998/mcpThat registration works on stock Claude Code, talking to Anthropic as usual. The helper exists for the other half, which is the part a CLI flag cannot do: choosing where the model runs.
What this does not do
It does not make a local model behave like a frontier model. The gap is real on long multi-file refactors and on tasks that need deep reasoning across a large context, and no amount of wiring closes it. Pick the model to fit the task: local for the loop you run fifty times a day, for anything under NDA, and for the flight. Anthropic's models for the hard thinking.
It also does not migrate anything. Your existing setup is untouched by design, which means it is also unimproved. Both CLIs stay on your PATH, and which one you type is the whole decision.
Try it
Download ToolPiper at modelpiper.com, load a chat model, then ask Claude Code to install the helper. Type claude-tp when you want the local model and claude when you want Anthropic's.
