Claude Code OpenAI Compatible Proxy: The Bridge Register and the Removal Drill

Claude Code bridges expose an Anthropic-format endpoint and translate outward. Register each one, canary what it breaks, and pin allowedProviders every quarter.

Hero diagram: a coding CLI sends Anthropic-format requests into a bridge, which fans out to three lanes: a first-party gateway to Claude models, a model-swap translator to other providers, and a consumer-login wrapper marked retireHero diagram: a coding CLI sends Anthropic-format requests into a bridge, which fans out to three lanes: a first-party gateway to Claude models, a model-swap translator to other providers, and a consumer-login wrapper marked retire
Three kinds of bridge can sit behind the same base URL. The register records which one each route is.

Since Sep 29, one managed setting can make Claude Code refuse a session pointed at anything but your gateway, including Anthropic’s own API and a developer’s proxy on localhost. Version 2.1.285 added allowedProviders; set it to ["customEndpoint"] and a session pointed anywhere else is refused. Bridge policy for coding CLIs can now be enforced, which means somebody has to write the list first.

Most of those bridges arrive through a search for a Claude Code OpenAI compatible proxy, and the phrase has the direction backwards. Claude Code speaks the Anthropic Messages, Bedrock and Vertex formats and nothing else. Every tool that lets it reach a GPT or Gemini model exposes an Anthropic-format endpoint to Claude Code and translates outward to the other provider. The translation is where things break, mostly without an error.

This piece gives you a bridge register, three tiers to sort every route into, and a quarterly removal drill that ends with the list pinned in managed settings. It starts with the first-party options, because the cheapest bridge to maintain is the one you never needed.

Anthropic’s gateway line and the Sep 15 to Sep 29 controls

Anthropic’s Other LLM gateways page states the policy in one sentence: “Anthropic doesn’t endorse, maintain, or audit third-party gateway products, and doesn’t support routing Claude Code to non-Claude models through any gateway.” It also warns that a gateway that doesn’t forward what Claude Code sends “breaks the corresponding features, so the gateway product needs to be kept updated as Claude Code evolves.”

Claude Code Docs page titled Other LLM gateways under Administration, Gateways, with the sidebar listing Claude apps gateway, Connect to a gateway, Organization rollout and Compatibility guide Screenshot: Claude Code Docs, “Other LLM gateways” (undated docs page), captured Oct 5, 2026.

The page sits beside the Claude apps gateway and a compatibility guide, and the window’s changes all point the same way. None of them is an enforcement action. They are first-party controls, listed in the Claude Code changelog:

  • Sep 15 and Sep 25 (2.1.273, 2.1.283): gateway hint headers such as x-claude-code-request-class (main, subagent, workflow, compaction, auxiliary), x-claude-code-agent-type, x-claude-code-compaction and x-claude-code-prompt-id. They stay off by default behind a custom base URL “because a proxy that rejects unknown headers would fail the request.”
  • Sep 18 (2.1.278): auto-mode classifier billing. On Enterprise, API, Bedrock, Agent Platform and Foundry, the server runs auto-mode safety checks inside the session’s own requests “and doesn’t charge for them.” A gateway that “strips or rewrites request headers, drops request fields … or edits responses” pushes the session back to billed classifier requests, with a “this session isn’t eligible” notice.
  • Sep 29 (2.1.285): “Added allowedProviders managed setting to limit which API providers a machine may use.”

On the community side, Claude Code Router (musistudio/claude-code-router) shipped v3.1.0 on Sep 10 and v3.1.1 on Sep 16, and now calls itself “a local model gateway and control plane for coding agents”, fronting Claude Code, Codex, Kimi CLI, OpenCode and others from a local endpoint; v3.1.1 was still the npm latest on Oct 5. Further back, Gemini CLI stopped serving personal accounts on Jun 18; The New Stack reports the successor is Antigravity CLI (agy).

The gateway compatibility guide is the document every bridge owner should read before anything else. The section on screen shows Claude Code changing what it sends by connection method: for a model ID it doesn’t recognize, such as a gateway alias, one method gets thinking with a fixed budget and no effort or context-management fields.

Claude Code gateway compatibility guide table comparing request behavior by connection method, including unrecognized model IDs such as a gateway alias, one-hour prompt cache TTL via cache_control and anthropic-beta, and the model used for background tasks Screenshot: Claude Code Docs, “Claude Code gateway compatibility guide” (undated docs page), captured Oct 5, 2026.

