SpyBara
Go Premium

Documentation 2026-06-27 01:01 UTC to 2026-06-29 23:02 UTC

25 files changed +1,907 −99. View all changes and history on the product overview
2026
Mon 29 23:02 Sat 27 01:01 Fri 26 23:00 Thu 25 23:58 Wed 24 22:02 Tue 23 22:00 Mon 22 23:59 Fri 19 22:58 Thu 18 22:00 Wed 17 17:02 Tue 16 21:57 Mon 15 23:02 Sat 13 21:59 Fri 12 22:00 Thu 11 23:01 Wed 10 23:57 Tue 9 06:34 Mon 8 06:52 Sat 6 06:24 Fri 5 06:45 Thu 4 06:52 Wed 3 06:53 Tue 2 06:51

admin-setup.md +8 −6

Details

42 42 

43## Decide how settings reach devices43## Decide how settings reach devices

44 44 

45Managed settings define policy that takes precedence over local developer configuration. Claude Code checks the four sources below in priority order and applies the first one that returns a non-empty configuration.45Managed settings define policy that takes precedence over local developer configuration. Claude Code checks the four sources below in priority order and applies the first one that returns a non-empty configuration, with one exception: a small set of [cross-source lock keys](/en/settings#settings-precedence), such as the sandbox allowlist locks, is honored when any admin-controlled source sets them.

46 46 

47| Mechanism | Delivery | Priority | Platforms |47| Mechanism | Delivery | Priority | Platforms |

48| :---------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------- | :------------- |48| :---------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------- | :------------- |

49| Server-managed | claude.ai admin console | Highest | All |49| Server-managed | claude.ai admin console, or a self-hosted [Claude apps gateway](/en/claude-apps-gateway) for gateway sign-ins | Highest | All |

50| plist / registry policy | macOS: `com.anthropic.claudecode` plist<br />Windows: `HKLM\SOFTWARE\Policies\ClaudeCode` | High | macOS, Windows |50| plist / registry policy | macOS: `com.anthropic.claudecode` plist<br />Windows: `HKLM\SOFTWARE\Policies\ClaudeCode` | High | macOS, Windows |

51| File-based managed | macOS: `/Library/Application Support/ClaudeCode/managed-settings.json`<br />Linux and WSL: `/etc/claude-code/managed-settings.json`<br />Windows: `C:\Program Files\ClaudeCode\managed-settings.json` | Medium | All |51| File-based managed | macOS: `/Library/Application Support/ClaudeCode/managed-settings.json`<br />Linux and WSL: `/etc/claude-code/managed-settings.json`<br />Windows: `C:\Program Files\ClaudeCode\managed-settings.json` | Medium | All |

52| Windows user registry | `HKCU\SOFTWARE\Policies\ClaudeCode` | Lowest | Windows only |52| Windows user registry | `HKCU\SOFTWARE\Policies\ClaudeCode` | Lowest | Windows only |

53 53 

54Server-managed settings reach devices at authentication time and refresh hourly during active sessions, with no endpoint infrastructure. They require a Claude for Teams or Enterprise plan, so deployments on other providers need one of the file-based or OS-level mechanisms instead.54A configured [`policyHelper`](/en/settings#compute-managed-settings-with-a-policy-helper) preempts all four sources: its output becomes the only managed configuration for the run. See [Settings precedence](/en/settings#settings-precedence).

55 

56Server-managed settings reach devices at authentication time and refresh hourly during active sessions, with no endpoint infrastructure. Delivery through the claude.ai admin console requires a Claude for Teams or Enterprise plan. Deployments on Bedrock, Vertex AI, or Foundry can get the same remote delivery by running a [Claude apps gateway](/en/claude-apps-gateway), or use one of the file-based or OS-level mechanisms instead.

55 57 

56If your organization mixes providers, configure [server-managed settings](/en/server-managed-settings) for claude.ai users plus a [file-based or plist/registry fallback](/en/settings#settings-files) so other users still receive managed policy.58If your organization mixes providers, configure [server-managed settings](/en/server-managed-settings) for claude.ai users plus a [file-based or plist/registry fallback](/en/settings#settings-files) so other users still receive managed policy.

57 59 


91Choose monitoring based on what you need to report on.93Choose monitoring based on what you need to report on.

92 94 

93| Capability | What you get | Availability | Where to start |95| Capability | What you get | Availability | Where to start |

94| :------------------ | :--------------------------------------------------- | :------------- | :--------------------------------------- |96| :------------------ | :--------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------- |

95| Usage monitoring | OpenTelemetry export of sessions, tools, and tokens | All providers | [Monitoring usage](/en/monitoring-usage) |97| Usage monitoring | OpenTelemetry export of sessions, tools, and tokens | All providers | [Monitoring usage](/en/monitoring-usage) |

96| Analytics dashboard | Per-user metrics, contribution tracking, leaderboard | Anthropic only | [Analytics](/en/analytics) |98| Analytics dashboard | Per-user metrics, contribution tracking, leaderboard | Anthropic only | [Analytics](/en/analytics) |

97| Cost tracking | Spend limits, rate limits, and usage attribution | Anthropic only | [Costs](/en/costs) |99| Cost tracking | Spend limits, rate limits, and usage attribution | Anthropic; on third-party clouds, a [Claude apps gateway](/en/claude-apps-gateway) provides per-user attribution and [spend limits](/en/claude-apps-gateway-spend-limits) | [Costs](/en/costs) |

98 100 

99Cloud providers expose spend through AWS Cost Explorer, GCP Billing, or Azure Cost Management. Claude for Teams and Enterprise plans include a usage dashboard at [claude.ai/analytics/claude-code](https://claude.ai/analytics/claude-code).101Cloud providers expose spend through AWS Cost Explorer, GCP Billing, or Azure Cost Management. Claude for Teams and Enterprise plans include a usage dashboard at [claude.ai/analytics/claude-code](https://claude.ai/analytics/claude-code).

100 102 


108| Zero Data Retention (ZDR) | Nothing stored after the request completes. Available to qualified accounts on Claude for Enterprise | [Zero data retention](/en/zero-data-retention) |110| Zero Data Retention (ZDR) | Nothing stored after the request completes. Available to qualified accounts on Claude for Enterprise | [Zero data retention](/en/zero-data-retention) |

109| Security architecture | Network model, encryption, authentication, audit trail | [Security](/en/security) |111| Security architecture | Network model, encryption, authentication, audit trail | [Security](/en/security) |

110 112 

111If you need request-level audit logging or to route traffic by data sensitivity, place an [LLM gateway](/en/llm-gateway) between developers and your provider. For regulatory requirements and certifications, see [Legal and compliance](/en/legal-and-compliance).113If you need request-level audit logging or to route traffic by data sensitivity, place a gateway between developers and your provider: a self-hosted [Claude apps gateway](/en/claude-apps-gateway) records a per-request audit log with IdP identity, or use another [LLM gateway](/en/llm-gateway). For regulatory requirements and certifications, see [Legal and compliance](/en/legal-and-compliance).

112 114 

113## Verify and onboard115## Verify and onboard

114 116 

Details

22* **Claude for Teams or Enterprise**: log in with the Claude.ai account your team admin invited you to.22* **Claude for Teams or Enterprise**: log in with the Claude.ai account your team admin invited you to.

23* **Claude Console**: log in with your Console credentials. Your admin must have [invited you](#claude-console-authentication) first.23* **Claude Console**: log in with your Console credentials. Your admin must have [invited you](#claude-console-authentication) first.

24* **Cloud providers**: if your organization uses [Amazon Bedrock](/en/amazon-bedrock), [Google Vertex AI](/en/google-vertex-ai), or [Microsoft Foundry](/en/microsoft-foundry), set the required environment variables before running `claude`. No browser login is needed.24* **Cloud providers**: if your organization uses [Amazon Bedrock](/en/amazon-bedrock), [Google Vertex AI](/en/google-vertex-ai), or [Microsoft Foundry](/en/microsoft-foundry), set the required environment variables before running `claude`. No browser login is needed.

25* **Cloud gateway**: if your organization runs a self-hosted [Claude apps gateway](/en/claude-apps-gateway), sign in with corporate SSO through `/login`. The gateway-issued token is the session's only credential.

25 26 

26To log out and re-authenticate, type `/logout` at the Claude Code prompt.27To log out and re-authenticate, type `/logout` at the Claude Code prompt.

27 28 


33 34 

34* [Claude for Teams or Enterprise](#claude-for-teams-or-enterprise), recommended for most teams35* [Claude for Teams or Enterprise](#claude-for-teams-or-enterprise), recommended for most teams

35* [Claude Console](#claude-console-authentication)36* [Claude Console](#claude-console-authentication)

37* [Claude apps gateway](/en/claude-apps-gateway), a self-hosted gateway that signs developers in with your IdP and routes inference to the cloud provider you configure

36* [Amazon Bedrock](/en/amazon-bedrock)38* [Amazon Bedrock](/en/amazon-bedrock)

37* [Google Vertex AI](/en/google-vertex-ai)39* [Google Vertex AI](/en/google-vertex-ai)

38* [Microsoft Foundry](/en/microsoft-foundry)40* [Microsoft Foundry](/en/microsoft-foundry)


119 * On Windows, credentials are stored in `%USERPROFILE%\.claude\.credentials.json` and inherit the access controls of your user profile directory, which restricts the file to your user account by default.121 * On Windows, credentials are stored in `%USERPROFILE%\.claude\.credentials.json` and inherit the access controls of your user profile directory, which restricts the file to your user account by default.

120 * If you've set the `CLAUDE_CONFIG_DIR` environment variable on Linux or Windows, the `.credentials.json` file lives under that directory instead.122 * If you've set the `CLAUDE_CONFIG_DIR` environment variable on Linux or Windows, the `.credentials.json` file lives under that directory instead.

121 * Claude Code manages `.credentials.json` through `/login` and `/logout`. To route requests through a custom API endpoint, set the [`ANTHROPIC_BASE_URL`](/en/env-vars) environment variable instead.123 * Claude Code manages `.credentials.json` through `/login` and `/logout`. To route requests through a custom API endpoint, set the [`ANTHROPIC_BASE_URL`](/en/env-vars) environment variable instead.

122* **Supported authentication types**: Claude.ai credentials, Claude API credentials, Azure Auth, Bedrock Auth, and Vertex Auth.124* **Supported authentication types**: Claude.ai credentials, Claude API credentials, Azure Auth, Bedrock Auth, Vertex Auth, and [Claude apps gateway](/en/claude-apps-gateway) session tokens.

123* **Custom credential scripts**: the [`apiKeyHelper`](/en/settings#available-settings) setting can be configured to run a shell script that returns an API key.125* **Custom credential scripts**: the [`apiKeyHelper`](/en/settings#available-settings) setting can be configured to run a shell script that returns an API key.

124* **Refresh intervals**: by default, `apiKeyHelper` is called after 5 minutes or on HTTP 401 response. Set `CLAUDE_CODE_API_KEY_HELPER_TTL_MS` environment variable for custom refresh intervals.126* **Refresh intervals**: by default, `apiKeyHelper` is called after 5 minutes or on HTTP 401 response. Set `CLAUDE_CODE_API_KEY_HELPER_TTL_MS` environment variable for custom refresh intervals.

125* **Slow helper notice**: if `apiKeyHelper` takes longer than 10 seconds to return a key, Claude Code displays a warning notice in the prompt bar showing the elapsed time. If you see this notice regularly, check whether your credential script can be optimized.127* **Slow helper notice**: if `apiKeyHelper` takes longer than 10 seconds to return a key, Claude Code displays a warning notice in the prompt bar showing the elapsed time. If you see this notice regularly, check whether your credential script can be optimized.


1375. `CLAUDE_CODE_OAUTH_TOKEN` environment variable. A long-lived OAuth token generated by [`claude setup-token`](#generate-a-long-lived-token). Use this for CI pipelines and scripts where browser login isn't available.1395. `CLAUDE_CODE_OAUTH_TOKEN` environment variable. A long-lived OAuth token generated by [`claude setup-token`](#generate-a-long-lived-token). Use this for CI pipelines and scripts where browser login isn't available.

1386. Subscription OAuth credentials from `/login`. This is the default for Claude Pro, Max, Team, and Enterprise users.1406. Subscription OAuth credentials from `/login`. This is the default for Claude Pro, Max, Team, and Enterprise users.

139 141 

142A signed-in [Claude apps gateway](/en/claude-apps-gateway) session sits outside this list: it is a provider selection like Bedrock or Vertex, and it outranks them. When a gateway session exists, the CLI authenticates with the gateway token even if `CLAUDE_CODE_USE_BEDROCK`, `CLAUDE_CODE_USE_VERTEX`, or `CLAUDE_CODE_USE_FOUNDRY` is set, and the bearer token, API key, and `apiKeyHelper` entries above are not used.

143 

140If you have an active Claude subscription but also have `ANTHROPIC_API_KEY` set in your environment, the API key takes precedence once approved. This can cause authentication failures if the key belongs to a disabled or expired organization. Run `unset ANTHROPIC_API_KEY` to fall back to your subscription, and check `/status` to confirm which method is active.144If you have an active Claude subscription but also have `ANTHROPIC_API_KEY` set in your environment, the API key takes precedence once approved. This can cause authentication failures if the key belongs to a disabled or expired organization. Run `unset ANTHROPIC_API_KEY` to fall back to your subscription, and check `/status` to confirm which method is active.

141 145 

142[Claude Code on the Web](/en/claude-code-on-the-web) always uses your subscription credentials. `ANTHROPIC_API_KEY` and `ANTHROPIC_AUTH_TOKEN` in the sandbox environment do not override them.146[Claude Code on the Web](/en/claude-code-on-the-web) always uses your subscription credentials. `ANTHROPIC_API_KEY` and `ANTHROPIC_AUTH_TOKEN` in the sandbox environment do not override them.

Details

9[Auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) lets Claude Code run without routine permission prompts by routing tool calls through a classifier that blocks anything irreversible, destructive, or aimed outside your environment. Deny and explicit ask rules are evaluated before the classifier and still block or prompt. Use the `autoMode` settings block to tell that classifier which repos, buckets, and domains your organization trusts, so it stops blocking routine internal operations.9[Auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) lets Claude Code run without routine permission prompts by routing tool calls through a classifier that blocks anything irreversible, destructive, or aimed outside your environment. Deny and explicit ask rules are evaluated before the classifier and still block or prompt. Use the `autoMode` settings block to tell that classifier which repos, buckets, and domains your organization trusts, so it stops blocking routine internal operations.

10 10 

11<Note>11<Note>

12 Auto mode is available to all users on the Anthropic API. On Amazon Bedrock, Google Cloud Vertex AI, and Microsoft Foundry, you must first [set `CLAUDE_CODE_ENABLE_AUTO_MODE`](/en/permission-modes#enable-auto-mode-on-bedrock-vertex-ai-or-foundry). If Claude Code reports auto mode as unavailable for your account, check the [full requirements](/en/permission-modes#eliminate-prompts-with-auto-mode), which also cover the supported models and Owner enablement on Team and Enterprise plans.12 Auto mode is available to all users on the Anthropic API. On Amazon Bedrock, Google Cloud Vertex AI, Microsoft Foundry, and signed-in [Claude apps gateway](/en/claude-apps-gateway) sessions, you must first [set `CLAUDE_CODE_ENABLE_AUTO_MODE`](/en/permission-modes#enable-auto-mode-on-bedrock-vertex-ai-or-foundry). If Claude Code reports auto mode as unavailable for your account, check the [full requirements](/en/permission-modes#eliminate-prompts-with-auto-mode), which also cover the supported models and Owner enablement on Team and Enterprise plans.

13</Note>13</Note>

14 14 

15By default, the classifier trusts only the working directory and the current repo's configured remotes. Actions like pushing to your company's source-control org or writing to a team cloud bucket are blocked until you add them to `autoMode.environment`.15By default, the classifier trusts only the working directory and the current repo's configured remotes. Actions like pushing to your company's source-control org or writing to a team cloud bucket are blocked until you add them to `autoMode.environment`.

claude-apps-gateway.md +319 −0 created

Details

1> ## Documentation Index

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt

3> Use this file to discover all available pages before exploring further.

4 

5# Claude apps gateway for Amazon Bedrock, Google Cloud, and Microsoft Foundry

6 

7> Run Claude Code through Amazon Bedrock, Google Cloud, or Microsoft Foundry behind a self-hosted gateway with SSO sign-in, per-group model access, and OTLP telemetry.

8 

9<Note>

10 If a third-party cloud isn't a requirement, [Claude for Enterprise](/en/authentication#claude-for-teams-or-enterprise) is usually the better fit: richer admin capabilities, such as SCIM provisioning, and nothing to host. Subscriptions are available through AWS Marketplace, where purchases can count toward an AWS spend commitment. The gateway is designed for organizations that must route inference through their own cloud provider, for example to meet [data residency](/en/claude-apps-gateway-deploy#compliance-posture) requirements.

11</Note>

12 

13Claude apps gateway is a self-hosted service that sits between your developers' Claude Code clients and your model provider. Developers sign in with your corporate identity provider (IdP) instead of holding API keys or cloud credentials. The gateway holds the upstream credential, enforces model access and [managed settings](/en/permissions#managed-settings) by IdP group, and relays usage telemetry to your own observability stack.

14 

15It is included in the `claude` binary, so the same executable that runs Claude Code on a laptop runs the gateway server with `claude gateway --config gateway.yaml`.

16 

17This page covers:

18 

19* [Why Claude apps gateway](#why-claude-apps-gateway), what it adds over running your own, and when something else fits better

20* A [quickstart](#quickstart) with [prerequisites](#prerequisites) that takes a gateway from zero to a signed-in developer

21* [Connecting developers](#connect-developers), including setting the gateway URL through managed settings

22* [Availability and limitations](#availability-and-limitations) covering which Claude Code features work through the gateway and what the server supports

23 

24Companion pages go deeper. The [configuration reference](/en/claude-apps-gateway-config) covers every option in the YAML file the quickstart writes, and the [deployment guide](/en/claude-apps-gateway-deploy) covers per-IdP setup, Kubernetes and Cloud Run deployment, and operations.

25 

26## Why Claude apps gateway

27 

28The [gateway overview](/en/gateways) covers what a gateway does and why you'd run one. Claude apps gateway is Anthropic's own gateway, built into the `claude` binary and tested alongside each Claude Code release, so it forwards the headers and request fields Claude Code sends without operators maintaining a separate allowlist. Once deployed it gives you:

29 

30* **Credentials**: the upstream API key or cloud credential lives only in your infrastructure. Developers authenticate with corporate SSO and receive short-lived bearer tokens, so offboarding happens in your IdP. Deprovision a user and their gateway access expires within the session lifetime, one hour by default.

31* **Access control**: your IdP groups map to model allowlists and [managed settings](/en/permissions#managed-settings) policies. The gateway enforces model access server-side, rejecting requests for non-granted models, and selects each group's managed settings policy, which the CLI applies at the [managed settings tier](/en/settings#settings-precedence). Different teams get different models, tools, and permissions, and a developer can't override what their policy locks.

32* **Settings delivery**: the gateway delivers managed settings to signed-in clients itself, taking the place of [server-managed settings](/en/server-managed-settings) from the claude.ai admin console.

33* **Telemetry**: each configured destination, such as Datadog, Splunk, or ClickHouse, receives [OpenTelemetry Protocol (OTLP) metrics](/en/monitoring-usage) with token counts, model, user identity, and latency by default, with logs and traces as per-destination opt-ins.

34* **Upstream routing**: clients speak the Anthropic Messages API to the gateway, and the gateway translates for each upstream, whether Bedrock, Google Cloud's Agent Platform, Foundry, or the Anthropic API, with failover between them. You can change regions, providers, or failover order without developers noticing or reconfiguring.

35 

36<Frame>

37 <img src="https://mintcdn.com/claude-code/-uq-4JE0W_JO5Er5/images/claude-gateway-architecture.svg?fit=max&auto=format&n=-uq-4JE0W_JO5Er5&q=85&s=adbd3b03aeb8b4983d082537b5547d55" alt="Diagram showing Claude Code clients connecting over HTTPS with bearer tokens to a self-hosted Claude apps gateway inside your infrastructure, which signs users in against your IdP, stores auth state in PostgreSQL, relays telemetry to your OTLP collector, and forwards inference to Amazon Bedrock, Google Cloud, Microsoft Foundry, or the Anthropic API" width="760" height="290" data-path="images/claude-gateway-architecture.svg" />

38</Frame>

39 

40<Note>

41 The gateway's own data plane sends nothing to Anthropic infrastructure unless the Anthropic API is a configured upstream. You control where telemetry, audit logs, managed settings, and your developers' IdP identity go, and the gateway sends none of them to Anthropic. For the remaining traffic the CLI process can send and how to close it, see [Compliance posture](/en/claude-apps-gateway-deploy#compliance-posture).

42</Note>

43 

44For which Claude Code features work through the gateway and what the server itself supports, see [Availability and limitations](#availability-and-limitations) below. For decisions such as cost, bypass, running multiple gateways, and serverless platforms, see the [deployment guide](/en/claude-apps-gateway-deploy#deployment).

45 

46### Other gateway implementations

47 

48If you already run an LLM gateway or API gateway that meets your needs, keep using it; [Other LLM gateways](/en/llm-gateway) covers configuring Claude Code against it.

49 

50The [gateway protocol reference](/en/llm-gateway-protocol) documents the contract Claude Code expects from any gateway: the endpoints it calls, the headers and body fields to forward, and what stops working when they're stripped. A running Claude apps gateway serves a superset of that contract at `GET /protocol`, adding the Claude apps gateway-specific endpoints for SSO sign-in, managed settings delivery, and telemetry. Fetch it with `curl https://claude-gateway.internal.example.com/protocol` from any deployed gateway, such as the one the [quickstart](#quickstart) below produces. Breaking changes to the protocol are announced in advance, but indefinite backwards compatibility isn't guaranteed.

51 

52## Quickstart

53 

54This quickstart walks the minimal path: register an OAuth client in your IdP, write a `gateway.yaml`, run the gateway alongside Postgres with Docker Compose, and verify sign-in end to end. It uses an Amazon Bedrock upstream; Google Cloud's Agent Platform, Foundry, and the Anthropic API are equally supported by swapping the `upstreams` block as shown in the [configuration reference](/en/claude-apps-gateway-config#upstreams). At the end you have a gateway a developer can `/login` to.

55 

56<Note>

57 **Deploy on your private network.** Claude Code only connects to a gateway whose address is private. This is a security guard, because a trusted gateway can push settings that run commands on developer machines. Put the gateway behind an internal load balancer or VPN and give it a hostname that resolves to private IPs only.

58</Note>

59 

60### Prerequisites

61 

62Have these in place before you start:

63 

64| You need | Details |

65| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

66| Claude Code v2.1.195 or later | The `claude gateway` subcommand and the gateway sign-in flow ship in v2.1.195. Earlier public builds don't include them. Both the machine running the gateway server and each developer's machine must be on v2.1.195 or later; run `claude update` to get the latest release. |

67| OpenID Connect (OIDC) identity provider | Okta, Microsoft Entra ID, Google Workspace, Keycloak, or Dex, or any other OIDC-compliant IdP such as PingFederate. The gateway runs standard OIDC discovery and the authorization-code flow against it. SAML and LDAP are not supported. |

68| PostgreSQL 14 or later | Backs the device sign-in flow, where the browser callback writes and the polling CLI reads, plus rate-limit counters. Any managed Postgres works, including the smallest tier. Without spend limits configured, the gateway stores a few KB of short-lived auth state; with [spend limits](/en/claude-apps-gateway-spend-limits), it also holds durable spend, audit, and identity tables that should be backed up. TLS via `?sslmode=require` is recommended. |

69| Model upstream | Amazon Bedrock credentials, Google Cloud credentials, a Microsoft Foundry resource, or an Anthropic API key. Multiple upstreams are supported with failover. |

70| HTTPS | The gateway must be reachable over `https://` from developer laptops and from any browser used for sign-in; the gateway serves the device-verification page on the same listener. Either provide a TLS cert via `listen.tls`, or run behind a TLS-terminating ingress and set `listen.public_url`. A plain `http://` origin is accepted only on loopback, for local development. |

71| Private-network address | At `/login`, Claude Code requires the gateway's hostname or IP address to resolve only to private addresses: RFC 1918, CGNAT `100.64.0.0/10`, IPv6 ULA `fc00::/7`, or loopback for local development. The check runs on each resolved IP, so if any address the name resolves to is public, `/login` rejects the URL. If developer machines route HTTPS through a corporate proxy, sign-in also requires the proxy host to resolve to private addresses; if it doesn't, add the gateway host to `NO_PROXY` so the CLI connects directly. |

72| Linux runtime | The gateway server runs only on the native Linux binary. macOS works for local development. Windows is not supported as a server platform. |

73 

74The gateway server requires the native `claude` binary; download a pinned release as described in [Install Claude Code](/en/setup). The server uses runtime features that aren't available when Claude Code runs under Node. If you see `requires the native binary` at boot, switch to one of the standalone install methods.

75 

76### Steps

77 

78<Steps>

79 <Step title="Register an OAuth client in your IdP">

80 Decide the gateway's hostname first, because the redirect URI must match it. Create a new OIDC web application and set the redirect URI to `https://claude-gateway.<your-domain>/oauth/callback`, where the host is the same value you set as [`listen.public_url`](/en/claude-apps-gateway-config#listen) in step 3. Note the `client_id` and `client_secret`. Per-IdP instructions are in [Identity provider setup](/en/claude-apps-gateway-deploy#identity-provider-setup).

81 </Step>

82 

83 <Step title="Provision a PostgreSQL database">

84 Any Postgres 14 or later works, including the smallest managed tier. The gateway runs its own schema migrations at boot, so the database user needs `CREATE TABLE` permission. If your security policy prohibits DDL from application roles, pre-create the schema instead; see [`store`](/en/claude-apps-gateway-config#store).

85 </Step>

86 

87 <Step title="Write gateway.yaml">

88 Secrets are read via `${ENV_VAR}` expansion so the file itself can live in version control. Use a `public_url` hostname that resolves to a private IP on your network, because `/login` rejects public addresses. The minimal config has five sections, and every other field has a default:

89 

90 ```yaml gateway.yaml theme={null}

91 listen:

92 host: 0.0.0.0

93 port: 8080

94 # Required behind any TLS-terminating proxy. Used for the IdP

95 # redirect_uri and the discovery document.

96 public_url: https://claude-gateway.internal.example.com

97 

98 oidc:

99 issuer: https://login.example.com # must serve /.well-known/openid-configuration

100 client_id: 0oa1example2

101 client_secret: ${OIDC_CLIENT_SECRET}

102 allowed_email_domains: [example.com] # reject id_tokens outside your org

103 userinfo_fallback: true # for IdPs whose id_token omits email/groups; harmless otherwise

104 

105 session:

106 jwt_secret: ${GATEWAY_JWT_SECRET} # openssl rand -base64 32

107 ttl_hours: 1 # also bounds revocation latency on IdP deprovision

108 

109 store:

110 postgres_url: ${GATEWAY_POSTGRES_URL} # add ?sslmode=require for managed Postgres

111 

112 upstreams:

113 - provider: bedrock

114 region: us-east-1

115 auth: {} # empty: AWS default credential chain

116 # (IRSA, EC2/ECS task role, env vars, ~/.aws)

117 

118 # Models are translated per upstream automatically. The built-in catalog

119 # maps claude-opus-4-8 to us.anthropic.claude-opus-4-8 and so on for every

120 # Bedrock-supported Claude model. Set false and add a `models:` list to

121 # expose only specific models.

122 auto_include_builtin_models: true

123 ```

124 

125 This config is enough for a working sign-in loop with the default Bedrock model catalog. Once it's running, add per-group RBAC and managed settings via [`managed.policies`](/en/claude-apps-gateway-config#managed), telemetry fan-out via [`telemetry`](/en/claude-apps-gateway-config#telemetry), and multi-upstream failover, provisioned-throughput ARNs, or non-US regions via [`models`](/en/claude-apps-gateway-config#models).

126 

127 <Note>

128 The Bedrock upstream needs an AWS principal with `bedrock:InvokeModel` and `bedrock:InvokeModelWithResponseStream` on both the `inference-profile/us.anthropic.*` ARNs and the underlying `foundation-model/anthropic.*` ARNs, and model access enabled in the Bedrock console for the Claude models you want. Supply the credential with IRSA on EKS, an ECS task role, or an EC2 instance profile rather than static keys. The [`upstreams` reference](/en/claude-apps-gateway-config#upstreams) has the full IAM details, the cross-cloud credential matrix, and the `auth` blocks for the other providers.

129 </Note>

130 </Step>

131 

132 <Step title="Run it">

133 Build a container image around the `claude` binary that meets the [image requirements](/en/claude-apps-gateway-deploy#container-image), then run it alongside Postgres:

134 

135 ```yaml docker-compose.yaml theme={null}

136 services:

137 gateway:

138 image: <your-registry>/claude-gateway:<version>

139 ports: ["8080:8080"]

140 volumes: ["./gateway.yaml:/etc/claude/gateway.yaml:ro"]

141 environment:

142 OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET}

143 GATEWAY_JWT_SECRET: ${GATEWAY_JWT_SECRET}

144 GATEWAY_POSTGRES_URL: postgres://gw:pw@postgres/gateway

145 # AWS credentials: in production, omit these and use an instance

146 # role. For local Compose testing, pass through your own:

147 AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}

148 AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}

149 AWS_SESSION_TOKEN: ${AWS_SESSION_TOKEN}

150 depends_on:

151 postgres:

152 condition: service_healthy

153 postgres:

154 image: postgres:16-alpine

155 environment: { POSTGRES_USER: gw, POSTGRES_PASSWORD: pw, POSTGRES_DB: gateway }

156 healthcheck:

157 test: ["CMD-SHELL", "pg_isready -U gw"]

158 interval: 5s

159 volumes: ["pgdata:/var/lib/postgresql/data"]

160 volumes: { pgdata: }

161 ```

162 

163 The gateway is a single Linux binary that reads the config, runs OIDC discovery against your IdP, applies its Postgres schema migrations, builds upstream clients, and starts listening. Boot is fail-closed for the config, the Postgres connection with a 5-second timeout, OIDC discovery, and upstream client construction. If any of those is unreachable or misconfigured, the gateway exits with an error rather than serving traffic in a degraded state.

164 

165 A successful boot doesn't validate the inference path, because Bedrock and Agent Platform instance credentials resolve on the first request, not at boot.

166 

167 Watch stderr for the boot sequence. Log lines use the format `[gateway] <timestamp> <level> <message>`, audit events are single-line JSON with an `evt` field, and a startup banner, omitted below, prints between the migration and listening lines. You should see, in order:

168 

169 ```text theme={null}

170 {"ts":"2026-06-10T17:03:21.114Z","evt":"config.load","path":"/etc/claude/gateway.yaml","sha256":"…"}

171 [gateway] 2026-06-10T17:03:21.408Z info migration 1 applied

172 [gateway] 2026-06-10T17:03:21.512Z info claude gateway listening on http://0.0.0.0:8080

173 ```

174 

175 If boot exits before the `claude gateway listening on` line, the last line of stderr names the problem:

176 

177 * an unreachable Postgres

178 * a Postgres role without DDL permission

179 * an unreachable or invalid OIDC discovery document

180 * a config schema violation with the offending field path

181 

182 Fix it and restart.

183 

184 If you already have a TLS-terminating ingress, skip Compose and run the binary directly with `claude gateway --config gateway.yaml`. Set `public_url` to the ingress origin and bind `listen` to a loopback or cluster-internal address.

185 </Step>

186 

187 <Step title="Verify the auth surface">

188 Three checks confirm the gateway can authenticate a real user before you hand it to a developer.

189 

190 The examples use the gateway's public URL; for the local Compose setup without an ingress, substitute `http://localhost:8080` in the first two checks. The third check opens `verification_uri_complete`, which is built from `public_url`, so for local Compose set `public_url: http://localhost:8080` in `gateway.yaml`, and add `http://localhost:8080/oauth/callback` as a second redirect URI on the OAuth client from step 1, because the gateway builds the IdP `redirect_uri` from `public_url`. The verification link then opens in your local browser.

191 

192 In Windows PowerShell, run `curl.exe`; the bare `curl` is an alias for `Invoke-WebRequest` and rejects these flags.

193 

194 First, fetch the discovery document, which confirms the gateway is up, the config is valid, and all boot checks passed:

195 

196 ```bash theme={null}

197 curl -s https://claude-gateway.internal.example.com/.well-known/oauth-authorization-server | jq

198 ```

199 

200 ```json theme={null}

201 {

202 "issuer": "https://claude-gateway.internal.example.com",

203 "device_authorization_endpoint": "…/oauth/device_authorization",

204 "token_endpoint": "…/oauth/token",

205 "grant_types_supported": ["urn:ietf:params:oauth:grant-type:device_code", "refresh_token"]

206 }

207 ```

208 

209 The response includes additional fields, such as `response_types_supported` and `scopes_supported`.

210 

211 Second, request a device authorization, which confirms the device sign-in flow works and Postgres is reachable and writable:

212 

213 ```bash theme={null}

214 curl -s -X POST https://claude-gateway.internal.example.com/oauth/device_authorization | jq

215 ```

216 

217 ```json theme={null}

218 {

219 "device_code": "…",

220 "user_code": "WDJB-MJHT",

221 "verification_uri": "https://claude-gateway.internal.example.com/device",

222 "verification_uri_complete": "https://claude-gateway.internal.example.com/device?user_code=WDJB-MJHT",

223 "expires_in": 600,

224 "interval": 5

225 }

226 ```

227 

228 Third, test the browser leg by opening `verification_uri_complete` in a browser and confirming the code. You should be redirected to your IdP's sign-in page, and after signing in, land back on the gateway with a signed-in confirmation.

229 

230 Use the first failing check to locate the problem:

231 

232 * **First check fails**: boot didn't complete; check stderr

233 * **Second check fails**: Postgres isn't reachable from the gateway or the role can't write; check the connection string and grants

234 * **Third check doesn't reach the IdP**: check that the IdP's redirect URI matches `https://<gateway>/oauth/callback` exactly

235 * **Third check reaches the IdP but bounces back with an error**: read the gateway's audit log, which records every auth rejection with the reason, such as `email domain not allowed`

236 </Step>

237 

238 <Step title="Log a developer in">

239 This last step happens on a developer machine, not the server. Push the two managed settings keys shown in [Set the gateway URL](#set-the-gateway-url) below to that machine, then run `/login`, press Enter on the **Cloud gateway** screen, and complete the browser sign-in.

240 </Step>

241</Steps>

242 

243## Connect developers

244 

245Developers connect from their own laptops with one browser sign-in, using their corporate work account. They don't need a claude.ai account, an API key, or a subscription, because requests to the model go through the gateway using the organization's upstream credential. Connection is driven by the [client-side managed settings](/en/claude-apps-gateway-config#client-side-managed-settings) you push via MDM, so there is no manual setup on the developer side; this section covers what the admin configures.

246 

247The CLI fingerprints the gateway's TLS leaf certificate on first connect and pins it per hostname. Publish the expected SHA-256 fingerprint alongside the gateway URL so developers have something to compare against. Get the fingerprint from the certificate file with `openssl x509 -noout -fingerprint -sha256 -in cert.pem`; the `/login` prompt shows the first 16 characters of the digest as lowercase hexadecimal with no separators. When the certificate rotates, every developer sees the trust prompt again, so treat rotations as a planned event and republish the fingerprint.

248 

249Once signed in, the [model picker](/en/model-config) shows the models in the developer's `availableModels` allowlist, managed settings apply at startup and refresh hourly, and telemetry routes to your collector. Sessions refresh silently before `ttl_hours` expiry, and a failed refresh after IdP deprovisioning prompts a re-login.

250 

251### Set the gateway URL

252 

253Set both keys in the per-OS [managed settings file](/en/settings#settings-files) you deploy via MDM or directly on disk, and `/login` opens directly on the **Cloud gateway** screen with the URL filled in:

254 

255```json theme={null}

256{

257 "forceLoginMethod": "gateway",

258 "forceLoginGatewayUrl": "https://claude-gateway.internal.example.com"

259}

260```

261 

262The developer presses Enter to connect. The first-connect TLS fingerprint prompt still appears.

263 

264There is no gateway option in the login picker for a developer to select manually, and `forceLoginGatewayUrl` is ignored in a developer's own settings files. `forceLoginMethod` alone, without a URL, leaves the developer at a "Contact your IT administrator" message. Both keys belong in the file you push to machines, not in the gateway's `managed.policies[].cli` block, which only reaches clients that are already connected.

265 

266### CI pipelines and remote machines

267 

268There is no service-token flow for unattended pipelines. Gateway sign-in always runs the browser device flow, so a CI job with no developer to approve the sign-in can't authenticate; configure those against your provider directly. Once a developer has signed in, every Claude Code invocation on that machine uses the gateway session, including non-interactive `claude -p` runs and sessions started by the Agent SDK, and the [gateway policy applies to all of them](/en/claude-apps-gateway-config#managed).

269 

270The device flow separates the polling CLI from the approving browser, so a remote development box with no display still works: the developer runs `/login` over SSH on the remote machine and opens the verification link in the browser on their laptop.

271 

272### What's enforced on developers

273 

274These guarantees apply to every signed-in gateway session.

275 

276* **Model access**: requests for models the policy doesn't grant return 400, and the `/model` picker is filtered to the policy's `availableModels` allowlist. Set [`enforceAvailableModels: true`](/en/model-config#default-model-behavior) in the policy so the Default option resolves to a model inside `availableModels` instead of to Claude Code's built-in default; without it, Default stays selectable and is rejected at request time if that model isn't granted.

277* **Telemetry destination**: when [telemetry forwarding](/en/claude-apps-gateway-config#telemetry) is configured, the OTLP export endpoint is pinned to the gateway, and the gateway-pushed configuration overrides locally set `OTEL_*` variables.

278* **Credentials**: the gateway token is the session's only credential. `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_API_KEY`, `apiKeyHelper`, and any earlier claude.ai login are ignored while signed in, so developers don't need to log out of claude.ai first.

279* **Managed settings**: locked keys can't be overridden locally. The CLI applies the policy at startup and on each hourly poll.

280* **Startup**: signed-in sessions exit at startup with an error after about 10 seconds when the gateway is unreachable, rather than starting without their settings.

281* **Deprovisioning**: a session whose user is disabled in the IdP expires within `ttl_hours` when the next refresh fails.

282 

283### What the organization can see

284 

285Usage telemetry carries the developer's identity, token counts, model, and latency to the organization's collector. The gateway doesn't log or store prompt or completion content. Whether richer telemetry such as logs and traces is collected, which can include commands and file paths, is the organization's [per-destination choice](/en/claude-apps-gateway-config#telemetry).

286 

287## Availability and limitations

288 

289The table covers which Claude Code features work when developers connect through the gateway, and what the gateway server itself supports. Where something isn't supported, the Notes column gives the alternative.

290 

291The gateway delivers the [`anthropic-beta`](https://platform.claude.com/docs/en/api/beta-headers) values the CLI sends to every upstream, so operators don't maintain a beta allowlist. For Bedrock, which ignores the header, the gateway moves the values into the request body's `anthropic_beta` field; the other upstreams receive the header as sent. The CLI's gateway-session beta set omits first-party-only betas and the extended-cache-ttl beta, which is why those rows below show as not available.

292 

293| Feature | Status | Notes |

294| ----------------------------------------------------------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

295| Inference forwarding (Bedrock, Agent Platform, Foundry, Anthropic) | Available | With per-upstream model translation and failover. The Bedrock upstream uses the `bedrock-runtime` endpoint and the AWS default credential chain; the Bedrock [Mantle endpoint](/en/amazon-bedrock#use-the-mantle-endpoint) is not a supported upstream. |

296| Model access and managed settings by IdP group | Available | Model access is enforced server-side; managed settings are delivered per IdP group and applied by the CLI at the [managed settings tier](/en/settings#settings-precedence) |

297| Telemetry fan-out (OTLP/HTTP) | Available | Identity-stamped per export; both protobuf and JSON encodings |

298| OIDC: Okta, Entra, Google, Keycloak, Dex | Available | Tested. Other OIDC-compliant IdPs should work |

299| Per-user and per-group spend limits | Available | See [Spend limits](/en/claude-apps-gateway-spend-limits) |

300| Server-side web search | Not available | The CLI can't see which upstream provider the gateway routes to, so it can't verify web search support and disables WebSearch on gateway sessions |

301| Standard prompt caching | Available | `cache_control` breakpoints are forwarded to every upstream |

302| 1-hour cache TTL | Not available | The CLI omits the extended-cache-ttl beta on gateway sessions, because not every upstream the gateway can route to supports the 1-hour TTL, so prompt caching through the gateway uses the 5-minute TTL; see the beta-header note above |

303| Auto mode | Available with opt-in | Follows the [third-party provider rules](/en/permission-modes#enable-auto-mode-on-bedrock-vertex-ai-or-foundry): set `CLAUDE_CODE_ENABLE_AUTO_MODE=1`, deliverable through the managed policy `env` block, and only the Opus models eligible on third-party providers can use it |

304| First-party-only optimizations such as global cache scope and token-efficient tools | Not available | The CLI doesn't enable them on gateway sessions; see the beta-header note above |

305| OTLP/gRPC | Not supported | OTLP over HTTP only |

306| SAML, LDAP, and other non-OIDC auth | Not supported | OIDC only. Front with an OIDC bridge if needed |

307| Multi-tenant (multiple OIDC issuers) | Not supported | One issuer per gateway. Run separate instances |

308| Windows server | Not supported | Deploy on Linux. macOS for local development only |

309| Helm chart | Not available | The gateway runs as a standard stateless Deployment; see the [deployment guide](/en/claude-apps-gateway-deploy#kubernetes) |

310| Admin UI | Not available | Configuration is the YAML file; redeploy to change it |

311 

312## Next steps

313 

314The quickstart leaves you with a minimal config running under Docker Compose. To take it further:

315 

316* Expand `gateway.yaml` beyond the minimal config, for example to add per-group RBAC, multi-upstream failover, or telemetry destinations. The [configuration reference](/en/claude-apps-gateway-config) covers every option.

317* Move from Compose to a production deployment on Kubernetes or Cloud Run, set up your IdP properly, and review the security model. The [deployment and operations guide](/en/claude-apps-gateway-deploy) covers per-IdP setup, container image requirements, health probes, and troubleshooting.

318* Put spend caps on individual developers or groups so a runaway workload can't consume your whole commitment. [Spend limits](/en/claude-apps-gateway-spend-limits) covers the admin API and how enforcement works.

319* For a complete worked example on Google Cloud, with Cloud Run, Cloud SQL, and Secret Manager, see [Deploy on Google Cloud](/en/claude-apps-gateway-on-gcp).

claude-apps-gateway-config.md +699 −0 created

Details

1> ## Documentation Index

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt

3> Use this file to discover all available pages before exploring further.

4 

5# Claude apps gateway configuration

6 

7> Reference for every gateway.yaml option: listener and TLS, OIDC, session, Postgres store, Bedrock/Agent Platform/Foundry upstreams, model routing, managed policies, and telemetry.

8 

9A Claude apps gateway deployment is configured by one YAML file, conventionally `gateway.yaml`. The file defines everything the gateway does: where it listens, how developers sign in, where inference goes, and which policies and telemetry apply. This page is the reference for every option in that file. To write your first one, start from the [quickstart](/en/claude-apps-gateway#quickstart), which builds a minimal working config and runs it; once you have a config you're happy with, the [deployment guide](/en/claude-apps-gateway-deploy) covers containerizing and hosting it on Kubernetes, Cloud Run, or your own platform.

10 

11The gateway reads the file once, at startup, with `claude gateway --config /path/to/gateway.yaml`. Every option is validated against a schema at boot, so a malformed config fails at start with a field-level error rather than at first use.

12 

13The [complete example](#complete-example) at the end of this page exercises every section.

14 

15## File structure

16 

17Five sections are [required](#required-sections). Every other section is [optional](#optional-sections), and an omitted section takes its defaults. Unknown keys fail boot, so a typo surfaces as a named error rather than a silently ignored setting.

18 

19**Required sections:**

20 

21* [`listen`](#listen): bind address, public URL, TLS termination

22* [`oidc`](#oidc): your identity provider (IdP), including issuer, client, claim mapping, and who may sign in

23* [`session`](#session): the bearer tokens the gateway mints, with secret and lifetime

24* [`store`](#store): PostgreSQL, for device grants and rate-limit counters

25* [`upstreams`](#upstreams): where inference goes, whether Anthropic, Bedrock, Agent Platform, or Foundry

26 

27**Optional sections:**

28 

29* [`admin`](#admin): Admin API auth and retention for spend limits

30* [`enforcement`](#enforcement): spend-limit fail-open or fail-closed behavior

31* [`models`](#models) and `auto_include_builtin_models`: admin-curated model list and per-upstream IDs

32* [`managed`](#managed): managed settings policies by IdP group

33* [`telemetry`](#telemetry): OTLP forwarding to your observability stack

34* [`access_control`, `limits`, `timeouts`, `rate_limits`](#http-tuning): IP allow/deny, request size caps, upstream time-to-first-byte, and per-IP sign-in limits

35 

36## Secret expansion

37 

38Don't write secrets such as `client_secret`, `jwt_secret`, or `postgres_url` directly in `gateway.yaml`. Reference them with one of the forms below, and the gateway resolves the value at boot from an environment variable or a file:

39 

40| Form | Resolves to | Use for |

41| --------------- | -------------------------------------------------------- | ---------------------------------------------------------------------- |

42| `${VAR}` | The environment variable `VAR`. Boot fails if undefined. | Container environment variables, AWS Secrets Manager via env injection |

43| `${file:/path}` | File contents, trimmed | Kubernetes Secret volume mounts, Vault Agent, SOPS |

44 

45## Required sections

46 

47### `listen`

48 

49The `listen` block controls where the gateway serves: the bind address and port, the externally visible origin, and optional TLS termination.

50 

51| Field | Required | Description |

52| ---------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

53| `host` | No | Bind address. Default `0.0.0.0`. |

54| `port` | No | Bind port. Default `8080`. |

55| `public_url` | Behind a proxy | The externally visible `https://` origin, used to build the IdP `redirect_uri` and discovery metadata. Required behind any TLS-terminating proxy such as an ALB, Ingress, or Cloud Run, because the gateway doesn't trust `X-Forwarded-*` headers when constructing its own origin; they are client-spoofable. `trusted_proxies` below governs client-IP resolution only. Also required to enable [telemetry](#telemetry), because the gateway builds the OTLP endpoint it pushes to clients from this URL. |

56| `tls.cert` / `tls.key` | No | PEM paths if the gateway terminates TLS itself |

57| `trusted_proxies` | No | CIDRs or IPs of load balancers in front of the gateway. When set, the gateway trusts `X-Forwarded-For` only from these peers and records the real client IP for per-IP rate limiting and audit. Equivalent to nginx `set_real_ip_from`. |

58 

59### `oidc`

60 

61OpenID Connect (OIDC) is the SSO protocol the gateway uses with your identity provider; see [Identity provider setup](/en/claude-apps-gateway-deploy#identity-provider-setup) for what to register on the IdP side. The `oidc` block connects the gateway to your identity provider and decides who can sign in. It names the issuer and OAuth client, maps the claims that carry email and groups, and restricts sign-in by email domain or group.

62 

63| Field | Required | Description |

64| ------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

65| `issuer` | Yes | OIDC discovery base. Must serve discovery at `/.well-known/openid-configuration`. Use HTTPS in production; the gateway accepts an `http://` issuer. A loopback issuer such as `http://localhost:8081` is rejected by the [SSRF guard](/en/claude-apps-gateway-deploy#threat-model-summary) unless `CLAUDE_GATEWAY_ALLOW_LOOPBACK=1` is set in the gateway's environment. |

66| `client_id` / `client_secret` | Yes | From your OAuth client registration |

67| `allowed_email_domains` | No | Reject id\_tokens whose `email` claim isn't in one of these domains, case-insensitive. Defense-in-depth against multi-tenant IdP misconfiguration. Independent of this setting, an id\_token whose `email_verified` claim is explicitly `false` is always rejected. |

68| `allowed_groups` | No | Restrict sign-in to members of these IdP groups, matched against `groups_claim`. A user in an allowed email domain but in none of these groups is rejected. Requires the IdP to emit the groups claim. |

69| `groups_claim` | No | Which id\_token claim carries group membership. Default `groups`. Microsoft Entra emits app roles under `roles`. Accepts a flat key or an RFC 6901 JSON Pointer such as `/resource_access/gateway/roles` for nested claims. |

70| `google_groups` | No | Look up the signed-in user's groups through the Google Workspace Admin SDK Directory API, because Google's id\_token carries no groups claim. Set `service_account_json_path` to a service-account key file with domain-wide delegation on the `https://www.googleapis.com/auth/admin.directory.group.readonly` scope, and `admin_email` to a Workspace administrator the service account impersonates; the Directory API requires a real admin subject. Each user's group email addresses become their groups claim, so `allowed_groups` and `managed.policies.match.groups` match on group emails. |

71| `email_claim` | No | Which id\_token claim carries the user's email. Default `email`. Some IdPs, such as ADFS and Entra B2C, emit `upn` or `preferred_username` instead. Accepts a flat key, a JSON Pointer, or a list of fallback keys where the first present key is used. |

72| `scopes` | No | Full override of the OIDC scopes the gateway requests. Default `[openid, profile, email, offline_access]`. Set when your IdP rejects scopes it doesn't recognize, or requires a custom scope to emit groups or email. Must include `openid`. Dropping `offline_access` disables refresh tokens, so developers re-run the browser login every `session.ttl_hours`. See [Identity provider setup](/en/claude-apps-gateway-deploy#identity-provider-setup) for per-IdP scope recipes such as Google's refresh-token flow. |

73| `extra_auth_params` | No | Extra query parameters appended to the IdP authorization request, verbatim. This is the override mechanism for IdP-specific behavior, such as `access_type: offline` for Google refresh tokens, `domain_hint` for some Entra tenants, or `acr_values` for step-up flows. Cannot override the gateway-managed protocol params: `state`, `nonce`, `redirect_uri`, PKCE, `scope`, `response_type`, `response_mode`, and `client_id`. |

74| `userinfo_fallback` | No | When the id\_token omits email or groups, fetch them from `/userinfo`. Needed for Keycloak lightweight access tokens, the Okta org server, and ADFS minimal tokens. The id\_token stays authoritative; userinfo only fills gaps. Default `false`. |

75| `use_pkce` | No | Send a PKCE (S256) challenge on the authorization request. Default `true`. Set `false` only if your IdP rejects PKCE for this confidential client. |

76| `clock_skew_seconds` | No | Tolerate clock drift when validating id\_token time claims. Default `0`, which is strict. Raise if you see "token expired / not yet valid" errors right after sign-in due to host/IdP clock skew. |

77| `token_endpoint_auth_method` | No | Override the token-endpoint auth method. Accepts `client_secret_basic` or `client_secret_post`. Auto-negotiated by default. |

78| `id_token_signed_response_alg` | No | Expected id\_token signing algorithm. Default `RS256`. Set for IdPs that sign with ES256, PS256, or EdDSA. |

79| `additional_authorized_parties` | No | Extra `azp` values to accept beyond `client_id`, for Keycloak broker and token-exchange flows |

80| `discovery_url` | No | Fetch the discovery document from this URL instead of deriving it from `issuer`, for IdPs behind a proxy that rewrites the issuer host. The path must contain `/.well-known/`. |

81| `form_action_origins` | No | Additional origins for the `/device` page's `Content-Security-Policy: form-action` directive. The gateway already allows `'self'` and the discovered `authorization_endpoint` origin, but Chrome enforces `form-action` against the entire redirect chain. If your IdP redirects through a second host, such as Azure AD federated to ADFS, hub-spoke Okta, or a corporate SSO interceptor, list every origin the authorization request may redirect through. |

82| `ca_cert_pem` | No | PEM CA cert that replaces the system trust store for IdP requests only. Use for Keycloak or Dex behind corporate PKI. |

83 

84### `session`

85 

86The `session` block shapes the bearer tokens the gateway mints after sign-in: the secret that signs them and how long they live.

87 

88| Field | Required | Description |

89| ------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

90| `jwt_secret` | Yes | At least 32 bytes of entropy, for example from `openssl rand -base64 32`. Signs the gateway's HS256 bearer tokens. Accepts a single string or an array for rotation: index 0 signs and all entries verify. To rotate, prepend a new secret, wait `ttl_hours`, then drop the old one. |

91| `ttl_hours` | No | Gateway bearer token lifetime. Default `1`. The CLI silently refreshes before expiry when the IdP issues refresh tokens. A shorter lifetime deprovisions faster; a longer one makes fewer IdP round-trips. If your IdP can't issue refresh tokens because `offline_access` is unavailable, there is no silent refresh, so raise this to `8` or `12` to avoid sending developers back to the browser login every hour. |

92 

93### `store`

94 

95The `store` block points the gateway at its PostgreSQL database, which holds device grants and rate-limit counters.

96 

97| Field | Required | Description |

98| ----------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

99| `postgres_url` | Yes | `postgres://` or `postgresql://` URL. Required: the device-grant rendezvous, where the browser callback writes and the polling CLI reads, needs cross-replica state. The gateway runs its own schema migrations at boot, so the role needs `CREATE TABLE` on the target schema. If your security policy prohibits DDL from the application role, run the migrations with an admin role, initially and again whenever a new release ships migrations, and grant the app role `SELECT, INSERT, UPDATE, DELETE` on the gateway's tables. See [Upgrades](/en/claude-apps-gateway-deploy#upgrades) and [Postgres](/en/claude-apps-gateway-deploy#postgres). |

100| `username` | No | Overrides the user in `postgres_url` |

101| `password` | No | Database credential. Set it here rather than in `postgres_url` so the credential stays out of the URL. Accepts any characters and takes precedence over URL credentials. |

102| `max_connections` | No | Postgres connection-pool size per replica. Default `5`, which is conservative and friendly to shared databases. With [spend limits](#admin) enabled, the hot path does a few operations per inference request, so raise it for a dedicated database under load, and keep replicas × this below the database's `max_connections`. |

103 

104For local development, point `postgres_url` at a throwaway Postgres container, for example `docker run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres`.

105 

106### `upstreams`

107 

108`upstreams` is an ordered list. The gateway forwards inference to the first upstream that resolves the requested model. On `5xx`, `429`, or timeout it fails over to the next; other `4xx` doesn't, because those errors are attributable to the request rather than the upstream. Multiple upstreams of the same provider must set a distinct `name:`.

109 

110Bedrock, Agent Platform, and Foundry clients are built once at startup, and their SDKs refresh credentials internally, so rotating cloud credentials doesn't require a restart. Static Anthropic API keys and bearers are read at startup; see [Anthropic API](#anthropic-api).

111 

112#### Anthropic API

113 

114The minimal Anthropic upstream is an API key from the [Claude Console](https://platform.claude.com):

115 

116```yaml theme={null}

117upstreams:

118 - provider: anthropic

119 auth:

120 api_key: ${ANTHROPIC_API_KEY}

121 # OR an OAuth bearer (e.g. a Workload-Identity-Federation-exchanged token):

122 # oauth_token: ${file:/var/run/secrets/anthropic-oauth-token}

123 # base_url: https://api.anthropic.com # default; override for a forward proxy

124```

125 

126The two credential forms differ in the header they send:

127 

128* **`api_key`**: sends `x-api-key`. Rotate it in the Claude Console and update the env var.

129* **`oauth_token`**: sends `Authorization: Bearer`. Use the bearer form when your org issues short-lived tokens instead of long-lived API keys. The bearer is read once at startup, so refresh by remounting the secret and restarting.

130 

131Instead of a static key or bearer, you can use Workload Identity Federation. Create a federation rule by following the [Workload Identity Federation guide](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation), then mount your workload's OIDC JWT as a file, such as a Kubernetes projected service-account token or a CI platform's id-token. The gateway exchanges the JWT for a short-lived bearer and refreshes it automatically. The token file is re-read on every exchange, so rotated projected tokens are picked up without a restart.

132 

133```yaml theme={null}

134upstreams:

135 - provider: anthropic

136 auth:

137 federation_rule_id: ${ANTHROPIC_FEDERATION_RULE_ID}

138 organization_id: ${ANTHROPIC_ORGANIZATION_ID}

139 identity_token_file: /var/run/secrets/anthropic/id-token

140 # workspace_id: wrkspc_... # required if the rule covers >1 workspace

141 # service_account_id: svac_... # optional expected-target check

142```

143 

144#### Amazon Bedrock

145 

146For the client-side Bedrock deployment that the gateway replaces or fronts, see [Claude Code on Amazon Bedrock](/en/amazon-bedrock). The gateway-side upstream:

147 

148```yaml theme={null}

149upstreams:

150 - provider: bedrock

151 region: us-east-1

152 auth: {} # preferred: AWS default credential chain

153 # OR explicit credentials:

154 # auth:

155 # aws_access_key_id: ${AWS_AKID}

156 # aws_secret_access_key: ${AWS_SK}

157 # aws_session_token: ${AWS_ST}

158 # OR a Bedrock API bearer token:

159 # auth:

160 # aws_bearer_token: ${AWS_BEARER_TOKEN}

161 # Override the bedrock-runtime endpoint for FIPS or VPC-endpoint deployments:

162 # base_url: https://bedrock-runtime-fips.us-east-1.amazonaws.com

163```

164 

165An empty `auth` block uses the AWS SDK's default credential chain: env vars, `~/.aws/credentials`, ECS task role, EC2 instance metadata, or IRSA on EKS. In production, give the gateway pod an IAM role instead of embedding static keys in a container image.

166 

167| Setup | How |

168| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

169| IAM permissions | Grant the gateway's principal `bedrock:InvokeModel` and `bedrock:InvokeModelWithResponseStream` on both the inference-profile ARNs and the underlying foundation-model ARNs. For the built-in catalog in US regions: `arn:aws:bedrock:<region>:<account>:inference-profile/us.anthropic.*` and `arn:aws:bedrock:*::foundation-model/anthropic.*`. |

170| Model access | In the Bedrock console, per region, request and enable model access for the Claude models you want. Cross-region inference profiles (`us.anthropic.*`) require model access in each region the profile spans. |

171| EKS (IRSA) | Create an IAM role with the policy above and a trust policy for your cluster's OIDC provider scoped to the gateway's service account. Annotate the service account with `eks.amazonaws.com/role-arn: arn:aws:iam::<acct>:role/claude-gateway`. `auth: {}` picks it up. |

172| ECS / EC2 | Attach the IAM role to the task definition or instance profile. `auth: {}` picks it up. |

173| Anywhere else | Pass credentials via the `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN` env vars, or set them explicitly in `auth:` with `${VAR}` expansion |

174| Region | `region:` is the API endpoint region. Cross-region inference profiles route across the geo (US, EU, APAC) regardless of which one you pick. For non-US regions or provisioned-throughput ARNs, add a [`models:`](#models) block with the right per-upstream IDs. |

175 

176#### Google Cloud Agent Platform

177 

178For the equivalent client-side setup, see [Claude Code on Google Cloud](/en/google-vertex-ai). The gateway-side upstream:

179 

180```yaml theme={null}

181upstreams:

182 - provider: vertex

183 region: us-east5

184 project_id: example-prod

185 auth: {} # preferred: Application Default Credentials

186 # OR a service account key file:

187 # auth: { service_account_json: /secrets/sa.json }

188 # Override the aiplatform endpoint for Private Service Connect:

189 # base_url: https://us-east5-aiplatform.p.googleapis.com

190```

191 

192An empty `auth` block uses Application Default Credentials: `GOOGLE_APPLICATION_CREDENTIALS`, GCE metadata, or GKE Workload Identity. Service-account JSON key files are supported but discouraged; use Workload Identity or attach a service account to the GCE or Cloud Run instance.

193 

194Set `region: global` to use [Agent Platform's global endpoint](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/locations) instead of a regional one. Google then routes each request to an available region, so you don't track per-region model availability. Setting a specific region pins every request to it.

195 

196| Setup | How |

197| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

198| IAM permissions | Grant the gateway's service account `roles/aiplatform.user` on the project, or a custom role with `aiplatform.endpoints.predict`. Enable the Agent Platform API (`aiplatform.googleapis.com`). |

199| Model access | In Model Garden, enable the Claude models for your project. They publish to specific regions; check the model card for supported regions. |

200| GKE (Workload Identity) | Bind a GCP service account to the gateway's Kubernetes service account and annotate the KSA with `iam.gke.io/gcp-service-account: claude-gateway@<proj>.iam.gserviceaccount.com`. `auth: {}` picks it up. |

201| Cloud Run / GCE | Set the service's service account to one with `roles/aiplatform.user`. `auth: {}` picks it up. |

202| Anywhere else | `auth: { service_account_json: /secrets/sa.json }`, the path to a JSON key file mounted as a secret. The field takes a file path, not the key contents, so no `${file:…}` expansion is involved. |

203 

204#### Microsoft Foundry

205 

206For the client-side Foundry deployment, see [Claude Code on Microsoft Foundry](/en/microsoft-foundry). The gateway-side upstream:

207 

208```yaml theme={null}

209upstreams:

210 - provider: foundry

211 resource: example-foundry # https://example-foundry.services.ai.azure.com

212 auth: { use_azure_ad: true } # preferred: DefaultAzureCredential / Managed Identity

213 # OR an API key:

214 # auth:

215 # api_key: ${FOUNDRY_API_KEY}

216```

217 

218`use_azure_ad: true` resolves through `DefaultAzureCredential`: Managed Identity on AKS, ACI, or App Service; the Azure CLI; or environment credentials. API keys work but are project-wide and don't rotate automatically. Foundry's endpoint is derived from `resource:`; set the optional `base_url` to override it for sovereign clouds such as Azure Government.

219 

220| Setup | How |

221| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

222| RBAC | Grant the gateway's identity `Azure AI User` or `Cognitive Services User` on the Foundry resource |

223| Deployments | Foundry uses admin-chosen deployment names, not canonical model IDs. Add a [`models:`](#models) block mapping each canonical ID to your deployment name. |

224| AKS (workload identity) | Federate a User-Assigned Managed Identity with the cluster's OIDC issuer and bind it to the gateway's service account. `use_azure_ad: true` picks it up via `WorkloadIdentityCredential`. |

225| ACI / App Service | Enable system-assigned or user-assigned managed identity on the resource. `use_azure_ad: true` picks it up. |

226| Anywhere else | `auth: { api_key: "${FOUNDRY_API_KEY}" }`. Quote `${…}` inside `{ }`. |

227 

228#### Multiple upstreams

229 

230The same provider can appear more than once with a distinct `name:`. This covers different regions, different accounts via different credential chains, provisioned throughput versus on-demand, and cross-provider fallback.

231 

232The gateway tries upstreams in order. `5xx`, `429`, timeouts, and missing-endpoint (`501`) fail over; other `4xx` doesn't. `429` is per-upstream capacity, so provisioned-throughput (PT) exhaustion fails over to on-demand. An upstream that can't resolve the requested model is skipped without a network round-trip.

233 

234This example routes a provisioned-throughput Bedrock allotment first, overflows to on-demand and a second account, and falls back to the Anthropic API last:

235 

236```yaml theme={null}

237upstreams:

238 # Primary: provisioned throughput in your home region.

239 - name: bedrock-pt

240 provider: bedrock

241 region: us-east-1

242 auth: {}

243 # Overflow: on-demand cross-region.

244 - name: bedrock-od

245 provider: bedrock

246 region: us-west-2

247 auth: {}

248 # Different account: a separate Bedrock allotment via assumed-role creds.

249 - name: bedrock-acct2

250 provider: bedrock

251 region: us-east-1

252 auth:

253 aws_access_key_id: ${ACCT2_AKID}

254 aws_secret_access_key: ${ACCT2_SK}

255 # Last resort: direct Anthropic API.

256 - name: anthropic-fallback

257 provider: anthropic

258 auth:

259 api_key: ${ANTHROPIC_API_KEY}

260 

261# Per-upstream model IDs are keyed on the upstream's `name:`; an upstream

262# without a `name:` defaults to its provider string (e.g. `bedrock`). Any

263# upstream not listed for a model is skipped, which is how you route a model

264# to provisioned throughput while everything else stays on-demand.

265models:

266 - id: claude-opus-4-8

267 label: Claude Opus 4.8

268 upstream_model:

269 bedrock-pt: arn:aws:bedrock:us-east-1:111111111111:provisioned-model/abcdef

270 bedrock-od: us.anthropic.claude-opus-4-8

271 bedrock-acct2: us.anthropic.claude-opus-4-8

272 anthropic-fallback: claude-opus-4-8

273```

274 

275| Lever | How |

276| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

277| Different regions | One Bedrock upstream per region, each with its own `region:`. With [`auto_include_builtin_models: true`](#models) the cross-region inference profiles route automatically; for region-pinned deployments use a `models:` block. |

278| Different accounts | One Bedrock upstream per account, each with its own credentials in `auth:`. The default chain (`auth: {}`) uses the pod's identity; for a second account, set explicit credentials or a bearer token. |

279| Provisioned throughput | Map the model to the provisioned-throughput ARN in `models:` for that upstream's name. Other upstreams keep the on-demand ID, so PT capacity is exhausted before failing over. |

280| VPC / FIPS endpoints | Set `base_url:` on the upstream to your VPC endpoint or FIPS endpoint URL |

281| Model-scoped routing | Omit an upstream from a model's `upstream_model:` map and that upstream is skipped for that model. For example, route Opus to provisioned throughput and Sonnet and Haiku to on-demand. |

282 

283Failing over between cloud providers, or to the direct Anthropic API, changes which agreement, geography, and other terms govern the request.

284 

285The CLI applies the same feature gating to gateways regardless of which upstream serves a given request, so failover doesn't send a body field an upstream would reject.

286 

287## Optional sections

288 

289### `admin`

290 

291Optional. Enables `/v1/organizations/spend_limits`, which mirrors Anthropic's public Admin API, and per-developer spend enforcement on `/v1/messages`. See [Spend limits](/en/claude-apps-gateway-spend-limits) for how caps are set and enforced; this section covers the `gateway.yaml` keys that turn the feature on and tune it.

292 

293```yaml theme={null}

294admin:

295 # Named static API keys for the admin endpoints, sent as x-api-key.

296 # The id appears in the audit log as admin-key:<id> so each key is

297 # attributable. Array for rotation: add the new key, roll clients,

298 # remove the old.

299 write_keys:

300 - { id: terraform, key: "${GATEWAY_ADMIN_WRITE_KEY_TF}" }

301 - { id: ci, key: "${GATEWAY_ADMIN_WRITE_KEY_CI}" }

302 read_keys:

303 - { id: reporting, key: "${GATEWAY_ADMIN_READ_KEY}" }

304 # IdP groups granted full admin via the normal gateway JWT (no API key).

305 admin_groups: [platform-finops]

306 blocked_message: request an increase at https://go.example.com/claude-limits

307```

308 

309| Field | Required | Description |

310| ------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

311| `write_keys` | No | Array of `{id, key}`. An `x-api-key` matching one of these can list, set, and delete spend limits. Key values must be at least 32 characters; `id`s must be unique across `read_keys` and `write_keys`. |

312| `read_keys` | No | Array of `{id, key}`. Read-only: every `GET` endpoint, including listing caps, fetching one by ID, and reading [`/effective`](/en/claude-apps-gateway-spend-limits#%2Feffective) and [`/audit`](/en/claude-apps-gateway-spend-limits#%2Faudit). |

313| `admin_groups` | No | IdP group names. A gateway JWT whose `groups` claim includes one of these has full admin access, read and write, and audits as `oidc:<sub>`. Use this for human admins; use API keys for machines. |

314| `blocked_message` | No | Appended verbatim to the `429 billing_error` a blocked developer sees. Write the whole instruction, such as a URL or a Slack channel. Unset, the error is `spend limit reached`. |

315| `audit_retention_days` | No | Default `365`. Older `admin_audit` rows are swept. |

316| `spend_retention_months` | No | Default `13`. `spend` counter rows older than this are swept. The default keeps a full year plus the current partial month for year-over-year reporting. |

317| `identity_retention_days` | No | Default `90`. Last-seen TTL for `principal_emails` rows, which hold each developer's email, display name, and groups (PII). Deliberately shorter than spend retention so a deprovisioned identity ages out while its anonymous spend counters remain. |

318| `group_limit_mode` | No | `min` (default) or `max`. When a developer is in several groups with caps, `min` enforces the most restrictive and `max` the least. Used by both enforcement and `/effective`. |

319 

320### `enforcement`

321 

322The `enforcement` block controls how spend-limit checks behave when the store is unavailable.

323 

324| Field | Required | Description |

325| ---------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

326| `fail_closed_on_error` | No | Default `false`. Spend enforcement fails open on a Postgres outage, so inference stays up. Set `true` to fail closed: over-cap developers are blocked, but so is everyone else if the store is unreachable. Has no effect without an [`admin:`](#admin) block. |

327 

328### `models`

329 

330The `models` block is an optional admin-curated model list, served at `/v1/models` and used to translate model IDs per upstream. It is required for non-US Bedrock regions, Bedrock provisioned-throughput ARNs, and Foundry deployment names.

331 

332```yaml theme={null}

333auto_include_builtin_models: true # false: expose only the list below

334models:

335 - id: claude-opus-4-8

336 label: Claude Opus 4.8

337 # description: optional text shown in clients that surface it

338 upstream_model:

339 anthropic: claude-opus-4-8

340 bedrock: us.anthropic.claude-opus-4-8 # or an inference-profile ARN

341 foundry: your-opus-deployment-name

342```

343 

344### `managed`

345 

346The `managed` block defines role-based access policies keyed on IdP groups or email domain. Policies are evaluated in order; the first match is selected, then merged onto the `match: {}` catch-all base described below. They are served per-user at `GET /managed/settings` with ETag/304 caching.

347 

348```yaml theme={null}

349managed:

350 policies:

351 # Specific groups first.

352 - match: { groups: [eng-contractors] }

353 cli:

354 availableModels: [claude-sonnet-4-6]

355 permissions: { deny: ["WebFetch", "WebSearch"] }

356 # Default catch-all last: matches everyone who authenticated.

357 - match: {}

358 cli:

359 availableModels: [claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5]

360```

361 

362A `match: {}` catch-all, conventionally listed last, is treated as a base layer. Every other policy inherits any key it doesn't set from the catch-all, so per-role entries only need to list what differs from the org default. The merge rules depend on the key type:

363 

364* **Allow-lists**: `availableModels` and `permissions.allow`. A specific policy's list fully replaces the base's.

365* **Deny-lists and hook arrays**: `permissions.deny`, `permissions.ask`, `disabledMcpjsonServers`, `deniedMcpServers`, `blockedMarketplaces`, and every `hooks` event-type array. These take the union of base and policy, so an org-wide deny or audit hook can't be accidentally dropped by a per-role override.

366* **Record-typed keys**: `env`, `modelOverrides`, and `skillOverrides`. These shallow-merge, so a per-role `env` block overrides keys it sets and inherits the rest from the base.

367 

368`availableModels` is also enforced server-side at `/v1/messages`, so a denied model returns `400` regardless of what the client sends.

369 

370| Matcher | Behavior |

371| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |

372| `match: {}` | Matches every authenticated user. Start with one of these and add group-scoped policies above it later. |

373| `match: { groups: [a, b] }` | Matches if the JWT's `groups` claim contains any of the listed groups. Case-sensitive: groups must match the IdP's exact casing. |

374| `match: { email_domain: example.com }` | Matches the part after the last `@` in the JWT's `email` claim, case-insensitive. Accepts one domain per policy. |

375| `match: { groups: [a], email_domain: example.com }` | Both conditions must match |

376 

377An authenticated user who matches no policy gets the gateway's defaults, which means every model in the catalog and no managed settings. Add a `match: {}` catch-all last if you want a guaranteed default policy.

378 

379<Note>

380 The gateway keeps no user directory of its own. It authorizes each request from the user's IdP token, reading group membership from the token's `groups` claim and evaluating policies against it. There is no roster to enumerate and no accounts to pre-create, and therefore no SCIM endpoint, because there is nothing for SCIM to sync into.

381 

382 Run user and group lifecycle management at the source of truth, which is your IdP's native SCIM provisioning or a dedicated identity-governance platform. Membership and deprovisioning governed there flow into the gateway automatically through the token. If you want SCIM provisioning of Claude accounts themselves, that is a [Claude for Enterprise](/en/admin-setup) capability.

383 

384 Two propagation clocks apply:

385 

386 * **Policy contents**: editing a policy and redeploying reaches connected clients on their next managed-settings poll, within an hour

387 * **Group membership**: changing a user's group membership changes which policy matches them. This takes effect on the next session re-mint, meaning the next silent refresh, bounded by `session.ttl_hours`.

388</Note>

389 

390#### What goes in `cli`

391 

392Each `cli` value is a complete Claude Code `managed-settings.json` document, the same schema you would deploy via MDM or `/etc/claude-code/managed-settings.json`, expressed here as YAML. The CLI applies the delivered document at the managed tier, above user and project settings.

393 

394The gateway validates each document against the CLI's settings schema at boot, so an unrecognized top-level key or a recognized key with a malformed value fails boot with an error naming every offending key. Deliberately open parts of the schema still accept arbitrary values, because newer clients may recognize entries the gateway's schema doesn't. These open keys are `env`, `pluginConfigs`, and keys nested under `permissions`.

395 

396Because validation uses the schema bundled with the gateway's installed version, putting a top-level settings key introduced by a newer Claude Code release into managed config requires upgrading the gateway first. Smoke-test a new policy on one client before rolling it out.

397 

398The full key reference is in [Claude Code settings](/en/settings#available-settings). The keys most operators reach for first:

399 

400```yaml theme={null}

401managed:

402 policies:

403 - match: {}

404 cli:

405 # Model access (also enforced server-side at /v1/messages)

406 availableModels: [claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5]

407 

408 # Permission policy

409 permissions:

410 deny:

411 - "WebFetch"

412 - "Read(./.env)"

413 - "Read(./secrets/**)"

414 disableBypassPermissionsMode: disable # blocks --dangerously-skip-permissions

415 allowManagedPermissionRulesOnly: true # ignore user/project permission rules

416 

417 # Environment pushed into the CLI process. DISABLE_UPDATES blocks

418 # background and manual updates; DISABLE_AUTOUPDATER stops only

419 # background updates.

420 env:

421 DISABLE_UPDATES: "1" # pin versions via your own distribution

422 

423 # Org-wide hooks. Hook commands run on developer machines, not the

424 # gateway, so the path must exist on every client OS in the policy.

425 hooks:

426 PostToolUse:

427 - matcher: "Edit|Write"

428 hooks:

429 - { type: command, command: /usr/local/bin/audit-edit.sh }

430```

431 

432| Key | Enforced by | Effect |

433| ------------------------------------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

434| `availableModels` | Gateway + CLI | Model allowlist. Also checked at `/v1/messages`, so a patched client can't bypass it. |

435| `permissions.allow` / `.deny` | CLI | Tool and command rules. See [Permissions](/en/permissions). |

436| `permissions.disableBypassPermissionsMode` | CLI | Set to `disable` to block [`bypassPermissions`](/en/permission-modes#skip-all-checks-with-bypasspermissions-mode), the mode that auto-approves every tool call, and the `--dangerously-skip-permissions` flag |

437| `allowManagedPermissionRulesOnly` | CLI | When `true`, user and project permission rules are ignored; only rules from this document apply |

438| `env` | CLI | Environment variables merged into the CLI process. Use for telemetry, auto-update, and model-name overrides. |

439| `hooks` | CLI | Org-wide [hooks](/en/hooks) |

440 

441Because these settings arrive over the network, the CLI shows each developer a one-time security approval dialog before applying anything that can run a shell command or alter where traffic goes. The dialog covers:

442 

443* `hooks`

444* `env` variables that aren't on the CLI's built-in safe list

445* shell-execution settings such as `apiKeyHelper` and `statusLine`

446* managed CLAUDE.md content

447 

448The safe list determines which `env` variables apply without approval:

449 

450* **On the safe list**: auto-update and model-name vars

451* **Not on the safe list**: proxy vars, base-URL vars, and `OTEL_EXPORTER_OTLP_ENDPOINT`

452 

453The gateway's [telemetry](#telemetry) configuration pushes `OTEL_EXPORTER_OTLP_ENDPOINT`, so setting `telemetry.forward_to` triggers the dialog on each interactive client. Non-interactive runs with the `-p` flag skip the dialog and apply settings without approval. The dialog protects the developer's machine from a compromised or hostile gateway, not the organization from the developer, so the `-p` skip is intentional rather than a gap.

454 

455If a developer declines, Claude Code exits rather than applying the policy. Pushing a new hook or non-safe env var to a broad policy therefore means an approval prompt on every matching developer's next startup.

456 

457The `cli` key was named `settings` in earlier releases. That spelling is still accepted as an alias, but new deployments should use `cli`.

458 

459#### Precedence with other managed sources

460 

461If a device also has a local `managed-settings.json` or MDM-delivered policy, the managed sources don't merge. The highest-priority source provides all policy settings, ranked in this order with highest priority first:

462 

4631. The [policy helper](/en/settings#compute-managed-settings-with-a-policy-helper)

4642. Gateway-delivered settings

4653. MDM, via the HKLM registry on Windows or a plist on macOS

4664. The `managed-settings.json` file

4675. The HKCU registry, on Windows only

468 

469Embedding hosts can supply policy through the SDK `managedSettings` option. It is ignored by default and applies only when a managed source opts in with [`parentSettingsBehavior: "merge"`](/en/settings#available-settings), filtered so it can tighten policy but not loosen it.

470 

471The exception is a small set of cross-source keys, honored when any admin source sets them; the user-writable HKCU tier is excluded:

472 

473* `sandbox.network.allowManagedDomainsOnly` and `sandbox.filesystem.allowManagedReadPathsOnly`: when locked, the corresponding allowlists are unioned across sources

474* [`allowAllClaudeAiMcps`](/en/settings#available-settings): allow-only override for the claude.ai MCP server allowlist

475* `sandbox.bwrapPath` and `sandbox.socatPath`: filesystem paths to the [sandbox](/en/sandboxing) helper binaries

476 

477`allowManagedPermissionRulesOnly` and `disableBypassPermissionsMode` are not cross-source, so only the winning source's value applies.

478 

479Gateway policies apply to every Claude Code invocation on the machine, including non-interactive `claude -p` runs and sessions spawned by the Agent SDK. If the gateway is unreachable at startup, signed-in sessions exit with an error rather than running without their policy.

480 

481<Warning>

482 `mcpServers` inside a policy's `cli` block is rejected at gateway boot. Per-group MCP distribution is not available; deploy MCP servers via the file-based `managed-mcp.json` on each device or let developers add them locally.

483</Warning>

484 

485### `telemetry`

486 

487The CLI sends OpenTelemetry Protocol (OTLP) over HTTP metrics, logs, and, when enabled, traces to the gateway, which relays them verbatim to each configured destination. See [Monitoring usage](/en/monitoring-usage) for the metrics and events the CLI emits.

488 

489The CLI stamps each export with the authenticated user's identity, read from the gateway-issued JWT: the `user.id`, `user.email`, and `user.groups` attributes. Per-developer cost and usage attribution therefore works with no developer-side configuration.

490 

491```yaml theme={null}

492telemetry:

493 forward_to:

494 - url: https://otel-collector.internal.example.com

495 headers:

496 Authorization: ${OTLP_TOKEN}

497 # Per-signal opt-in. Default: metrics only.

498 metrics: true

499 logs: false

500 traces: false

501 - url: https://api.datadoghq.com/api/v2/otlp

502 headers:

503 DD-API-KEY: ${DD_API_KEY}

504```

505 

506<Warning>

507 Each destination opts into `metrics`, `logs`, and `traces` independently, and the default is metrics only. The signals differ in sensitivity:

508 

509 * **Metrics**: aggregate counters such as token counts, request counts, and latency

510 * **Logs and traces**: can carry full bash commands, tool inputs, and file paths, covering anything Claude Code does on a developer's machine

511 

512 Enable logs and traces only on destinations with the access controls and retention policy that data warrants.

513</Warning>

514 

515Telemetry is off in the CLI by default. Configuring `telemetry.forward_to` together with `listen.public_url` turns it on. The gateway pushes five env vars to every connected client through `/managed/settings`:

516 

517* `CLAUDE_CODE_ENABLE_TELEMETRY=1`

518* `OTEL_METRICS_EXPORTER=otlp`

519* `OTEL_LOGS_EXPORTER=otlp`

520* `OTEL_TRACES_EXPORTER=otlp`

521* `OTEL_EXPORTER_OTLP_ENDPOINT=<public_url>`

522 

523The pushed endpoint is built from the public URL, so metrics and logs need no OTEL configuration from developers or policies. The pushed configuration is applied at the managed tier, overriding `OTEL_*` variables a developer sets locally.

524 

525[Traces](/en/monitoring-usage#traces-beta) additionally require `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1` on each client. The gateway doesn't push that variable, so set it through a managed policy's `env` block. It isn't on the CLI's safe list, so delivering it through a policy is covered by the same [security approval dialog](#managed) that the pushed OTLP endpoint already triggers.

526 

527Both protobuf and JSON OTLP encodings are relayed, and any OpenTelemetry-compatible backend works as a destination.

528 

529### HTTP tuning

530 

531Four optional top-level blocks, `access_control`, `limits`, `timeouts`, and `rate_limits`, tune the HTTP surface. The defaults suit most deployments.

532 

533| Block | Key | Default | Description |

534| ---------------- | ---------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

535| `access_control` | `allow_cidrs` / `deny_cidrs` | empty | Inbound IP allow/deny by client address, after `trusted_proxies` resolution. `deny_cidrs` is checked first; a client it matches is rejected even if `allow_cidrs` also matches. If `allow_cidrs` is non-empty the gateway is default-deny. `/healthz` and `/readyz` are exempt from `allow_cidrs`. |

536| `limits` | `max_request_bytes` | 32 MiB | Max inbound request body; oversize requests get `413` before the body is buffered. Raise for large file or image requests. |

537| `limits` | `max_request_header_bytes` | unset | When set, oversize headers return `431` |

538| `limits` | `max_url_length` | unset | When set, an over-long URL returns `414` |

539| `timeouts` | `upstream_ttfb_ms` | 120000 | Max wait for the upstream's response headers (time to first byte). The response body then streams with no wall-clock cap. Applies to the direct Anthropic upstream path; Bedrock, Agent Platform, and Foundry are bounded by their provider SDK's own timeout. |

540| `rate_limits` | `device_authorization.max` / `.window_seconds` | 30 / 600 | Per-IP rate limit on the unauthenticated device-authorization endpoint. Raise for a large org behind a shared egress IP or NAT. These limits apply only to the device-grant sign-in flow, not to `/v1/messages` inference. See [User-code brute-force resistance](/en/claude-apps-gateway-deploy#user-code-brute-force-resistance). |

541| `rate_limits` | `device_verify.max` / `.window_seconds` | 10 / 600 | Per-IP rate limit on `user_code` submissions at `/device` |

542 

543## Complete example

544 

545This full reference config exercises every core section; the [HTTP tuning blocks](#http-tuning) keep their defaults. Copy it, delete what you don't need, and fill in your values. The config in the [Quickstart](/en/claude-apps-gateway#quickstart) is a minimal version of this.

546 

547```yaml gateway.yaml theme={null}

548# Run with:

549# claude gateway --config gateway.yaml

550#

551# Operational log verbosity is controlled by the CLAUDE_GATEWAY_LOG_LEVEL

552# environment variable (info | warn | error; default info). It does not

553# affect audit events, which are always emitted.

554 

555listen:

556 host: 0.0.0.0

557 port: 8080

558 public_url: https://claude-gateway.internal.example.com

559 # Omit the tls block when running behind a TLS-terminating ingress.

560 # tls:

561 # cert: /certs/gateway.crt

562 # key: /certs/gateway.key

563 # trusted_proxies:

564 # - 10.0.0.0/8

565 

566oidc:

567 issuer: https://example.okta.com

568 client_id: 0oa1example2

569 client_secret: ${OIDC_CLIENT_SECRET}

570 allowed_email_domains:

571 - example.com

572 # Required when the issuer is the Okta org server, whose id_tokens

573 # can omit email and groups; the gateway fills them from /userinfo.

574 userinfo_fallback: true

575 # allowed_groups: [claude-code-users]

576 # Okta emits groups only when the `groups` scope is requested and the

577 # app's groups claim filter allows them. The contractors policy below

578 # matches on groups, so the scope is requested here.

579 scopes: [openid, profile, email, offline_access, groups]

580 # extra_auth_params: { access_type: offline, prompt: consent } # Google

581 # groups_claim: groups # Entra app roles: use `roles`

582 # email_claim: email

583 

584session:

585 jwt_secret: ${GATEWAY_JWT_SECRET} # openssl rand -base64 32

586 # ttl_hours: 1

587 

588store:

589 postgres_url: ${GATEWAY_POSTGRES_URL}

590 # max_connections: 5

591 

592# Enables /v1/organizations/spend_limits (mirrors the Anthropic Admin API)

593# and per-developer spend enforcement on /v1/messages. Omit to disable.

594# Caps themselves are set via the admin API, not here.

595# admin:

596# write_keys:

597# - { id: terraform, key: "${GATEWAY_ADMIN_WRITE_KEY_TF}" }

598# read_keys:

599# - { id: reporting, key: "${GATEWAY_ADMIN_READ_KEY}" }

600# admin_groups: [platform-finops]

601# blocked_message: request an increase at https://go.example.com/claude-limits

602# # audit_retention_days: 365

603# # spend_retention_months: 13

604# # identity_retention_days: 90

605# # group_limit_mode: min

606 

607# enforcement:

608# fail_closed_on_error: false

609 

610upstreams:

611 - provider: anthropic

612 auth:

613 api_key: ${ANTHROPIC_API_KEY}

614 

615 # - provider: bedrock

616 # region: us-east-1

617 # auth: {}

618 

619 # - provider: vertex

620 # region: us-east5

621 # project_id: example-prod

622 # auth: {}

623 

624 # - provider: foundry

625 # resource: example-foundry

626 # auth: { use_azure_ad: true }

627 

628auto_include_builtin_models: true

629models:

630 - id: claude-opus-4-8

631 label: Claude Opus 4.8

632 upstream_model:

633 anthropic: claude-opus-4-8

634 # bedrock: us.anthropic.claude-opus-4-8

635 # vertex: claude-opus-4-8

636 # foundry: <your-opus-deployment-name>

637 - id: claude-sonnet-4-6

638 label: Claude Sonnet 4.6

639 upstream_model:

640 anthropic: claude-sonnet-4-6

641 - id: claude-haiku-4-5

642 label: Claude Haiku 4.5

643 upstream_model:

644 anthropic: claude-haiku-4-5

645 

646managed:

647 policies:

648 - match: { groups: [contractors] }

649 cli:

650 availableModels: [claude-haiku-4-5]

651 # Constrain the Default picker option to availableModels instead of

652 # the tier default, so contractors don't get a 400 on the default.

653 enforceAvailableModels: true

654 # allow auto-approves these tools; it does not block the rest.

655 # Add deny rules to restrict tools.

656 permissions: { allow: [Read, Grep] }

657 - match: {}

658 cli:

659 availableModels: [claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5]

660 permissions:

661 allow: [Read, Grep, Bash, Edit]

662 deny: ["WebFetch"]

663 env: { HTTP_PROXY: http://proxy.example.com:8080 }

664 

665telemetry:

666 forward_to:

667 - url: https://otel.internal.example.com:4318

668 headers:

669 Authorization: Bearer ${OTEL_TOKEN}

670```

671 

672## Client-side managed settings

673 

674Everything above configures the gateway server. Pointing developer machines at it is configured separately, on each device, through Claude Code's [managed settings](/en/settings#settings-files). The gateway can't push these keys itself, because they're what tell the client where the gateway is.

675 

676For the CLI, set both keys in the per-OS `managed-settings.json`:

677 

678```json theme={null}

679{

680 "forceLoginMethod": "gateway",

681 "forceLoginGatewayUrl": "https://claude-gateway.internal.example.com"

682}

683```

684 

685Deploy that file to each device, typically via your MDM platform. The file path differs by platform:

686 

687| Platform | Path |

688| ------------- | ----------------------------------------------------------------------------------------------------------------------------- |

689| macOS | `/Library/Application Support/ClaudeCode/managed-settings.json`, or the `com.anthropic.claudecode` managed preferences domain |

690| Linux and WSL | `/etc/claude-code/managed-settings.json` |

691| Windows | `C:\Program Files\ClaudeCode\managed-settings.json`, or Group Policy via the HKLM registry |

692 

693`forceLoginGatewayUrl`, and the `"gateway"` value of `forceLoginMethod`, are honored only from the admin-controlled managed tier. A developer setting them in their own `~/.claude/settings.json` has no effect.

694 

695## Related

696 

697* [Claude apps gateway overview](/en/claude-apps-gateway): quickstart and developer connection

698* [Deployment guide](/en/claude-apps-gateway-deploy): IdP setup, container image, Kubernetes and Cloud Run, and operations

699* [Spend limits](/en/claude-apps-gateway-spend-limits): per-developer caps and the Admin API

claude-apps-gateway-deploy.md +263 −0 created

Details

1> ## Documentation Index

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt

3> Use this file to discover all available pages before exploring further.

4 

5# Claude apps gateway deployment and operations

6 

7> Register the gateway with your IdP, build the container, deploy on Kubernetes or Cloud Run, and operate it: health checks, secret rotation, upgrades, and security.

8 

9This page covers the operational side of running [Claude apps gateway](/en/claude-apps-gateway): registering an OAuth client in your identity provider (IdP), deploying the gateway as a container, and running it day-to-day. For every option in the `gateway.yaml` file the gateway reads at boot, see the [Configuration reference](/en/claude-apps-gateway-config).

10 

11A production deployment follows four steps in order, and the sections below match them. The first two are where you make choices; the second two are reference material to consult once it's running.

12 

131. [Set up your identity provider](#identity-provider-setup): register the OAuth client and check the per-IdP notes for Okta, Entra, and Google

142. [Deploy the gateway](#deployment): build a pinned container image and run it on Kubernetes, Cloud Run, or your own platform. This section also covers cost, bypass, multiple-gateway, and serverless decisions

153. [Set up operations](#operations): logs, health probes, outage behavior, secret rotation, and upgrades. Reference for when you're wiring up monitoring and runbooks

164. [Review the security posture](#security): what data flows where, the threat model, and compliance answers. Reference for a security review

17 

18If a sign-in or boot fails along the way, go straight to [Troubleshooting](#troubleshooting), which is keyed on the error you see.

19 

20<Note>

21 **Deploy on your private network.** Claude Code only connects to a gateway whose address is private. This is a security guard, because a trusted gateway can push settings that run commands on developer machines. Put the gateway behind an internal load balancer or VPN and give it a hostname that resolves to private IPs only.

22</Note>

23 

24## Identity provider setup

25 

26Register a confidential OAuth/OpenID Connect (OIDC) web application with a single redirect URI, `https://<gateway>/oauth/callback`, and assign it to the users or groups who should have gateway access.

27 

28Any OIDC-compliant IdP works: Okta, Microsoft Entra ID, Google Workspace, Keycloak, Dex, PingFederate, and others. The IdP must meet three requirements:

29 

30* Serves `/.well-known/openid-configuration`, over HTTPS in production; the gateway accepts an [`http://` issuer](/en/claude-apps-gateway-config#oidc), and a loopback issuer additionally requires `CLAUDE_GATEWAY_ALLOW_LOOPBACK=1`

31* Supports the authorization-code flow. PKCE (Proof Key for Code Exchange) is on by default; disable it with `oidc.use_pkce: false` for IdPs that don't support it

32* Returns `email` and optionally `groups` in the id\_token, or serves them from the userinfo endpoint with `oidc.userinfo_fallback: true`

33 

34For private PKI, set `oidc.ca_cert_pem`.

35 

36A few providers handle email and group claims differently:

37 

38* **Okta**: the org authorization server at `https://example.okta.com` returns a thin id\_token that omits `email` and `groups`, so set `oidc.userinfo_fallback: true` whenever you use it as `issuer`. A custom authorization server such as `https://example.okta.com/oauth2/default` that includes `email` and optionally `groups` in the id\_token emits them directly and needs no fallback. Okta emits `groups` only when the `groups` scope is requested in `oidc.scopes` and the app's groups claim filter allows it; `userinfo_fallback` can't fill a claim the IdP wasn't asked for.

39* **Microsoft Entra ID**: `issuer` = `https://login.microsoftonline.com/<tenant-id>/v2.0`. Entra emits group Object IDs rather than names, so use the GUIDs in `managed.policies.match.groups`, or use App Roles for human-readable names. If your tenant emits roles under `roles` instead of `groups`, set `oidc.groups_claim: roles`.

40* **Google Workspace**: `issuer` = `https://accounts.google.com`. Google's id\_token doesn't carry groups. To use group-based `allowed_groups` or `managed.policies` with Google as the IdP, configure [`oidc.google_groups`](/en/claude-apps-gateway-config#oidc), which looks up each user's groups through the Admin SDK Directory API using a service account with domain-wide delegation. Without it, use `oidc.allowed_email_domains` for membership gating and `managed.policies.match.email_domain` for policy assignment. Google also ignores the standard `offline_access` scope. For refresh tokens, set `oidc.scopes: [openid, profile, email]` and `oidc.extra_auth_params: { access_type: offline, prompt: consent }`.

41 

42<Note>

43 The gateway is tested against a wide range of identity providers, but some have quirks that haven't surfaced in testing. If you hit one, [file a GitHub issue](https://github.com/anthropics/claude-code/issues) so it can be fixed.

44</Note>

45 

46<Warning>

47 Refresh tokens let the gateway renew a developer's session silently, without sending the developer back to the browser. They also drive deprovisioning, because when the IdP disables a user, the next refresh fails and the session ends within `ttl_hours`. The gateway requests `offline_access` by default to get a refresh token. If your IdP requires explicit consent for offline access, configure the OAuth client to allow it.

48 

49 If your IdP can't issue refresh tokens at all, the gateway still works, but there is no silent renewal, so developers re-run the browser login when their session expires. To keep that from happening every hour, raise [`session.ttl_hours`](/en/claude-apps-gateway-config#session) to `8` or `12`. The tradeoff is deprovisioning latency, because without refresh tokens a disabled user keeps access until the longer TTL elapses.

50</Warning>

51 

52## Deployment

53 

54The gateway is a single Linux binary. It scales horizontally because replicas are stateless and Postgres is the shared coordination layer. Run it however you run stateless services in your environment. The rest of this section states what the image needs, with short notes for Kubernetes and Cloud Run.

55 

56The gateway is designed to run inside your network, because it holds your upstream credential and acts as the single egress point for inference. It can run anywhere your developers and your IdP can reach over HTTPS; treat it like any other service holding a production credential.

57 

58A few decisions shape the deployment beyond where it runs:

59 

60* **Cost**: there is no separate license or per-seat fee for the gateway; it's part of the `claude` binary. You pay for inference through your existing cloud or Anthropic commitment, plus the compute for the container and your telemetry collector.

61* **Bypass**: the gateway doesn't enforce that the only route to a model goes through it. A developer with their own credential can still call the provider directly, so closing that path is a network policy decision, for example blocking egress to `api.anthropic.com` except from the gateway. Blocking that egress also breaks the [WebFetch domain safety check](/en/data-usage#webfetch-domain-safety-check), which calls `api.anthropic.com` from each developer's machine; set `skipWebFetchPreflight: true` in the managed policy to disable it.

62* **Multiple gateways**: each gateway is a separate deployment with its own config. The CLI stores its trust fingerprint and credentials per gateway hostname, so different teams can connect to different gateways without conflict. To serve multiple OIDC issuers, run separate instances.

63* **Serverless**: Cloud Run works; set `min-instances: 1` to avoid cold OIDC discovery. Lambda and Cloud Functions don't, because the gateway is a long-running HTTP server.

64 

65Every production topology here puts an L7 proxy, such as an Ingress, Cloud Run's front end, or an ALB, in front of plain-HTTP replicas. Set [`listen.trusted_proxies`](/en/claude-apps-gateway-config#listen) to the proxy's source ranges so the gateway reads client IPs from `X-Forwarded-For`. The gateway honors the header only when the TCP peer is trusted; the [Google Cloud worked example](/en/claude-apps-gateway-on-gcp) has concrete values per topology. Without trusted proxies, every request appears to come from the proxy's IP, which collapses per-IP rate limits into one shared bucket and records the proxy's IP in audit events.

66 

67### Container image

68 

69Build your own image around the native `claude` binary from the standard Claude Code release:

70 

711. Download the Linux build for your image architecture from a pinned release; see [Install a specific version](/en/setup#install-a-specific-version) for the download URL.

722. Verify it against the release's GPG-signed `manifest.json` as described in [Binary integrity and code signing](/en/setup#binary-integrity-and-code-signing).

733. Copy it into the build context.

74 

75Mirror the release into your internal registry if your builds can't reach the release host, and pin the version your fleet runs.

76 

77Beyond the binary, the image needs:

78 

79* **A glibc-based image**: the glibc build's only dynamic dependencies are glibc libraries. Musl-based images need the `linux-x64-musl` or `linux-arm64-musl` build plus additional packages; see [Alpine Linux setup](/en/setup#alpine-linux-and-musl-based-distributions).

80* **A writable state directory**: the gateway runs as any user, but minimal images have no writable home. Set `CLAUDE_CONFIG_DIR` to a writable path such as `/tmp/.claude`.

81* **The container command**: `claude gateway --config /etc/claude/gateway.yaml`, with the config file mounted read-only and secrets supplied as environment variables; the gateway listens on `listen.port`, default `8080`.

82 

83### Kubernetes

84 

85Run the gateway as a Deployment, like any stateless service:

86 

87* Mount the config from a ConfigMap and secrets from a Secret; reference secrets in the YAML via `${file:/path/to/secret}` or as environment variables

88* Terminate TLS at the Ingress and set `listen.public_url` to the Ingress hostname

89* Point the readiness probe at `GET /readyz` and the liveness probe at `GET /healthz`

90 

91<Note>

92 **Workload identity**

93 

94 Prefer the platform's workload identity over static keys: IRSA on EKS for Bedrock, Workload Identity on GKE for Agent Platform, and workload identity on AKS for Foundry. Set `auth: {}` in the upstream block, or `use_azure_ad: true` for Foundry, and the gateway picks up the pod's identity through that provider's default credential chain. For a cross-cloud pairing, such as a Bedrock upstream on GKE, set explicit credentials in the upstream's `auth` block instead. The [`upstreams` reference](/en/claude-apps-gateway-config#upstreams) has per-platform setup details.

95</Note>

96 

97### Cloud Run

98 

99Configure the service as follows:

100 

101* Leave `listen.port` at its default of `8080`, which matches Cloud Run's default `PORT`, or set `port: ${PORT}`

102* Set `public_url` to the externally reachable origin. For production this is normally an internal load balancer's hostname, because `/login` [rejects public addresses](/en/claude-apps-gateway#prerequisites) and the `*.run.app` URL resolves to one, so the Cloud Run URL alone works only for a `curl` or browser smoke test. The exception is a network where `*.run.app` resolves privately through Private Service Connect and a Cloud DNS private zone; in that topology the Cloud Run URL is a valid `public_url`. The [Google Cloud worked example](/en/claude-apps-gateway-on-gcp#deploy-the-gateway) covers both.

103* Mount the config as a secret volume

104* Set `min-instances: 1` to avoid a cold OIDC discovery on first request

105 

106<Note>

107 For a complete worked example on Google Cloud, covering Cloud Run or GKE, Cloud SQL, and Secret Manager, see [Deploy on Google Cloud](/en/claude-apps-gateway-on-gcp).

108</Note>

109 

110### Push the gateway URL to developer machines

111 

112Once the gateway is serving, push `forceLoginMethod` and `forceLoginGatewayUrl` to each developer's machine through managed settings, via MDM or by writing the per-OS `managed-settings.json` directly. Without this, `/login` shows the standard account picker with no gateway option. See [Client-side managed settings](/en/claude-apps-gateway-config#client-side-managed-settings) for the file paths.

113 

114## Operations

115 

116Once the gateway is serving traffic, day-to-day operation is reading its logs, probing its health, and rotating its secrets on your schedule. The subsections cover each, plus what Postgres holds and how upgrades and rollbacks behave.

117 

118### Logs

119 

120The gateway writes two streams to stderr, both JSON-friendly:

121 

122* **Audit events**: single-line JSON per security-relevant event. Pipe stderr to your log aggregator. The events emitted include `config.load`, `session.mint`, `session.refresh`, `device.authorize`, `device.verify`, `auth.denied`, `access.denied`, `inference`, `managed.serve`, `spend.blocked`, and `admin.denied`. Fields vary by event:

123 * Successful mint and refresh events carry `sub`, `email`, `client_ip`, and the result

124 * Denial events carry the reason, path, and client IP, since no identity exists at denial

125 * `inference` records which upstream served the request and the response status

126 * `admin.denied` records a rejected admin-API auth attempt with the reason (`invalid_key` or `no_credentials`), client IP, method, and path, without the presented key material

127* **Operational logs**: human-readable `[gateway]`-prefixed lines for boot, warnings, and upstream errors. The `CLAUDE_GATEWAY_LOG_LEVEL` environment variable controls verbosity and accepts `info`, `warn`, or `error`, with `info` as the default. It doesn't affect audit events, which are always emitted.

128 

129### Health

130 

131The gateway serves `GET /healthz` as a liveness probe and `GET /readyz` as a readiness probe; `/readyz` verifies the store is reachable. Both are exempt from `access_control.allow_cidrs`, so probes keep working on a locked-down listener.

132 

133The OAuth discovery document at `/.well-known/oauth-authorization-server` also returns `200` only after config load, OIDC discovery, upstream client construction, and Postgres migration all succeed, so it doubles as an end-to-end boot check.

134 

135A running gateway also serves a description of the paths and request shapes it accepts at `<public_url>/protocol`, matched to the version you're running. The contents are not stable across releases.

136 

137### Outage behavior

138 

139If Postgres goes down, the gateway itself keeps serving signed-in developers and new sign-ins fail. Whether developers actually keep working depends on how your orchestrator handles readiness:

140 

141* **Existing sessions**: bearer tokens validate locally with the JWT secret, session refreshes don't touch the store, and the gateway process can still serve inference

142* **New sign-ins**: fail until Postgres recovers, because the device flow and its rate-limit counters live in Postgres

143* **[Spend-limit enforcement](/en/claude-apps-gateway-spend-limits#postgres-availability)**: fails open by default during the outage, so inference still flows; flip it to fail closed if you'd rather block than run unmetered

144* **Readiness**: `/readyz` reports not-ready during the outage, so orchestrators that gate traffic on readiness remove every replica from rotation at once. In that topology all traffic, including inference the gateway could still serve, fails at the load balancer until Postgres recovers. The liveness probe on `/healthz` keeps passing, so replicas are not restarted. Point the readiness probe at `/healthz` instead if you'd rather signed-in developers keep working through a store outage; the cost is that new sign-ins fail against a replica that still reports ready.

145 

146If your IdP goes down, existing sessions work until `ttl_hours`, and new logins and refreshes fail. Set a longer `ttl_hours` if your IdP has frequent maintenance windows.

147 

148### JWT secret rotation

149 

150Rotate the signing secret in three steps so existing sessions stay valid:

151 

1521. Generate a new secret. Prepend it to the `session.jwt_secret` array.

1532. Roll the deployment. New tokens sign with the new secret; old tokens still verify.

1543. After `ttl_hours` plus a margin, remove the old secret and roll again.

155 

156Rotation is also the only way to force sessions out before they expire: bearer tokens validate locally against the JWT secret, so there is no per-session revocation. Replacing the secret outright, without keeping the old one in the array, invalidates every outstanding session at once. For individual offboarding, deprovision the user in your IdP; their session ends within `ttl_hours`.

157 

158### Postgres

159 

160The gateway holds five tables, all created by its boot-time migrations:

161 

162| Table | Contents | Retention |

163| ------------------ | ----------------------------------------------------------------------------- | --------------------------------------------------------------- |

164| `kv` | Device grants (10-minute TTL) and rate-limit counters | TTL per row |

165| `spend` | Per-principal period-to-date spend counters, in cents | `admin.spend_retention_months`, default 13 |

166| `spend_limits` | Configured spend caps | Until deleted via the API |

167| `admin_audit` | Admin API mutation trail | `admin.audit_retention_days`, default 365 |

168| `principal_emails` | Each principal's last-seen email, display name, and IdP groups. Contains PII. | `admin.identity_retention_days` since last activity, default 90 |

169 

170A 30-second loop expires `kv` rows past their TTL, and an hourly sweep enforces the retention windows on the spend tables, so nothing grows without bound. Without [spend limits](/en/claude-apps-gateway-spend-limits) configured, only `kv` is written. If your security policy prohibits DDL from the application role, pre-create these tables and `_migrations` with an admin role and grant the app role `SELECT, INSERT, UPDATE, DELETE` on each.

171 

172With spend limits in use, a lost database means lost spend tracking and caps, not just developer re-logins, so run regular backups. To erase one departed developer immediately rather than waiting on retention, run `DELETE FROM principal_emails WHERE principal = '<sub>'` directly; that removes the only table holding their email, name, and groups. `spend` and `admin_audit` rows reference the pseudonymous OIDC `sub` only.

173 

174### Upgrades

175 

176Replicas are stateless, so a rolling restart is safe at any time. The gateway runs schema migrations at boot, which means deploying the new binary self-migrates the database. If the database role can't run DDL, pre-create the schema, including the `_migrations` table seeded to the current version; otherwise boot fails attempting `CREATE TABLE`.

177 

178Migrations are append-only, so rolling back to a prior binary that knows fewer migrations is safe; it ignores the extra rows. Rollback also re-validates the YAML against the older binary's schema, so a config that adopted a key introduced by the newer release fails boot on the older one. Remove the new key before rolling back.

179 

180Because you pin the gateway's version in your own image, fixes in new Claude Code releases, including security fixes, reach your deployment only when you update the pin and redeploy. Include the gateway in the same patching cadence you use for other services that hold production credentials.

181 

182## Security

183 

184This section answers the questions a security review asks: what data flows through the gateway and where it goes, which attacks the design defends against, and which answers belong in a compliance questionnaire.

185 

186### Data flow

187 

188| Data | Path | Sent to Anthropic by the gateway |

189| ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | -------------------------------------------------- |

190| Inference (prompts, completions) | CLI → gateway → your upstream | Only if the Anthropic API is a configured upstream |

191| Telemetry (OTLP metrics, plus [opt-in logs and traces](/en/claude-apps-gateway-config#telemetry)) | CLI → gateway → your collector | Never |

192| Identity (email, groups, sub) | IdP → gateway → JWT → CLI; the CLI stamps it on OTLP exports | Never |

193| Managed settings | Your gateway YAML → CLI | Never |

194| Audit log | Gateway stderr → your aggregator | Never |

195 

196### Threat model summary

197 

198The gateway sits inside your network perimeter, but individual developer laptops are not treated as trusted. The design accounts for this in three ways:

199 

200* Developers hold short-lived JWTs instead of raw upstream keys. The CLI-to-gateway leg uses the RFC 8628 device grant, and the gateway's authorization-code exchange with the IdP runs PKCE in the default configuration, so an intercepted IdP authorization code is useless.

201* The device-verification page enforces same-origin POST and a per-IP rate limit per RFC 8628 §5.1. See [User-code brute-force resistance](#user-code-brute-force-resistance).

202* Outbound requests go through a server-side request forgery (SSRF) guard that resolves DNS, blocks link-local and cloud-metadata addresses plus loopback by default, and pins the connection to the resolved IP, so operator-influenced URLs such as the IdP and OTLP destinations can't be redirected to cloud metadata endpoints. RFC 1918 private ranges are deliberately allowed, because IdPs and OTLP collectors commonly live on private IPs. For local development against a loopback IdP or collector, set `CLAUDE_GATEWAY_ALLOW_LOOPBACK=1` in the gateway's environment; leave it unset in production.

203 

204If you add your own egress controls, the gateway must reach the metadata server whenever it uses instance-metadata credentials such as workload identity.

205 

206Two threats are out of scope because they are your infrastructure to secure:

207 

208* **A compromised gateway host**: the host both holds the upstream credential and distributes [managed settings](/en/claude-apps-gateway-config#managed) to every connected developer, so control over the gateway's configuration is comparable to control over your MDM. The CLI's one-time approval dialog for shell-capable settings limits silent changes but doesn't replace host security.

209* **A malicious OIDC provider**: the provider signs the id\_tokens the gateway trusts, so it can assert any identity. Vetting and securing your IdP is your responsibility.

210 

211### User-code brute-force resistance

212 

213The `user_code` a developer types into the `/device` verification page is 8 characters drawn from a 20-character alphabet, which yields 20⁸ or about 2.56×10¹⁰ combinations, and it expires after 10 minutes.

214 

215The gateway applies per-IP rate limits on the device-grant endpoints, configurable via [`rate_limits`](/en/claude-apps-gateway-config#http-tuning). Raise the limits if many developers sign in from a single shared corporate NAT address. The limits apply only to the sign-in flow, not to inference.

216 

217### Compliance posture

218 

219* **Data residency**: the gateway's own data plane sends nothing to Anthropic unless the Anthropic API is a configured upstream; when it is, your existing data-handling agreement applies to the inference path. Telemetry, audit, identity, and settings go only to the destinations you configure.

220* **Host-process traffic**: the host process is the Claude Code CLI, which can send startup analytics and update checks to Anthropic. For strict-egress deployments, set `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` in the gateway's container environment.

221* **Client analytics**: the CLI disables its own usage analytics while signed in to a gateway, and error reporting is off by default on third-party API surfaces.

222* **Client machines**: developers' CLIs still send WebFetch hostname checks and version checks to Anthropic unless `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` and `skipWebFetchPreflight: true` are set. See [data usage](/en/data-usage).

223* **Survey ratings**: the gateway credential disables the Anthropic-bound rating sink, so ratings are not sent to Anthropic.

224* **Transcript sharing**: choosing Yes on a survey's transcript-share prompt writes a local file under `~/.claude/feedback-bundles/` instead of uploading to Anthropic.

225* **Client updates**: update checks are separate from gateway traffic. Pin versions through your own distribution and set `DISABLE_UPDATES` if laptops must not fetch releases. `DISABLE_AUTOUPDATER` stops only background updates while `claude update` still works.

226* **TLS**: serve `public_url` over HTTPS in production, either from the gateway's own listener via `listen.tls` or from a TLS-terminating ingress in front of plain-HTTP replicas with `listen.public_url` set. The gateway doesn't refuse plain HTTP. The IdP must serve HTTPS in production, and Postgres supports `?sslmode=require`. Set `Strict-Transport-Security` at your ingress.

227* **Vulnerability disclosure**: follow [Reporting security issues](/en/security#reporting-security-issues)

228 

229## Troubleshooting

230 

231For questions and feedback, use [Claude Code support](https://support.claude.com/en/collections/14445694-claude-code), or open an issue on the [Claude Code GitHub repository](https://github.com/anthropics/claude-code/issues). When reporting a problem, include:

232 

233* **Gateway issue**: the gateway's stderr for the relevant window, your `gateway.yaml` with secrets redacted, the gateway version, shown on the landing page at `/` and in the `x-cc-gateway-version` response header on `/managed/settings`, and what changed recently

234* **Login issue**: the developer runs `claude --debug-file ./claude-debug.txt`, reproduces, and sends that file plus the gateway's audit log for the same window

235* **Inference issue**: the model requested, the upstreams configured, and the gateway's audit log for the request, which records which upstream served it and the response status

236 

237| Symptom | Cause | Fix |

238| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

239| A developer's `/login` shows the standard account picker instead of the **Cloud gateway** screen | `forceLoginMethod` or `forceLoginGatewayUrl` is not set in managed settings on that machine | Deploy the [managed settings file](/en/claude-apps-gateway#set-the-gateway-url) to the device; `/login` reads the gateway URL from there |

240| Startup shows `Gateway login is configured in managed settings, but this Claude Code build does not include Cloud gateway support.` | The installed Claude Code build predates gateway support | Have the developer update Claude Code to a release that includes Cloud gateway support |

241| CLI `/login`: `Gateway hosts must be on your organization's private network; <host> resolves to the public (or unrecognized) address <ip>` | The gateway hostname resolves to at least one public IP address. Claude Code checks each resolved address and requires every one to be private. A common cause is a dual-stack name where one family resolves to a public address, including AWS internal dual-stack load balancers, which return public-range AAAA addresses | Have the gateway name resolve only to private addresses on developer machines. For a dual-stack name, drop the public-range record or serve a separate internal-only DNS name. See the [private-network prerequisite](/en/claude-apps-gateway#prerequisites). |

242| CLI `/login`: `Gateway login requires a direct connection and does not support connecting through an HTTP proxy` | An `HTTPS_PROXY` or `HTTP_PROXY` applies to the gateway host and the proxy's hostname resolves to a public address. A proxy whose host resolves only to private addresses is allowed and doesn't trigger this error | Add the gateway host to `NO_PROXY` on the developer's machine so the connection is direct, or use a proxy whose hostname resolves to private addresses |

243| CLI `/login`: `Could not resolve gateway host <host>` | The machine can't resolve the gateway's internal DNS name, typically because it isn't on the corporate network | Have the developer connect to your network or VPN, then retry `/login` |

244| Boot exits with a config validation error naming `store.postgres_url` | No Postgres configured; the gateway requires Postgres | Set `store.postgres_url`. For local development, use a throwaway container: `docker run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres`. |

245| Boot exits: `requires the native binary` | Running under Node instead of the native binary | Install Claude Code with one of the [standalone install methods](/en/setup) |

246| Boot exits with an OIDC discovery error after `config.load` | `oidc.issuer` unreachable, or TLS chain not trusted | Check the issuer is reachable from the pod and serves `/.well-known/openid-configuration`. Set `ca_cert_pem` for private PKI. |

247| Boot exits with a Postgres permission error | App role lacks `CREATE TABLE` | Pre-create the schema with an admin role and grant DML to the app role, or grant DDL temporarily for boots that apply new migrations |

248| `/oauth/callback` shows "Sign-in could not be completed" | Email domain rejected, id\_token validation failed, or `email_verified` is explicitly `false`, which the gateway always rejects with no override | Check `allowed_email_domains` and that the IdP returns a verified `email` claim. For `email_verified: false`, fix the IdP-side verification. If your IdP emits email under a different claim name, set `oidc.email_claim`. |

249| Log: `token exchange failed: id_token missing email claim` | The IdP isn't including `email` in the id\_token by default. This rejection fires only when `allowed_email_domains` is set; without it, a missing email mints a session with no email | Configure the IdP to emit `email` in the id\_token. Okta: add `email` to a custom authorization server's ID-token claims. Entra: add `email` as an optional claim on the app registration. PingFederate: enable an OpenID Connect Policy that emits `email`. If the IdP serves `email` from the userinfo endpoint but won't include it in the id\_token, such as the Okta org authorization server, set `oidc.userinfo_fallback: true`. |

250| Every Bedrock request returns 502; log shows `Could not load credentials from any providers` | On EC2, IMDSv2's default hop limit of 1 blocks the instance-metadata request from inside the container. Boot and `/readyz` pass anyway because the AWS SDK resolves instance credentials on the first request, not at client construction | Raise the hop limit with `aws ec2 modify-instance-metadata-options --instance-id <id> --http-put-response-hop-limit 2`, or set it in the launch template. The change applies to every container on the instance. Prefer ECS task roles where available, which read credentials from the ECS container-credentials endpoint and avoid the change entirely, or apply the change on a dedicated gateway instance to limit the exposure. |

251| IdP error: unknown or unsupported scope | The IdP rejects scopes it doesn't recognize | Set `oidc.scopes` to exactly the list your IdP accepts; it must include `openid`. The default is `openid profile email offline_access`. |

252| Sessions don't silently renew after setting `oidc.scopes` | `offline_access` was dropped from the override | Add `offline_access` back if your IdP supports it. Without a refresh token, developers re-run the browser login every `session.ttl_hours`. |

253| Browser shows "This request came from another site and was blocked" | Cross-site form POST, blocked as CSRF protection. Expected for embedded or proxied pages | Open the verification link directly |

254| Chrome blocks the Approve button with "Refused to send form data … violates … Content Security Policy directive: form-action", but the same page works in Safari or Firefox | Chrome enforces `form-action` against the entire redirect chain. Your IdP redirects onward to a second host that isn't allowlisted. | Add each additional origin in the redirect chain to `oidc.form_action_origins`. Open Chrome DevTools → Console on the Approve page to see which origin was blocked. |

255| Sign-in completes at the IdP but the callback fails, with a CSP error in Chrome or "this sign-in link has expired" in Safari | The IdP returned the code via `response_mode=form_post`, which auto-submits it cross-origin via POST to `/oauth/callback`. Chrome blocks that under a strict CSP; Safari allows the submit but the callback reads only the query string. | Make sure your IdP honors `response_mode=query`, which the gateway requests explicitly so the callback is a plain redirect |

256| Login works locally but fails behind an ALB | `public_url` not set, so the IdP gets the inner `http://` origin as `redirect_uri` | Set `listen.public_url` to the external `https://` origin |

257| Developer sees the trust prompt repeatedly | TLS cert is rotating per replica or per request | Use a stable cert at the ingress, or terminate TLS once and run replicas over plain HTTP internally |

258| CLI `/login`: "Could not verify the gateway's TLS certificate" or `SELF_SIGNED_CERT_IN_CHAIN` | Gateway's TLS chain is signed by a private CA not in the CLI host's trust store | Claude Code reads the OS trust store by default on the native binary and on Node 22.15 or later; [`CLAUDE_CODE_CERT_STORE`](/en/network-config#ca-certificate-store) controls this behavior. If the CA is installed in the OS trust store, ensure developers are on a current runtime. Otherwise set `NODE_EXTRA_CA_CERTS` to the CA certificate PEM before launching. The first-connect fingerprint prompt still applies. |

259 

260## Related

261 

262* [Claude apps gateway overview](/en/claude-apps-gateway): quickstart and developer connection

263* [Configuration reference](/en/claude-apps-gateway-config): every `gateway.yaml` option

claude-apps-gateway-on-gcp.md +318 −0 created

Details

1> ## Documentation Index

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt

3> Use this file to discover all available pages before exploring further.

4 

5# Deploy Claude apps gateway on Google Cloud

6 

7> A worked example of running Claude apps gateway on Google Cloud: Cloud Run or GKE, Cloud SQL for PostgreSQL, Secret Manager, and service-account auth to Agent Platform.

8 

9<Note>

10 This page walks through one way to run Claude apps gateway on Google Cloud. The configuration is a working example for customer-managed infrastructure rather than a supported production deployment; use it to see how the pieces fit together before adapting it to your own environment. For the platform-agnostic requirements, see the [deployment guide](/en/claude-apps-gateway-deploy).

11</Note>

12 

13This example provisions Claude apps gateway on Google Cloud with Google Cloud's Agent Platform as the model upstream, using either Cloud Run or GKE for compute. Google Workspace is the example identity provider (IdP), but any OpenID Connect (OIDC) compliant IdP works; only the `oidc` block changes. See [Identity provider setup](/en/claude-apps-gateway-deploy#identity-provider-setup) for per-IdP details.

14 

15## What you'll build

16 

17<Frame>

18 <img src="https://mintcdn.com/claude-code/-uq-4JE0W_JO5Er5/images/claude-gateway-gcp-architecture.svg?fit=max&auto=format&n=-uq-4JE0W_JO5Er5&q=85&s=cb705151c69128ac0da235852d5600ab" alt="Diagram of Claude apps gateway on Google Cloud: Claude Code clients connect over HTTPS to the gateway (Cloud Run or GKE), which runs inside a VPC alongside a private-IP Cloud SQL database for session state. The gateway signs users in via OIDC against Google Workspace, reads config and secrets from Secret Manager, forwards model requests to Agent Platform, and pulls its image from Artifact Registry at deploy." width="760" height="400" data-path="images/claude-gateway-gcp-architecture.svg" />

19</Frame>

20 

21The reference configuration provisions:

22 

23* **Cloud Run** service or **GKE** Deployment running the gateway container

24* **Artifact Registry** repository for the gateway image

25* **Cloud SQL for PostgreSQL** instance, private IP only, for the gateway's [store](/en/claude-apps-gateway-config#store)

26* **Secret Manager** secrets for `gateway.yaml`, the JWT signing key, the OIDC client secret, and the Postgres URL

27* **Service account** with `roles/aiplatform.user`, attached directly on Cloud Run or bound via Workload Identity on GKE

28* **Internal Application Load Balancer** on Cloud Run, or an internal **GKE Ingress** of class `gce-internal` on GKE, for HTTPS

29 

30## Prerequisites

31 

32* A GCP project with billing enabled, and permission to create the resources above

33* The `gcloud` CLI, authenticated with `gcloud auth login`, and Docker installed locally

34* For the GKE track: `kubectl`, and a GKE cluster on the VPC created in the walkthrough below

35* Access to the Claude models you need in Model Garden, in a region that publishes them

36* A Google Workspace OAuth 2.0 web-application client with redirect URI `https://<gateway-host>/oauth/callback`; see [Identity provider setup](/en/claude-apps-gateway-deploy#identity-provider-setup)

37* A TLS hostname for the gateway, typically an internal DNS name pointing at the load balancer

38 

39Set the project and region once:

40 

41```bash theme={null}

42export PROJECT_ID=<your-project>

43export REGION=us-east5 # a region where the Claude models you need are published in Model Garden

44gcloud config set project "$PROJECT_ID"

45```

46 

47## Deploy the gateway

48 

49The steps below provision the full deployment with `gcloud` commands.

50 

51<Steps>

52 <Step title="Enable APIs">

53 Enable the service APIs the walkthrough uses:

54 

55 ```bash theme={null}

56 gcloud services enable \

57 aiplatform.googleapis.com \

58 artifactregistry.googleapis.com \

59 sqladmin.googleapis.com \

60 secretmanager.googleapis.com \

61 iamcredentials.googleapis.com \

62 iam.googleapis.com \

63 compute.googleapis.com \

64 servicenetworking.googleapis.com \

65 run.googleapis.com \

66 container.googleapis.com

67 ```

68 

69 The APIs you need depend on the deployment path:

70 

71 * `compute` and `servicenetworking`: needed for the private-IP Cloud SQL path

72 * `run`: Cloud Run only

73 * `container`: GKE only

74 </Step>

75 

76 <Step title="Create the service account and grant IAM">

77 The gateway runs as a dedicated service account with permission to call Agent Platform. It reaches Cloud SQL over the VPC with a password user, so no Cloud SQL IAM role is required:

78 

79 ```bash theme={null}

80 gcloud iam service-accounts create claude-gateway --display-name="Claude apps gateway"

81 SA="claude-gateway@${PROJECT_ID}.iam.gserviceaccount.com"

82 

83 gcloud projects add-iam-policy-binding "$PROJECT_ID" \

84 --member="serviceAccount:${SA}" --role="roles/aiplatform.user" --condition=None

85 ```

86 

87 Then enable the Claude models for the project in Model Garden; models publish to specific regions, so check each model card.

88 </Step>

89 

90 <Step title="Build and push the image to Artifact Registry">

91 Build the image per the [container image requirements](/en/claude-apps-gateway-deploy#container-image), using the `linux-x64` glibc binary, and push it:

92 

93 ```bash theme={null}

94 gcloud artifacts repositories create claude-gateway \

95 --repository-format=docker --location="$REGION"

96 gcloud auth configure-docker "${REGION}-docker.pkg.dev" --quiet

97 

98 # Cloud Run requires linux/amd64. --provenance=false avoids a buildx OCI

99 # image index that Cloud Run rejects.

100 docker build --platform=linux/amd64 --provenance=false \

101 -t "${REGION}-docker.pkg.dev/${PROJECT_ID}/claude-gateway/gateway:<version>" .

102 docker push "${REGION}-docker.pkg.dev/${PROJECT_ID}/claude-gateway/gateway:<version>"

103 ```

104 </Step>

105 

106 <Step title="Provision Cloud SQL for PostgreSQL">

107 Create the instance on a VPC via Private Services Access so it has no public IP; this also satisfies projects where `constraints/sql.restrictPublicIp` is enforced:

108 

109 ```bash theme={null}

110 VPC=cc-gateway-vpc

111 gcloud compute networks create "$VPC" --subnet-mode=custom

112 gcloud compute networks subnets create cc-gateway-subnet \

113 --network="$VPC" --region="$REGION" --range=10.0.0.0/24

114 

115 # Private Services Access: one-time per VPC

116 gcloud compute addresses create "google-managed-services-${VPC}" \

117 --global --purpose=VPC_PEERING --prefix-length=16 --network="$VPC"

118 gcloud services vpc-peerings connect \

119 --service=servicenetworking.googleapis.com \

120 --ranges="google-managed-services-${VPC}" --network="$VPC"

121 

122 gcloud sql instances create claude-gateway-db \

123 --database-version=POSTGRES_16 --tier=db-g1-small --region="$REGION" \

124 --network="projects/${PROJECT_ID}/global/networks/${VPC}" --no-assign-ip

125 gcloud sql databases create claude_gateway --instance=claude-gateway-db

126 PGPASS="$(openssl rand -hex 24)"

127 gcloud sql users create gateway --instance=claude-gateway-db --password="$PGPASS"

128 

129 PRIVATE_IP="$(gcloud sql instances describe claude-gateway-db \

130 --format='value(ipAddresses[0].ipAddress)')"

131 GATEWAY_POSTGRES_URL="postgres://gateway:${PGPASS}@${PRIVATE_IP}:5432/claude_gateway?sslmode=require"

132 ```

133 

134 The Cloud Run or GKE runtime must be on, or routed into, this VPC.

135 </Step>

136 

137 <Step title="Write gateway.yaml">

138 The `upstreams` block points at Agent Platform with `auth: {}`, so the gateway authenticates via Application Default Credentials from the runtime service account. See the [configuration reference](/en/claude-apps-gateway-config) for every field.

139 

140 Two `listen` fields depend on what fronts the gateway:

141 

142 * `public_url`: required behind Cloud Run or a GKE Ingress. The gateway builds the IdP `redirect_uri` and its discovery document only from this value, never from `X-Forwarded-*` headers.

143 * `trusted_proxies`: the front end's source ranges. The gateway honors `X-Forwarded-For` only when the TCP peer is in this list, then walks the chain past trusted hops, so per-IP sign-in rate limits and audit events record developer IPs instead of the load balancer's.

144 

145 Set `trusted_proxies` to match your front end. An external GKE Ingress of class `gce` isn't listed: it provisions a public forwarding-rule address, which the `/login` [private-network check](/en/claude-apps-gateway#prerequisites) rejects.

146 

147 | Front end | `trusted_proxies` |

148 | -------------------------------------------------------- | --------------------------------------------------- |

149 | Cloud Run reached directly, no load balancer | `[169.254.0.0/16]` |

150 | Internal Application Load Balancer in front of Cloud Run | `169.254.0.0/16` plus your proxy-only subnet's CIDR |

151 | GKE internal Ingress, class `gce-internal` | Your proxy-only subnet's CIDR |

152 

153 The example below uses the internal-load-balancer-in-front-of-Cloud-Run values.

154 

155 ```yaml gateway.yaml theme={null}

156 listen:

157 host: 0.0.0.0

158 port: 8080

159 public_url: https://claude-gateway.internal.example.com

160 trusted_proxies: [169.254.0.0/16, <your-proxy-only-subnet-cidr>]

161 

162 oidc:

163 issuer: https://accounts.google.com

164 client_id: <your-oauth-client-id>

165 client_secret: ${OIDC_CLIENT_SECRET} # GKE: ${file:/secrets/oidc-client-secret}

166 allowed_email_domains: [example.com]

167 # Google ignores offline_access; these yield refresh tokens:

168 scopes: [openid, profile, email]

169 extra_auth_params: { access_type: offline, prompt: consent }

170 

171 session:

172 jwt_secret: ${GATEWAY_JWT_SECRET} # GKE: ${file:/secrets/jwt-secret}

173 

174 store:

175 postgres_url: ${GATEWAY_POSTGRES_URL} # GKE: ${file:/secrets/postgres-url}

176 

177 upstreams:

178 - provider: vertex

179 region: <your-region> # must match $REGION

180 project_id: <your-project>

181 auth: {} # ADC via the runtime service account

182 ```

183 

184 <Note>

185 Google id\_tokens carry no `groups` claim. To use group-based policies in [`managed.policies`](/en/claude-apps-gateway-config#managed) with Google Workspace as the IdP, configure [`oidc.google_groups`](/en/claude-apps-gateway-config#oidc), which looks up each user's groups through the Admin SDK Directory API using a service account with domain-wide delegation. Without it, match on `email_domain` instead.

186 </Note>

187 </Step>

188 

189 <Step title="Store secrets in Secret Manager">

190 Create four secrets and grant `roles/secretmanager.secretAccessor` to the `claude-gateway` service account:

191 

192 | Secret | Source |

193 | ---------------------------- | ----------------------------------------------- |

194 | `gateway-jwt-secret` | `openssl rand -base64 32` |

195 | `gateway-oidc-client-secret` | Google Cloud Console → OAuth client |

196 | `gateway-postgres-url` | `$GATEWAY_POSTGRES_URL` from the Cloud SQL step |

197 | `gateway-config` | the full `gateway.yaml` from the previous step |

198 

199 How the secrets reach the container differs by track:

200 

201 * On GKE they mount as files via the Secret Manager CSI driver, and `gateway.yaml` references `${file:/secrets/...}`.

202 * On Cloud Run, which can't mount multiple secrets into one directory, `gateway.yaml` mounts as a file and the other three inject as environment variables, so `gateway.yaml` references `${GATEWAY_JWT_SECRET}`, `${OIDC_CLIENT_SECRET}`, and `${GATEWAY_POSTGRES_URL}` instead.

203 </Step>

204 

205 <Step title="Deploy">

206 <Tabs>

207 <Tab title="Cloud Run">

208 The command below deploys for production behind an internal load balancer.

209 

210 ```bash theme={null}

211 gcloud run deploy claude-gateway \

212 --image="${REGION}-docker.pkg.dev/${PROJECT_ID}/claude-gateway/gateway:<version>" \

213 --region="$REGION" \

214 --service-account="claude-gateway@${PROJECT_ID}.iam.gserviceaccount.com" \

215 --min-instances=1 \

216 --timeout=3600 \

217 --ingress=internal-and-cloud-load-balancing \

218 --network="$VPC" --subnet=cc-gateway-subnet --vpc-egress=private-ranges-only \

219 --set-secrets=/etc/claude/gateway.yaml=gateway-config:latest,GATEWAY_JWT_SECRET=gateway-jwt-secret:latest,OIDC_CLIENT_SECRET=gateway-oidc-client-secret:latest,GATEWAY_POSTGRES_URL=gateway-postgres-url:latest \

220 --no-invoker-iam-check

221 ```

222 

223 Direct VPC egress, via `--network`, `--subnet`, and `--vpc-egress=private-ranges-only`, lets the service reach the Cloud SQL private IP directly. Public egress to the Agent Platform endpoints and `accounts.google.com` goes directly to the internet rather than through the VPC, so no Cloud NAT is needed.

224 

225 The invoker IAM check must be open or disabled. The gateway runs its own OIDC and its clients carry no GCP token, so Cloud Run's invoker check has to admit unauthenticated requests. The gateway's OIDC sign-in authenticates the request once it reaches the container, with `allowed_email_domains` gating which domains may sign in.

226 

227 Two flags admit unauthenticated requests:

228 

229 * `--no-invoker-iam-check`: disables the check with no `allUsers` binding to manage, and works under Domain Restricted Sharing

230 * `--allow-unauthenticated`: grants `allUsers` the `run.invoker` role; use it if your organization doesn't allow `--no-invoker-iam-check`

231 

232 Ingress restriction via `--ingress` is a separate, independent layer from the invoker check; keep it set to limit the service to your corporate network.

233 

234 By default the Cloud Run `*.run.app` URL resolves to a public address, which the `/login` [private-network check](/en/claude-apps-gateway#prerequisites) rejects. Two topologies give developers a privately resolvable hostname, and Cloud Run provisions neither for you:

235 

236 * **Internal Application Load Balancer**, the topology the deploy command above assumes: deploy with `--ingress=internal-and-cloud-load-balancing`, provision an internal Application Load Balancer in front of the service with an internal DNS name and certificate, and set `listen.public_url` to that hostname.

237 * **Internal-only ingress with no load balancer**: deploy with `--ingress=internal` and leave `listen.public_url` as the `*.run.app` URL, the default in the [reference assets](#terraform-reference) below. For `*.run.app` to resolve privately, your network team must already operate a Private Service Connect endpoint for Google APIs, a Cloud DNS private zone resolving `*.run.app` to it, and on-premises routing to that endpoint.

238 

239 Google's [private networking guide for Cloud Run](https://cloud.google.com/run/docs/securing/private-networking) covers the infrastructure both options need. Verify sign-in once the gateway is serving on a private hostname; until then, confirm the container booted from its logs in Cloud Run.

240 

241 Update the OAuth client's authorized redirect URI to `<public_url>/oauth/callback` before the first sign-in. Redeploy after changing `public_url`, because the gateway builds its public origin only from that setting and ignores `X-Forwarded-Host` and `X-Forwarded-Proto`. `X-Forwarded-For` is honored for client IPs only when `listen.trusted_proxies` is set.

242 </Tab>

243 

244 <Tab title="GKE">

245 The cluster must be on the `$VPC` created in the Cloud SQL step so pods can reach the database's private IP; VPC peering alone doesn't work, because Cloud SQL private IP is itself a peered network and peering is non-transitive. To create a new cluster on that VPC, pass `--network="$VPC" --subnetwork=cc-gateway-subnet` to `gcloud container clusters create`.

246 

247 Enable Workload Identity on the cluster and its node pools, then bind the Google service account to the Kubernetes service account so pods inherit its credentials:

248 

249 ```bash theme={null}

250 gcloud container clusters update <cluster> --region="$REGION" \

251 --workload-pool="${PROJECT_ID}.svc.id.goog"

252 # On a Standard cluster, existing node pools also need GKE_METADATA;

253 # Autopilot enables this by default.

254 gcloud container node-pools update <pool> --cluster=<cluster> \

255 --region="$REGION" --workload-metadata=GKE_METADATA

256 

257 kubectl create namespace claude-gateway

258 kubectl create serviceaccount gateway -n claude-gateway

259 

260 gcloud iam service-accounts add-iam-policy-binding \

261 "claude-gateway@${PROJECT_ID}.iam.gserviceaccount.com" \

262 --role roles/iam.workloadIdentityUser \

263 --member "serviceAccount:${PROJECT_ID}.svc.id.goog[claude-gateway/gateway]"

264 

265 kubectl annotate serviceaccount gateway -n claude-gateway \

266 iam.gke.io/gcp-service-account="claude-gateway@${PROJECT_ID}.iam.gserviceaccount.com"

267 ```

268 

269 Deploy the gateway as a standard Deployment plus a Service and an internal Ingress, class `gce-internal`, as described in [Kubernetes deployment](/en/claude-apps-gateway-deploy#kubernetes), with:

270 

271 * `serviceAccountName: gateway`

272 * the Secret Manager CSI driver mounting secrets at `/secrets`

273 * the readiness probe pointed at `GET /readyz`

274 

275 Attach a BackendConfig with a raised `timeoutSec` to the gateway Service: the load balancer backend service behind GKE Ingress defaults to a 30-second timeout, which cuts off long streaming responses.

276 

277 Don't apply an egress NetworkPolicy that blocks `169.254.169.254` on a Workload Identity cluster; the pod must reach the metadata server for credentials. The gateway's built-in [SSRF guard](/en/claude-apps-gateway-deploy#threat-model-summary) is the defense there.

278 

279 The gateway logs a boot warning that the metadata endpoint is reachable and suggests applying an egress NetworkPolicy. Under Workload Identity that warning is expected, because the pod needs the endpoint.

280 </Tab>

281 </Tabs>

282 </Step>

283 

284 <Step title="Push the gateway URL to developer machines">

285 The gateway is now running, but developers can't reach it from `/login` until the gateway URL is on their machines. Set `forceLoginMethod` and `forceLoginGatewayUrl` in the [managed settings file](/en/claude-apps-gateway#set-the-gateway-url) you deploy to each device via MDM. There is no gateway option in the login picker for a developer to select manually.

286 </Step>

287</Steps>

288 

289## Terraform reference

290 

291The [reference deployment assets](https://github.com/anthropics/claude-code/tree/main/examples/gateway/gcp) automate the Cloud Run track on this page; the config and image assets apply to both tracks:

292 

293* `setup.sh`: an idempotent `gcloud` provisioner that walks the full Cloud Run path, from enabling APIs through the first deploy

294* `terraform/`: the same deployment as infrastructure-as-code, for a greenfield deploy: a targeted apply to create the Artifact Registry repo, then build and push the image, then a full apply

295* `gateway.yaml.example` and a `Dockerfile` for the distroless runtime image

296 

297The artifacts default Cloud Run ingress to `internal`, so no load balancer is required. To match this page's production-behind-an-ALB deployment, run `setup.sh` with `INGRESS=internal-and-cloud-load-balancing`, or set the Terraform variable `ingress` to `INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER`. The artifacts also default the invoker layer to an `allUsers` `run.invoker` grant rather than `--no-invoker-iam-check`, the inverse of this page's walkthrough; either works, and the choice depends on your organization's policy constraints.

298 

299The assets are provided as working examples, not as a supported production artifact; review and adapt them to your environment.

300 

301## Troubleshooting

302 

303For gateway boot and login errors, see the platform-agnostic [troubleshooting table](/en/claude-apps-gateway-deploy#troubleshooting). The entries below are specific to Google Cloud.

304 

305| Symptom | Cause | Fix |

306| ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

307| Cloud Run returns `403 Forbidden` before reaching the container | The invoker IAM check is still enabled | Deploy with `--no-invoker-iam-check`, or grant `allUsers` the `run.invoker` role with `--allow-unauthenticated` |

308| `--no-invoker-iam-check` rejected with `invoker_iam_disabled is not currently available` | Blocked by `constraints/run.managed.requireInvokerIam` | Use `--allow-unauthenticated`. If Domain Restricted Sharing via `constraints/iam.allowedPolicyMemberDomains` blocks that too, use the GKE track, which exposes the gateway at the network layer with no `allUsers` binding. |

309| `Container manifest type … must support amd64/linux` at deploy | Image was built on a non-amd64 host, or buildx emitted an OCI image index | Build with `--platform=linux/amd64 --provenance=false` |

310| Gateway boot exits with a Postgres connection-timeout error on Cloud Run | Service isn't attached to the VPC, or Cloud SQL has no private IP on that VPC; the store stops waiting after 5 seconds | Deploy with `--network` and `--subnet` for Direct VPC egress, and create the Cloud SQL instance with `--no-assign-ip` and `--network` pointing at the same VPC |

311| Agent Platform requests return `403 PERMISSION_DENIED` | Runtime isn't using the `claude-gateway` service account, or the model isn't enabled in Model Garden for the project | Set `--service-account` on Cloud Run or bind Workload Identity on GKE, and enable each Claude model in Model Garden for the target region |

312| Streaming responses cut off after a fixed duration | Front-end request timeout: the load balancer backend service behind GKE Ingress defaults to 30 seconds and Cloud Run to 300 seconds | Attach a BackendConfig with a raised `timeoutSec` on GKE, or deploy with `--timeout=3600` on Cloud Run |

313 

314## Next steps

315 

316* [Configuration reference](/en/claude-apps-gateway-config): every `gateway.yaml` option, including `managed.policies` and `telemetry`

317* [Deployment and operations](/en/claude-apps-gateway-deploy): IdP setup, health checks, JWT secret rotation, upgrades, and the security model

318* [Claude apps gateway overview](/en/claude-apps-gateway): quickstart and connecting developers

Details

1> ## Documentation Index

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt

3> Use this file to discover all available pages before exploring further.

4 

5# Claude apps gateway spend limits

6 

7> Cap each developer's spend through the Claude apps gateway by day, week, or month. Set limits with an Admin API and the gateway enforces them live on every request.

8 

9Spend limits cap how much each developer can spend through your [Claude apps gateway](/en/claude-apps-gateway) in a given day, week, or month. When a developer passes their cap, the gateway returns `429` on their next request and blocks them until the period resets or an admin raises the cap. Use spend limits to give each developer, group, or the whole organization a ceiling on a credential everyone shares.

10 

11A Claude apps gateway forwards all inference through one shared upstream credential, so your provider's bill attributes everything to that credential, not to individual developers. Without per-developer limits, one runaway agent fleet can spend the organization's entire commitment. Spend limits are the gateway's per-developer view and circuit breaker on top of that shared bill.

12 

13## Set a cap

14 

15With the [`admin:`](/en/claude-apps-gateway-config#admin) block configured in `gateway.yaml`, the gateway serves an admin API at `/v1/organizations/spend_limits` and enforces caps live on every inference request. Caps themselves are set through that API, not in `gateway.yaml`; each `POST /v1/organizations/spend_limits` request creates or replaces one cap from `{scope, amount, period}`. The API mirrors the wire shapes of Anthropic's public [Admin API](https://platform.claude.com/docs/en/manage-claude/admin-api) spend-limits endpoints, so an HTTP client written against that contract can target the gateway by changing its base URL.

16 

17This request sets an org-wide default of \$500 per month for every developer:

18 

19```bash theme={null}

20curl -sS https://claude-gateway.internal.example.com/v1/organizations/spend_limits \

21 -H "x-api-key: $GATEWAY_ADMIN_WRITE_KEY" \

22 -H "Content-Type: application/json" \

23 -d '{"scope": {"type": "organization"}, "amount": "50000", "period": "monthly"}'

24```

25 

26This request layers a tighter \$100-per-day cap on each member of the `contractors` group:

27 

28```bash theme={null}

29curl -sS https://claude-gateway.internal.example.com/v1/organizations/spend_limits \

30 -H "x-api-key: $GATEWAY_ADMIN_WRITE_KEY" \

31 -H "Content-Type: application/json" \

32 -d '{"scope": {"type": "rbac_group", "rbac_group_id": "contractors"}, "amount": "10000", "period": "daily"}'

33```

34 

35| Field | Values | Description |

36| ------------ | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

37| `scope.type` | `user`, `rbac_group`, `organization` | `user` targets one developer by their OpenID Connect (OIDC) `sub`, the stable user ID your identity provider assigns; pass it as `scope.user_id`. `rbac_group` targets an [IdP group](/en/claude-apps-gateway-config#managed) by name; pass it as `scope.rbac_group_id`. `organization` is the org-wide default. The gateway accepts all three; Anthropic's public `POST` is user-only today. |

38| `amount` | Whole-number string of USD cents, or `null` | `null` is unlimited. `"0"` is a zero cap, which blocks every request. |

39| `period` | `daily`, `weekly`, `monthly` | A scope can hold one cap per period, and each enforces independently: a developer is blocked if over any of them. |

40 

41A group or organization cap is a per-seat default that each member inherits, not a shared pool. Per period, a developer's effective cap resolves in this order: a per-user override, then the most restrictive of their group caps, then the org default, then unlimited. [`admin.group_limit_mode: max`](/en/claude-apps-gateway-config#admin) flips the multi-group tie-break to least-restrictive instead.

42 

43### Authenticate to the admin API

44 

45Send one of:

46 

47* An `x-api-key` header matching a key in [`admin.write_keys`](/en/claude-apps-gateway-config#admin) for full access, or `admin.read_keys` for `GET`-only access. Each key carries an `id` that appears in the audit log as `admin-key:<id>`, so give Terraform, CI, and each automation its own.

48* A gateway bearer token whose `groups` claim includes one of [`admin.admin_groups`](/en/claude-apps-gateway-config#admin). This is full access and audits as `oidc:<sub>`, so prefer it for human admins.

49 

50## How enforcement works

51 

52On each `/v1/messages` request, the gateway resolves the developer's caps and period-to-date spend in one Postgres query. If they're over any cap, the request returns `429` with `error.type: billing_error` and the header `x-should-retry: false`. The message is `spend limit reached`, followed by your [`admin.blocked_message`](/en/claude-apps-gateway-config#admin) if set.

53 

54`/v1/messages/count_tokens` is exempt. Token counting is free, so it runs regardless of cap state.

55 

56After each response, a usage meter reads token counts off the response as it streams to the client, prices them at USD list price, and increments Postgres counters for all three period buckets. The meter is a single reader on the stream, so the client's bytes are untouched and a metering failure doesn't break the response.

57 

58Spend limits estimate spend from token counts at USD list price; they're a circuit breaker, not an invoice. For authoritative billing, reconcile against your provider's own usage reporting, such as the Anthropic Usage & Cost Admin API, invocation logs on Bedrock, or Cloud Monitoring on Google Cloud.

59 

60Pricing uses the same table the Claude Code CLI uses for its own cost display, with the same model-ID canonicalization across Anthropic, Bedrock (`us.anthropic.…-v1:0`), Agent Platform (`claude-…@date`), and Foundry ID forms. A model ID the table can't place, such as a Foundry deployment name or an inference-profile ARN, is priced at the unknown-model default tier of \$5/\$25 per million input/output tokens rather than zero, so an unrecognized ID can't bypass a cap by going unmetered. The gateway warns at boot and once per ID at runtime when a model prices through the fallback.

61 

62Client aborts are billed too. The upstream reports output tokens only in the stream's terminal frame, so an aborted stream doesn't carry them. The meter keeps a conservative floor estimate from the streamed content size, about four characters per token, and bills it when and only when the terminal usage frame is missing. A complete stream always bills the upstream-reported count. Without this, a capped developer could stream output and abort each request immediately before the end, spending without ever being counted.

63 

64### Postgres availability

65 

66The pre-check queries Postgres with a two-second timeout. If the store is unreachable or times out, enforcement fails open by default: the request proceeds and the gateway logs a warning. Set [`enforcement.fail_closed_on_error: true`](/en/claude-apps-gateway-config#enforcement) to fail closed instead, which returns the same `429 billing_error` with the message `spend limit unavailable`. Fail-open keeps a store outage from becoming an inference outage; fail-closed guarantees no unmetered spend.

67 

68## Admin API reference

69 

70The endpoints below are served under `/v1/organizations/spend_limits`.

71 

72| Method and path | Description |

73| ---------------------------------------------- | ------------------------------------------------------------ |

74| `GET /v1/organizations/spend_limits` | List configured caps. Query: `?limit=&after_id=&before_id=`. |

75| `POST /v1/organizations/spend_limits` | Create or replace a cap for `{scope, period}`. |

76| `GET /v1/organizations/spend_limits/{id}` | Fetch one cap by its `spl_`-prefixed ID. |

77| `DELETE /v1/organizations/spend_limits/{id}` | Delete one cap. Returns `{type: "spend_limit_deleted", id}`. |

78| `GET /v1/organizations/spend_limits/effective` | Resolved cap and to-date spend per principal per period. |

79| `GET /v1/organizations/spend_limits/audit` | Admin mutation trail, newest-first. Query: `?limit=`. |

80 

81Conventions mirror Anthropic's Admin API:

82 

83* A `type` on every object

84* `spl_`-prefixed IDs

85* Amounts as whole-number strings of USD cents; `POST` rejects any other `currency` with `400`

86* The `{type: "error", error: {type, message}, request_id}` error envelope

87* A `request-id` response header on every admin response, success or error, matching the body's `request_id`

88 

89Every mutation writes a before/after row to `admin_audit` in the same transaction, attributed to `admin-key:<id>` or `oidc:<sub>`.

90 

91The `spend_limit_increase_requests` queue is not implemented.

92 

93### `/effective`

94 

95`GET /v1/organizations/spend_limits/effective` returns Anthropic's `SpendSummary` schema: each row is a principal for a period, with the resolved cap, period-to-date spend, and an `actor` object. Gateway-specific differences:

96 

97* `user_id` is the OIDC `sub`.

98* `actor.name` and `actor.email_address` are `null` until the principal's first inference request through the gateway. The gateway has no user directory; it records last-seen values from each user's own session JWT.

99* Each row also carries a `groups` array, the principal's last-seen IdP groups. This is a gateway extension so an admin UI can show every cap tier that applies; Anthropic-shaped clients ignore it.

100* Without a `user_ids[]` filter, it lists principals with recorded spend, because the gateway can't enumerate all org members.

101 

102Group-sourced caps resolve against those last-seen groups with the same `group_limit_mode` tie-break that enforcement uses, so the viewer shows the cap that actually applies.

103 

104| Query parameter | Description |

105| ---------------- | --------------------------------------------------------------------------------------------------- |

106| `user_ids[]` | Repeatable. Filter to specific principals by OIDC `sub`. |

107| `period[]` | Repeatable. Filter to `daily`, `weekly`, or `monthly` rows. |

108| `sort` | `spend_desc` lists top spenders first. Requires exactly one `period[]`. |

109| `q` | Case-insensitive substring filter over the OIDC `sub`, last-seen email, and last-seen display name. |

110| `limit` / `page` | Page size (1–1000, default 20) and the opaque cursor from the previous response's `next_page`. |

111 

112<Warning>

113 `q=` and `user_ids[]=` ride GET query strings, so any fronting proxy or load balancer captures them in its access logs. If your PII log policy is strict, scrub these parameters there.

114</Warning>

115 

116### `/audit`

117 

118Returns the spend-limit mutation trail: who changed which cap, before/after snapshots, and the optional reason, newest-first. `has_more` is exact. This endpoint follows the local Admin API conventions rather than a first-party wire shape.

119 

120### Pagination

121 

122The raw list pages by `after_id` and `before_id`, which are mutually exclusive `spl_…` IDs; results are ordered by creation and `has_more` reflects the traversal direction. `/effective` pages by the opaque `next_page` token passed back as `?page=`, with principals ordered ascending so pages stay stable while spend is being recorded. `limit` is 1–1000, default 20, on both.

123 

124## Data lifecycle

125 

126The gateway holds four spend-related tables; an hourly sweep enforces the retention windows:

127 

128| Table | Contents | Retention |

129| ------------------ | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |

130| `spend` | Per-principal period-to-date counters in cents | [`admin.spend_retention_months`](/en/claude-apps-gateway-config#admin), default 13 |

131| `spend_limits` | The configured caps | Until deleted via the API |

132| `admin_audit` | The mutation trail | [`admin.audit_retention_days`](/en/claude-apps-gateway-config#admin), default 365 |

133| `principal_emails` | Each principal's last-seen email, display name, and IdP groups. Contains PII. | [`admin.identity_retention_days`](/en/claude-apps-gateway-config#admin) since last activity, default 90 |

134 

135`identity_retention_days` is deliberately shorter than `spend_retention_months`: a deprovisioned identity stops refreshing and ages out, while its anonymous spend counters remain for year-over-year reporting.

136 

137When a developer leaves, delete any per-user cap via `DELETE /v1/organizations/spend_limits/{id}`; their spend and identity rows age out on the retention windows above. To erase one person immediately, for offboarding or a data subject access request (DSAR), run `DELETE FROM principal_emails WHERE principal = '<sub>'` directly against the gateway database. That removes the only table holding their email, name, and groups. The `spend` and `admin_audit` rows reference the pseudonymous OIDC `sub` only and age out on their own windows.

138 

139## Related

140 

141* [`admin` and `enforcement` configuration](/en/claude-apps-gateway-config#admin): enabling the admin API and tuning retention

142* [Deployment guide](/en/claude-apps-gateway-deploy#postgres): Postgres schema and backup guidance

Details

20| `claude -c -p "query"` | Continue via SDK | `claude -c -p "Check for type errors"` |20| `claude -c -p "query"` | Continue via SDK | `claude -c -p "Check for type errors"` |

21| `claude -r "<session>" "query"` | Resume session by ID or name | `claude -r "auth-refactor" "Finish this PR"` |21| `claude -r "<session>" "query"` | Resume session by ID or name | `claude -r "auth-refactor" "Finish this PR"` |

22| `claude update` | Update to latest version | `claude update` |22| `claude update` | Update to latest version | `claude update` |

23| `claude gateway` | Start the self-hosted [Claude apps gateway](/en/claude-apps-gateway) server, for administrators deploying SSO and policy in front of Claude Code on Bedrock, Vertex AI, or Foundry. Requires `--config` pointing at a [`gateway.yaml`](/en/claude-apps-gateway-config). Available in Claude Code v2.1.195 and later. | `claude gateway --config gateway.yaml` |

23| `claude install [version]` | Install or reinstall the native binary. Accepts a version like `2.1.118`, or `stable` or `latest`. See [Install a specific version](/en/setup#install-a-specific-version) | `claude install stable` |24| `claude install [version]` | Install or reinstall the native binary. Accepts a version like `2.1.118`, or `stable` or `latest`. See [Install a specific version](/en/setup#install-a-specific-version) | `claude install stable` |

24| `claude auth login` | Sign in to your Anthropic account. Use `--email` to pre-fill your email address, `--sso` to force SSO authentication, and `--console` to sign in with Anthropic Console for API usage billing instead of a Claude subscription | `claude auth login --console` |25| `claude auth login` | Sign in to your Anthropic account. Use `--email` to pre-fill your email address, `--sso` to force SSO authentication, and `--console` to sign in with Anthropic Console for API usage billing instead of a Claude subscription | `claude auth login --console` |

25| `claude auth logout` | Log out from your Anthropic account | `claude auth logout` |26| `claude auth logout` | Log out from your Anthropic account | `claude auth logout` |

costs.md +1 −1

Details

45 For organizations with custom rate limits, Claude Code traffic in this workspace counts toward your organization's overall API rate limits. You can set a [workspace rate limit](https://platform.claude.com/docs/en/api/rate-limits#setting-lower-limits-for-workspaces) on this workspace's Limits page in the Claude Console to cap Claude Code's share and protect other production workloads.45 For organizations with custom rate limits, Claude Code traffic in this workspace counts toward your organization's overall API rate limits. You can set a [workspace rate limit](https://platform.claude.com/docs/en/api/rate-limits#setting-lower-limits-for-workspaces) on this workspace's Limits page in the Claude Console to cap Claude Code's share and protect other production workloads.

46</Note>46</Note>

47 47 

48On Bedrock, Vertex, and Foundry, Claude Code does not send metrics from your cloud. Organizations that already route Claude Code through an [LLM gateway](/en/llm-gateway) can track spend there, since the gateway sees every request.48On Bedrock, Vertex, and Foundry, Claude Code doesn't send metrics from your cloud. A self-hosted [Claude apps gateway](/en/claude-apps-gateway) provides per-user usage attribution, OTLP metrics with token counts, and [per-user spend limits](/en/claude-apps-gateway-spend-limits) on these providers. Organizations that route Claude Code through a different [LLM gateway](/en/llm-gateway) can track spend at the gateway instead, since it sees every request.

49 49 

50### Rate limit recommendations50### Rate limit recommendations

51 51 

data-usage.md +2 −2

Details

29 29 

30After the rating prompt, you may see a separate follow-up asking "Can Anthropic look at your session transcript to help us improve Claude Code?". This is an optional second step distinct from the rating:30After the rating prompt, you may see a separate follow-up asking "Can Anthropic look at your session transcript to help us improve Claude Code?". This is an optional second step distinct from the rating:

31 31 

32* **Yes**: uploads your conversation transcript, any subagent transcripts, and the raw session log file from disk to Anthropic. Known API key and token patterns are redacted before upload. Source code, file contents, and other conversation content are uploaded as-is. Shared transcripts are retained for up to 6 months.32* **Yes**: uploads your conversation transcript, any subagent transcripts, and the raw session log file from disk to Anthropic. Known API key and token patterns are redacted before upload. Source code, file contents, and other conversation content are uploaded as-is. Shared transcripts are retained for up to 6 months. On Bedrock, Vertex AI, Foundry, and signed-in [Claude apps gateway](/en/claude-apps-gateway) sessions, Yes writes the same payload to a local archive under `~/.claude/feedback-bundles/` instead of uploading; nothing leaves your machine until you forward that file.

33* **No**: declines without sending anything33* **No**: declines without sending anything

34* **Don't ask again**: declines and stops this follow-up from appearing in future sessions34* **Don't ask again**: declines and stops this follow-up from appearing in future sessions

35 35 


105 105 

106## Default behaviors by API provider106## Default behaviors by API provider

107 107 

108By default, error reporting, telemetry, and bug reporting are disabled when using Bedrock, Vertex, Foundry, or Claude Platform on AWS. Session quality surveys and the WebFetch domain safety check are exceptions and run regardless of provider. You can opt out of all non-essential traffic, including surveys, at once by setting `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`. This variable does not affect the WebFetch check, which has its own opt-out. Here are the full default behaviors:108By default, error reporting, telemetry, and bug reporting are disabled when using Bedrock, Vertex, Foundry, or Claude Platform on AWS. Session quality surveys and the WebFetch domain safety check are exceptions and run regardless of provider. On a signed-in [Claude apps gateway](/en/claude-apps-gateway) session, usage analytics, error reporting, and survey ratings to Anthropic are disabled by the gateway credential itself, with no setting to re-enable them. You can opt out of all non-essential traffic, including surveys, at once by setting `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`. This variable does not affect the WebFetch check, which has its own opt-out. Here are the full default behaviors:

109 109 

110| Service | Claude API | Vertex API | Bedrock API | Foundry API | Claude Platform on AWS |110| Service | Claude API | Vertex API | Bedrock API | Foundry API | Claude Platform on AWS |

111| ------------------------------------ | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |111| ------------------------------------ | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |

env-vars.md +2 −2

Details

152| `CLAUDE_CODE_ATTRIBUTION_HEADER` | Set to `0` to omit the attribution block (client version and prompt fingerprint) from the start of the system prompt. Disabling it improves prompt-cache hit rates when routing through an [LLM gateway](/en/llm-gateway). Anthropic API caching is unaffected |152| `CLAUDE_CODE_ATTRIBUTION_HEADER` | Set to `0` to omit the attribution block (client version and prompt fingerprint) from the start of the system prompt. Disabling it improves prompt-cache hit rates when routing through an [LLM gateway](/en/llm-gateway). Anthropic API caching is unaffected |

153| `CLAUDE_CODE_AUTO_COMPACT_WINDOW` | Set the context capacity in tokens used for auto-compaction calculations. Defaults to the model's context window: 200K for standard models or 1M for [extended context](/en/model-config#extended-context) models. Use a lower value like `500000` on a 1M model to treat the window as 500K for compaction purposes. The value is capped at the model's actual context window. `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` is applied as a percentage of this value. Setting this variable decouples the compaction threshold from the status line's `used_percentage`, which always uses the model's full context window |153| `CLAUDE_CODE_AUTO_COMPACT_WINDOW` | Set the context capacity in tokens used for auto-compaction calculations. Defaults to the model's context window: 200K for standard models or 1M for [extended context](/en/model-config#extended-context) models. Use a lower value like `500000` on a 1M model to treat the window as 500K for compaction purposes. The value is capped at the model's actual context window. `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` is applied as a percentage of this value. Setting this variable decouples the compaction threshold from the status line's `used_percentage`, which always uses the model's full context window |

154| `CLAUDE_CODE_AUTO_CONNECT_IDE` | Override automatic [IDE connection](/en/vs-code). By default, Claude Code connects automatically when launched inside a supported IDE's integrated terminal. Set to `false` to prevent this. Set to `true` to force a connection attempt when auto-detection fails, such as when tmux obscures the parent terminal. Takes precedence over the [`autoConnectIde`](/en/settings#global-config-settings) global config setting |154| `CLAUDE_CODE_AUTO_CONNECT_IDE` | Override automatic [IDE connection](/en/vs-code). By default, Claude Code connects automatically when launched inside a supported IDE's integrated terminal. Set to `false` to prevent this. Set to `true` to force a connection attempt when auto-detection fails, such as when tmux obscures the parent terminal. Takes precedence over the [`autoConnectIde`](/en/settings#global-config-settings) global config setting |

155| `CLAUDE_CODE_CERT_STORE` | Comma-separated list of CA certificate sources for TLS connections. `bundled` is the Mozilla CA set shipped with Claude Code. `system` is the operating system trust store. Default is `bundled,system` |155| `CLAUDE_CODE_CERT_STORE` | Comma-separated list of CA certificate sources for TLS connections. `bundled` is the Mozilla CA set shipped with Claude Code. `system` is the operating system trust store, read only on runtimes with `tls.getCACertificates`: the native binary, or Node 22.15 or later for npm installs. See [CA certificate store](/en/network-config#ca-certificate-store). Default is `bundled,system` |

156| `CLAUDE_CODE_CHILD_SESSION` | {/* min-version: 2.1.172 */}Set to `1` in subprocesses Claude Code spawns via the Bash, PowerShell, and Monitor tools, [hook](/en/hooks) commands, and [status line](/en/statusline) commands. Not set for stdio [MCP server](/en/mcp) subprocesses, which are long-lived and outlive the session that spawned them. Unlike `CLAUDECODE`, this is only set by Claude Code itself when it launches a subprocess and not by IDE extensions, so it reliably distinguishes a nested session from a top-level `claude` launched in an IDE-integrated terminal. A nested interactive `claude` TUI started this way is automatically excluded from `--resume`, `--continue`, up-arrow history, and the `claude agents` list. Non-interactive `claude -p` sessions still persist. Set `CLAUDE_CODE_FORCE_SESSION_PERSISTENCE=1` to override this exclusion. Requires Claude Code v2.1.172 or later |156| `CLAUDE_CODE_CHILD_SESSION` | {/* min-version: 2.1.172 */}Set to `1` in subprocesses Claude Code spawns via the Bash, PowerShell, and Monitor tools, [hook](/en/hooks) commands, and [status line](/en/statusline) commands. Not set for stdio [MCP server](/en/mcp) subprocesses, which are long-lived and outlive the session that spawned them. Unlike `CLAUDECODE`, this is only set by Claude Code itself when it launches a subprocess and not by IDE extensions, so it reliably distinguishes a nested session from a top-level `claude` launched in an IDE-integrated terminal. A nested interactive `claude` TUI started this way is automatically excluded from `--resume`, `--continue`, up-arrow history, and the `claude agents` list. Non-interactive `claude -p` sessions still persist. Set `CLAUDE_CODE_FORCE_SESSION_PERSISTENCE=1` to override this exclusion. Requires Claude Code v2.1.172 or later |

157| `CLAUDE_CODE_CLIENT_CERT` | Path to client certificate file for mTLS authentication |157| `CLAUDE_CODE_CLIENT_CERT` | Path to client certificate file for mTLS authentication |

158| `CLAUDE_CODE_CLIENT_KEY` | Path to client private key file for mTLS authentication |158| `CLAUDE_CODE_CLIENT_KEY` | Path to client private key file for mTLS authentication |


188| `CLAUDE_CODE_DISABLE_VIRTUAL_SCROLL` | Set to `1` to disable virtual scrolling in [fullscreen rendering](/en/fullscreen) and render every message in the transcript. Use this if scrolling in fullscreen mode shows blank regions where messages should appear |188| `CLAUDE_CODE_DISABLE_VIRTUAL_SCROLL` | Set to `1` to disable virtual scrolling in [fullscreen rendering](/en/fullscreen) and render every message in the transcript. Use this if scrolling in fullscreen mode shows blank regions where messages should appear |

189| `CLAUDE_CODE_DISABLE_WORKFLOWS` | Set to `1` to disable [workflows](/en/workflows#turn-workflows-off). Equivalent to the [`disableWorkflows`](/en/settings#available-settings) setting |189| `CLAUDE_CODE_DISABLE_WORKFLOWS` | Set to `1` to disable [workflows](/en/workflows#turn-workflows-off). Equivalent to the [`disableWorkflows`](/en/settings#available-settings) setting |

190| `CLAUDE_CODE_EFFORT_LEVEL` | Set the effort level for supported models. Values: `low`, `medium`, `high`, `xhigh`, `max`, or `auto` to use the model default. Available levels depend on the model. Takes precedence over `/effort` and the `effortLevel` setting. See [Adjust effort level](/en/model-config#adjust-effort-level) |190| `CLAUDE_CODE_EFFORT_LEVEL` | Set the effort level for supported models. Values: `low`, `medium`, `high`, `xhigh`, `max`, or `auto` to use the model default. Available levels depend on the model. Takes precedence over `/effort` and the `effortLevel` setting. See [Adjust effort level](/en/model-config#adjust-effort-level) |

191| `CLAUDE_CODE_ENABLE_AUTO_MODE` | {/* min-version: 2.1.158 */}Set to `1` to make [auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) available on Amazon Bedrock, Google Cloud Vertex AI, and Microsoft Foundry. Requires Claude Code v2.1.158 or later. Has no effect on the Anthropic API, where auto mode is available by default. See [Enable auto mode on Bedrock, Vertex AI, or Foundry](/en/permission-modes#enable-auto-mode-on-bedrock-vertex-ai-or-foundry) |191| `CLAUDE_CODE_ENABLE_AUTO_MODE` | {/* min-version: 2.1.158 */}Set to `1` to make [auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) available on Amazon Bedrock, Google Cloud Vertex AI, Microsoft Foundry, and signed-in [Claude apps gateway](/en/claude-apps-gateway) sessions. Requires Claude Code v2.1.158 or later. Has no effect on the Anthropic API, where auto mode is available by default. See [Enable auto mode on Bedrock, Vertex AI, or Foundry](/en/permission-modes#enable-auto-mode-on-bedrock-vertex-ai-or-foundry) |

192| `CLAUDE_CODE_ENABLE_AWAY_SUMMARY` | Override [session recap](/en/interactive-mode#session-recap) availability. Set to `0` to force recaps off regardless of the `/config` toggle. Set to `1` to force recaps on when [`awaySummaryEnabled`](/en/settings#available-settings) is `false`. Takes precedence over the setting and `/config` toggle |192| `CLAUDE_CODE_ENABLE_AWAY_SUMMARY` | Override [session recap](/en/interactive-mode#session-recap) availability. Set to `0` to force recaps off regardless of the `/config` toggle. Set to `1` to force recaps on when [`awaySummaryEnabled`](/en/settings#available-settings) is `false`. Takes precedence over the setting and `/config` toggle |

193| `CLAUDE_CODE_ENABLE_BACKGROUND_PLUGIN_REFRESH` | Set to `1` to refresh plugin state at turn boundaries in [non-interactive mode](/en/headless) after a background install completes. Off by default because the refresh changes the system prompt mid-session, which invalidates [prompt caching](/en/prompt-caching) for that turn |193| `CLAUDE_CODE_ENABLE_BACKGROUND_PLUGIN_REFRESH` | Set to `1` to refresh plugin state at turn boundaries in [non-interactive mode](/en/headless) after a background install completes. Off by default because the refresh changes the system prompt mid-session, which invalidates [prompt caching](/en/prompt-caching) for that turn |

194| `CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL` | Set to `1` to route the "How is Claude doing?" session quality survey to your own [OpenTelemetry collector](/en/monitoring-usage) when Anthropic-bound nonessential traffic is blocked. Survey ratings are emitted only as OTEL events to your configured collector. No survey data is sent to Anthropic in this mode. Applies when `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`, `DISABLE_TELEMETRY`, or `DO_NOT_TRACK` is set, and has no effect otherwise. `CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY` and the organization product feedback policy take precedence |194| `CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL` | Set to `1` to route the "How is Claude doing?" session quality survey to your own [OpenTelemetry collector](/en/monitoring-usage) when Anthropic-bound nonessential traffic is blocked. Survey ratings are emitted only as OTEL events to your configured collector. No survey data is sent to Anthropic in this mode. Applies when `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`, `DISABLE_TELEMETRY`, or `DO_NOT_TRACK` is set, and has no effect otherwise. `CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY` and the organization product feedback policy take precedence |

gateways.md +73 −0 created

Details

1> ## Documentation Index

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt

3> Use this file to discover all available pages before exploring further.

4 

5# Run Claude Code through a gateway

6 

7> Route Claude Code through a self-hosted gateway for centralized credentials, usage tracking, and cost controls. Covers the architecture, Anthropic's Claude apps gateway, and using other gateway products.

8 

9A gateway is a proxy your organization runs between Claude Code and a model provider. Claude Code sends API traffic to the gateway instead of directly to the provider, and the gateway forwards it using a credential your organization holds. Developers authenticate to the gateway rather than holding provider credentials, so authentication, usage tracking, budgets, and audit logging happen in one place you control.

10 

11Claude Code includes a self-hosted gateway, [Claude apps gateway](/en/claude-apps-gateway), in the `claude` binary, so you don't have to adopt a separate gateway product to run one. If your organization already runs an [LLM gateway](/en/llm-gateway), Claude Code works with that too.

12 

13This page covers:

14 

15* [How a gateway sits between Claude Code and your provider](#how-a-gateway-works)

16* [Choosing between Claude apps gateway and a gateway you already run](#choose-a-gateway)

17* [How gateways interact with claude.ai subscriptions](#subscriptions-and-gateways)

18* [What's configured separately from the gateway](#configure-separately-from-the-gateway)

19 

20## How a gateway works

21 

22Each developer's Claude Code is pointed at the gateway's address and authenticates with a gateway-issued credential.

23 

24The gateway authenticates the developer, applies whatever access and budget rules you configure, and forwards the request to your provider with the organization's credential. The provider can be Anthropic's API or a [cloud provider](/en/third-party-integrations) such as Amazon Bedrock, Google Cloud's Agent Platform, or Microsoft Foundry; the gateway's configuration decides. With Claude apps gateway, or another gateway that exposes a single Anthropic-format endpoint, changing provider doesn't require touching developer machines.

25 

26<Frame>

27 <img src="https://mintcdn.com/claude-code/-uq-4JE0W_JO5Er5/images/llm-gateway-flow.svg?fit=max&auto=format&n=-uq-4JE0W_JO5Er5&q=85&s=1c1a8dcc0cfcc3a58652cc8e28cd3e20" alt="Diagram showing Claude Code routing through a gateway. In a developer machines zone, the Claude Code CLI and VS Code extension send requests to the gateway address with a per-developer credential. In a zone labeled your infrastructure, the gateway handles authentication, usage tracking, budgets, and routing, and forwards requests with your organization's credential. In a model providers zone, a solid arrow leads to the provider you configure, shown as the Anthropic API, and dashed arrows lead to other provider options, illustrated with Amazon Bedrock, Google Cloud, and Microsoft Foundry as examples." width="780" height="322" data-path="images/llm-gateway-flow.svg" />

28</Frame>

29 

30Two kinds of credential are involved:

31 

32* **Developer credential**: each developer holds their own, issued by the gateway. It authenticates them to the gateway and identifies them in usage tracking

33* **Provider credential**: the gateway holds one credential for your provider account, shared by all forwarded traffic

34 

35## Choose a gateway

36 

37Claude Code works with Anthropic's own gateway or with a gateway your organization already runs.

38 

39### Claude apps gateway

40 

41Claude apps gateway is Anthropic's self-hosted gateway, included in the `claude` binary. It routes to Amazon Bedrock, Google Cloud, Microsoft Foundry, or the Anthropic API as the upstream. Developers sign in with your corporate identity provider through `/login`, the gateway enforces model access and [managed settings](/en/permissions#managed-settings) by IdP group, and it emits [OpenTelemetry Protocol (OTLP)](/en/monitoring-usage) usage metrics to your own observability stack.

42 

43Because it is built and tested alongside each Claude Code release, it forwards the headers and request fields Claude Code sends. A gateway maintained separately needs its [forwarding rules updated](/en/llm-gateway-protocol#forward-as-open-lists) as those headers and fields change with each release; Claude apps gateway releases with the CLI, so there is no list to keep current. See [Availability and limitations](/en/claude-apps-gateway#availability-and-limitations) for the small set of features that behave differently on a gateway session.

44 

45The gateway sign-in is a browser SSO step, and there is no service-token flow, so a CI pipeline with no developer to approve the sign-in can't authenticate through it; configure those against your provider directly. Agent SDK sessions and `claude -p` runs on a machine where a developer has signed in use that machine's gateway session and are governed by its policies. See [CI pipelines and remote machines](/en/claude-apps-gateway#ci-pipelines-and-remote-machines).

46 

47See [Claude apps gateway](/en/claude-apps-gateway) to deploy it.

48 

49### Other gateways

50 

51If your organization already runs an LLM gateway or API gateway, you can use it instead. Anthropic doesn't endorse, maintain, or audit other gateway products, and doesn't support routing Claude Code to non-Claude models through any gateway. See [Other LLM gateways](/en/llm-gateway) for the admin rollout checklist, what a gateway must implement, and how to point Claude Code at it.

52 

53## Subscriptions and gateways

54 

55When developers connect through a gateway with a gateway credential, usage is billed to your organization's provider account at API rates, and their claude.ai subscriptions aren't used or charged. Setting [`ANTHROPIC_AUTH_TOKEN`](/en/env-vars) for a gateway you run, or signing in to a Claude apps gateway with `/login`, turns off subscription login for that session. Every request forwarded under that credential is charged to the account behind the gateway's provider credential.

56 

57The exception is setting only `ANTHROPIC_BASE_URL`, with no gateway credential. Requests still route through the gateway, but a saved claude.ai login stays the active credential, so the subscription's usage limits and billing apply. [Other LLM gateways](/en/llm-gateway#subscriptions-and-gateways) covers that configuration and what the gateway has to forward for it to work.

58 

59## Configure separately from the gateway

60 

61A gateway routes model API requests. A few things you might expect it to handle are configured elsewhere:

62 

63* **Which model answers**: pick the model with the `/model` command or [model environment variables](/en/model-config#setting-your-model). The gateway decides where requests go, not which model the developer selects. Claude apps gateway can bound the choice with a per-group `availableModels` allowlist, but the developer still picks within it.

64* **Other network traffic**: Claude Code itself sends version checks and downloads directly to Anthropic, separate from the gateway path. Whether the optional client telemetry stream is also on depends on your provider; the [telemetry defaults table](/en/data-usage#telemetry-services) covers each case. On a signed-in Claude apps gateway session, the gateway credential disables the Anthropic-bound analytics and, when [telemetry forwarding](/en/claude-apps-gateway-config#telemetry) is configured, pins OTLP export to the gateway. Your network still needs egress to the [required domains](/en/network-config), or set [`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`](/en/env-vars) to turn off the optional streams.

65* **Corporate HTTP proxies**: an `HTTPS_PROXY` sits between Claude Code and every server it talks to, including the gateway. If your network requires one, [configure the proxy](/en/network-config) in addition to the gateway. For Claude apps gateway specifically, [sign-in checks that the proxy host is also on a private network](/en/claude-apps-gateway#prerequisites); if it isn't, add the gateway host to `NO_PROXY` so the CLI connects to it directly.

66 

67## Next steps

68 

69The next page depends on who runs the gateway. Anthropic's gateway runs from the `claude` binary and has its own setup guide; a gateway your organization already runs has a protocol to implement and an admin rollout checklist.

70 

71* [Claude apps gateway](/en/claude-apps-gateway) to deploy Anthropic's self-hosted gateway with SSO sign-in and OTLP telemetry

72* [Other LLM gateways](/en/llm-gateway) for what a gateway your organization already runs must implement, and how to point Claude Code at it

73* [Set up Claude Code for your organization](/en/admin-setup) for the wider rollout decisions a gateway is one part of

llm-gateway.md +10 −36

Details

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt

3> Use this file to discover all available pages before exploring further.3> Use this file to discover all available pages before exploring further.

4 4 

5# LLM gateways5# Other LLM gateways

6 6 

7> Route Claude Code through an LLM gateway for centralized authentication, usage tracking, and cost controls. Covers connecting Claude Code to a gateway, rolling one out for your organization, what Claude Code sends to a gateway, and how gateways interact with claude.ai subscriptions.7> Route Claude Code through an LLM gateway your organization already runs. Covers connecting Claude Code to a gateway, rolling one out for your organization, and what Claude Code sends to a gateway.

8 8 

9An LLM gateway is a proxy your organization runs between Claude Code and a model provider. Claude Code sends API traffic to the gateway, and the gateway forwards it to the provider using a credential your organization controls.9This section covers using a gateway product your organization already runs, rather than [Claude apps gateway](/en/claude-apps-gateway). For what a gateway is, how it sits between Claude Code and your provider, and how to choose between Claude apps gateway and another product, see the [gateway overview](/en/gateways).

10 10 

11<Note>11<Note>

12 * If you're a developer connecting to an existing gateway: [connect Claude Code to your gateway](/en/llm-gateway-connect)12 * If you're a developer connecting to an existing gateway: [connect Claude Code to your gateway](/en/llm-gateway-connect)


14 * If you're configuring a gateway product: the [gateway protocol reference](/en/llm-gateway-protocol)14 * If you're configuring a gateway product: the [gateway protocol reference](/en/llm-gateway-protocol)

15</Note>15</Note>

16 16 

17Any gateway that exposes a [supported API format](/en/llm-gateway-protocol#api-formats) works. 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. Deploy the gateway following its own documentation, then complete the Claude Code side with the [rollout steps below](#roll-out-a-gateway).

18 

17## What a gateway provides19## What a gateway provides

18 20 

19A gateway gives your organization one place to manage:21A gateway gives your organization one place to manage:


24* **Audit logging**: log every model request for compliance26* **Audit logging**: log every model request for compliance

25* **Provider switching**: change the provider in gateway configuration, without touching developer machines27* **Provider switching**: change the provider in gateway configuration, without touching developer machines

26 28 

27All of these except provider switching apply whether the upstream is Anthropic's API or a [cloud provider](/en/third-party-integrations).29All of these except provider switching apply whether the upstream is Anthropic's API or a [cloud provider](/en/third-party-integrations). Provider switching without reconfiguring developer machines also depends on the gateway exposing a single [Anthropic-format endpoint](/en/llm-gateway-protocol#api-formats) regardless of upstream; a gateway that exposes a provider's own format ties the client configuration to that provider.

28 30 

29The tradeoff is that the gateway becomes infrastructure your organization operates. Claude Code adds capabilities with each release, and a gateway that doesn't forward them breaks the corresponding features, so the gateway product needs to be kept updated as Claude Code evolves. The [gateway protocol reference](/en/llm-gateway-protocol) covers what to forward.31The tradeoff is that the gateway becomes infrastructure your organization operates. Claude Code adds capabilities with each release, and a gateway that doesn't forward them breaks the corresponding features, so the gateway product needs to be kept updated as Claude Code evolves. The [gateway protocol reference](/en/llm-gateway-protocol) covers what to forward.

30 32 

31## How a gateway works

32 

33By default, Claude Code sends requests directly to Anthropic's API at `api.anthropic.com`. To route through a gateway, set `ANTHROPIC_BASE_URL` to the gateway's address; Claude Code sends the same requests there instead. The gateway authenticates the developer, attaches your organization's provider credential, and forwards each request to whichever provider it's configured for.

34 

35`ANTHROPIC_BASE_URL` is the address variable for most gateways. A gateway that fronts a specific cloud provider, such as Bedrock, Vertex, Foundry, or the Claude Platform on AWS, uses that provider's base URL variable instead; [API formats](/en/llm-gateway-protocol#api-formats) lists which variable goes with each configuration.

36 

37<Frame>

38 <img src="https://mintcdn.com/claude-code/zIcIE_SQv4Z0Zbhc/images/llm-gateway-flow.svg?fit=max&auto=format&n=zIcIE_SQv4Z0Zbhc&q=85&s=490607d033d235694efb49a73a5b9e4b" alt="Diagram showing Claude Code routing through an LLM gateway. In a developer machines zone, the Claude Code CLI, VS Code extension, and CI or Agent SDK clients send requests to the gateway, with the base URL variable for the gateway's API format pointing at it and each developer holding a per-developer credential, and the desktop app reaches the same gateway through organization-distributed configuration. In a zone labeled your infrastructure, the LLM gateway handles authentication, usage tracking, budgets, and routing, and forwards requests with your organization's credential. In a model providers zone, a solid arrow leads to the provider you configure, shown as the Anthropic API, and dashed arrows lead to other provider options, illustrated with Amazon Bedrock, Google Vertex AI, and Microsoft Foundry as examples." width="780" height="322" data-path="images/llm-gateway-flow.svg" />

39</Frame>

40 

41Two kinds of credential are involved:

42 

43* **Developer credentials**: each developer holds their own, issued by the gateway. It authenticates them to the gateway and identifies them in usage tracking

44* **Provider credential**: the gateway holds one credential for your provider account, shared by all forwarded traffic. You don't provision provider keys per developer

45 

46The gateway forwards each request to the provider you configure, such as the Anthropic API, [Amazon Bedrock](/en/amazon-bedrock), [Google Vertex AI](/en/google-vertex-ai), [Microsoft Foundry](/en/microsoft-foundry), or the [Claude Platform on AWS](/en/claude-platform-on-aws). Because Claude Code talks only to the gateway, the provider choice is the gateway's configuration, not the client's.

47 

48## Roll out a gateway33## Roll out a gateway

49 34 

50When you're ready to roll out an LLM gateway to your organization, the sequence is the same whichever gateway product you choose:35When you're ready to roll out an LLM gateway to your organization, the sequence is the same whichever gateway product you choose:


56 41 

57[Roll out an LLM gateway for your organization](/en/llm-gateway-rollout) walks each step and shows the configuration files to distribute at each one. The gateway is one part of organization setup; for policy enforcement, usage visibility, and data handling decisions, see [Set up Claude Code for your organization](/en/admin-setup).42[Roll out an LLM gateway for your organization](/en/llm-gateway-rollout) walks each step and shows the configuration files to distribute at each one. The gateway is one part of organization setup; for policy enforcement, usage visibility, and data handling decisions, see [Set up Claude Code for your organization](/en/admin-setup).

58 43 

59## Third-party gateways

60 

61Any gateway that exposes a [supported API format](/en/llm-gateway-protocol#api-formats) works. Anthropic doesn't endorse, maintain, or audit third-party gateway products. Deploy them following their own documentation, then complete the Claude Code side of the rollout with the [rollout steps](/en/llm-gateway-rollout).

62 

63## Subscriptions and gateways44## Subscriptions and gateways

64 45 

65While a [gateway credential variable](/en/llm-gateway-connect#set-the-credential-variable) or `apiKeyHelper` is active, a developer's claude.ai subscription isn't used: the credential replaces the subscription login for that session, and the subscription's usage limits don't apply. That traffic is billed per token to whoever owns the credential the gateway forwards, such as your organization's Anthropic Console account, or your Bedrock, Vertex, or Foundry account when the gateway routes there.46While a [gateway credential variable](/en/llm-gateway-connect#set-the-credential-variable) or `apiKeyHelper` is active, a developer's claude.ai subscription isn't used: the credential replaces the subscription login for that session, and the subscription's usage limits don't apply. That traffic is billed per token to whoever owns the credential the gateway forwards, such as your organization's Anthropic Console account, or your Bedrock, Agent Platform, or Foundry account when the gateway routes there.

66 

67Setting only `ANTHROPIC_BASE_URL`, without a gateway credential, doesn't replace the subscription. Requests still route through the gateway, but a saved claude.ai login remains the active credential, so its usage limits and billing apply. Gateways that pass this traffic on to Anthropic must forward the OAuth capability in `anthropic-beta`; see the [request headers reference](/en/llm-gateway-protocol#request-headers).

68 

69## Configure separately from the gateway

70 

71A gateway determines where model API requests are sent. Model selection, the rest of Claude Code's network traffic, and corporate proxies are configured separately:

72 47 

73* **Model selection**: the base URL decides where requests go, not which model answers them. Pick the model with the `/model` command or the model environment variables; see [how to set your model](/en/model-config#setting-your-model)48[`ANTHROPIC_BASE_URL`](/en/llm-gateway-connect#set-the-base-url-and-credential) is the variable that points Claude Code at the gateway. Setting only that variable, without a gateway credential, doesn't replace the subscription. Requests still route through the gateway, but a saved claude.ai login remains the active credential, so its usage limits and billing apply. Gateways that pass this traffic on to Anthropic must forward the OAuth capability in `anthropic-beta`; see the [request headers reference](/en/llm-gateway-protocol#request-headers).

74* **Client-side traffic**: version checks and optional client telemetry, both disabled with [`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`](/en/env-vars), and login traffic when a claude.ai or Console login is in use, go to Anthropic's update and authentication endpoints rather than the gateway. See [network access requirements](/en/network-config#network-access-requirements) for the domains

75* **Corporate proxies**: a proxy set with `HTTPS_PROXY` sits between Claude Code and every server it talks to, including the gateway. If your network requires a proxy, configure both; see [proxy configuration](/en/network-config#proxy-configuration)

76 49 

77## Related pages50## Related pages

78 51 

52* [Gateway overview](/en/gateways): how a gateway works and how to choose between Claude apps gateway and another product

53* [Claude apps gateway](/en/claude-apps-gateway): Anthropic's self-hosted gateway with SSO sign-in and OTLP telemetry

79* [Connect Claude Code to an LLM gateway](/en/llm-gateway-connect): set the base URL and credential on your own machine, with per-surface configuration and a troubleshooting table54* [Connect Claude Code to an LLM gateway](/en/llm-gateway-connect): set the base URL and credential on your own machine, with per-surface configuration and a troubleshooting table

80* [Roll out an LLM gateway for your organization](/en/llm-gateway-rollout): the admin checklist for deploying a gateway, issuing developer credentials, and distributing managed settings55* [Roll out an LLM gateway for your organization](/en/llm-gateway-rollout): the admin checklist for deploying a gateway, issuing developer credentials, and distributing managed settings

81* [Gateway protocol reference](/en/llm-gateway-protocol): what Claude Code sends to a gateway, for operators configuring one, covering endpoints, headers to forward, and feature pass-through56* [Gateway protocol reference](/en/llm-gateway-protocol): what Claude Code sends to a gateway, for operators configuring one, covering endpoints, headers to forward, and feature pass-through

82* [Set up Claude Code for your organization](/en/admin-setup): the wider rollout decisions a gateway is one part of, including policy enforcement and usage visibility

Details

203 anthropic_api_key: ${{ secrets.GATEWAY_API_KEY }}203 anthropic_api_key: ${{ secrets.GATEWAY_API_KEY }}

204```204```

205 205 

206For a bearer-token gateway, pass the same secret as both the `anthropic_api_key` input and `ANTHROPIC_AUTH_TOKEN` in the workflow `env` block. The action requires `anthropic_api_key`, `CLAUDE_CODE_OAUTH_TOKEN`, or workload identity federation before it launches Claude Code, and it doesn't read `ANTHROPIC_AUTH_TOKEN`, so the input satisfies that launch check while the env variable puts the key in the `Authorization` header the gateway reads. The copy in `x-api-key` is ignored:206For a bearer-token gateway, pass the same secret twice: as the `anthropic_api_key` input and as `ANTHROPIC_AUTH_TOKEN` in the workflow `env` block. The action requires `anthropic_api_key`, `CLAUDE_CODE_OAUTH_TOKEN`, or workload identity federation before it launches Claude Code, and it doesn't read `ANTHROPIC_AUTH_TOKEN`, so the input is there only to satisfy that launch check. The env variable is what puts the key in the `Authorization` header the gateway reads; the copy in `x-api-key` is ignored:

207 207 

208```yaml theme={null}208```yaml theme={null}

209env:209env:


282```json theme={null}282```json theme={null}

283{283{

284 "env": {284 "env": {

285 "ANTHROPIC_CUSTOM_HEADERS": "X-Org-Route: prod\nX-Tenant: acme"285 "ANTHROPIC_CUSTOM_HEADERS": "X-Org-Route: prod\nX-Tenant: example"

286 }286 }

287}287}

288```288```


346 346 

347### Route to a cloud provider through a gateway347### Route to a cloud provider through a gateway

348 348 

349These configurations point Claude Code at a gateway through a provider-specific base URL variable in place of `ANTHROPIC_BASE_URL`. Bedrock and Vertex gateways accept those providers' native request formats; Foundry and Claude Platform on AWS gateways accept the Anthropic Messages format and differ only in which base URL variable reaches them.349These configurations point Claude Code at a gateway through a provider-specific base URL variable in place of `ANTHROPIC_BASE_URL`. Bedrock and Agent Platform gateways accept those providers' native request formats; Foundry and Claude Platform on AWS gateways accept the Anthropic Messages format and differ only in which base URL variable reaches them.

350 350 

351Use one only if your gateway team specifically named Bedrock, Vertex, Foundry, or the Claude Platform on AWS. If the [verification request](#verify-the-connection) above returned JSON, you can skip this section.351Use one only if your gateway team specifically named Bedrock, Agent Platform, Foundry, or the Claude Platform on AWS. If the [verification request](#verify-the-connection) above returned JSON, you can skip this section.

352 352 

353Set the block for the provider your gateway team named. The skip-auth variables tell Claude Code not to sign requests with provider credentials, since the gateway holds those. If the gateway needs its own token, add `ANTHROPIC_AUTH_TOKEN` after the block, except for Foundry, which uses `ANTHROPIC_FOUNDRY_API_KEY` as shown.353Set the block for the provider your gateway team named. The skip-auth variables tell Claude Code not to sign requests with provider credentials, since the gateway holds those. If the gateway needs its own token, add `ANTHROPIC_AUTH_TOKEN` after the block, except for Foundry, which uses `ANTHROPIC_FOUNDRY_API_KEY` as shown.

354 354 


372 </Tab>372 </Tab>

373</Tabs>373</Tabs>

374 374 

375#### Google Vertex AI375#### Google Cloud's Agent Platform

376 376 

377<Tabs>377<Tabs>

378 <Tab title="Bash or Zsh">378 <Tab title="Bash or Zsh">

Details

8 8 

9This page documents the requests Claude Code sends to a gateway, including the endpoints it calls, the headers and body fields the gateway must forward, and which features stop working when it doesn't. It is written for operators configuring a gateway product to work with Claude Code.9This page documents the requests Claude Code sends to a gateway, including the endpoints it calls, the headers and body fields the gateway must forward, and which features stop working when it doesn't. It is written for operators configuring a gateway product to work with Claude Code.

10 10 

11A running [Claude apps gateway](/en/claude-apps-gateway) serves a machine-readable version of this contract at `GET /protocol`, covering the same forwarding requirements plus the Claude apps gateway-specific endpoints for SSO sign-in, managed-settings delivery, and telemetry. Claude apps gateway runs from the same `claude` binary as the CLI, so the [Claude apps gateway quickstart](/en/claude-apps-gateway#quickstart) is the shortest path to a running instance you can fetch the spec from.

12 

11<Note>13<Note>

12 * To roll out an existing or third-party gateway for your organization, see [Roll out an LLM gateway](/en/llm-gateway-rollout)14 * To roll out an existing or third-party gateway for your organization, see [Roll out an LLM gateway](/en/llm-gateway-rollout)

13 * If you're an individual developer authenticating Claude Code to a gateway with a credential you were given, see [Connect Claude Code to an LLM gateway](/en/llm-gateway-connect)15 * If you're an individual developer authenticating Claude Code to a gateway with a credential you were given, see [Connect Claude Code to an LLM gateway](/en/llm-gateway-connect)


30 32 

31## API formats33## API formats

32 34 

33A gateway must expose at least one of the following API formats to Claude Code clients. Which format Claude Code speaks is determined by the client's configuration: the variable in the Selected by column of the table below points Claude Code at your gateway in that format.35A gateway must expose at least one of the following API formats to Claude Code clients. Which format Claude Code speaks is determined by the client's configuration: the variable in the Selected by column of the table below points Claude Code at your gateway in that format. Agent Platform is Google Cloud's Claude endpoint, formerly Vertex AI; its variable names keep the `VERTEX` spelling.

34 36 

35| Format | Selected by | Endpoints | Forward unchanged |37| Format | Selected by | Endpoints | Forward unchanged |

36| :------------------ | :------------------------------------------------------------ | :----------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------- |38| :------------------------ | :------------------------------------------------------------ | :----------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------- |

37| Anthropic Messages | `ANTHROPIC_BASE_URL` | `/v1/messages`, `/v1/messages/count_tokens` (optional) | `anthropic-beta` and `anthropic-version` request headers |39| Anthropic Messages | `ANTHROPIC_BASE_URL` | `/v1/messages`, `/v1/messages/count_tokens` (optional) | `anthropic-beta` and `anthropic-version` request headers |

38| Bedrock InvokeModel | `ANTHROPIC_BEDROCK_BASE_URL` with `CLAUDE_CODE_USE_BEDROCK=1` | `/model/{model}/invoke`, `/model/{model}/invoke-with-response-stream` | `anthropic_beta` and `anthropic_version` request body fields |40| Bedrock InvokeModel | `ANTHROPIC_BEDROCK_BASE_URL` with `CLAUDE_CODE_USE_BEDROCK=1` | `/model/{model}/invoke`, `/model/{model}/invoke-with-response-stream` | `anthropic_beta` and `anthropic_version` request body fields |

39| Vertex rawPredict | `ANTHROPIC_VERTEX_BASE_URL` with `CLAUDE_CODE_USE_VERTEX=1` | `:rawPredict`, `:streamRawPredict`, `count-tokens:rawPredict` (optional) | `anthropic-beta` and `anthropic-version` request headers, and the `anthropic_version` request body field |41| Agent Platform rawPredict | `ANTHROPIC_VERTEX_BASE_URL` with `CLAUDE_CODE_USE_VERTEX=1` | `:rawPredict`, `:streamRawPredict`, `count-tokens:rawPredict` (optional) | `anthropic-beta` and `anthropic-version` request headers, and the `anthropic_version` request body field |

40 42 

41### Foundry and Claude Platform on AWS43### Foundry and Claude Platform on AWS

42 44 


44 46 

45### Optional endpoints and startup traffic47### Optional endpoints and startup traffic

46 48 

47Token-counting endpoints are the only optional ones: when they're absent, Claude Code estimates context usage locally. Inference requests post to `/v1/messages?beta=true`, so match on the path, not the full URL. The Vertex method suffixes attach to the publisher model path, as in `/projects/{project}/locations/{location}/publishers/anthropic/models/{model}:streamRawPredict`.49Token-counting endpoints are the only optional ones: when they're absent, Claude Code estimates context usage locally. Inference requests post to `/v1/messages?beta=true`, so match on the path, not the full URL. The Agent Platform method suffixes attach to the publisher model path, as in `/projects/{project}/locations/{location}/publishers/anthropic/models/{model}:streamRawPredict`.

48 50 

49A gateway also sees best-effort startup traffic it can reject without breaking anything: a `HEAD /` connectivity probe, and on Bedrock-format gateways a `GET /inference-profiles?type=SYSTEM_DEFINED` request.51A gateway also sees best-effort startup traffic it can reject without breaking anything: a `HEAD /` connectivity probe, and on Bedrock-format gateways a `GET /inference-profiles?type=SYSTEM_DEFINED` request.

50 52 


56 58 

57Which format the client speaks determines what your gateway receives. The common failure mode is a mismatch between the format the client sends to your gateway and the format the upstream provider behind it accepts.59Which format the client speaks determines what your gateway receives. The common failure mode is a mismatch between the format the client sends to your gateway and the format the upstream provider behind it accepts.

58 60 

59* When the client speaks the Bedrock or Vertex format, Claude Code sends only the subset of its full capability set that those providers accept61* When the client speaks the Bedrock or Agent Platform format, Claude Code sends only the subset of its full capability set that those providers accept

60* When the client speaks the Anthropic Messages format, Claude Code sends the full set, even if your gateway forwards to a Bedrock or Vertex upstream62* When the client speaks the Anthropic Messages format, Claude Code sends the full set, even if your gateway forwards to a Bedrock or Agent Platform upstream

61 63 

62Bridging that difference is your gateway's job. [Feature pass-through](#feature-pass-through) describes what breaks when it doesn't.64Bridging that difference is your gateway's job. [Feature pass-through](#feature-pass-through) describes what breaks when it doesn't.

63 65 


66Claude Code includes these headers on API requests. Header names are case-insensitive on the wire. Forward `anthropic-version` and `anthropic-beta` unchanged, plus `anthropic-workspace-id` when the upstream is the [Claude Platform on AWS](/en/claude-platform-on-aws); the rest the gateway may consume for routing, attribution, and tracing, and need not forward.68Claude Code includes these headers on API requests. Header names are case-insensitive on the wire. Forward `anthropic-version` and `anthropic-beta` unchanged, plus `anthropic-workspace-id` when the upstream is the [Claude Platform on AWS](/en/claude-platform-on-aws); the rest the gateway may consume for routing, attribution, and tracing, and need not forward.

67 69 

68| Header | Description |70| Header | Description |

69| :------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |71| :------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

70| `Authorization`, `x-api-key` | The developer's gateway credential, in one or both headers depending on which [credential variable](/en/llm-gateway-connect#set-the-credential-variable) they set |72| `Authorization`, `x-api-key` | The developer's gateway credential, in one or both headers depending on which [credential variable](/en/llm-gateway-connect#set-the-credential-variable) they set |

71| `anthropic-version` | API version, currently `2023-06-01`. Bedrock- and Vertex-format requests also carry the `anthropic_version` body field, whose value is the provider dialect string, not this header's value |73| `anthropic-version` | API version, currently `2023-06-01`. Bedrock- and Agent Platform-format requests also carry the `anthropic_version` body field, whose value is the provider dialect string, not this header's value |

72| `anthropic-beta` | Comma-separated capability values for the request. Forward the header verbatim; do not allowlist individual values, because the set changes with Claude Code releases. When the developer authenticates with a claude.ai login, which is possible when `ANTHROPIC_BASE_URL` is set without a gateway credential variable, this header also carries an OAuth capability that the upstream requires, and stripping it fails those requests with `401` |74| `anthropic-beta` | Comma-separated capability values for the request. Forward the header verbatim; don't allowlist individual values, because the set changes with Claude Code releases. When the developer authenticates with a claude.ai login, which is possible when `ANTHROPIC_BASE_URL` is set without a gateway credential variable, this header also carries an OAuth capability that the upstream requires, and stripping it fails those requests with `401` |

73| `x-claude-code-session-id` | A unique identifier for the current Claude Code session. Use it to aggregate all requests from one session without parsing request bodies |75| `x-claude-code-session-id` | A unique identifier for the current Claude Code session. Use it to aggregate all requests from one session without parsing request bodies |

74| `x-claude-code-agent-id` | Identifier of the [subagent](/en/sub-agents) that issued the request, present only on requests from an agent Claude Code spawned inside the session. Use it with the session ID to attribute cost to parallel agents |76| `x-claude-code-agent-id` | Identifier of the [subagent](/en/sub-agents) that issued the request, present only on requests from an agent Claude Code spawned inside the session. Use it with the session ID to attribute cost to parallel agents |

75| `x-claude-code-parent-agent-id` | Identifier of the agent that spawned the requesting agent, present only for nested agents |77| `x-claude-code-parent-agent-id` | Identifier of the agent that spawned the requesting agent, present only for nested agents |

76 78 

77Subagent IDs are generated fresh for each spawn. Teammate agents, the named members of an [agent team](/en/agent-teams), reuse a stable name-based ID across reconnections. In both cases the ID identifies an agent, not a person or a device, so do not treat the agent ID header as a user identifier.79Subagent IDs are generated fresh for each spawn. Teammate agents, the named members of an [agent team](/en/agent-teams), reuse a stable name-based ID across reconnections. In both cases the ID identifies an agent, not a person or a device, so don't treat the agent ID header as a user identifier.

78 80 

79If your developers set `ANTHROPIC_CUSTOM_HEADERS`, those headers appear on requests as well.81If your developers set `ANTHROPIC_CUSTOM_HEADERS`, those headers appear on requests as well.

80 82 


84 86 

85When forwarding to an Anthropic-format upstream, pass `anthropic-*` request headers and request body fields through unchanged rather than allowlisting the ones you see today. A gateway pinned to an observed list strips the next capability's header or field and breaks it on the release that introduces it.87When forwarding to an Anthropic-format upstream, pass `anthropic-*` request headers and request body fields through unchanged rather than allowlisting the ones you see today. A gateway pinned to an observed list strips the next capability's header or field and breaks it on the release that introduces it.

86 88 

87The exception is a non-Anthropic upstream such as Bedrock or Vertex, where bridging the schema difference is the gateway's job; see [feature pass-through](#feature-pass-through).89The exception is a non-Anthropic upstream such as Bedrock or Agent Platform, where bridging the schema difference is the gateway's job; see [feature pass-through](#feature-pass-through).

88 90 

89## System prompt attribution block91## System prompt attribution block

90 92 

91Claude Code prepends a short attribution block to the system prompt containing the client version and a fingerprint derived from the conversation. The `api.anthropic.com` endpoint strips the block before processing, so it does not affect first-party prompt caching; any other upstream receives it as part of the prompt. Anthropic and the cloud providers' Claude endpoints read it for attribution, so to omit it set [`CLAUDE_CODE_ATTRIBUTION_HEADER=0`](/en/env-vars) rather than stripping it in the gateway.93Claude Code prepends a short attribution block to the system prompt containing the client version and a fingerprint derived from the conversation. The `api.anthropic.com` endpoint strips the block before processing, so it doesn't affect first-party prompt caching; any other upstream receives it as part of the prompt. Anthropic and the cloud providers' Claude endpoints read it for attribution, so to omit it set [`CLAUDE_CODE_ATTRIBUTION_HEADER=0`](/en/env-vars) rather than stripping it in the gateway.

92 94 

93{/* min-version: 2.1.181 */}From Claude Code v2.1.181, the block is stable for the lifetime of a conversation when requests route through a custom base URL, so a gateway-side prompt cache keyed on the full request body works without disabling it. Before v2.1.181 the block included a per-request token; on those versions, set `CLAUDE_CODE_ATTRIBUTION_HEADER=0` if your gateway implements such a cache.95{/* min-version: 2.1.181 */}From Claude Code v2.1.181, the block is stable for the lifetime of a conversation when requests route through a custom base URL, so a gateway-side prompt cache keyed on the full request body works without disabling it. Before v2.1.181 the block included a per-request token; on those versions, set `CLAUDE_CODE_ATTRIBUTION_HEADER=0` if your gateway implements such a cache.

94 96 

95## Feature pass-through97## Feature pass-through

96 98 

97Claude Code treats an `ANTHROPIC_BASE_URL` gateway as an Anthropic-format endpoint and sends it the beta headers and request body fields it sends to `api.anthropic.com`, except a small set of diagnostics and defaults reserved for direct connections.99Claude Code treats an `ANTHROPIC_BASE_URL` gateway as an Anthropic-format endpoint and sends it the beta headers and request body fields it sends to `api.anthropic.com`, except a small set of diagnostics and defaults reserved for direct connections, such as the fine-grained tool streaming default covered below. That set varies by release, so don't depend on its contents.

98 100 

99Capabilities that add body fields pair them with a beta header, and the pair travels together. A gateway that strips the header while passing the body, or forwards an Anthropic-format body to an upstream with a different schema, produces hard `400` errors; only when both halves are absent together does the feature turn off quietly. A gateway that rewrites or redacts request bodies for content inspection breaks the pairing the same way stripping does, so inspect without modifying. The table notes where a feature deviates from the pairing.101Capabilities that add body fields pair them with a beta header, and the pair travels together. A gateway that strips the header while passing the body, or forwards an Anthropic-format body to an upstream with a different schema, produces hard `400` errors; only when both halves are absent together does the feature turn off quietly. A gateway that rewrites or redacts request bodies for content inspection breaks the pairing the same way stripping does, so inspect without modifying. The table notes where a feature deviates from the pairing.

100 102 


106| [Context management](https://platform.claude.com/docs/en/build-with-claude/context-management) | Context management beta header pairs with the `context_management` body field | `400` with `Extra inputs are not permitted`. Common when a gateway accepts Anthropic-format requests but forwards them to Bedrock | Forward both, or [`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1`](/en/env-vars) |108| [Context management](https://platform.claude.com/docs/en/build-with-claude/context-management) | Context management beta header pairs with the `context_management` body field | `400` with `Extra inputs are not permitted`. Common when a gateway accepts Anthropic-format requests but forwards them to Bedrock | Forward both, or [`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1`](/en/env-vars) |

107| [Extended context](https://platform.claude.com/docs/en/build-with-claude/context-windows#1m-token-context-window) and [interleaved thinking](https://platform.claude.com/docs/en/build-with-claude/extended-thinking#interleaved-thinking) | Beta headers only, no body field | Silently unavailable when the header is stripped; the upstream never sees the capability request | Forward `anthropic-beta` verbatim |109| [Extended context](https://platform.claude.com/docs/en/build-with-claude/context-windows#1m-token-context-window) and [interleaved thinking](https://platform.claude.com/docs/en/build-with-claude/extended-thinking#interleaved-thinking) | Beta headers only, no body field | Silently unavailable when the header is stripped; the upstream never sees the capability request | Forward `anthropic-beta` verbatim |

108| Beta [tool fields](https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview) | Tool-related beta headers pair with tool schema fields such as `strict` and `defer_loading` | `400` naming the unrecognized tool schema field when the body passes through without its header | Forward both, or `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1` |110| Beta [tool fields](https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview) | Tool-related beta headers pair with tool schema fields such as `strict` and `defer_loading` | `400` naming the unrecognized tool schema field when the body passes through without its header | Forward both, or `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1` |

109| [Effort](https://platform.claude.com/docs/en/build-with-claude/effort) and [structured outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs) | The `output_config` body field carries effort, structured-output format, and task budget settings; each pairs with its own beta header | `400` naming `output_config`, often `Extra inputs are not permitted`, on Bedrock and Vertex upstreams | Forward the field and its headers together |111| [Effort](https://platform.claude.com/docs/en/build-with-claude/effort) and [structured outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs) | The `output_config` body field carries effort, structured-output format, and task budget settings; each pairs with its own beta header | `400` naming `output_config`, often `Extra inputs are not permitted`, on Bedrock and Agent Platform upstreams | Forward the field and its headers together |

110| [Token counting](https://platform.claude.com/docs/en/build-with-claude/token-counting) | No beta pairing; uses the `count_tokens` endpoint | Claude Code falls back to estimating context usage locally | Expose the endpoint if you want exact counts |112| [Token counting](https://platform.claude.com/docs/en/build-with-claude/token-counting) | No beta pairing; uses the `count_tokens` endpoint | Claude Code falls back to estimating context usage locally | Expose the endpoint if you want exact counts |

111 113 

112The `ANTHROPIC_DEFAULT_*_MODEL_SUPPORTED_CAPABILITIES` [variables](/en/model-config) declare model capabilities only in the provider configurations: `CLAUDE_CODE_USE_BEDROCK`, `CLAUDE_CODE_USE_VERTEX`, `CLAUDE_CODE_USE_FOUNDRY`, and [`CLAUDE_CODE_USE_MANTLE`](/en/amazon-bedrock#use-the-mantle-endpoint). They have no effect behind an `ANTHROPIC_BASE_URL` gateway.114The `ANTHROPIC_DEFAULT_*_MODEL_SUPPORTED_CAPABILITIES` [variables](/en/model-config) declare model capabilities only in the provider configurations: `CLAUDE_CODE_USE_BEDROCK`, `CLAUDE_CODE_USE_VERTEX`, `CLAUDE_CODE_USE_FOUNDRY`, and [`CLAUDE_CODE_USE_MANTLE`](/en/amazon-bedrock#use-the-mantle-endpoint). They have no effect behind an `ANTHROPIC_BASE_URL` gateway.

113 115 

114### Automatic retry and error forwarding116### Automatic retry and error forwarding

115 117 

116Claude Code retries automatically after some upstream rejections and disables the rejected capability for the rest of the conversation. Rejections of the `thinking` field, of [thinking signatures](https://platform.claude.com/docs/en/build-with-claude/extended-thinking), and of mid-conversation system messages all recover this way. Context management and tool schema field rejections do not retry; those `400` errors reach the developer.118Claude Code retries automatically after some upstream rejections and disables the rejected capability for the rest of the conversation. Rejections of the `thinking` field, of [thinking signatures](https://platform.claude.com/docs/en/build-with-claude/extended-thinking), and of mid-conversation system messages all recover this way. Context management and tool schema field rejections don't retry; those `400` errors reach the developer.

117 119 

118The retry logic matches on the upstream's error wording, so forward error response bodies unmodified. A gateway that wraps upstream errors in its own envelope breaks the recovery path even when it preserves the status code.120The retry logic matches on the upstream's error wording, so forward error response bodies unmodified. A gateway that wraps upstream errors in its own envelope breaks the recovery path even when it preserves the status code.

119 121 

120### Disable pre-release capabilities122### Disable pre-release capabilities

121 123 

122`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1` stops Claude Code from sending pre-release capabilities and their body fields on every provider, including context management and the beta tool fields. It does not affect adaptive reasoning, which is selected by model rather than by beta, and it never suppresses the OAuth capability that subscription authentication requires.124`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1` stops Claude Code from sending pre-release capabilities and their body fields on every provider, including context management and the beta tool fields. It doesn't affect adaptive reasoning, which is selected by model rather than by beta, and it never suppresses the OAuth capability that subscription authentication requires.

123 125 

124The set of capabilities Claude Code sends grows over releases. For current beta header strings, see the [beta headers reference](https://platform.claude.com/docs/en/api/beta-headers); test your gateway against new Claude Code releases rather than pinning to an observed list.126The set of capabilities Claude Code sends grows over releases. For current beta header strings, see the [beta headers reference](https://platform.claude.com/docs/en/api/beta-headers); test your gateway against new Claude Code releases rather than pinning to an observed list.

125 127 


127 129 

128When `ANTHROPIC_BASE_URL` points at a gateway that exposes the Anthropic Messages format, Claude Code can query the gateway's `/v1/models` endpoint at startup and add the returned models to the `/model` picker.130When `ANTHROPIC_BASE_URL` points at a gateway that exposes the Anthropic Messages format, Claude Code can query the gateway's `/v1/models` endpoint at startup and add the returned models to the `/model` picker.

129 131 

130Developers enable it by setting [`CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1`](/en/env-vars), in their own environment or through managed settings. Discovery is off by default so that gateways backed by a shared API key do not surface every model the key can access to every user. This requires Claude Code v2.1.129 or later.132Developers enable it by setting [`CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1`](/en/env-vars), in their own environment or through managed settings. Discovery is off by default so that gateways backed by a shared API key don't surface every model the key can access to every user. This requires Claude Code v2.1.129 or later.

131 133 

132### When discovery runs134### When discovery runs

133 135 

134Discovery applies only to the Anthropic Messages format. It does not run when:136Discovery applies only to the Anthropic Messages format. It doesn't run when:

135 137 

136* Any `CLAUDE_CODE_USE_*` provider variable is set, even if `ANTHROPIC_BASE_URL` is also set138* Any `CLAUDE_CODE_USE_*` provider variable is set, even if `ANTHROPIC_BASE_URL` is also set

137* `ANTHROPIC_BASE_URL` is unset or points at `api.anthropic.com`139* `ANTHROPIC_BASE_URL` is unset or points at `api.anthropic.com`


139 141 

140### Request and response142### Request and response

141 143 

142The request is `GET /v1/models?limit=1000` with a 3-second timeout, and any redirect is treated as failure so the credential cannot leak to a redirect target. A gateway that responds slowly or redirects `/v1/models`, even `http` to `https`, fails discovery silently; serve the endpoint directly at the configured base URL.144The request is `GET /v1/models?limit=1000` with a 3-second timeout, and any redirect is treated as failure so the credential can't leak to a redirect target. A gateway that responds slowly or redirects `/v1/models`, even `http` to `https`, fails discovery silently; serve the endpoint directly at the configured base URL.

143 145 

144The discovery request sends exactly one credential header:146The discovery request sends exactly one credential header:

145 147 


161 163 

162### Picker entries and caching164### Picker entries and caching

163 165 

164The picker is the interactive model list that opens when a developer runs `/model` in Claude Code. Each discovered entry is labeled "From gateway" and uses `display_name` when provided. A discovered ID is skipped only when it exactly matches a row already in the picker, or when both the discovered and existing IDs resolve to [Fable](/en/model-config#work-with-fable-5). Built-in rows are keyed on aliases such as `sonnet`, so a discovered ID such as `claude-sonnet-4-6` adds its own "From gateway" row alongside the built-in entry. The [`availableModels` managed setting](/en/settings#available-settings) bounds what discovery can add.166The picker is the interactive model list that opens when a developer runs `/model` in Claude Code. Each discovered entry is labeled "From gateway" and uses `display_name` when provided. The [`availableModels` managed setting](/en/settings#available-settings) bounds what discovery can add.

167 

168A discovered ID is skipped only when it exactly matches a row already in the picker, or when both the discovered and existing IDs resolve to [Fable](/en/model-config#work-with-fable-5). Built-in rows are keyed on aliases such as `sonnet`, so a discovered ID such as `claude-sonnet-4-6` adds its own "From gateway" row alongside the built-in entry rather than replacing it.

165 169 

166Results are cached to `~/.claude/cache/gateway-models.json`, or `%USERPROFILE%\.claude\cache\gateway-models.json` on Windows, and refreshed on each startup. If the request fails or the gateway does not implement `/v1/models`, the picker falls back to the cached list from the previous startup or to the built-in model list. If your gateway serves Claude models under aliases that don't match the discovery filter, developers can add those aliases manually with the [model configuration](/en/model-config) variables.170Results are cached to `~/.claude/cache/gateway-models.json`, or `%USERPROFILE%\.claude\cache\gateway-models.json` on Windows, and refreshed on each startup. If the request fails or the gateway doesn't implement `/v1/models`, the picker falls back to the cached list from the previous startup or to the built-in model list. If your gateway serves Claude models under aliases that don't match the discovery filter, developers can add those aliases manually with the [model configuration](/en/model-config) variables.

167 171 

168## Related resources172## Related resources

169 173 

170For the rest of the gateway documentation set and the underlying API references:174For the rest of the gateway documentation set and the underlying API references:

171 175 

172* [LLM gateways overview](/en/llm-gateway): what a gateway is and how it interacts with claude.ai subscriptions176* [Gateway overview](/en/gateways): what a gateway is and how to choose between Claude apps gateway and another product

177* [Other LLM gateways](/en/llm-gateway): how to roll out a gateway your organization runs and how it interacts with claude.ai subscriptions

173* [Roll out an LLM gateway for your organization](/en/llm-gateway-rollout): the admin checklist that uses this contract178* [Roll out an LLM gateway for your organization](/en/llm-gateway-rollout): the admin checklist that uses this contract

174* [Connect Claude Code to an LLM gateway](/en/llm-gateway-connect): per-developer configuration and the troubleshooting table179* [Connect Claude Code to an LLM gateway](/en/llm-gateway-connect): per-developer configuration and the troubleshooting table

175* [Beta headers reference](https://platform.claude.com/docs/en/api/beta-headers): the current set of `anthropic-beta` values180* [Beta headers reference](https://platform.claude.com/docs/en/api/beta-headers): the current set of `anthropic-beta` values

Details

20* A gateway deployed on your infrastructure, serving HTTPS at the exact address you'll distribute to developers, not an address that redirects to it, and configured to route Claude model names to your provider20* A gateway deployed on your infrastructure, serving HTTPS at the exact address you'll distribute to developers, not an address that redirects to it, and configured to route Claude model names to your provider

21* A provider credential for the gateway to forward with:21* A provider credential for the gateway to forward with:

22 * For the Anthropic API: an API key from the [Claude Console](https://platform.claude.com/settings/keys)22 * For the Anthropic API: an API key from the [Claude Console](https://platform.claude.com/settings/keys)

23 * For a cloud provider: cloud credentials with model access. See the prerequisites on the [Amazon Bedrock](/en/amazon-bedrock#prerequisites), [Google Vertex AI](/en/google-vertex-ai#prerequisites), or [Microsoft Foundry](/en/microsoft-foundry#prerequisites) page23 * For a cloud provider: cloud credentials with model access. See the prerequisites on the [Amazon Bedrock](/en/amazon-bedrock#prerequisites), [Google Cloud's Agent Platform](/en/google-vertex-ai#prerequisites), or [Microsoft Foundry](/en/microsoft-foundry#prerequisites) page

24* A way to deliver settings files to developer machines, such as MDM or configuration management24* A way to deliver settings files to developer machines, such as MDM or configuration management

25 * If you don't have one yet, [how settings reach devices](/en/admin-setup#decide-how-settings-reach-devices) compares the options25 * If you don't have one yet, [how settings reach devices](/en/admin-setup#decide-how-settings-reach-devices) compares the options

26 26 


164The same set of variables applies whichever path you choose. Most rollouts only need `ANTHROPIC_BASE_URL` and a credential; include the conditional rows when your gateway setup calls for them.164The same set of variables applies whichever path you choose. Most rollouts only need `ANTHROPIC_BASE_URL` and a credential; include the conditional rows when your gateway setup calls for them.

165 165 

166| Variable or setting | What it does | Include when |166| Variable or setting | What it does | Include when |

167| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |167| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

168| `ANTHROPIC_BASE_URL` | Sends Claude Code's API requests to the gateway instead of `api.anthropic.com` | Always |168| `ANTHROPIC_BASE_URL` | Sends Claude Code's API requests to the gateway instead of `api.anthropic.com` | Always |

169| `apiKeyHelper`, or a credential in `ANTHROPIC_AUTH_TOKEN` or `ANTHROPIC_API_KEY` | Authenticates each request to the gateway. The helper runs a command to fetch the key; the variables hold a static key, sent as `Authorization: Bearer` and `x-api-key` respectively | Always; one of the three |169| `apiKeyHelper`, or a credential in `ANTHROPIC_AUTH_TOKEN` or `ANTHROPIC_API_KEY` | Authenticates each request to the gateway. The helper runs a command to fetch the key; the variables hold a static key, sent as `Authorization: Bearer` and `x-api-key` respectively | Always; one of the three |

170| `ANTHROPIC_CUSTOM_HEADERS` | Adds extra HTTP headers to every API request | Your gateway requires a tenant or routing header on every request |170| `ANTHROPIC_CUSTOM_HEADERS` | Adds extra HTTP headers to every API request | Your gateway requires a tenant or routing header on every request |

171| `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY` | Queries the gateway's `/v1/models` at startup and adds the returned names to the `/model` picker | Your gateway serves `/v1/models` and you want developers' pickers populated from it |171| `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY` | Queries the gateway's `/v1/models` at startup and adds the returned names to the `/model` picker | Your gateway serves `/v1/models` and you want developers' pickers populated from it |

172| `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS` | Stops Claude Code sending pre-release capability headers and body fields | Your gateway forwards to a Bedrock or Vertex upstream that rejects beta fields; see [Gateway requirements](#gateway-requirements) |172| `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS` | Stops Claude Code sending pre-release capability headers and body fields | Your gateway forwards to a Bedrock or Agent Platform upstream that rejects beta fields; see [Gateway requirements](#gateway-requirements) |

173| `ANTHROPIC_MODEL` or [`ANTHROPIC_DEFAULT_HAIKU_MODEL`](/en/model-config) | Set which model name Claude Code requests for the main session and for background traffic | Your gateway routes model names that don't match Claude Code's defaults, or you route [background functionality](/en/costs#background-token-usage) to a different model. Route both the override names and Claude Code's default names at the gateway, since some sub-calls can request the default name regardless of the override |173| `ANTHROPIC_MODEL` or [`ANTHROPIC_DEFAULT_HAIKU_MODEL`](/en/model-config) | Set which model name Claude Code requests for the main session and for background traffic | Your gateway routes model names that don't match Claude Code's defaults, or you route [background functionality](/en/costs#background-token-usage) to a different model. Route both the override names and the built-in model IDs Claude Code requests when no override is set, since some background sub-calls request a built-in ID regardless of the override; [model configuration](/en/model-config) covers which model each part of a session uses |

174| `ANTHROPIC_BEDROCK_BASE_URL`, `ANTHROPIC_VERTEX_BASE_URL`, `ANTHROPIC_FOUNDRY_BASE_URL`, or `ANTHROPIC_AWS_BASE_URL` with the [variables for that provider](/en/llm-gateway-connect#route-to-a-cloud-provider-through-a-gateway) | Point Claude Code at the gateway through a provider-specific base URL. Bedrock and Vertex also switch to those providers' native request format | Your gateway fronts Bedrock, Vertex, Foundry, or the Claude Platform on AWS; see [API formats](/en/llm-gateway-protocol#api-formats) |174| `ANTHROPIC_BEDROCK_BASE_URL`, `ANTHROPIC_VERTEX_BASE_URL`, `ANTHROPIC_FOUNDRY_BASE_URL`, or `ANTHROPIC_AWS_BASE_URL` with the [variables for that provider](/en/llm-gateway-connect#route-to-a-cloud-provider-through-a-gateway) | Point Claude Code at the gateway through a provider-specific base URL. Bedrock and Agent Platform also switch to those providers' native request format | Your gateway fronts Bedrock, Agent Platform, Foundry, or the Claude Platform on AWS; see [API formats](/en/llm-gateway-protocol#api-formats) |

175 175 

176#### Distribute through managed settings176#### Distribute through managed settings

177 177 


188 188 

189Add the conditional variables from the table to the same `env` block. A managed `ANTHROPIC_BASE_URL` is enforced and cannot be overridden by a developer's shell export, since Claude Code applies it over the process environment and lower-precedence settings.189Add the conditional variables from the table to the same `env` block. A managed `ANTHROPIC_BASE_URL` is enforced and cannot be overridden by a developer's shell export, since Claude Code applies it over the process environment and lower-precedence settings.

190 190 

191Do not include `forceLoginMethod` or `forceLoginOrgUUID` in managed settings alongside a gateway credential. On Claude Code v2.1.146 and later, either key blocks `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, and `apiKeyHelper` at startup, so developers see `This machine's managed settings require a first-party login` and cannot proceed. {/* min-version: 2.1.146 */}191Do not include `forceLoginMethod` or `forceLoginOrgUUID` in managed settings alongside a gateway credential. On Claude Code v2.1.146 and later, either key, with any value, blocks `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, and `apiKeyHelper` at startup, so developers see `This machine's managed settings require a first-party login` and cannot proceed. {/* min-version: 2.1.146 */}

192 192 

193[Server-managed settings](/en/server-managed-settings#platform-availability) delivery requires a direct connection to `api.anthropic.com`, so it does not reach gateway-routed sessions. Gateway deployments use this file-based managed settings path, which enforces the same keys.193[Server-managed settings](/en/server-managed-settings#platform-availability) delivery requires a direct connection to `api.anthropic.com`, so it does not reach gateway-routed sessions. Gateway deployments use this file-based managed settings path, which enforces the same keys.

194 194 

Details

402| `terminal.type` | Terminal type, such as `iTerm.app`, `vscode`, `cursor`, or `tmux` | Always included when detected |402| `terminal.type` | Terminal type, such as `iTerm.app`, `vscode`, `cursor`, or `tmux` | Always included when detected |

403| Keys from `OTEL_RESOURCE_ATTRIBUTES` | Custom attributes you set, such as `department` or `team.id`. See [Multi-team organization support](#multi-team-organization-support) | `OTEL_METRICS_INCLUDE_RESOURCE_ATTRIBUTES` (default: true) |403| Keys from `OTEL_RESOURCE_ATTRIBUTES` | Custom attributes you set, such as `department` or `team.id`. See [Multi-team organization support](#multi-team-organization-support) | `OTEL_METRICS_INCLUDE_RESOURCE_ATTRIBUTES` (default: true) |

404 404 

405When Claude Code is signed in to a [Claude apps gateway](/en/claude-apps-gateway), the CLI stamps exports with the authenticated identity from the gateway session: `user.id` is the IdP subject rather than an anonymous installation identifier, `user.email` is the signed-in email, and `user.groups` carries IdP group membership as a comma-separated string. Each export also carries `identity.source: gateway-oidc`. The gateway identity is applied last, so `user.*` and `identity.*` keys set through `OTEL_RESOURCE_ATTRIBUTES` are ignored on gateway sessions.

406 

405Events additionally include the following attributes. These are never attached to metrics because they would cause unbounded cardinality:407Events additionally include the following attributes. These are never attached to metrics because they would cause unbounded cardinality:

406 408 

407* `prompt.id`: UUID correlating a user prompt with all subsequent events until the next prompt. See [Event correlation attributes](#event-correlation-attributes).409* `prompt.id`: UUID correlating a user prompt with all subsequent events until the next prompt. See [Event correlation attributes](#event-correlation-attributes).


1072 1074 

1073### Attribute actions to users1075### Attribute actions to users

1074 1076 

1075The [standard attributes](#standard-attributes) on each event include the authenticated user's identity: `user.email`, `user.account_uuid`, `user.account_id`, and `organization.id` when signed in with a Claude account, plus the installation-scoped `user.id` and the per-session `session.id`.1077The [standard attributes](#standard-attributes) on each event include the authenticated user's identity: `user.email`, `user.account_uuid`, `user.account_id`, and `organization.id` when signed in with a Claude account, plus `user.id` and the per-session `session.id`. `user.id` is an installation-scoped identifier, except on [Claude apps gateway](/en/claude-apps-gateway) sessions, where it is the IdP subject from the gateway-issued token.

1076 1078 

1077MCP tool calls, Bash commands, and file edits are therefore attributed to the developer who started the session. Claude Code doesn't act under a separate service account; the identity recorded on each event is the developer's own Claude account.1079MCP tool calls, Bash commands, and file edits are therefore attributed to the developer who started the session. Claude Code doesn't act under a separate service account; the identity recorded on each event is the developer's own Claude account, or the developer's IdP identity on a [Claude apps gateway](/en/claude-apps-gateway) session.

1078 1080 

1079When Claude Code authenticates with a direct API key, or against Bedrock, Vertex AI, or Microsoft Foundry, there is no Claude account in the session and only `user.id` and `session.id` are populated. In these deployments, attach user identity yourself with `OTEL_RESOURCE_ATTRIBUTES`, set per user through the [managed settings](#administrator-configuration) file or a launch wrapper:1081When Claude Code authenticates with a direct API key, or against Bedrock, Vertex AI, or Microsoft Foundry, there is no Claude account in the session and only `user.id` and `session.id` are populated. In these deployments, attach user identity yourself with `OTEL_RESOURCE_ATTRIBUTES`, set per user through the [managed settings](#administrator-configuration) file or a launch wrapper. Claude apps gateway sessions need none of this: the CLI stamps the IdP identity automatically, as described in [Standard attributes](#standard-attributes).

1080 1082 

1081```bash theme={null}1083```bash theme={null}

1082export OTEL_RESOURCE_ATTRIBUTES="enduser.id=jdoe@example.com,enduser.directory_id=S-1-5-21-..."1084export OTEL_RESOURCE_ATTRIBUTES="enduser.id=jdoe@example.com,enduser.directory_id=S-1-5-21-..."

Details

55 55 

56## CA certificate store56## CA certificate store

57 57 

58By default, Claude Code trusts both its bundled Mozilla CA certificates and your operating system's certificate store. Enterprise TLS-inspection proxies such as CrowdStrike Falcon and Zscaler work without additional configuration when their root certificate is installed in the OS trust store.58By default, Claude Code trusts both its bundled Mozilla CA certificates and your operating system's certificate store. Reading the OS store requires a runtime with `tls.getCACertificates`: the native installer always has it, and npm installs need Node 22.15 or later. On older Node versions, only the bundled set and `NODE_EXTRA_CA_CERTS` apply. Enterprise TLS-inspection proxies such as CrowdStrike Falcon and Zscaler work without additional configuration when their root certificate is installed in the OS trust store and the runtime can read it.

59 59 

60`CLAUDE_CODE_CERT_STORE` accepts a comma-separated list of sources. Recognized values are `bundled` for the Mozilla CA set shipped with Claude Code and `system` for the operating system trust store. The default is `bundled,system`.60`CLAUDE_CODE_CERT_STORE` accepts a comma-separated list of sources. Recognized values are `bundled` for the Mozilla CA set shipped with Claude Code and `system` for the operating system trust store. The default is `bundled,system`.

61 61 


117 117 

118Claude Code also sends optional operational telemetry by default, which you can disable with environment variables. See [Telemetry services](/en/data-usage#telemetry-services) for how to disable it before finalizing your allowlist.118Claude Code also sends optional operational telemetry by default, which you can disable with environment variables. See [Telemetry services](/en/data-usage#telemetry-services) for how to disable it before finalizing your allowlist.

119 119 

120When using [Amazon Bedrock](/en/amazon-bedrock), [Google Vertex AI](/en/google-vertex-ai), or [Microsoft Foundry](/en/microsoft-foundry), model traffic and authentication go to your provider instead of `api.anthropic.com`, `claude.ai`, or `platform.claude.com`. The WebFetch tool still calls `api.anthropic.com` for its [domain safety check](/en/data-usage#webfetch-domain-safety-check) unless you set `skipWebFetchPreflight: true` in [settings](/en/settings).120When using [Amazon Bedrock](/en/amazon-bedrock), [Google Vertex AI](/en/google-vertex-ai), [Microsoft Foundry](/en/microsoft-foundry), or a signed-in [Claude apps gateway](/en/claude-apps-gateway) session, model traffic and authentication go to your provider or gateway instead of `api.anthropic.com`, `claude.ai`, or `platform.claude.com`. The WebFetch tool still calls `api.anthropic.com` for its [domain safety check](/en/data-usage#webfetch-domain-safety-check) unless you set `skipWebFetchPreflight: true` in [settings](/en/settings).

121 121 

122[Claude Code on the web](/en/claude-code-on-the-web) and [Code Review](/en/code-review) connect to your repositories from Anthropic-managed infrastructure. If your GitHub Enterprise Cloud organization restricts access by IP address, enable [IP allow list inheritance for installed GitHub Apps](https://docs.github.com/en/enterprise-cloud@latest/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/managing-allowed-ip-addresses-for-your-organization#allowing-access-by-github-apps). The Claude GitHub App registers its IP ranges, so enabling this setting allows access without manual configuration. To [add the ranges to your allow list manually](https://docs.github.com/en/enterprise-cloud@latest/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/managing-allowed-ip-addresses-for-your-organization#adding-an-allowed-ip-address) instead, or to configure other firewalls, see the [Anthropic API IP addresses](https://platform.claude.com/docs/en/api/ip-addresses).122[Claude Code on the web](/en/claude-code-on-the-web) and [Code Review](/en/code-review) connect to your repositories from Anthropic-managed infrastructure. If your GitHub Enterprise Cloud organization restricts access by IP address, enable [IP allow list inheritance for installed GitHub Apps](https://docs.github.com/en/enterprise-cloud@latest/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/managing-allowed-ip-addresses-for-your-organization#allowing-access-by-github-apps). The Claude GitHub App registers its IP ranges, so enabling this setting allows access without manual configuration. To [add the ranges to your allow list manually](https://docs.github.com/en/enterprise-cloud@latest/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/managing-allowed-ip-addresses-for-your-organization#adding-an-allowed-ip-address) instead, or to configure other firewalls, see the [Anthropic API IP addresses](https://platform.claude.com/docs/en/api/ip-addresses).

123 123 

Details

176 176 

177* **Plan**: All plans.177* **Plan**: All plans.

178* **Owner**: on Team and Enterprise, an Owner must enable it in [Claude Code admin settings](https://claude.ai/admin-settings/claude-code) before users can turn it on. Administrators can also lock it off by setting `permissions.disableAutoMode` to `"disable"` in [managed settings](/en/permissions#managed-settings).178* **Owner**: on Team and Enterprise, an Owner must enable it in [Claude Code admin settings](https://claude.ai/admin-settings/claude-code) before users can turn it on. Administrators can also lock it off by setting `permissions.disableAutoMode` to `"disable"` in [managed settings](/en/permissions#managed-settings).

179* **Model**: on the Anthropic API, Claude Opus 4.6 or later, or Sonnet 4.6. On Amazon Bedrock, Google Cloud Vertex AI, and Microsoft Foundry, only Claude Opus 4.7 and Opus 4.8. Older models, including Sonnet 4.5, Opus 4.5, Haiku, and claude-3 models, are not supported on any provider.179* **Model**: on the Anthropic API, Claude Opus 4.6 or later, or Sonnet 4.6. On Amazon Bedrock, Google Cloud Vertex AI, Microsoft Foundry, and signed-in [Claude apps gateway](/en/claude-apps-gateway) sessions, only Claude Opus 4.7 and Opus 4.8. Older models, including Sonnet 4.5, Opus 4.5, Haiku, and claude-3 models, are not supported on any provider.

180* **Provider**: available by default on the Anthropic API. On Amazon Bedrock, Google Cloud Vertex AI, and Microsoft Foundry, auto mode is off until you [set `CLAUDE_CODE_ENABLE_AUTO_MODE`](#enable-auto-mode-on-bedrock-vertex-ai-or-foundry).180* **Provider**: available by default on the Anthropic API. On Amazon Bedrock, Google Cloud Vertex AI, Microsoft Foundry, and signed-in Claude apps gateway sessions, auto mode is off until you [set `CLAUDE_CODE_ENABLE_AUTO_MODE`](#enable-auto-mode-on-bedrock-vertex-ai-or-foundry).

181 181 

182If Claude Code reports auto mode as unavailable, one of these requirements is unmet; this is not a transient outage. A separate message that names a model and says auto mode "cannot determine the safety" of an action is a transient classifier outage; see the [error reference](/en/errors#auto-mode-cannot-determine-the-safety-of-an-action).182If Claude Code reports auto mode as unavailable, one of these requirements is unmet; this is not a transient outage. A separate message that names a model and says auto mode "cannot determine the safety" of an action is a transient classifier outage; see the [error reference](/en/errors#auto-mode-cannot-determine-the-safety-of-an-action).

183 183 


185 185 

186### Enable auto mode on Bedrock, Vertex AI, or Foundry186### Enable auto mode on Bedrock, Vertex AI, or Foundry

187 187 

188On [Amazon Bedrock](/en/amazon-bedrock), [Google Cloud Vertex AI](/en/google-vertex-ai), and [Microsoft Foundry](/en/microsoft-foundry), auto mode does not appear in the `Shift+Tab` cycle until `CLAUDE_CODE_ENABLE_AUTO_MODE` is set to `1`. The variable works in Claude Code v2.1.158 and later. Only Claude Opus 4.7 and Opus 4.8 are supported on these providers.188On [Amazon Bedrock](/en/amazon-bedrock), [Google Cloud Vertex AI](/en/google-vertex-ai), [Microsoft Foundry](/en/microsoft-foundry), and signed-in [Claude apps gateway](/en/claude-apps-gateway) sessions, auto mode does not appear in the `Shift+Tab` cycle until `CLAUDE_CODE_ENABLE_AUTO_MODE` is set to `1`. The variable works in Claude Code v2.1.158 and later. Only Claude Opus 4.7 and Opus 4.8 are supported on these providers.

189 189 

190To enable it for one developer, add the variable to the `env` block in `~/.claude/settings.json`:190To enable it for one developer, add the variable to the `env` block in `~/.claude/settings.json`:

191 191 


203 203 

204To prevent developers from enabling auto mode, set `disableAutoMode` to `"disable"` in managed settings. This overrides the enable variable.204To prevent developers from enabling auto mode, set `disableAutoMode` to `"disable"` in managed settings. This overrides the enable variable.

205 205 

206If you connect through an [LLM gateway](/en/llm-gateway) configured with `ANTHROPIC_BASE_URL`, auto mode may already be reachable without the enable variable, because the gateway routes requests through the Anthropic API. The `disableAutoMode` setting applies the same way in that configuration.206If you connect through an [LLM gateway](/en/llm-gateway) configured with `ANTHROPIC_BASE_URL`, auto mode may already be reachable without the enable variable, because the gateway routes requests through the Anthropic API. This does not apply to a signed-in [Claude apps gateway](/en/claude-apps-gateway) session, which is its own provider class and requires the enable variable. The `disableAutoMode` setting applies the same way in either configuration.

207 207 

208### What the classifier blocks by default208### What the classifier blocks by default

209 209 

permissions.md +1 −1

Details

394 394 

395## Managed settings395## Managed settings

396 396 

397For organizations that need centralized control over Claude Code configuration, administrators can deploy managed settings that can't be overridden by user or project settings. These policy settings follow the same format as regular settings files and can be delivered through MDM/OS-level policies, managed settings files, or [server-managed settings](/en/server-managed-settings). See [settings files](/en/settings#settings-files) for delivery mechanisms and file locations.397For organizations that need centralized control over Claude Code configuration, administrators can deploy managed settings that can't be overridden by user or project settings. These policy settings follow the same format as regular settings files and can be delivered through MDM/OS-level policies, managed settings files, [server-managed settings](/en/server-managed-settings), or a self-hosted [Claude apps gateway](/en/claude-apps-gateway). See [settings files](/en/settings#settings-files) for delivery mechanisms and file locations.

398 398 

399### Managed-only settings399### Managed-only settings

400 400 

quickstart.md +1 −0

Details

100* [Claude Pro, Max, Team, or Enterprise](https://claude.com/pricing?utm_source=claude_code\&utm_medium=docs\&utm_content=quickstart_login) (recommended)100* [Claude Pro, Max, Team, or Enterprise](https://claude.com/pricing?utm_source=claude_code\&utm_medium=docs\&utm_content=quickstart_login) (recommended)

101* [Claude Console](https://console.anthropic.com/) (API access with pre-paid credits). On first login, a "Claude Code" workspace is automatically created in the Console for centralized cost tracking.101* [Claude Console](https://console.anthropic.com/) (API access with pre-paid credits). On first login, a "Claude Code" workspace is automatically created in the Console for centralized cost tracking.

102* [Amazon Bedrock, Google Vertex AI, or Microsoft Foundry](/en/third-party-integrations) (enterprise cloud providers)102* [Amazon Bedrock, Google Vertex AI, or Microsoft Foundry](/en/third-party-integrations) (enterprise cloud providers)

103* A self-hosted [Claude apps gateway](/en/claude-apps-gateway), if your organization runs one: your admin pre-configures the gateway URL, and `/login` opens directly on the **Cloud gateway** screen for you to sign in with corporate SSO

103 104 

104Once logged in, your credentials are stored and you won't need to log in again.105Once logged in, your credentials are stored and you won't need to log in again.

105 106 

Details

135 135 

136Server-managed settings and [endpoint-managed settings](/en/settings#settings-files) both occupy the highest tier in the Claude Code [settings hierarchy](/en/settings#settings-precedence). No other settings level can override them, including command line arguments.136Server-managed settings and [endpoint-managed settings](/en/settings#settings-files) both occupy the highest tier in the Claude Code [settings hierarchy](/en/settings#settings-precedence). No other settings level can override them, including command line arguments.

137 137 

138Within the managed tier, the first source that delivers a non-empty configuration wins. Server-managed settings are checked first, then endpoint-managed settings. Sources do not merge: if server-managed settings deliver any keys at all, endpoint-managed settings are ignored entirely. If server-managed settings deliver nothing, endpoint-managed settings apply.138Within the managed tier, a configured [`policyHelper`](/en/settings#compute-managed-settings-with-a-policy-helper) preempts every other managed source, including server-managed settings: its output becomes the only managed configuration for the run. Otherwise the first source that delivers a non-empty configuration wins. Server-managed settings are checked first, then endpoint-managed settings. Sources do not merge: if server-managed settings deliver any keys at all, other endpoint-managed settings are ignored. One exception applies: a small set of [cross-source lock keys](/en/settings#settings-precedence), such as the sandbox allowlist locks, is honored when any admin-controlled managed source sets them; the user-writable HKCU registry tier is excluded. If server-managed settings deliver nothing, endpoint-managed settings apply.

139 139 

140If you clear your server-managed configuration in the admin console with the intent of falling back to an endpoint-managed plist or registry policy, be aware that [cached settings](#fetch-and-caching-behavior) persist on client machines until the next successful fetch. Run `/status` to see which managed source is active.140If you clear your server-managed configuration in the admin console with the intent of falling back to an endpoint-managed plist or registry policy, be aware that [cached settings](#fetch-and-caching-behavior) persist on client machines until the next successful fetch. Run `/status` to see which managed source is active.

141 141 


196* **Shell command settings**: settings that execute shell commands196* **Shell command settings**: settings that execute shell commands

197* **Custom environment variables**: variables not in the known safe allowlist197* **Custom environment variables**: variables not in the known safe allowlist

198* **Hook configurations**: any hook definition198* **Hook configurations**: any hook definition

199* **Managed CLAUDE.md content**: a `claudeMd` value delivered through managed settings

199 200 

200When these settings are present, users see a security dialog explaining what is being configured. Users must approve to proceed. If a user rejects the settings, Claude Code exits.201When these settings are present, users see a security dialog explaining what is being configured. Users must approve to proceed. If a user rejects the settings, Claude Code exits.

201 202 


211* Google Vertex AI212* Google Vertex AI

212* Microsoft Foundry213* Microsoft Foundry

213* [Claude Platform on AWS](/en/claude-platform-on-aws)214* [Claude Platform on AWS](/en/claude-platform-on-aws)

214* Custom API endpoints via `ANTHROPIC_BASE_URL` or [LLM gateways](/en/llm-gateway)215* Custom API endpoints via `ANTHROPIC_BASE_URL` or third-party [LLM gateways](/en/llm-gateway)

216 

217For Bedrock, Vertex AI, and Foundry deployments, a self-hosted [Claude apps gateway](/en/claude-apps-gateway) provides the equivalent remote managed-settings delivery: gateway-signed-in clients fetch managed settings from the gateway instead of `api.anthropic.com`. The failure semantics differ at startup: a gateway client that can't reach the gateway exits with an error instead of falling back to cached settings, while the hourly background refresh is fail-open on both channels.

215 218 

216## Audit logging219## Audit logging

217 220 

settings.md +6 −5

Details

87 * `.claude/settings.local.json` for settings that are not checked in, useful for personal preferences and experimentation. When Claude Code creates `.claude/settings.local.json`, it configures git to ignore the file. If you create the file yourself, add it to your gitignore manually.87 * `.claude/settings.local.json` for settings that are not checked in, useful for personal preferences and experimentation. When Claude Code creates `.claude/settings.local.json`, it configures git to ignore the file. If you create the file yourself, add it to your gitignore manually.

88* **Managed settings**: For organizations that need centralized control, Claude Code supports multiple delivery mechanisms for managed settings. All use the same JSON format and cannot be overridden by user or project settings:88* **Managed settings**: For organizations that need centralized control, Claude Code supports multiple delivery mechanisms for managed settings. All use the same JSON format and cannot be overridden by user or project settings:

89 89 

90 * **Server-managed settings**: delivered from Anthropic's servers via the Claude.ai admin console. See [server-managed settings](/en/server-managed-settings).90 * **Server-managed settings**: delivered remotely at sign-in, either from Anthropic's servers via the claude.ai admin console or from a self-hosted [Claude apps gateway](/en/claude-apps-gateway). See [server-managed settings](/en/server-managed-settings).

91 * **MDM/OS-level policies**: delivered through native device management on macOS and Windows:91 * **MDM/OS-level policies**: delivered through native device management on macOS and Windows:

92 * macOS: `com.anthropic.claudecode` managed preferences domain. The plist's top-level keys mirror `managed-settings.json`, with nested settings as dictionaries and arrays as plist arrays. Deploy via configuration profiles in Jamf, Iru (Kandji), or similar MDM tools.92 * macOS: `com.anthropic.claudecode` managed preferences domain. The plist's top-level keys mirror `managed-settings.json`, with nested settings as dictionaries and arrays as plist arrays. Deploy via configuration profiles in Jamf, Iru (Kandji), or similar MDM tools.

93 * Windows: `HKLM\SOFTWARE\Policies\ClaudeCode` registry key with a `Settings` value (REG\_SZ or REG\_EXPAND\_SZ) containing JSON (deployed via Group Policy or Intune)93 * Windows: `HKLM\SOFTWARE\Policies\ClaudeCode` registry key with a `Settings` value (REG\_SZ or REG\_EXPAND\_SZ) containing JSON (deployed via Group Policy or Intune)


254| `fileCheckpointingEnabled` | {/* min-version: 2.1.119 */}**Default**: `true`. Snapshot files before each edit so [`/rewind`](/en/checkpointing) can restore them. Appears in `/config` as **Rewind code (checkpoints)**. To disable via environment variable, set [`CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING`](/en/env-vars) in `env` | `false` |254| `fileCheckpointingEnabled` | {/* min-version: 2.1.119 */}**Default**: `true`. Snapshot files before each edit so [`/rewind`](/en/checkpointing) can restore them. Appears in `/config` as **Rewind code (checkpoints)**. To disable via environment variable, set [`CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING`](/en/env-vars) in `env` | `false` |

255| `fileSuggestion` | Configure a custom script for `@` file autocomplete. See [File suggestion settings](#file-suggestion-settings) | `{"type": "command", "command": "~/.claude/file-suggestion.sh"}` |255| `fileSuggestion` | Configure a custom script for `@` file autocomplete. See [File suggestion settings](#file-suggestion-settings) | `{"type": "command", "command": "~/.claude/file-suggestion.sh"}` |

256| `footerLinksRegexes` | {/* min-version: 2.1.176 */}Render extra clickable badges in the footer when a regex matches turn output. Each entry has a `pattern`, a `url` template with `{name}` placeholders filled from named capture groups, and an optional `label`. Read from user, `--settings` flag, and managed settings only. See [Footer link badges](#footer-link-badges) for URL constraints, scheme allowlist, and limits. Requires Claude Code v2.1.176 or later | `[{"type": "regex", "pattern": "\\b(?<key>PROJ-\\d+)\\b", "url": "https://issues.example.com/browse/{key}", "label": "{key}"}]` |256| `footerLinksRegexes` | {/* min-version: 2.1.176 */}Render extra clickable badges in the footer when a regex matches turn output. Each entry has a `pattern`, a `url` template with `{name}` placeholders filled from named capture groups, and an optional `label`. Read from user, `--settings` flag, and managed settings only. See [Footer link badges](#footer-link-badges) for URL constraints, scheme allowlist, and limits. Requires Claude Code v2.1.176 or later | `[{"type": "regex", "pattern": "\\b(?<key>PROJ-\\d+)\\b", "url": "https://issues.example.com/browse/{key}", "label": "{key}"}]` |

257| `forceLoginMethod` | Use `claudeai` to restrict login to Claude.ai accounts, `console` to restrict login to Claude Console accounts. When set in managed settings, sessions authenticated by `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, or `apiKeyHelper` are blocked at startup, since neither value can be satisfied without first-party OAuth. Third-party provider sessions such as Bedrock, Vertex, and Foundry are not blocked: they authenticate against your cloud provider rather than Anthropic | `claudeai` |257| `forceLoginMethod` | Use `claudeai` to restrict login to Claude.ai accounts, `console` to restrict login to Claude Console accounts, or `gateway` to restrict login to a cloud gateway; see [Claude apps gateway](/en/claude-apps-gateway). When set to any value in managed settings, sessions authenticated by `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, or `apiKeyHelper` are blocked at startup, since an environment credential cannot satisfy the required login method. Third-party provider sessions such as Bedrock, Vertex, and Foundry are not blocked: they authenticate against your cloud provider rather than Anthropic | `claudeai` |

258| `forceLoginGatewayUrl` | Pre-fills and locks the gateway URL on the `/login` Cloud gateway screen. Either this key or `forceLoginMethod: "gateway"` surfaces that screen; set both so the URL is filled in. Honored only at the managed policy tier; ignored in user and project settings. See [Claude apps gateway](/en/claude-apps-gateway#set-the-gateway-url) | `"https://claude-gateway.example.com"` |

258| `forceLoginOrgUUID` | Require login to belong to a specific Anthropic organization. Accepts a single UUID string, which also pre-selects that organization during login, or an array of UUIDs where any listed organization is accepted without pre-selection. When set in managed settings, login fails if the authenticated account does not belong to a listed organization, and sessions authenticated by `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, or `apiKeyHelper` are blocked at startup since organization membership cannot be verified for them. Third-party provider sessions such as Bedrock, Vertex, and Foundry are not blocked: use your cloud IAM to restrict which cloud accounts can be used. An empty array fails closed and blocks login with a misconfiguration message | `"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"` or `["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"]` |259| `forceLoginOrgUUID` | Require login to belong to a specific Anthropic organization. Accepts a single UUID string, which also pre-selects that organization during login, or an array of UUIDs where any listed organization is accepted without pre-selection. When set in managed settings, login fails if the authenticated account does not belong to a listed organization, and sessions authenticated by `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, or `apiKeyHelper` are blocked at startup since organization membership cannot be verified for them. Third-party provider sessions such as Bedrock, Vertex, and Foundry are not blocked: use your cloud IAM to restrict which cloud accounts can be used. An empty array fails closed and blocks login with a misconfiguration message | `"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"` or `["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"]` |

259| `forceRemoteSettingsRefresh` | (Managed settings only) Block CLI startup until remote managed settings are freshly fetched from the server. If the fetch fails, the CLI exits rather than continuing with cached or no settings. When not set, startup continues without waiting for remote settings. See [fail-closed enforcement](/en/server-managed-settings#enforce-fail-closed-startup) | `true` |260| `forceRemoteSettingsRefresh` | (Managed settings only) Block CLI startup until remote managed settings are freshly fetched from the server. If the fetch fails, the CLI exits rather than continuing with cached or no settings. When not set, startup continues without waiting for remote settings. See [fail-closed enforcement](/en/server-managed-settings#enforce-fail-closed-startup) | `true` |

260| `gcpAuthRefresh` | Custom script that refreshes GCP Application Default Credentials when they expire or cannot be loaded. See [advanced credential configuration](/en/google-vertex-ai#advanced-credential-configuration) | `gcloud auth application-default login` |261| `gcpAuthRefresh` | Custom script that refreshes GCP Application Default Credentials when they expire or cannot be loaded. See [advanced credential configuration](/en/google-vertex-ai#advanced-credential-configuration) | `gcloud auth application-default login` |


612}613}

613```614```

614 615 

615When the helper emits `managedSettings`, that object replaces the file-based managed settings for the run. When the helper exits non-zero at startup, Claude Code prints the error and refuses to start, so a helper that needs outage resilience should serve from its own cache and exit `0`.616When the helper emits `managedSettings`, that object becomes the only managed settings source for the run, taking precedence over remote, MDM, and file-based sources. When the helper exits non-zero at startup, Claude Code prints the error and refuses to start, so a helper that needs outage resilience should serve from its own cache and exit `0`.

616 617 

617### Settings precedence618### Settings precedence

618 619 


6211. **Managed settings** ([server-managed](/en/server-managed-settings), [MDM/OS-level policies](#configuration-scopes), or [managed settings](/en/settings#settings-files))6221. **Managed settings** ([server-managed](/en/server-managed-settings), [MDM/OS-level policies](#configuration-scopes), or [managed settings](/en/settings#settings-files))

622 * Policies deployed by IT through server delivery, MDM configuration profiles, registry policies, or managed settings files623 * Policies deployed by IT through server delivery, MDM configuration profiles, registry policies, or managed settings files

623 * Cannot be overridden by any other level, including command line arguments624 * Cannot be overridden by any other level, including command line arguments

624 * Within the managed tier, precedence is: server-managed > MDM/OS-level policies > file-based (`managed-settings.d/*.json` + `managed-settings.json`) > HKCU registry (Windows only). Only one managed source is used; sources do not merge across tiers. Within the file-based tier, drop-in files and the base file are merged together.625 * Within the managed tier, precedence is: [`policyHelper`](#compute-managed-settings-with-a-policy-helper) output, which when configured is the only managed source used > remote (claude.ai [server-managed](/en/server-managed-settings) or [Claude apps gateway](/en/claude-apps-gateway)-delivered) > MDM/OS-level policies > file-based (`managed-settings.d/*.json` + `managed-settings.json`) > HKCU registry (Windows only). Only one managed source is used; sources do not merge across tiers, with one exception: the sandbox lock keys `sandbox.network.allowManagedDomainsOnly` and `sandbox.filesystem.allowManagedReadPathsOnly`, with their associated allowlists, `allowAllClaudeAiMcps`, and the sandbox binary paths `sandbox.bwrapPath` and `sandbox.socatPath` are honored when any admin-controlled managed source sets them; the user-writable HKCU tier is excluded. Within the file-based tier, drop-in files and the base file are merged together.

625 * Embedding hosts such as Claude Desktop can supply policy via the SDK `managedSettings` option. By default this is ignored when an admin-deployed managed source is present: server-managed settings, an MDM or OS-level policy, or a managed settings file. The user-writable HKCU registry fallback does not count as an admin-deployed source. Administrators can opt in by setting [`parentSettingsBehavior`](#available-settings) to `"merge"`. The embedder's values are filtered so they can tighten managed policy but not loosen it.626 * Embedding hosts such as Claude Desktop can supply policy via the SDK `managedSettings` option. By default this is ignored when an admin-deployed managed source is present: server-managed settings, an MDM or OS-level policy, or a managed settings file. The user-writable HKCU registry fallback does not count as an admin-deployed source. Administrators can opt in by setting [`parentSettingsBehavior`](#available-settings) to `"merge"`. The embedder's values are filtered so they can tighten managed policy but not loosen it.

626 627 

6272. **Command line arguments**6282. **Command line arguments**


651 652 

652### Verify active settings653### Verify active settings

653 654 

654Run `/status` inside Claude Code to see which settings sources are active. Inside the menu, the **Status** tab includes a `Setting sources` line that lists each layer Claude Code loaded for the current session, such as `User settings` or `Project local settings`. When [managed settings](/en/admin-setup#decide-how-settings-reach-devices) are in effect, the entry shows the delivery channel in parentheses, for example `Enterprise managed settings (remote)`, `(plist)`, `(HKLM)`, `(HKCU)`, or `(file)`. A layer appears in the list only when that source is loaded with at least one key, so an empty list means no settings sources were found.655Run `/status` inside Claude Code to see which settings sources are active. Inside the menu, the **Status** tab includes a `Setting sources` line that lists each layer Claude Code loaded for the current session, such as `User settings` or `Project local settings`. When [managed settings](/en/admin-setup#decide-how-settings-reach-devices) are in effect, the entry shows the delivery channel in parentheses, for example `Enterprise managed settings (remote)`, `(plist)`, `(HKLM)`, `(HKCU)`, or `(file)`. The `remote` channel covers both claude.ai server-managed settings and [Claude apps gateway](/en/claude-apps-gateway)-delivered policies. A layer appears in the list only when that source is loaded with at least one key, so an empty list means no settings sources were found.

655 656 

656The `Setting sources` line confirms which sources are being read. It does not show which layer supplied each individual key. The **Config** tab in the same dialog is an editor for a fixed set of toggles such as theme and verbose output, not a view of your `settings.json` contents.657The `Setting sources` line confirms which sources are being read. It does not show which layer supplied each individual key. The **Config** tab in the same dialog is an editor for a fixed set of toggles such as theme and verbose output, not a view of your `settings.json` contents.

657 658 

Details

194 194 

195* [Claude for Teams or Enterprise](/en/authentication#claude-for-teams-or-enterprise)195* [Claude for Teams or Enterprise](/en/authentication#claude-for-teams-or-enterprise)

196* [Anthropic Console](/en/authentication#claude-console-authentication)196* [Anthropic Console](/en/authentication#claude-console-authentication)

197* [Claude apps gateway](/en/claude-apps-gateway), a self-hosted gateway that adds IdP sign-in in front of Amazon Bedrock, Google Vertex AI, Microsoft Foundry, or the Anthropic API

197* [Amazon Bedrock](/en/amazon-bedrock)198* [Amazon Bedrock](/en/amazon-bedrock)

198* [Claude Platform on AWS](/en/claude-platform-on-aws)199* [Claude Platform on AWS](/en/claude-platform-on-aws)

199* [Google Vertex AI](/en/google-vertex-ai)200* [Google Vertex AI](/en/google-vertex-ai)