Internal Gateway
If your organization runs Claude Code against an internal LLM gateway -
typically with an apiKeyHelper for OAuth refresh, custom routing
headers, and OTEL telemetry pinned via managed-settings.json.
Not Diamond can sit between Claude Code and the gateway and routes each turn to the cheapest model that still meets quality. Below is what’s supported and how to confirm it’s working.
The one conflict: ANTHROPIC_BASE_URL
Section titled “The one conflict: ANTHROPIC_BASE_URL”managed-settings.json is the highest-precedence config layer in Claude
Code - above shell env, user settings, and project settings. The proxy
steers Claude Code by exporting
ANTHROPIC_BASE_URL=http://127.0.0.1:8082 via the launch environment.
If managed-settings.json also sets ANTHROPIC_BASE_URL, the managed
value wins and Claude Code bypasses the local proxy entirely.
The proxy detects this at startup and refuses to launch. To resolve, remove
ANTHROPIC_BASE_URL from managed-settings.json and supply the gateway
URL to the proxy instead.
1. Adjust managed-settings.json
Section titled “1. Adjust managed-settings.json”Remove the ANTHROPIC_BASE_URL entry from env. Leave everything else
in place - apiKeyHelper, ANTHROPIC_CUSTOM_HEADERS,
CLAUDE_CODE_API_KEY_HELPER_TTL_MS, and the OTEL_* exporters are all
preserved by the proxy.
// /Library/Application Support/ClaudeCode/managed-settings.json (macOS)// /etc/claude-code/managed-settings.json (Linux)// C:\ProgramData\ClaudeCode\managed-settings.json (Windows){ "apiKeyHelper": "your-token-refresh-command", "model": "sonnet", "effortLevel": "medium", "env": { "ENABLE_TOOL_SEARCH": "true", "CLAUDE_CODE_ENABLE_TELEMETRY": "1", "OTEL_EXPORTER_OTLP_ENDPOINT": "https://your-otel-collector", "OTEL_EXPORTER_OTLP_PROTOCOL": "http/json", "OTEL_LOGS_EXPORTER": "otlp", "OTEL_METRICS_EXPORTER": "otlp", "OTEL_TRACES_EXPORTER": "otlp",
// ANTHROPIC_BASE_URL removed - the proxy sets it on launch. "ANTHROPIC_CUSTOM_HEADERS": "source: claude-code\norg-id: 42\nprovider: anthropic", "CLAUDE_CODE_API_KEY_HELPER_TTL_MS": "7200000" }}2. Configure the proxy
Section titled “2. Configure the proxy”notdiamond loginnotdiamond init --credential forwarded --gateway-url https://your-gatewayThis writes ~/.notdiamond/config.json with credential type forwarded
and your gateway URL.
3. Run
Section titled “3. Run”notdiamond claudeEach operator on a managed Claude Code install needs to run steps 2 and 3 once.
What flows through unchanged
Section titled “What flows through unchanged”| Item | How it’s preserved |
|---|---|
apiKeyHelper token | Claude Code stamps the refreshed Authorization: Bearer … on every outbound request. The proxy forwards it to the gateway verbatim. No token is stored by the proxy. |
ANTHROPIC_CUSTOM_HEADERS (source, org-id, provider, …) | The proxy captures every inbound header that isn’t reserved and forwards it to the gateway, so your routing layer sees the same metadata it does without the proxy. |
OTEL_* exporters | Claude Code emits OTEL directly to your collector - it never touches the proxy. Unaffected. |
Verification
Section titled “Verification”After notdiamond claude launches, check that requests are reaching the
proxy and the proxy is calling your gateway:
notdiamond status # shows provider = forwarded and uptimenotdiamond logs -f # tails per-request rowsA healthy turn shows one line per request with status: 200 and a
non-null routed_model / routed_effort. To confirm exactly which
headers arrived at the gateway, check the gateway’s own access log - the
proxy never logs raw bearer tokens locally.
If notdiamond logs shows status: 502 with an error: field
containing a gateway message, the gateway rejected the request. The
message usually identifies what’s missing (an expected routing header,
an unrecognized token, etc.). For more detail per request, use
notdiamond logs --debug.
Note that if your account has routing visibility hidden from members, the --debug long-context diagnostics are redacted for regular users. They are still visibile to Owners and Admins.
What’s not supported
Section titled “What’s not supported”- Pinning
ANTHROPIC_BASE_URLinmanaged-settings.json. The proxy refuses to launch. Move the gateway URL tonotdiamond init --gateway-urlinstead. - Stripping or rewriting the inbound
Authorizationheader. The proxy passes the bearer through; the gateway is responsible for validating it. - Hot-reload of
managed-settings.jsonchanges. Restart Claude Code to pick up new managed-settings values. The proxy itself does not need to be restarted.