# Claude apps gateway compared with Claude Code Router

- **Edition:** CGV-WB/1.0
- **Companion HTML:** CGV-TK/1.0 (`claude-gateway-vs-ccr.html`)
- **Neighbour, not this twin:** CML-WB/1.0 (`claude-mod-landscape.md`) covers extension surfaces. It is not a substitute for these rows.
- **Prepared for:** Karolis Valickas
- **Date:** 3 October 2026
- **Date format:** D Month YYYY. Times already in Europe/Vilnius are kept with the EEST label from the fetch (UTC+3 on these dates).
- **Status:** Formative comparison. Not a validated control catalogue. Not a recommendation to deploy either product.
- **Scope:** Only facts from the 3 October 2026 fetch named in the source bank. This pass did not re-fetch the pages.
- **Units:** Spend amounts in the gateway Admin example are USD cents, not dollars. Star count is the integer 37524 seen on 3 October 2026.
- **Spelling:** British English in prose. API tokens keep their source spelling (`organization` inside the spend JSON, `parentSettingsBehavior`).

## Status banner

Where the fetch left a hole, the row is unverified (`??`) or partial (`~`). A gap is not a claim that the missing thing is false. Do not fill GAP-01 to GAP-06 from memory.

## How to read badges

| Badge | Meaning in this edition |
| --- | --- |
| ✓ | Stated in the 3 October 2026 fetch and tied to a source URL in the bank. |
| ~ | Stated, but one cell is only an absence in the pages fetched, or the claim is partial. |
| ?? | Unverified. Not fetched, not stated, or explicitly unreliable. Not a fact to build on. |


There is no `✓✓` or `✓✓✓` in this edition. This pass did not re-fetch the pages. On a comparison row, the badge is the weaker cell. A checked sentence can sit next to an unverified one.

## What this contains

These two products are easy to mix up because both can sit in front of Claude Code. They are not the same thing.

| ID | Instrument | What it is not |
| --- | --- | --- |
| L-ID | Side-by-side identity (R01 to R20) | Not a merged product, and not the extension-landscape twin |
| L-CONN | Connection methods and client variables (V01 to V09) | Not a statement that CCR implements every base URL |
| L-ROUTE | Routing, auth, and spend | Not a full gateway.yaml schema |
| L-CALL | Who calls whom | Not a packet capture |
| L-HOST | Ports, hosting, config actually seen | Not a current CCR JSON schema |
| L-FAIL | Useful case and fail case | Not a measured outage |
| L-DEC | Edition decisions DEC-01 to DEC-09 | Not new product facts beyond the fetch |
| L-GAP | GAP-01 to GAP-06 | Not evidence that the missing thing is false |


# Part 1 — Two products, side by side

Read the left cell as Claude apps gateway and the right cell as Claude Code Router (CCR). Desktop reading order is gateway then CCR.

```mermaid
flowchart TB
  cc["Claude Code"]
  gw["Claude apps gateway"]
  ccr["CCR on 127.0.0.1 port 3456"]
  orgUp["Organisation upstream"]
  prov["Provider the user configured"]
  cc -->|"gateway sign-in"| gw
  cc -->|"ANTHROPIC_BASE_URL"| ccr
  gw --> orgUp
  ccr --> prov
```

Caption: Two different hops. Gateway sign-in is not ANTHROPIC_BASE_URL. Neither hop is required for the other to exist.