Why a translator in front of an agent is not a chat proxy

A translator in front of a chat window fails where you can see it. In front of an agent it fails inside the loop: a stripped field gets a request rejected mid-task, a missing stream ping aborts a long tool run, and a dropped cache marker multiplies the bill with no error at all. In an unattended lane, nobody sees the stall until the morning.

Build the bridge register for every coding CLI

One row per route, not per product. A route is the path from one client CLI, through one bridge, to one set of upstream models. The illustrative rows below show the columns; the values are examples, not recommendations.

Client CLI Bridge (exact repo, version) Tier Credential carried Upstream models What it breaks Owner Removal date
Claude Code Claude apps gateway (in the claude binary) 1 SSO via /login Claude on Bedrock Nothing seen; canary green Platform lead Review each quarter
Claude Code LiteLLM proxy at a pinned release, /v1/messages route 1 LiteLLM key Claude on Vertex Check cache_control pass-through Gateway owner Review each quarter
Claude Code musistudio/claude-code-router v3.1.1 2 Own API keys per upstream GPT, Gemini Caching, thinking, usage display Named developer End of quarter
Codex model_providers entry to org gateway 1 env_key variable OpenAI models Responses features not forwarded Gateway owner Review each quarter
Any CLI Wrapper carrying a Pro or Max login for others 3 Subscription OAuth Any Terms Nobody Today

Two rules make the register useful. The bridge column names the exact project and a pinned version, with an owner/repo whenever the name is generic, or the row is incomplete. And the tier belongs to the route: the same LiteLLM proxy is tier 1 when it forwards Claude models and tier 2 when it routes Claude Code to GPT.

Sort every route into one of three tiers

Tier 1, first-party gateway. The Claude apps gateway, or any Anthropic-format gateway that forwards Claude models to a supported upstream; for Codex, a documented model_providers entry that forwards OpenAI models. This is the documented path. It can still break features if it strips fields, so it still gets a canary.

Tier 2, model-swap translator. Claude Code Router, a LiteLLM route to GPT or Gemini, and the several unrelated repositories that share the name claude-code-proxy (1rgs/claude-code-proxy and fuergaosi233/claude-code-proxy share a name and nothing else). The LiteLLM tutorial shows the shape plainly: Claude Code gets ANTHROPIC_BASE_URL=http://0.0.0.0:4000 and ANTHROPIC_AUTH_TOKEN=$LITELLM_MASTER_KEY, and the proxy translates /v1/messages to OpenAI, Gemini, Vertex or Azure. The tutorial lists no feature caveats; Anthropic’s compatibility guide lists many. Run on your own API keys, these routes sit under the docs’ “doesn’t support” line (the terms text quoted below targets consumer-plan credentials), and they are where silent breakage concentrates.

Tier 3, consumer-login wrapper. Anything that carries a Free, Pro or Max login into another app or for other people. Anthropic’s legal and compliance page says it “does not permit third-party developers to offer Claude.ai login into their own applications, or to route requests through Free, Pro, or Max plan credentials on behalf of their users.” The account risk is covered in unofficial AI wrappers; in this register a tier-3 row has one valid removal date, today.

Start with the first-party routes before you register a translator

Before anyone adds a tier-2 row, check whether a first-party route does the job. The Claude apps gateway is built into the claude binary, signs users in through SSO with /login, exports OTLP telemetry, and forwards to the Anthropic API, Bedrock, Claude Platform on AWS, Google Cloud or Foundry. If your organization already runs a gateway, point Claude Code at it and keep Claude models upstream. The connection shape from the docs, with your values filled in:

export ANTHROPIC_BASE_URL="<your gateway URL>"
export ANTHROPIC_AUTH_TOKEN="<token your gateway issues>"

An apiKeyHelper script in settings can supply the token instead of a static variable. Either way, record the credential in the register, because the docs draw a billing line here. With a gateway credential, users’ “claude.ai subscriptions aren’t used or charged.” Setting only ANTHROPIC_BASE_URL keeps the claude.ai login active, and “the subscription’s usage limits and billing apply”; a gateway on that path must forward the OAuth anthropic-beta value or requests fail with 401.

If the real need is a different model, the first-party answer is usually that model’s own CLI as a separate lane, not a translator in front of Claude Code. A bridge is a rented loop part like any other, and own the loop, rent the model covers how to label one.

Fill “what it breaks” from the compatibility guide

Don’t guess the breakage column. Copy it from the compatibility guide and the auto-mode billing page, then confirm each row with the canary in the drill below.

