[BUG] Desktop Code tab ignores ANTHROPIC_BASE_URL from ~/.claude/settings.json (terminal CLI honors it)

Status Open
Reported on v2.1.281
Maintainer reply None cached
Activity 4 comments · opened Sep 27, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Sessions started from the Claude desktop app's Code tab always send API traffic to https://api.anthropic.com, ignoring env.ANTHROPIC_BASE_URL in ~/.claude/settings.json. The terminal claude CLI, reading the same settings file, routes to the configured endpoint as expected.

The desktop app spawns the bundled claude process with ANTHROPIC_BASE_URL=https://api.anthropic.com in its environment (confirmed by inspecting the spawned process's environment). Although the session loads user settings (--setting-sources=user,project,local), the injected value wins over the settings file. There is no desktop app setting to change it, so there is no supported way to put a local proxy in front of Code tab sessions.

What Should Happen?

Code tab sessions should honor env.ANTHROPIC_BASE_URL from user settings, the same way the terminal CLI does.

If the pinning is intentional (e.g. to protect how the host delivers the OAuth token), please either offer an opt-in setting that allows a user-approved local endpoint (127.0.0.1 / localhost), or document that the Code tab does not support custom base URLs.

Error Messages/Logs

No error is shown — traffic silently bypasses the configured endpoint.

Spawned Code tab process environment (relevant part):
ANTHROPIC_BASE_URL=https://api.anthropic.com
CLAUDE_CODE_ENTRYPOINT=claude-desktop

Local proxy request counter (Prometheus metric):
- Before terminal test: headroom_requests_total 26
- After one terminal `claude -p` call: headroom_requests_total 28 (0 failed)
- After several further Code tab turns: headroom_requests_total 28 (unchanged)

Steps to Reproduce

  1. Run any local Anthropic-compatible proxy that counts requests, e.g. on http://127.0.0.1:6767.
  2. Add to ~/.claude/settings.json:

``json
{ "env": { "ANTHROPIC_BASE_URL": "http://127.0.0.1:6767" } }
``

  1. In a terminal, run claude -p "hi" → the proxy's request counter increments. ✅
  2. Open the Claude desktop app → Code tab → start a session and send a few messages → the proxy's counter does not change. ❌
  3. Optionally, from a Bash tool call inside the Code tab session, run echo $ANTHROPIC_BASE_URL → prints https://api.anthropic.com.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.281 (bundled in Claude desktop app 2.9939.2, Code tab); terminal CLI 2.1.283 behaves correctly

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Other

Additional Information

  • Claude desktop app 2.9939.2, macOS 27.0 (26A428), Apple Silicon (arm64)
  • Signed in with a Claude subscription (OAuth), not an API key
  • The Code tab is launched by the desktop app, not from a terminal, hence "Other" for Terminal/Shell.
  • Related (different symptom, same root observation that the desktop app always injects ANTHROPIC_BASE_URL): #81973
  • Use case: local token-compression / observability proxies (Headroom in my case), which work with the terminal CLI but cannot be used from the Code tab today.

View original on GitHub ↗

3 Comments

stonianua · 17 days ago