| ID | Concern | Claude apps gateway | Claude Code Router | Badge | Source |
| --- | --- | --- | --- | --- | --- |
| R01 | What it is | Anthropic self-hosted gateway inside the claude binary, started with `claude gateway --config gateway.yaml`. Anthropic does not host the data plane. | Community local model gateway and control plane, repository musistudio/claude-code-router, licence MIT. One local endpoint that routes, fails over, and logs to providers the user configures. | ✓ | SRC-01; SRC-06; SRC-11 |
| R02 | Who it sits between | Sits between Claude Code (and opt-in Claude Desktop) and an upstream the organisation holds. Corporate OIDC, per-group model access, and OTLP telemetry are part of that product description. | Agents talk to the local gateway. CCR then calls the provider the user selected. It does not claim to be an organisation control plane. | ✓ | SRC-01; SRC-06 |
| R03 | Who runs it | The organisation, on a Linux server. macOS is only for local development. Windows is not a server. | The user, via the desktop app, the npm CLI `@musistudio/claude-code-router`, or Docker. | ✓ | SRC-01; SRC-06; SRC-09 |
| R04 | Where clients send traffic | Clients speak the Anthropic Messages API to the gateway. The quickstart listener is host `0.0.0.0`, port `8080`, with a separate `public_url`. | Default model gateway `http://127.0.0.1:3456`. Default management UI `http://127.0.0.1:3458`. In Docker, host port 3458 proxies to the in-container gateway `127.0.0.1:3456`. | ✓ | SRC-01; SRC-06; SRC-08 |
| R05 | Upstreams named | Amazon Bedrock, Claude Platform on AWS, Google Cloud Agent Platform, Microsoft Foundry, or the Anthropic API, with failover. Nothing is sent to Anthropic unless the Anthropic API is a configured upstream. | README lists OpenAI Chat/Responses, Anthropic Messages, Gemini Generate Content/Interactions, OpenRouter, DeepSeek, SiliconFlow, Moonshot, Kimi Code, Mistral, Z.AI, Bailian, and custom compatible providers. | ✓ | SRC-01; SRC-06 |
| R06 | Native Bedrock, Foundry, or Vertex | Those clouds are named gateway upstreams (R05). A gateway in front of Claude Platform on AWS must also forward `anthropic-workspace-id`. | Not stated. Protocols listed for CCR are OpenAI, Anthropic Messages, and Gemini. Whether CCR speaks Bedrock InvokeModel, Foundry, or Vertex as native upstreams is unverified. | ?? | SRC-03; SRC-04; GAP-04 |
| R07 | Products | Claude Code v2.1.195 or newer. Claude Platform on AWS as an upstream needs v2.1.198 or newer on the server. Claude Desktop Cowork and Code tabs, plus Chat if enabled, via `/user/bootstrap` (server v2.1.203 or newer). Not a claude.ai session: no `/design-sync`, `/design-login`, or Remote Control. No unattended CI token; browser device flow only. | Claims Claude Code (CLI and app), Claude Design, Codex (CLI and app), Grok CLI, Kimi CLI, Kilo Code, OpenCode (CLI and app), Pi, ZCode, WorkBuddy, and compatible API clients. Does not claim claude.ai, Desktop policy, or the Anthropic API. | ✓ | SRC-01; SRC-06 |
| R08 | How Claude Code is pointed at it | Managed settings: `forceLoginMethod` `gateway`, `forceLoginGatewayUrl`, `parentSettingsBehavior` `merge`. Claude Code only connects at `/login` if the host resolves to private addresses or a declared owned public block. | `ANTHROPIC_BASE_URL` can point Claude Code at an Anthropic Messages gateway, including CCR. Setting only that variable does not replace a saved claude.ai login. A gateway credential or `/login` does. These are different connection methods. The compatibility guide says the method changes which betas and model IDs Claude Code sends. | ✓ | SRC-01; SRC-03; SRC-04 |
| R09 | Auth | OIDC only: Okta, Entra ID, Google Workspace, Keycloak, Dex, PingFederate, or any OIDC IdP. SAML and LDAP are not supported. One issuer. Short-lived bearer, default `ttl_hours` 1. The upstream credential stays on the gateway. | Management UI/RPC token (`ccr_web_token` or `CCR_WEB_AUTH_TOKEN`) and separate CCR client API keys (`Authorization` Bearer or `x-api-key`). Upstream keys stay in the local data directory. Local login import where supported. No corporate OIDC or SSO in the fetched README or CLI guide. That absence is not a proof it cannot exist on an unfetched page. | ~ | SRC-01; SRC-06; SRC-09 |
| R10 | Model access | The gateway translates model IDs per upstream (`auto_include_builtin_models`). IdP groups map to `availableModels`. A model that was not granted returns 400. The developer picks inside the allowlist. | Conditions on headers and bodies, prefixes, rewrites, retries, and ordered fallbacks. Profiles set the model per agent. | ✓ | SRC-01; SRC-06 |
| R11 | Spend caps | Optional per-user, per-IdP-group, and organisation caps in USD cents, for a day, a week, or a month. Over the cap: HTTP 429, `error.type` `billing_error`, `x-should-retry` false. Amounts are estimates, not the provider invoice. Postgres is required. | Separate client keys with expiration, and local request, token, and image limits. Logs show an estimated cost. No organisation Admin API and no IdP-group USD caps in the pages fetched. That absence is not a proof those APIs do not exist elsewhere. | ~ | SRC-02; SRC-06; SRC-09 |
| R12 | Where it runs | Linux server. macOS only for local development. Windows is not a server. Postgres 14 or newer. Private network. HTTPS. Plain HTTP only for loopback. | Desktop app on macOS, Windows, and Linux. CLI needs Node.js 22 or newer. The Docker guide says read it before exposing CCR remotely. What that guide requires beyond that sentence was not copied here. | ✓ | SRC-01; SRC-06; SRC-08; SRC-09 |
| R13 | What breaks | A separate gateway must forward new headers and body fields or features break. This gateway is released with the CLI so operators do not keep an allowlist. On a gateway session the CLI turns off server-side WebSearch, the 1-hour cache TTL, Remote Control, design login and design sync, and feature-flag features such as `/import`. Indefinite backwards compatibility of the protocol is not guaranteed. | The current README and the ccrdesk troubleshooting page do not document Claude Code request-shape breakage. What happens when the request shape changes is unverified (GAP-03). Tag v3.0.22 notes fixes for SSE corrupting multi-byte characters split across chunks, and for the Claude Code path in the local-agent auth hook. Anthropic's compatibility guide, which is not a CCR document, says stripping `anthropic-beta` or rewriting bodies yields 400s. | ~ | SRC-01; SRC-04; SRC-06; SRC-07; GAP-03 |
| R14 | Licence | Not stated on the gateway docs. Unverified. | MIT on the README and on the npm page. | ?? | GAP-05; SRC-06; SRC-11 |
| R15 | Version seen on 3 October 2026 | Client and server floors are in R07. No separate gateway package version was in the fetch. | npm showed 3.1.1, MIT, updated 16 September 2026 15:28 EEST. Tag v3.0.22 published 24 August 2026 15:23 EEST is not that npm package version. | ✓ | SRC-01; SRC-06; SRC-11 |
| R16 | Stars and forks | Not a public GitHub project in this comparison. No star count. | Stars seen on 3 October 2026: 37524. That integer is the fetched count. Fork count is not reliable and stays unverified. | ~ | SRC-06; GAP-06 |
| R17 | Config that was actually seen | Quickstart groups are in Part 6. The full `gateway.yaml` reference was not fetched. Unverified beyond those named fields. | Config directory `~/.claude-code-router` (Windows `%APPDATA%\claude-code-router`). Live config is `config.sqlite`, not a JSON file the current README shows. Generated runtime file `gateway.config.json`. The current README has no `config.json` schema. The linked configuration page is a dashboard-widget guide, not a schema. | ?? | SRC-01; SRC-06; SRC-08; GAP-01; GAP-02 |
| R18 | Endorsement | Documented by Anthropic as its own gateway, released with the CLI. | Anthropic does not endorse, maintain, or audit third-party gateways, and does not support routing Claude Code to non-Claude models through any gateway. The CCR README is explicitly about routing to those other providers. | ✓ | SRC-01; SRC-03; SRC-06 |
| R19 | Protocol list versus the public guide | `GET /protocol` on a running Claude apps gateway is that product's own endpoint list. It is not the public compatibility guide. | Not claimed for CCR. The public guide is https://code.claude.com/docs/en/llm-gateway-protocol. | ✓ | SRC-01; SRC-04 |
| R20 | Billing off a claude.ai subscription | A gateway credential or `/login` is what switches the client. Gateway sign-in is the managed-settings path in R08. | `ANTHROPIC_BASE_URL` alone does not switch billing off a claude.ai subscription, including when that URL is CCR. | ✓ | SRC-03 |