Matrix chart of what a bridge breaks in Claude Code: ten bridge behaviors such as stripped cache_control, stripped anthropic-beta, rewritten headers and buffered streams, each mapped to its symptom and marked silent cost, hard failure or degradedMatrix chart of what a bridge breaks in Claude Code: ten bridge behaviors such as stripped cache_control, stripped anthropic-beta, rewritten headers and buffered streams, each mapped to its symptom and marked silent cost, hard failure or degraded Sorted by how you find out. The silent-cost rows show up on the invoice, not in the terminal.

The two rows that cost money without an error deserve a sentence each. A bridge that strips cache_control produces “No error: the conversation bills as uncached input on every turn.” A bridge that rewrites headers, fields or responses makes auto-mode safety checks fall back to billed classifier requests on plans where they would otherwise be free. Neither shows up as a failed request.

One more row belongs in every register: per the compatibility guide, the fast-mode availability check and the WebFetch safety check call api.anthropic.com directly regardless of ANTHROPIC_BASE_URL. If the bridge is meant to be the only egress, it isn’t; record that in the last-hop register too.

Turn on gateway hint headers only where the canary passes

Hint headers let a tier-1 gateway tell main turns from subagents, workflows, compaction and auxiliary calls, which is what you need to attribute cost by request class instead of by user. They are off by default behind a custom base URL for a good reason: a proxy that rejects unknown headers fails every request. Set CLAUDE_CODE_GATEWAY_HINT_HEADERS=1 for one lane, run the canary from the drill, and only then roll it to the rest. Never turn it on in front of a tier-2 translator you don’t maintain.

Add the Codex and Antigravity rows

Codex reads custom providers from model_providers in config.toml, with a base_url, an env_key and wire_api = "responses" per the Codex advanced config docs. The shape, with illustrative values:

[model_providers.org-gateway]
base_url = "<your gateway URL>"
env_key = "ORG_GATEWAY_KEY"
wire_api = "responses"

The direction flips for Codex. Its bridges must speak the Responses API to Codex and translate outward from there, so community translators for it, such as lidge-jun/opencodex, go in tier 2 with the same exact-repo rule. Any Gemini CLI row that relied on a personal account stopped working on Jun 18; mark it retired and re-check API-key and Vertex rows by hand.

Run the quarterly removal drill

The drill takes one sitting per team, every quarter, and its output is a shorter register. Each step below matches a box in the diagram.

Flow diagram of the quarterly removal drill for coding-CLI bridges: inventory endpoint overrides, register or retire, canary each bridge, flip the lane to direct, pin allowedProviders, retire tier-3 rows today, then repeat next quarterFlow diagram of the quarterly removal drill for coding-CLI bridges: inventory endpoint overrides, register or retire, canary each bridge, flip the lane to direct, pin allowedProviders, retire tier-3 rows today, then repeat next quarter Six steps, one loop a quarter. A bridge that fails its canary or has no owner leaves the register before the pin goes on.

Step 1: Inventory every endpoint override on every machine

List every ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN, apiKeyHelper, Codex model_providers entry and OPENAI_BASE_URL, in shell profiles, project settings and user settings. A rough per-machine sweep, illustrative; adjust paths to your fleet:

env | grep -E '^(ANTHROPIC_BASE_URL|ANTHROPIC_AUTH_TOKEN|OPENAI_BASE_URL)='
grep -rnE 'ANTHROPIC_BASE_URL|apiKeyHelper' ~/.claude .claude 2>/dev/null
grep -nA4 'model_providers' ~/.codex/config.toml 2>/dev/null
lsof -nP -iTCP -sTCP:LISTEN | grep -iE 'node|python|litellm|router'

The last line catches local listeners that a developer started by hand. Claude Code Router’s local endpoint and a LiteLLM proxy both show up there.

Step 2: Register or retire each hit

Every hit becomes a row or a removal. A row needs the exact repo and version, the tier, the credential and a named owner before the end of the day. A hit nobody claims within a week gets removed from the machine, and the developer gets a note explaining the first-party route.

Step 3: Canary each bridge

Run the same short canary through every registered bridge after each Claude Code upgrade and at every drill:

  • A two-turn session shows cache-read tokens above zero on the second turn.
  • One tool call (read a file, run a harmless command) succeeds.
  • /status shows “Auto mode server: Enabled” on plans where that applies.
  • The usage display is populated, so rate-limit headers made it through.
  • /context shows real counts, not approximations, so count_tokens is forwarded.
  • The gateway log shows zero 400 responses for the session.