Thanks for the clean repro — especially the process-env check (ANTHROPIC_BASE_URL=https://api.anthropic.com on the Code-tab spawn) and the proxy counter that stays flat while the terminal CLI increments. That pins this as host injection winning over env from ~/.claude/settings.json, not a settings-load miss (--setting-sources=user,project,local is already set).

Suggestion for the team: resolve the effective endpoint through one shared configuration-precedence path for CLI and Desktop Code tab. If Desktop must pin the OAuth endpoint for token delivery, reject the conflicting user setting visibly (or document “unsupported on Code tab”) instead of silently overriding it. Endpoint provenance in diagnostics would help a lot here: effective value, winning source, and any overridden source.

Regression idea: launch a terminal CLI session and a Code-tab session from the same settings.json with a local proxy ANTHROPIC_BASE_URL, then assert either identical routing or an explicit unsupported-setting error — never silent bypass.

Happy to refine if you’ve already got a documented intentional pin for OAuth hosts.

3JIou-home · 16 days ago

Same issue here, and a few extra data points that may help narrow it down.

Environment: macOS 15.6 (arm64), Claude desktop 2.9939.2, Code tab CLI 2.1.281, terminal CLI 2.1.278, claude.ai subscription (OAuth). The proxy is a self-hosted Headroom instance reachable only over VPN; ~/.claude/settings.json has "env": {"ANTHROPIC_BASE_URL": "http://<proxy>/llm"}.

1. A process env var beats the settings env block, even in the terminal CLI. I counted requests in the proxy's access log:

env -u ANTHROPIC_BASE_URL claude -p ok        # → goes through the proxy
ANTHROPIC_BASE_URL=https://api.anthropic.com claude -p ok        # → goes direct
ANTHROPIC_BASE_URL=https://api.anthropic.com claude -p ok \
  --settings '{"env":{"ANTHROPIC_BASE_URL":"http://<proxy>/llm"}}'        # → still direct

So the settings env only fills in variables that aren't set yet. That contradicts llm-gateway-connect: "When both a shell export and a settings-file env block set the same variable, the settings-file value applies." Because the desktop app always passes ANTHROPIC_BASE_URL=https://api.anthropic.com to its sessions, no settings file can change the destination. That includes managed settings, if they follow the same rule.

2. SSH environments don't help either. For an SSH environment (I pointed one at the same Mac), the app installs its server under ~/.claude/remote/srv/… and the CLI under ~/.claude/remote/ccd-cli/<version> on the remote side. It then launches the CLI with the same ANTHROPIC_BASE_URL=https://api.anthropic.com (plus CLAUDE_CODE_OAUTH_TOKEN). The remote user's settings.json loses the same way as in point 1.

3. Third-party inference is not an alternative for subscription users. The gateway provider in "Configure Third-Party Inference" switches the whole app into 3P mode. That means not signing in to Anthropic (per the installation docs), so no subscription. We just want the Code tab to send the same subscription OAuth traffic through our own proxy, which the terminal CLI already does.

Workaround (unsupported, breaks on every CLI update): an SSH environment to 127.0.0.1 plus a wrapper in place of ~/.claude/remote/ccd-cli/<version> that runs unset ANTHROPIC_BASE_URL and then execs the real binary. After that the settings value applies, and the proxy log shows claude-cli/2.1.281 (external, claude-desktop) requests with 200s. A launchd WatchPaths agent re-wraps new versions. It works, but it's clearly not something anyone should need.

What would fix it for us: either don't inject ANTHROPIC_BASE_URL when the user's settings define one, or add an explicit opt-in (for example an allowlist of base URLs) for Code-tab sessions, local and SSH. Separately, please either fix the precedence described in point 1 or correct the docs.

tosscar · 9 days ago

Reproduced on Windows 11 as well, so this does not look macOS-specific.

Environment

  • OS: Windows 11 Pro 10.0.26200 (x64)
  • Claude desktop app: v2.19675.0
  • Claude Code tab CLI(bundled/terminal): 2.1.288 ; Claude Code CLI 2.1.288 & 2.1.289 behaves correctly
  • Auth: OAuth (subscription), not an API key

Setup
~/.claude/settings.json (C:\Users\<user>\.claude\settings.json):

{
  "env": {
    "ANTHROPIC_BASE_URL": "http://127.0.0.1:8787"
  }
}

A local compression proxy (Headroom 0.39.1) listens on 127.0.0.1:8787 and exposes request counters at /stats.

Result

  • Desktop Code tab, new session: $env:ANTHROPIC_BASE_URL in the session shell is https://api.anthropic.com, not the value from settings.json. The proxy receives no /v1/messages requests (request counter unchanged).
  • Terminal claude with no ANTHROPIC_BASE_URL in the parent environment: the settings.json value is honored. Counter went 2 -> 4 for one claude -p call, and OAuth works through the proxy.
  • Terminal claude with ANTHROPIC_BASE_URL=https://api.anthropic.com set in the parent environment: settings.json is not applied (counter unchanged). This matches the usual "process env wins over settings.json" precedence, and it shows the cause is the desktop app injecting that variable into the spawned process.

Conclusion
Same as the macOS report: the Code tab spawns the agent with ANTHROPIC_BASE_URL=https://api.anthropic.com, which takes precedence over env.ANTHROPIC_BASE_URL in settings.json. There is no setting in the desktop app to change it, so a local proxy cannot be placed in front of Code tab sessions on Windows either.

Use case
Putting a local context-compression / caching proxy (e.g. Headroom, LiteLLM-style gateways) in front of sessions. The terminal CLI and VS Code extension work. The desktop Code tab is the only client that cannot.

Request
Either honor a user-configured ANTHROPIC_BASE_URL (settings.json env or an app setting) in the Code tab, or document that it is unsupported.

Related: headroomlabs-ai/headroom#869 (same behavior reported on macOS, from the proxy side).

Showing cached comments. Read the full discussion on GitHub ↗