Connect Claude Code to an LLM gateway
Check whether your admin already pointed Claude Code at the company gateway, or set the base URL and credential yourself, test it and fix common errors.
If your company runs an LLM gateway, Claude Code should talk to it with a credential the company issued rather than your personal claude.ai login. This page is for the developer at the keyboard. First check whether it is already set up for you; if it is not, configure it yourself in about five minutes.
Admins deploying the gateway want Roll out an LLM gateway. Gateway operators want the compatibility guide.
Is it already configured?
Admins can push the gateway address and credential through managed settings, device management or an apiKeyHelper. Check before you change anything:
- Run
claude. If you land on the login screen rather than a session, nobody distributed a gateway credential. Skip to configuring it yourself. - Run
/status. It opens on the Status tab. Look for:- an
Anthropic base URLline. It only appears when a gateway address is set. No line means you are not routed through the gateway. - an
Auth tokenorAPI keyline namingANTHROPIC_AUTH_TOKEN,ANTHROPIC_API_KEYor anapiKeyHelper. If you see aLogin methodline naming a claude.ai account instead, the credential is missing and you should set it yourself.
- an
- Send a prompt. A normal reply means you are done.
If both status lines look right but prompts fail, go to troubleshooting.
Configure it yourself
Ask your gateway team for two things: the gateway's base URL, and a credential (either a fixed key or token, or a command that prints one).
Pick the credential variable
Each option puts the credential in a different HTTP header, and a credential in a header the gateway does not read fails with 401.
| What the gateway team said | Variable | Header sent |
|---|---|---|
| "Bearer token" or "Authorization header" | ANTHROPIC_AUTH_TOKEN | Authorization: Bearer ... |
| "API key" or "x-api-key" | ANTHROPIC_API_KEY | x-api-key: ... |
| The credential rotates or lives in a vault | apiKeyHelper setting | Both headers |
If nobody told you, start with ANTHROPIC_AUTH_TOKEN and switch if the test below returns 401.
Set the base URL and credential
For a first attempt, export the values in your shell so you can test before persisting anything. The values here are invented; use your own.
export ANTHROPIC_BASE_URL=https://ai-proxy.acme-retail.co.uk
export ANTHROPIC_AUTH_TOKEN=gw_live_7c2f91
In PowerShell:
$env:ANTHROPIC_BASE_URL = "https://ai-proxy.acme-retail.co.uk"
$env:ANTHROPIC_AUTH_TOKEN = "gw_live_7c2f91"
Exports only reach that terminal and programs started from it; an editor launched from the dock will not see them. Add them to ~/.zshrc, ~/.bashrc or your PowerShell $PROFILE to make them stick. Shell exports also do not reliably reach background agents hosted by the supervisor (see Agent view), so use a settings file for anything that must always route through the gateway.
Once it works, move the values into the env block of a settings file:
~/.claude/settings.json(Windows:%USERPROFILE%\.claude\settings.json) applies to every project..claude/settings.local.jsonapplies to one project. Claude Code adds it to your global gitignore when it writes a setting there itself; if you create it by hand, gitignore it first.
{
"env": {
"ANTHROPIC_BASE_URL": "https://ai-proxy.acme-retail.co.uk",
"ANTHROPIC_AUTH_TOKEN": "gw_live_7c2f91"
}
}
Warning: Never put a credential in a project's
.claude/settings.json. That file is committed and everyone who clones the repo gets it.
If the shell and a settings file both set the same variable, the settings file wins. /status shows which values are in force.
Test the connection
Before opening Claude Code, hit the gateway directly with a one-token request. A failure here is about the gateway or the credential, not your Claude Code set-up. This uses the shell exports, so keep them set even if you have also written a settings file.
curl -sS -w '\nHTTP %{http_code}\n' "$ANTHROPIC_BASE_URL/v1/messages" \
-H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
--data '{"model":"claude-sonnet-4-6","max_tokens":1,"messages":[{"role":"user","content":"ping"}]}'
For an x-api-key gateway, swap the Authorization line for -H "x-api-key: $ANTHROPIC_API_KEY". In PowerShell, Invoke-RestMethod -Method Post with a -Headers hashtable does the same job.
Reading the result:
- JSON beginning
{"id":"msg_with acontentarray: the URL and credential work. - An error about an unknown model: also fine. The gateway authenticated you before rejecting the model name.
401: the credential was refused. If you guessed the variable, switch to the other one and retry.
Then start claude from the same shell, send a message and run /status. The Anthropic base URL line should show the gateway, and the Auth token or API key line should name the variable you set.
When you also have a claude.ai login
A gateway credential variable outranks a saved claude.ai login or Console key. The login stays on disk, unused, and comes back if you unset the variable. ANTHROPIC_AUTH_TOKEN takes over immediately; ANTHROPIC_API_KEY asks you once, in interactive mode, to approve it. If startup warns that two credential sources are active, run /logout to keep only the gateway credential, or unset the variable to go back to the login.
Other surfaces
The CLI reads the variables and settings files above. Everything else differs.
VS Code extension
Put the variables in VS Code's own user settings (run Preferences: Open User Settings (JSON)) under claudeCode.environmentVariables. The extension checks credentials from this setting before it launches; values in ~/.claude/settings.json reach the spawned process but not that login check.
{
"claudeCode.environmentVariables": [
{ "name": "ANTHROPIC_BASE_URL", "value": "https://ai-proxy.acme-retail.co.uk" },
{ "name": "ANTHROPIC_AUTH_TOKEN", "value": "gw_live_7c2f91" }
]
}
See VS Code for the rest of the extension's settings.
Desktop app
The desktop app ignores ANTHROPIC_BASE_URL and settings.json. It reads its own third-party inference configuration instead:
- Pushed by your admin. If the organisation deployed it, the app routes through the gateway with no action from you.
- Set locally. Use Help, then Troubleshooting, then Enable Developer Mode. The app restarts with a Developer menu; choose Developer, then Configure Third-Party Inference, and enter the gateway URL. An admin-pushed configuration overrides this and makes the form read-only.
While a gateway configuration is active, Anthropic-hosted cloud environments are not offered and Remote Control is unavailable. SSH sessions are in beta with a gateway and need Claude Desktop v1.40609.0 or later. They are off until hosts are listed in the sshHostAllowlist key, and because the remote machine connects to the gateway itself, a gateway on your laptop's localhost will not work. A Gateway was unreachable message means the app could not reach the base URL at startup; run the curl test.
GitHub Actions
The GitHub action reads ANTHROPIC_BASE_URL and ANTHROPIC_CUSTOM_HEADERS from the workflow env, and you pass the credential as the anthropic_api_key input, which the action exports as ANTHROPIC_API_KEY (so it travels as x-api-key).
For a bearer-token gateway, the action does not read ANTHROPIC_AUTH_TOKEN on its own but does insist on anthropic_api_key, CLAUDE_CODE_OAUTH_TOKEN or workload identity federation before launching. So pass the same secret twice:
env:
ANTHROPIC_BASE_URL: https://ai-proxy.acme-retail.co.uk
ANTHROPIC_AUTH_TOKEN: ${{ secrets.AI_PROXY_TOKEN }}
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.AI_PROXY_TOKEN }}
The env variable puts the token in Authorization; the input satisfies the launch check and its x-api-key copy is ignored. For an x-api-key gateway, drop the ANTHROPIC_AUTH_TOKEN line.
Agent SDK
The Agent SDK has no gateway options; it hands environment variables to the Claude Code process it spawns via an env option. The two languages differ:
- TypeScript: setting
options.envreplaces the whole environment, so spreadprocess.envinto it. - Python:
ClaudeAgentOptions(env=...)is merged over the inherited environment, so gateway variables in the parent process carry through.
const run = query({
prompt: "Summarise yesterday's failing tests",
options: {
env: { ...process.env, ANTHROPIC_BASE_URL: proxyUrl, ANTHROPIC_AUTH_TOKEN: proxyToken },
},
});
Slack, cloud sessions, Remote Control and voice
Claude Code in Slack and cloud sessions are not part of a gateway deployment, and gateway variables set in a cloud environment's configuration are not applied. If traffic must stay on the gateway, do not enable these for those users.
Remote Control and voice dictation need a claude.ai identity, so both are unavailable while ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN or an apiKeyHelper is active. Remote Control is additionally blocked whenever ANTHROPIC_BASE_URL points at a non-Anthropic host (since v2.1.196). To get them back, log in with claude.ai and unset the credential (voice) or the credential plus ANTHROPIC_BASE_URL (Remote Control). The Remote Control section of claude doctor says what is blocking it.
Optional extras
Only set these if your admin asks, your network restricts egress, or the troubleshooting table points you here.
Extra headers
Some gateways want a tenant or routing header alongside the credential. Set ANTHROPIC_CUSTOM_HEADERS with one Name: Value per line; in JSON, separate pairs with \n:
{
"env": {
"ANTHROPIC_CUSTOM_HEADERS": "X-Cost-Centre: platform\nX-Region: uk"
}
}
Headers like these count as headers needing approval under server-managed settings, and when they come from a project settings file Claude Code applies them under the usual rules for project env values.
Gateway models in the picker
Set CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 and Claude Code asks the gateway for its model list at startup and adds those names to /model. Each shows the gateway's description, or From gateway if none is supplied. A modelPicker lineup with replaceBuiltInOptions hides discovered names too, though the model already in use keeps its row. To check discovery ran, start claude --debug and look for [gatewayDiscovery] lines in ~/.claude/debug/<session-id>.txt; it logs the count on first success and again only when the list changes.
Rotating credentials with apiKeyHelper
apiKeyHelper is a command whose standard output is the credential. Use it when keys expire or come from a vault or SSO tool. It must print nothing except the key: from v2.1.227 a banner or log line alongside it makes the helper fail.
#!/bin/bash
# ~/bin/proxy-token.sh
op read "op://Engineering/ai-proxy/token"
{ "apiKeyHelper": "~/bin/proxy-token.sh" }
On Windows, reference something like powershell -NoProfile -File C:\\tools\\proxy-token.ps1, escaping backslashes in JSON. Output is cached for five minutes; change that with CLAUDE_CODE_API_KEY_HELPER_TTL_MS (for example 900000 for 15 minutes). The value goes out in both Authorization and x-api-key. The settings reference entry for apiKeyHelper lists the other triggers for a re-run.
Silencing traffic outside the gateway
Version checks, telemetry, release notes and similar requests go to Anthropic and services like GitHub, not through the gateway. On an egress-locked network they show up as blocked connections. Claude Code only attaches a credential to telemetry or usage-metrics requests bound for the host that credential belongs to: with ANTHROPIC_BASE_URL set, telemetry goes to Anthropic without your gateway key, and with a gateway credential active, usage metrics are not reported to the Console analytics dashboard. (Before v2.1.246 the gateway credential could be attached to those Anthropic-bound requests.)
To switch it all off, set CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 next to the gateway variables. Be aware that it:
- disables auto-updates, so you need another update route;
- skips the fast mode availability check, so
/fastreports unavailable unless a previous check already enabled it; - does not stop gateway model discovery (before v2.1.257 it froze the cached list);
- does not stop the WebFetch domain safety check to
api.anthropic.com; disable that separately withskipWebFetchPreflight: true.
Data usage lists each telemetry stream and its switch.
Gateways that speak a cloud provider's format
Use these only if your gateway team named Amazon Bedrock, Google Cloud's Agent Platform, Microsoft Foundry or Claude Platform on AWS. If the curl test returned JSON, you do not need them. Bedrock and Agent Platform routes accept those providers' native formats, and Claude Code trims the beta headers and fields it sends to what that provider accepts; Foundry and Claude Platform on AWS routes take the Anthropic Messages format.
| Provider | Variables to set |
|---|---|
| Amazon Bedrock | CLAUDE_CODE_USE_BEDROCK=1, ANTHROPIC_BEDROCK_BASE_URL, CLAUDE_CODE_SKIP_BEDROCK_AUTH=1 |
| Google Cloud's Agent Platform | CLAUDE_CODE_USE_VERTEX=1, ANTHROPIC_VERTEX_BASE_URL, ANTHROPIC_VERTEX_PROJECT_ID, CLOUD_ML_REGION, CLAUDE_CODE_SKIP_VERTEX_AUTH=1 |
| Microsoft Foundry | CLAUDE_CODE_USE_FOUNDRY=1, ANTHROPIC_FOUNDRY_BASE_URL, plus ANTHROPIC_FOUNDRY_API_KEY or ANTHROPIC_FOUNDRY_AUTH_TOKEN |
| Claude Platform on AWS | CLAUDE_CODE_USE_ANTHROPIC_AWS=1, ANTHROPIC_AWS_BASE_URL, ANTHROPIC_AWS_WORKSPACE_ID, CLAUDE_CODE_SKIP_ANTHROPIC_AWS_AUTH=1 |
Notes per provider:
- Skip-auth variables stop Claude Code signing requests with cloud credentials, since the gateway holds those. If the gateway also wants its own token on the Bedrock, Agent Platform or Claude Platform on AWS routes, add
ANTHROPIC_AUTH_TOKEN(sent as bearer) or useANTHROPIC_CUSTOM_HEADERSfor another scheme. Keep the skip-auth variable set: without it, Claude Code strips anyAuthorizationheader those would add. - Bedrock: leave
AWS_BEARER_TOKEN_BEDROCKunset. If set, it is sent asAuthorizationin place of your gateway token even with skip-auth on. - Agent Platform: the project ID and region go into each request path. Per-model region overrides (
VERTEX_REGION_CLAUDE_*), version pins (ANTHROPIC_DEFAULT_OPUS_MODEL,ANTHROPIC_DEFAULT_SONNET_MODEL,ANTHROPIC_DEFAULT_HAIKU_MODEL) and capability declarations such asANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIESwork as described in Google Vertex AI and Model configuration. - Foundry:
ANTHROPIC_FOUNDRY_API_KEYtravels asx-api-key;ANTHROPIC_FOUNDRY_AUTH_TOKENtravels as bearer and wins if both are set (v2.1.203+). For a gateway that injects its ownAuthorization, setCLAUDE_CODE_SKIP_FOUNDRY_AUTH=1and leave both unset. - Claude Platform on AWS: the workspace ID comes from your Claude Platform on AWS set-up.
Confirm with /status. A Bedrock route, for instance, shows API provider: Amazon Bedrock, a Bedrock base URL row and AWS auth skipped. If the base URL row is missing, the variable never reached the session.
Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| Startup warns about two credential sources and says auth may not work as expected | A gateway credential and a saved login are both present | /logout to keep the gateway credential, or unset the variable |
401 about an invalid token | Wrong credential, or right credential in the wrong header | Re-check the variable table; get a new key if revoked |
Your apiKeyHelper script is failing | The helper printed nothing usable | Run it by hand; re-authenticate to your vault. See Errors |
Connection refused or Can't reach the API server, often after a pause for retries | Wrong URL, or VPN or firewall blocking the path | Run the curl test, then check the address with the gateway team |
API returned an empty or malformed response (HTTP 200) | Something returned HTML (an error or login page) instead of an API response | Find the route in front of the gateway that is answering |
400 mentioning context_management or Extra inputs are not permitted | Upstream rejects fields Claude Code sends | Set CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1; for betas it does not cover, use the matching CLAUDE_CODE_USE_* provider variable |
400 mentioning thinking or adaptive | Upstream model build lacks adaptive reasoning (requested for Claude 4.6+) | Upgrade the upstream; on Opus 4.6 and Sonnet 4.6, CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1 also works |
400 with a context limit in the gateway's own words | Gateway enforces a smaller window and rewrites the error, so auto-compact does not trigger | /compact to recover; set CLAUDE_CODE_AUTO_COMPACT_WINDOW (clamped to at least 100,000) and lower CLAUDE_CODE_MAX_OUTPUT_TOKENS |
Every request 400s over a tool schema pattern on v2.1.265 to v2.1.267 | Artifact tool schema uses \p{...} classes the gateway's regex engine rejects | Update to v2.1.268+, or turn artifacts off |
Every request 400s over an unknown tool type such as advisor_20260301 on v2.1.275 | An advisor declaration was sent even with the advisor off | Update to v2.1.276+, or set CLAUDE_CODE_DISABLE_ADVISOR_TOOL=1 |
Gateway models missing from /model | Names not built in, or a replacing modelPicker lineup | Enable discovery, or add the models to the lineup |
/fast says unavailable due to network issues | The check goes straight to api.anthropic.com, or Anthropic rejected a gateway key | Allowlist the host or use the skip variables in Fast mode |
/fast says disabled by your organisation with ANTHROPIC_AUTH_TOKEN | The check needs a claude.ai login or Anthropic key | Set CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK=1 |
| Asked to log in although curl works | No credential readable before first-run setup; project env blocks apply only after the trust prompt | Put ANTHROPIC_AUTH_TOKEN in a shell export, ~/.claude/settings.json or managed settings |
ANTHROPIC_API_KEY silently ignored | It was declined at the one-time approval | Turn on Use custom API key in /config |
This machine's managed settings require a first-party login | Managed settings set forceLoginMethod, forceLoginOrgUUID or forceLoginGatewayUrl, which cannot coexist with gateway credentials | Admin removes those keys, or you drop the gateway credential |
403 HTML page and nothing in gateway logs | A WAF blocked the body (prompts contain XML-like tags and code) | Exempt /v1/messages from body inspection, for example AWS WAF's CrossSiteScripting_Body rule |
| TLS errors though curl works | Claude Code's runtime does not trust your inspection proxy's CA | Set NODE_EXTRA_CA_CERTS; see Network configuration |
Repeated login prompts after removing the gateway set-up are usually a credential storage issue; see Authentication.