### Do not confuse

| ID | Rule |
| --- | --- |
| DEC-01 | CCR is not the Claude apps gateway. Do not describe one with the other's ports, sign-in, or licence. |
| DEC-02 | Gateway sign-in is `forceLoginMethod` `gateway` plus `forceLoginGatewayUrl`. `ANTHROPIC_BASE_URL` is a different connection, including when it points at CCR. |
| DEC-03 | `ANTHROPIC_BASE_URL` alone does not move billing off a claude.ai subscription. A gateway credential or `/login` does. |
| DEC-04 | CCR port 3456 is the model gateway. Port 3458 is the management UI. In Docker, 3458 is the public front door and proxies to 3456. The apps-gateway quickstart listener is `0.0.0.0:8080` with a separate `public_url`. |
| DEC-05 | Anthropic does not support non-Claude models through any gateway. The CCR README is about routing to other providers. A CCR route is not an Anthropic-supported path. |
| DEC-06 | `GET /protocol` on a running apps gateway is that product's endpoint list. The public compatibility guide is a different document. |
| DEC-07 | A historical CCR `config.json` shape is not current. The live file seen in this fetch is `config.sqlite`. |
| DEC-08 | Git tag v3.0.22 (24 August 2026 15:23 EEST) is not the npm package version fetched the same day (3.1.1, updated 16 September 2026 15:28 EEST). |
| DEC-09 | A gap stays unverified. It is not a finding that the missing thing is false. |


