Interactive TUI requires direct api.anthropic.com reachability, ignoring ANTHROPIC_BASE_URL (2.1.251)
Version: 2.1.251 (native installer, Linux x64, Debian container)
Summary
The interactive TUI refuses to start unless it can reach api.anthropic.com
directly, even when ANTHROPIC_BASE_URL is set to an endpoint that serves
the API correctly. claude -p on the identical configuration works completely.
In a sandbox where outbound network is deny-by-default and the only permitted
route is a local gateway named by ANTHROPIC_BASE_URL, the TUI cannot start at
all. The API path itself is fine — it is the startup check that consults a host
it was configured not to use.
Reproduction
Linux container. ANTHROPIC_BASE_URL=http://127.0.0.10:9100, pointing at a
local HTTP server that answers the API. api.anthropic.com mapped by/etc/hosts to a local address so what it receives can be observed. No proxy
environment variables set.
claude -p "Reply with exactly: OK"→ works. Requests arrive at the base
URL (HEAD /api/hello, then POST /v1/messages?beta=true), a correct answer
is returned, and the usage block is present.
claude(interactive) → refuses to start, with a message naming
api.anthropic.com regardless of the configured base URL.
What the startup check requires
Varying only what the direct path offers, with the base URL working throughout:
| direct path offers | TUI |
|---|---|
| TCP handshake completes, nothing else (3 connections accepted) | refuses — Connection to api.anthropic.com timed out after 10 seconds |
| TLS handshake completes, self-signed cert | refuses — DEPTH_ZERO_SELF_SIGNED_CERT |
| TLS handshake completes, cert trusted via NODE_EXTRA_CA_CERTS, no HTTP response | refuses — timed out after 10 seconds |
| Trusted TLS + HTTP responses | starts |
So it needs a full HTTP response over trusted TLS. In the passing case the
direct path received:
GET /api/oauth/profile
GET /api/hello
POST /api/event_logging/v2/batch
/api/hello is also sent to ANTHROPIC_BASE_URL in every case, so that part is
already base-URL-aware; the other two are not.
With a proxy variable set instead, the message names the proxy
(A proxy is configured via https_proxy) and reports the proxy's status rather
than trying the base URL.
Expected
Requests the startup check makes should honour ANTHROPIC_BASE_URL when it is
set, as /v1/messages already does — or the check's failure should be
non-fatal, as it appears to be in -p mode.
Note
claude -p makes the same direct attempts, has them fail, and continues anyway.
The check appears to be advisory in one mode and blocking in the other.