A failed box is a row in the breakage column, with a date. Two failed boxes on a tier-2 route is a removal.

Step 4: Flip the lane to direct and confirm it still runs

Unset the bridge for one lane, point it at a first-party route, and run the same task. If the lane cannot run without the bridge, the register says so, and the owner writes down what would replace it. A lane that only works through a translator has a single point of failure you chose without a fallback.

Step 5: Pin allowedProviders in managed settings

Once the register is current, pin it. The managed settings entry, as the docs describe it for a fleet that should only use your gateway, is the setting plus the gateway’s ANTHROPIC_BASE_URL in the same file’s env block:

{
  "allowedProviders": ["customEndpoint"],
  "env": { "ANTHROPIC_BASE_URL": "<your gateway URL>" }
}

With that in place, Claude Code “refuses a session pointed anywhere else, including at Anthropic directly or at a developer’s own proxy”, and accepts ANTHROPIC_BASE_URL only with the value in that file. The 2.1.285 changelog says the setting can limit a machine to “Anthropic API, a custom endpoint, Bedrock, Mantle, Vertex AI, Foundry, Claude Platform on AWS, or a Cloud gateway”; check the settings reference for each value’s identifier before you write it. Then test the pin on one machine by pointing Claude Code at a local translator and confirming the refusal. Managed settings are fleet policy, the same way permission modes are fleet policy.

Step 6: Retire tier-3 rows today

Any row that carries a subscription login for another client or another person comes out the day you find it. Remove the wrapper, revoke the session it held, and move the work to an API key or a first-party gateway. This is the one step with no review period.

The unattended-lane rule

A tier-2 translator never fronts an unattended lane. Overnight jobs, CI agents and scheduled sweeps run on tier-1 routes only, because the failure classes in the chart, from stalls and idle-timeout aborts to uncached billing, are exactly the ones nobody is awake to catch.

Where bridges fail quietly, and the signal for each

Each failure below has a cheap signal. Wire the signal to the register owner, not to a shared channel.

  • Uncached billing. Signal: cache-read tokens stay at zero after turn one, or cost per session jumps right after a bridge upgrade.
  • Billed classifier. Signal: on API or Enterprise sessions, /status shows “Auto mode server: Disabled”, or users report the “this session isn’t eligible” notice.
  • 400s after a CLI upgrade. Signal: errors cluster in the hours after a Claude Code release, because the bridge strips a new beta field.
  • Stalls and aborts. Signal: long tool runs end with idle timeouts only on bridged lanes.
  • Blank usage display. Signal: developers on a bridge can’t see their limits, so they hit them blind.
  • Shadow proxy returns. Signal: refusal messages from allowedProviders in a team channel, which is the pin doing its job and the register missing a row.
  • Name collision. Signal: a row that says claude-code-proxy with no owner or repo.

For LiteLLM rows, the patch posture lives in the LiteLLM patch clock; for MCP and tool gateways, which are a different layer from model-traffic bridges, see the agent gateway control plane.

Bridges are fleet policy, not a developer preference

A bridge on one laptop is a preference. The same bridge on forty laptops, with a subscription login on three of them and no owner on any, is fleet state nobody chose. The register and the pin turn it back into a decision with a name next to it, and the drill keeps it that way each quarter.

Keep the register next to the other lists that describe what runs in-process and in front of your CLIs. Mods ship as in-process code and get their own manifest in the Claude Code mods fleet manifest. The session-level view of which lane ran through which bridge belongs in the same place you watch every session, the multi-agent command center.

FAQ

Can Claude Code use an OpenAI compatible API?

Not directly. Claude Code speaks only the Anthropic Messages, Bedrock and Vertex formats. Bridges such as Claude Code Router or a LiteLLM proxy expose an Anthropic-format endpoint and translate outward to OpenAI-compatible providers. Anthropic’s docs say it doesn’t support routing Claude Code to non-Claude models through any gateway, so expect silent breakage.

What does allowedProviders do in Claude Code?

Added in Claude Code 2.1.285 on Sep 29, 2026, the managed setting limits which API providers a machine may use. Set to customEndpoint only, Claude Code refuses any session pointed elsewhere, including Anthropic directly and a developer’s own local proxy. It turns a bridge register into enforced fleet policy.

Sources

YOU'RE THROUGH THIS ONE.

Keep connecting the dots.

Back to the library