# Part 2 — Connection methods

```mermaid
flowchart TB
  subgraph gateSign["Gateway sign-in"]
    flm["forceLoginMethod gateway"]
    flu["forceLoginGatewayUrl"]
  end
  subgraph otherGw["Other gateway including CCR"]
    base["ANTHROPIC_BASE_URL"]
    keep["Does not replace a saved claude.ai login"]
  end
  flm --> flu
  base --> keep
```

Caption: Left branch is apps-gateway sign-in. Right branch is any Anthropic Messages gateway, including CCR. The right branch does not clear a saved claude.ai login by itself.


### Managed settings for the apps gateway

| Key | Value in the fetch |
| --- | --- |
| `forceLoginMethod` | `gateway` |
| `forceLoginGatewayUrl` | `https://claude-gateway.internal.example.com` (quickstart example) |
| `parentSettingsBehavior` | `merge` |


Claude Code only connects at `/login` if the host resolves to private addresses or a declared owned public block. ✓ SRC-01

### Claude Code client variables

These variables are from the Anthropic gateway docs. They describe how Claude Code talks to a gateway. They are not a feature list for CCR. Bedrock, Vertex, and Foundry variables do not close GAP-04.

| ID | Variable | What the fetch says | Badge | Source |
| --- | --- | --- | --- | --- |
| V01 | `ANTHROPIC_BASE_URL` | Points Claude Code at an Anthropic Messages gateway (`/v1/messages`, optional `/v1/messages/count_tokens`). Setting only this does not replace a saved claude.ai login. | ✓ | SRC-03 |
| V02 | `ANTHROPIC_AUTH_TOKEN` | Sent as `Authorization` Bearer. | ✓ | SRC-03 |
| V03 | `ANTHROPIC_API_KEY` | Sent as `x-api-key`. | ✓ | SRC-03 |
| V04 | `ANTHROPIC_BEDROCK_BASE_URL` | Used with `CLAUDE_CODE_USE_BEDROCK=1`. This is a Claude Code client variable. It is not evidence that CCR speaks Bedrock InvokeModel (GAP-04). | ✓ | SRC-03 |
| V05 | `ANTHROPIC_VERTEX_BASE_URL` | Used with `CLAUDE_CODE_USE_VERTEX=1`. Same caveat as V04 for CCR (GAP-04). | ✓ | SRC-03 |
| V06 | `ANTHROPIC_FOUNDRY_BASE_URL` | Foundry base URL for a gateway in front of that upstream. Not a CCR feature claim (GAP-04). | ✓ | SRC-03 |
| V07 | `ANTHROPIC_AWS_BASE_URL` | Claude Platform on AWS. A gateway in front of that platform must also forward `anthropic-workspace-id`. | ✓ | SRC-03; SRC-04 |
| V08 | `allowedProviders` | A managed machine can be pinned to one base URL with `allowedProviders` set to a list containing `customEndpoint`. Claude Code v2.1.285 or newer. | ✓ | SRC-03 |
| V09 | `forceLoginMethod`, `forceLoginGatewayUrl`, `parentSettingsBehavior` | Gateway sign-in, not the `ANTHROPIC_BASE_URL` path. Quickstart example URL `https://claude-gateway.internal.example.com`. `parentSettingsBehavior` value `merge`. | ✓ | SRC-01 |


Pinning: `allowedProviders` with `customEndpoint` is Claude Code v2.1.285 or newer. ✓ SRC-03

# Part 3 — Routing, auth, and spend

```mermaid
flowchart TB
  req["Gateway request"]
  allow{"Model granted to the IdP group"}
  deny["400"]
  cap{"Optional USD cent cap"}
  ok["Call the configured upstream"]
  over["429 billing_error"]
  req --> allow
  allow -->|"no"| deny
  allow -->|"yes"| cap
  cap -->|"under or no cap"| ok
  cap -->|"over cap"| over
```

Caption: Apps-gateway allowlist and optional cap. 400 means the model was not granted. 429 means the cap was exceeded. Estimates are not the provider invoice.


```mermaid
flowchart TB
  key["CCR client key"]
  lim["Local request token and image limits"]
  log["Logs show an estimated cost"]
  noOrg["No organisation Admin API in pages fetched"]
  key --> lim
  lim --> log
  key --> noOrg
```

Caption: CCR limits seen in the fetch are local to client keys and logs. No organisation Admin API was in the pages fetched.


