Build1 publisher3 min readPublished
Your shell exports never reach the Claude Code panel, and your gateway logs know it
A dev.to writeup shows ANTHROPIC_BASE_URL set in a terminal does not reach the VS Code extension's agent process, which inherits the editor's environment instead.
The Engineer · Build desk
Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction
What happened
- Running `export ANTHROPIC_BASE_URL=http://127.0.0.1:20128` in a shell routes the claude CLI to a local endpoint.
- Opening the Claude Code panel in VS Code in the same project, after that export, still talks to Anthropic directly.
- The claude CLI reads the environment of the process it was started from.
- The VS Code extension spawns its agent process from the VS Code window process, so its environment is whatever VS Code itself was started with, that is the desktop or login environment rather than the shell where the export was typed.
- Consequence one: export in a terminal, then open the panel, and nothing happens because the panel never saw the variable.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
Exporting `ANTHROPIC_BASE_URL=http://127.0.0.1:20128` in a shell does route the `claude` CLI to a local endpoint [1]. Open the Claude Code panel in VS Code in the same project and it still talks to Anthropic directly [2]. If your compliance story is "we set the base URL and all agent traffic goes through our gateway," half your traffic is probably not going through your gateway.
The mechanism, per a dev.to writeup by Vinh Nguyen Thanh, is unremarkable once stated: the CLI reads the environment of the process you launched it from [3], while the extension spawns its agent process from the VS Code window process, so it sees whatever environment VS Code itself was started with, typically the desktop or login environment [4]. That produces two failures pointing in opposite directions. Export in a terminal and then open the panel, and nothing happens, because the panel never saw the variable [5]. Launch VS Code from that terminal so it inherits the variables, and now every workspace in that window is routed, including the ones you wanted talking to Anthropic directly [6].
The only hook the extension offers is a settings key, `claudeCode.environmentVariables`, a list of name and value pairs injected into the agent process [7]. The author's audit is a `jq` read of the user settings file, at `Library/Application Support/Code/User/settings.json` on macOS, `.config/Code/User/settings.json` on Linux, and `$APPDATA/Code/User/settings.json` on Windows [8]. On a machine that has never been switched it prints nothing set, meaning the extension is inheriting the VS Code process environment [9]. That is the check worth running across a fleet, because a shell profile audit will tell you nothing useful about the panel [22].
The key has machine scope, not workspace scope: turn routing on for one project and every VS Code window on that box is routed [10]. So per-repo enforcement is not available through this hook at all [23]. Turning it off means deleting entries rather than flipping a flag, and if you remove the token but leave `ANTHROPIC_BASE_URL` behind, the panel points at a router with no credential [11]. The array is also shared with unrelated variables such as proxy settings or `NODE_EXTRA_CA_CERTS`, one careless overwrite from disappearing [12].
The author's response is a toolkit that treats the array as partly owned, managing exactly six names and writing back everything else untouched [13][14], with a `settings.json.bak-claude-router` copy taken before any write and a restore-and-exit-non-zero path if serialisation throws [15]. Switching on or off requires a Developer: Reload Window, because the agent process reads its environment once at spawn [17]. On the CLI side the wrapper stays in process scope, unsetting `ANTHROPIC_API_KEY` so a leftover key cannot beat the router token, then exec'ing `claude` [18]. The stated cost of the asymmetry: you cannot have one routed window and one direct window at the same time [20]. The endpoint in question is a 9Router instance exposing an Anthropic-compatible `/v1/messages` in front of multiple providers, configured from a gitignored local file [21].
Two things to watch. First, whether the extension ever gains a workspace-scoped environment hook, which is the difference between per-repo policy and per-laptop policy [23]. Second, your gateway's request counts against seat counts, since a panel that silently bypasses the proxy shows up as absence, not as an error [9][5].