Claude Code configuration
Claude Code custom API base URL: what ANTHROPIC_BASE_URL really does
Pointing Claude Code at a corporate proxy, a self-hosted gateway, or a translator for another provider takes exactly one environment variable. The variable is the easy part. The part that wastes an afternoon is that it is read once, at the moment the agent process starts, and never re-checked. Change it while the agent is running and nothing happens, with no error to tell you why.
Direct answer · verified May 18, 2026
Set the ANTHROPIC_BASE_URL environment variable to your endpoint URL. For the Claude Code CLI, put it in the env block of ~/.claude/settings.json so it applies to every session, or export it in your shell before you run claude. In Fazm, skip the files: open Settings, Advanced, AI Chat, Custom API Endpoint, and paste the URL.
The single catch that applies everywhere: the value is read once when the agent process is created. A change only takes effect after that process restarts. The rest of this page is about that one sentence.
What ANTHROPIC_BASE_URL is, in one paragraph
Claude Code talks to api.anthropic.com by default. The official environment-variable reference describes ANTHROPIC_BASE_URL as a way to “override the API endpoint to route requests through a proxy or gateway.” When it is set, every request goes to the URL you give it instead. The request body, the streaming protocol, and the auth headers do not change; only the destination does. Whatever sits behind that URL just has to accept the same shape of request that Anthropic accepts.
For the CLI, the durable way to set it is the env block of your settings file, because that survives shell restarts and applies to every session:
// ~/.claude/settings.json
{
"env": {
"ANTHROPIC_BASE_URL": "http://127.0.0.1:8766"
}
}For a one-off, an export before launching the CLI works just as well:
export ANTHROPIC_BASE_URL="http://127.0.0.1:8766" claude
That is the whole “how.” If you want the longer setup walkthrough, with a minimal working proxy and the GitHub Copilot bridge pattern, there is a companion guide for that. This page is about the failure mode that guide does not dwell on.
The part every guide skips: the variable is frozen at spawn
Here is the mental model that fixes most ANTHROPIC_BASE_URL confusion. An environment is not a live channel. When the operating system creates a process, it hands that process a copy of the environment as it existed at that instant. The process keeps that copy for its entire life. Nothing you do in a shell afterward reaches back into a process that already started.
So the order of operations matters more than the value. Export the variable, then start claude: it works. Start claude, then export the variable in another tab: that running session never sees it. Put the variable in settings.json: Claude Code reads the file when it starts, so a new session picks it up, but a session that is already open does not re-read the file mid-run. Every one of these is the same rule with a different surface.
Same value, two outcomes, decided entirely by timing
You export ANTHROPIC_BASE_URL in a terminal, then switch back to a Claude Code session that was already open. You expect the next request to hit your proxy.
- The running process snapshotted its environment at launch
- Your new export lives in the shell, not in that process
- Every request still goes to api.anthropic.com
- No error and no warning, so the change looks like it worked
This is also why the variable behaves so differently for a terminal tool versus a desktop app. A terminal session inherits whatever your shell currently has. A macOS app launched from the Dock, Spotlight, or Finder inherits almost nothing from your shell, because ~/.zshrc only runs for interactive shells and LaunchServices never opens one. A custom endpoint exported in your shell can work perfectly for claude in a terminal and have literally zero effect on the same agent running inside an app.
Verify it instead of assuming it
You do not have to guess whether a process actually has the variable. On macOS and Linux, ps eww <pid> prints a process’s full environment. Grep it for the variable name and you get a definitive yes or no, with no detour through your shell:
A reliable way to change the endpoint and confirm it
Set the value where it persists
Put ANTHROPIC_BASE_URL in the env block of ~/.claude/settings.json rather than only your shell. A file-based value cannot drift out of sync with a forgotten export.
Fully quit the agent process
Not just the window or tab. The OS-level process has to end so the next one is created with a fresh copy of the environment. A reload or a new tab inside the same process is not enough.
Confirm with ps eww before you trust it
Find the new process id and dump its environment. If ANTHROPIC_BASE_URL is listed, the routing change is real. If it is not, you restarted the wrong thing.
Watch where the first request lands
Your proxy should log an incoming request the moment the agent makes its first call. If the proxy log stays empty, traffic is still going straight to Anthropic.
How Fazm makes the restart invisible
Fazm is a native macOS app that wraps the real Claude Code agent loop. Because it is a GUI app, the “export in your shell” path does not exist for it at all. So the custom endpoint is handled entirely inside the app, in three short pieces of source you can read yourself.
The three files, all in the open-source repo
Desktop/Sources/Chat/ACPBridge.swift, lines 527 to 530. When the app spawns the agent subprocess, it reads theUserDefaultskeycustomApiEndpointand, when it is not empty, setsenv["ANTHROPIC_BASE_URL"]on that child process. The comment in the source says it out loud: “allows proxying through Copilot, corporate gateways, etc.”Desktop/Sources/Providers/ChatProvider.swift,restartBridgeForEndpointChange()at line 3079. The instant you change the endpoint in Settings, this stops the running bridge so the next query spawns a fresh subprocess that re-reads the variable. This is the function that turns the env-var-staleness problem into a non-event.Desktop/Sources/MainWindow/Pages/SettingsPage.swift. The toggle in Settings, Advanced, AI Chat. The field shows the placeholderyour-proxy:8766and a note that ends: “The endpoint must speak the Anthropic API format; a raw Gemini or OpenAI key will not work here.”
The shape is worth noticing. A CLI user has to know that the environment is frozen at spawn, has to remember to restart the right process, and has to verify it landed. Fazm collapses all of that into a text field and one function call. You paste a URL; the subprocess that was holding the stale value is stopped, and the next one comes up with the new endpoint. The whole thing is readable at github.com/m13v/fazm.
Stop editing dotfiles to change one URL
Fazm runs the real Claude Code agent loop in a native macOS app, with the custom endpoint as a settings toggle that restarts the agent for you. Free to start, open source, runs locally.
Download Fazm for macOS →One behavior change worth knowing: MCP tool search
This one is recent enough that most older write-ups miss it entirely. Setting a custom base URL does not only redirect traffic; it also flips a default. The official documentation states that when ANTHROPIC_BASE_URL is set to a non-first-party host, MCP tool search is disabled by default. If your proxy correctly forwards tool_reference blocks, you can turn it back on by also setting ENABLE_TOOL_SEARCH=true.
The practical takeaway: if you point Claude Code at a custom endpoint and then notice tool discovery behaving differently than it did on the default API, do not assume your proxy is broken. Check whether you need that toggle first. A custom endpoint is a configuration change with a side effect, not just a hostname swap, and this is the side effect.
Troubleshooting, by symptom
Almost every “ANTHROPIC_BASE_URL is not working” report comes down to one of five things. Match the symptom, not the theory.
| Symptom | Likely cause | Fix |
|---|---|---|
| Requests still hit api.anthropic.com | The agent was already running when you set the variable | Fully quit and relaunch the agent process, then confirm with ps eww |
| Works in the terminal, not in a desktop app | GUI apps do not inherit your shell environment | Use the app’s own endpoint setting, not ~/.zshrc |
| Endpoint points somewhere you did not set | A stale value in settings.json is overriding your shell | The settings file env block wins; clear it there |
| 404 on every request through the proxy | Trailing-slash mismatch on the base URL or path | Try the URL both with and without a trailing slash |
| Tool discovery behaves oddly | MCP tool search is off by default on non-first-party hosts | Set ENABLE_TOOL_SEARCH=true if your proxy forwards tool references |
Routing Claude Code through a gateway for a team?
Talk through the corporate-proxy and bring-your-own-gateway setup, and where a native wrapper removes the per-laptop env-var babysitting.
Frequently asked questions
How do I set a custom API base URL in Claude Code?
Set the ANTHROPIC_BASE_URL environment variable to your endpoint URL. For the Claude Code CLI, the cleanest place is the env block of ~/.claude/settings.json, which applies to every session: { "env": { "ANTHROPIC_BASE_URL": "http://127.0.0.1:8766" } }. You can also export it in your shell (export ANTHROPIC_BASE_URL="...") before running claude. The official docs describe the variable as: override the API endpoint to route requests through a proxy or gateway. In Fazm there is no file to edit: open Settings, Advanced, AI Chat, Custom API Endpoint, toggle it on, and paste the URL.
Why is my ANTHROPIC_BASE_URL change not taking effect?
Because environment variables are read once, at the moment a process is created, and never again. If Claude Code (or any app that wraps it) was already running when you changed the variable, that running process is still holding the value it had at launch. The export in your shell updates your shell, not the agent that started ten minutes ago. There is no error and no warning; requests just keep going to the old endpoint. The fix is always the same: fully quit the agent process and start it again so it inherits the current environment.
Why does ANTHROPIC_BASE_URL not work when I set it in ~/.zshrc and launch a Mac app from the Dock?
macOS GUI apps launched from the Dock, Spotlight, or Finder do not inherit your shell environment at all. ~/.zshrc only runs for interactive shells, so an app started by LaunchServices never sees a single line of it. This is why a custom endpoint set in your shell works for the claude CLI in a terminal but has zero effect on a desktop app. A GUI app has to read the value from somewhere it controls: its own settings store, a config file, or a managed profile. Fazm reads it from UserDefaults and injects it into the agent subprocess itself.
Does ANTHROPIC_BASE_URL change anything else about how Claude Code works?
Yes, and this is recent enough that older guides miss it. The official environment-variable docs state that when ANTHROPIC_BASE_URL is set to a non-first-party host, MCP tool search is disabled by default. If your proxy correctly forwards tool_reference blocks, you can re-enable it by also setting ENABLE_TOOL_SEARCH=true. If you point at a custom endpoint and notice tool discovery behaving differently, that toggle is the reason, not a bug in your proxy.
Do I also need ANTHROPIC_AUTH_TOKEN when I set a custom base URL?
It depends entirely on what your endpoint expects. ANTHROPIC_BASE_URL only changes where requests go; it does not change authentication. If your proxy validates the standard Anthropic x-api-key header, keep using ANTHROPIC_API_KEY. If it expects a bearer token instead (many corporate gateways and the GitHub Copilot bridge pattern do), set ANTHROPIC_AUTH_TOKEN, which the docs describe as a custom value for the Authorization header that gets prefixed with Bearer automatically. Use one or the other based on your gateway, not both blindly.
Can I point ANTHROPIC_BASE_URL at an OpenAI or Gemini key directly?
No. ANTHROPIC_BASE_URL only swaps the hostname; the request body, streaming format, and tool-call shapes are still the Anthropic Messages API. A raw OpenAI or Gemini endpoint speaks a different protocol and will reject the request. What goes behind ANTHROPIC_BASE_URL has to be something that accepts the Anthropic /v1/messages shape, which means either Anthropic itself, a compatible gateway (AWS Bedrock through an adapter, a corporate proxy), or a small translator process you run that converts between protocols. Fazm's own settings note says it plainly: the endpoint must speak the Anthropic API format; a raw Gemini or OpenAI key will not work here.
If I set ANTHROPIC_BASE_URL in both my shell and settings.json, which wins?
The settings.json env block wins. Claude Code applies the values in its settings files on top of the inherited shell environment, so a key present in settings.json overrides the same key exported in your shell. If you are debugging a custom endpoint and it stubbornly points somewhere you did not expect, check ~/.claude/settings.json (and any project-level .claude/settings.json) for a stale ANTHROPIC_BASE_URL before you keep editing your shell profile.
How does Fazm apply a custom endpoint without me restarting anything?
Fazm stores the URL in the UserDefaults key customApiEndpoint. When it spawns the agent subprocess, ACPBridge.swift reads that key and, if it is not empty, sets ANTHROPIC_BASE_URL on the child process environment (lines 527 to 530). The piece that solves the staleness problem is restartBridgeForEndpointChange() in ChatProvider.swift, around line 3079: the moment you change the endpoint in Settings, it stops the running bridge so the next query spawns a fresh subprocess that re-reads the variable. You change one field; the restart that every CLI user has to remember happens for you.
Related
Keep reading
Route Claude API through a custom endpoint with ANTHROPIC_BASE_URL
The companion how-to: why you would want a custom endpoint, a minimal working proxy in Node, the GitHub Copilot bridge pattern, and a shipping checklist.
Claude Code persistent sessions, what wraps and what does not
Sessions already live on disk, but auto-restore, one-click fork, and no auto-compact are what you have to add. File paths and line numbers included.
Claude Code API cost management
Where the token spend actually goes in a real Claude Code project, and the levers that move the bill without changing how you work.
Comments (••)
Leave a comment to see what others are saying.Public and anonymous. No signup.