```mermaid
flowchart TB
  subgraph gwA["Gateway"]
    oidc["OIDC one issuer"]
    bearer["Short-lived bearer default ttl_hours 1"]
    cred["Upstream credential stays on the gateway"]
  end
  subgraph ccrA["CCR"]
    web["Management token"]
    client["Separate client API keys"]
    local["Upstream keys in the local data directory"]
  end
  oidc --> bearer
  bearer --> cred
  web --> client
  client --> local
```

Caption: Gateway auth is OIDC with the upstream credential held on the gateway. CCR auth in the fetched pages is a management token plus client keys, with upstream keys on the machine.


### Spend example (apps gateway only)

POST `/v1/organizations/spend_limits` with header `x-api-key`. The body below is the example from the fetch. `amount` is USD cents, so `50000` means 500.00 US dollars as an estimate, not a provider invoice. The JSON key `organization` is the API spelling. ✓ SRC-02

```json
{"scope":{"type":"organization"},"amount":"50000","period":"monthly"}
```

Over the cap the gateway returns 429, `error.type` `billing_error`, and `x-should-retry` false. Periods named: daily, weekly, monthly. Scopes named: per-user, per-IdP-group, and organisation. Postgres is required. The example above is only the organisation scope. Per-user and per-group JSON bodies were not copied. ✓ SRC-02

# Part 4 — Who calls whom

```mermaid
sequenceDiagram
  participant Code as Claude Code
  participant Gate as Apps gateway
  participant Up as Configured upstream
  Code->>Gate: Anthropic Messages API
  Gate->>Up: Model id translated for that upstream
  Up-->>Gate: Provider response
  Gate-->>Code: Messages response
```

Caption: Apps gateway translates the model id for the configured upstream. The upstream credential stays on the gateway.


```mermaid
sequenceDiagram
  participant Agent as Agent
  participant Ccr as CCR gateway
  participant Prov as Selected provider
  Agent->>Ccr: Request to the local gateway
  Ccr->>Prov: Call after route and fallback
  Prov-->>Ccr: Provider response
  Ccr-->>Agent: Response
```

Caption: The agent talks to CCR. CCR calls the provider it selected. This is not the apps-gateway sequence.


### Gateway path, in words

1. An operator starts `claude gateway --config gateway.yaml` on a Linux server.
2. The client is directed with `forceLoginMethod` `gateway` and `forceLoginGatewayUrl`.
3. The person completes a browser device flow against the one OIDC issuer. There is no unattended CI token.
4. Claude Code speaks the Anthropic Messages API to the gateway.
5. The gateway translates the model id and calls the organisation upstream. Nothing is sent to Anthropic unless the Anthropic API is that upstream.
6. If a cap is configured and exceeded, the gateway returns 429 as in Part 3.

### CCR path, in words

1. The user starts CCR with the desktop app, `ccr ui` after `npm install -g @musistudio/claude-code-router` (Node.js 22 or newer), or Docker.
2. Agents use the local gateway, default `http://127.0.0.1:3456`.
3. The management UI defaults to `http://127.0.0.1:3458`.
4. Profiles set the model per agent. Routes can use header and body conditions, prefixes, rewrites, retries, and ordered fallbacks.
5. CCR calls the selected provider. Upstream keys are in the local data directory.

Baseline for both paths: Claude Code on a claude.ai login, or an Anthropic credential, with neither intermediary. Setting only `ANTHROPIC_BASE_URL` does not leave that baseline. A gateway credential or `/login` does. On an apps-gateway session the CLI also turns off the features in R13, and the session is not a claude.ai session. ✓ SRC-01 SRC-03

# Part 5 — Ports, hosting, and breakage

```mermaid
flowchart LR
  subgraph appsGw["Claude apps gateway"]
    p8080["Listener host 0.0.0.0 port 8080"]
    purl["Separate public_url"]
  end
  subgraph ccrLocal["CCR defaults"]
    p3456["Model gateway port 3456"]
    p3458["Management UI port 3458"]
  end
  p8080 --> purl
  p3458 -->|"Docker front door proxies to 3456"| p3456
```

Caption: Do not treat 3456, 3458, and 8080 as the same port. Docker's 3458 is a front door. The apps gateway separates the listener from public_url.


```mermaid
flowchart TB
  shape["Claude Code request shape changes"]
  gwShip["Apps gateway ships with the CLI"]
  other["A separate gateway"]
  ccrDoc["CCR README and troubleshooting"]
  off["Gateway session turns listed features off"]
  drop["Dropped new headers or body fields break features"]
  gap["Request-shape outcome not documented there"]
  shape --> gwShip
  gwShip --> off
  shape --> other
  other --> drop
  shape --> ccrDoc
  ccrDoc --> gap
```

Caption: The apps gateway ships with the CLI. A separate gateway, including a community one, has to keep up with new headers and body fields. CCR's fetched docs do not say what happens when the request shape changes.


# Part 6 — Config actually seen

### Apps gateway quickstart groups

These are the groups named in the quickstart. This is not a paste of `gateway.yaml`. Nesting, defaults, and every other key are unverified (GAP-01, SRC-12).

| Group | Field | Value named in the quickstart |
| --- | --- | --- |
| listen | host | `0.0.0.0` |
| listen | port | `8080` |
| listen | public_url | `https://claude-gateway.internal.example.com` |
| oidc | issuer | Named. The example value was not copied. |
| oidc | client_id | Named. The example value was not copied. |
| oidc | client_secret | `${OIDC_CLIENT_SECRET}` |
| session | jwt_secret | `${GATEWAY_JWT_SECRET}` |
| session | ttl_hours | `1` |
| store | postgres_url | `${GATEWAY_POSTGRES_URL}` |
| upstreams | provider | `bedrock` |
| upstreams | region | `us-east-1` |
| upstreams | auth | `{}` |
| (top level, as named) | auto_include_builtin_models | `true` |


### CCR files and variables actually seen

| Item | Value |
| --- | --- |
| Model gateway default | `http://127.0.0.1:3456` |
| Management UI default | `http://127.0.0.1:3458` |
| Open the UI | `ccr ui` after `npm install -g @musistudio/claude-code-router` (Node.js 22 or newer) |
| Web bind | `CCR_WEB_HOST`, `CCR_WEB_PORT`, `CCR_WEB_AUTH_TOKEN` |
| Config directory | `~/.claude-code-router` (Windows `%APPDATA%\claude-code-router`) |
| Live config | `config.sqlite`, not a JSON file the current README shows |
| Generated runtime file | `gateway.config.json` |
| Docker public base | `CCR_PUBLIC_BASE_URL` default `http://127.0.0.1:3458` |
| Docker gateway bind | `CCR_GATEWAY_HOST`, `CCR_GATEWAY_PORT` |
| Docker ports | Host 3458 proxies to in-container gateway `127.0.0.1:3456` |
| Schema | Current README has no config.json schema. Linked configuration page is a dashboard-widget guide. Historical config.json is not current (GAP-02). |


# Part 7 — Useful case and fail case

```mermaid
flowchart LR
  org["Organisation"]
  keep["Hold the upstream and the data plane"]
  gw["Claude apps gateway"]
  user["User"]
  route["One local endpoint to chosen providers"]
  ccr["Claude Code Router"]
  org --> keep
  keep --> gw
  user --> route
  route --> ccr
```

Caption: Two different jobs. The organisation job is the apps gateway. The local routing job is CCR. Anthropic does not support the second job when the provider is not Claude.


### Expected stories

| Step | Apps gateway | CCR |
| --- | --- | --- |
| 1 | Operator runs the gateway on Linux with the quickstart groups. | User runs the desktop app, the npm CLI, or Docker. |
| 2 | Clients use gateway sign-in, not only a base URL. | Agents use port 3456. The UI is port 3458. |
| 3 | Person signs in with the browser device flow. One OIDC issuer. | Management token and client API keys. No corporate OIDC in the fetched README or CLI guide. |
| 4 | Messages go to the organisation upstream. Credential stays on the gateway. | CCR calls a provider from the README list. Keys stay in the local data directory. |
| 5 | Optional cap can return 429. Non-granted models return 400. | Local key limits and an estimated cost in the logs. No organisation cap API in the pages fetched. |


### Where the apps gateway is the fitting tool

An organisation wants the data plane off Anthropic's hosting unless the Anthropic API is a chosen upstream, with OIDC groups, an allowlist, failover across the named upstreams, and optional USD-cent caps. Claude Code will only complete `/login` when the host is private or a declared owned public block. ✓ SRC-01 SRC-02

### Where CCR is the fitting tool

A person wants one local endpoint in front of the providers the README lists, for the agents CCR claims, with routes, fallbacks, and local logs. That job is outside Anthropic support when the model is not Claude. ✓ SRC-03 SRC-06

### Where the apps gateway fails or goes quiet

A separate gateway that drops new headers or body fields breaks features. Protocol compatibility is not promised indefinitely. Even on this gateway, a gateway session turns off server-side WebSearch, the 1-hour cache TTL, Remote Control, design login and design sync, and feature-flag features such as `/import`. There is no unattended CI token. Windows cannot be the server. ✓ SRC-01

### Where CCR fails or goes quiet

The fetched README and troubleshooting page do not say what happens when Claude Code changes request shape (GAP-03). Anthropic's own guide says stripping `anthropic-beta` or rewriting bodies yields 400s; that sentence is not a CCR test result. Tag v3.0.22 records two fixes (SSE multi-byte splits, and the Claude Code path in the local-agent auth hook). Those are fix notes, not a compatibility promise. The Docker guide says to read it before exposing CCR remotely; the failure mode if you skip that was not quoted. ✓ for the citations, ?? for the unstated outcome. SRC-04 SRC-06 SRC-07 SRC-08

# Part 8 — Provenance

## Edition decisions

These restate the fetch so a later edit cannot merge the products. They are not extra measurements.

| ID | Decision |
| --- | --- |
| DEC-01 | CCR is not the Claude apps gateway. Do not describe one with the other's ports, sign-in, or licence. |
| DEC-02 | Gateway sign-in is `forceLoginMethod` `gateway` plus `forceLoginGatewayUrl`. `ANTHROPIC_BASE_URL` is a different connection, including when it points at CCR. |
| DEC-03 | `ANTHROPIC_BASE_URL` alone does not move billing off a claude.ai subscription. A gateway credential or `/login` does. |
| DEC-04 | CCR port 3456 is the model gateway. Port 3458 is the management UI. In Docker, 3458 is the public front door and proxies to 3456. The apps-gateway quickstart listener is `0.0.0.0:8080` with a separate `public_url`. |
| DEC-05 | Anthropic does not support non-Claude models through any gateway. The CCR README is about routing to other providers. A CCR route is not an Anthropic-supported path. |
| DEC-06 | `GET /protocol` on a running apps gateway is that product's endpoint list. The public compatibility guide is a different document. |
| DEC-07 | A historical CCR `config.json` shape is not current. The live file seen in this fetch is `config.sqlite`. |
| DEC-08 | Git tag v3.0.22 (24 August 2026 15:23 EEST) is not the npm package version fetched the same day (3.1.1, updated 16 September 2026 15:28 EEST). |
| DEC-09 | A gap stays unverified. It is not a finding that the missing thing is false. |


## Gaps

```mermaid
flowchart TB
  gaps["Unverified on 3 October 2026"]
  yaml["Full gateway.yaml reference"]
  schema["Current CCR JSON schema"]
  shape["CCR when the request shape changes"]
  native["CCR native Bedrock Foundry or Vertex"]
  lic["claude binary licence"]
  forks["Fork count"]
  gaps --> yaml
  gaps --> schema
  gaps --> shape
  gaps --> native
  gaps --> lic
  gaps --> forks
```

Caption: Each branch is unverified. Do not invent a schema, a licence, a fork count, or a native cloud protocol to close a branch.


| ID | Gap | Badge |
| --- | --- | --- |
| GAP-01 | The full gateway.yaml reference at https://code.claude.com/docs/en/claude-apps-gateway-config was not fetched in full. Keys not named in the quickstart are unverified. | ?? |
| GAP-02 | No current CCR JSON schema. The current README does not contain a config.json schema. The linked configuration page is a dashboard-widget guide. An older config.json shape exists in a historical commit and is not current. | ?? |
| GAP-03 | The README and the ccrdesk Q&A do not state what happens when the Claude Code request shape changes. GitHub issues about beta-header overwrites were not fetched in full. | ?? |
| GAP-04 | Whether CCR speaks Bedrock InvokeModel, Foundry, or Vertex as native upstreams was not stated. Protocols listed are OpenAI, Anthropic Messages, and Gemini. | ?? |
| GAP-05 | No licence text for the claude binary on the gateway docs. | ?? |
| GAP-06 | Fork count for musistudio/claude-code-router is not reliable. Stars seen on 3 October 2026 were 37524. That star integer is a fetched count, not a fork count. | ?? |


## Sources

```mermaid
flowchart LR
  anth["Anthropic docs fetched 3 Oct 2026"]
  gh["CCR README"]
  npm["npm page"]
  desk["ccrdesk guides fetched"]
  page["This comparison"]
  anth --> page
  gh --> page
  npm --> page
  desk --> page
```

Caption: Claims in this twin come from the 3 October 2026 fetch of these pages. SRC-05 and SRC-10 are listed so the source list stays complete. They do not add a silent fact.


| ID | Name | URL | Role in this edition |
| --- | --- | --- | --- |
| SRC-01 | Claude apps gateway | https://code.claude.com/docs/en/claude-apps-gateway | Fetched 3 October 2026. Product, quickstart fields, clients, auth, hosting, breakage, managed settings. |
| SRC-02 | Spend limits | https://code.claude.com/docs/en/claude-apps-gateway-spend-limits | Fetched 3 October 2026. Caps, 429 body, example POST. Amount unit is USD cents. |
| SRC-03 | LLM gateway (other gateways) | https://code.claude.com/docs/en/llm-gateway | Fetched 3 October 2026. Client variables, endorsement sentence, non-Claude models. |
| SRC-04 | LLM gateway protocol | https://code.claude.com/docs/en/llm-gateway-protocol | Fetched 3 October 2026. Public compatibility guide. Distinct from GET /protocol on a running apps gateway. |
| SRC-05 | Gateways index | https://code.claude.com/docs/en/gateways | Named in the 3 October 2026 source list. No sentence in this twin is sourced only from this page, because the fetch notes did not quote a distinct claim from it. |
| SRC-06 | Claude Code Router README | https://github.com/musistudio/claude-code-router | Fetched 3 October 2026. Stars 37524 that day. Product claims, provider list, MIT. |
| SRC-07 | CCR troubleshooting | https://ccrdesk.top/en/troubleshooting/ | Fetched 3 October 2026. Does not document Claude Code request-shape breakage. |
| SRC-08 | CCR Docker guide | https://ccrdesk.top/en/guides/docker/ | Fetched 3 October 2026. Port proxy and public base URL. |
| SRC-09 | CCR CLI guide | https://ccrdesk.top/en/guides/cli/ | Fetched 3 October 2026. Used with the README for the OIDC absence and the CLI entry (`ccr ui`, Node.js 22 or newer). |
| SRC-10 | CCR provider guide | https://ccrdesk.top/en/guides/provider/ | Named in the 3 October 2026 source list. Provider names in this twin are the README list. No extra provider was taken from this page. |
| SRC-11 | npm package | https://www.npmjs.com/package/@musistudio/claude-code-router | Fetched 3 October 2026. Version 3.1.1, MIT, updated 16 September 2026 15:28 EEST. |
| SRC-12 | gateway.yaml reference | https://code.claude.com/docs/en/claude-apps-gateway-config | Not fetched in full. GAP-01. Do not treat Part 6 as that page. |


```mermaid
flowchart TB
  row["One concern per row"]
  left["Left cell is Claude apps gateway"]
  right["Right cell is Claude Code Router"]
  gap["A hole stays unverified"]
  row --> left
  row --> right
  row --> gap
```

Caption: How to read the inventory. Left cell gateway, right cell CCR, and a hole stays a hole.


## Limitations

- Formative. Not a security audit, a penetration test, or a purchasing recommendation.
- This pass did not re-fetch any page. If a doc changed after 3 October 2026, this edition is stale.
- SRC-12 was not fetched in full. Part 6 must not be treated as the configuration reference.
- Absence in a fetched CCR page is `~` or `??`, not a proof of absence in the project.
- The star count 37524 was seen on 3 October 2026. It is not a live count and it is not a fork count.
- Tag time 24 August 2026 15:23 EEST and npm time 16 September 2026 15:28 EEST are the fetch's timestamps. Both are already Europe/Vilnius (EEST, UTC+3).
- Inline scripts passed `node --check`. Each `diagrams/gwc-*.mmd` rendered with `@mermaid-js/mermaid-cli@11.4.2` (exit 0). A headless Chrome pass clicked every tab: each panel became `section.on`, the hash matched, and each diagram was an SVG with no Mermaid syntax error. That is not a human visual review.
- Neighbour landscape CML-WB/1.0 is a different fact set. Do not copy a router sentence from that file over these rows.

## Diagram index

| File | Tab concern |
| --- | --- |
| diagrams/gwc-01-two-paths.mmd | Two connection methods |
| diagrams/gwc-02-gateway-seq.mmd | Apps gateway call order |
| diagrams/gwc-03-ccr-seq.mmd | CCR call order |
| diagrams/gwc-04-signin.mmd | Sign-in versus base URL |
| diagrams/gwc-05-ports.mmd | Ports |
| diagrams/gwc-06-usecase.mmd | Two jobs |
| diagrams/gwc-07-breakage.mmd | Request-shape risk |
| diagrams/gwc-08-auth.mmd | Auth |
| diagrams/gwc-09-spend.mmd | Gateway allowlist and cap |
| diagrams/gwc-10-gaps.mmd | Unverified branches |
| diagrams/gwc-11-sources.mmd | Source set |
| diagrams/gwc-12-ccr-limits.mmd | CCR local limits |
| diagrams/gwc-13-read.mmd | How to read a row |

