refactor(env): rename E2A_BASE_URL to E2A_API_URL; split it from the CLI's E2A_URL#522
Conversation
…CLI's E2A_URL The client-side base-URL env vars named one concept badly and two concepts identically, so following the docs silently misrouted traffic. E2A_URL and the SDKs' E2A_BASE_URL are NOT the same thing. The CLI's api_url is the deployment root: `login` opens a browser against it (login.ts:310) and points users at /get-started, a Next.js route the Go backend does not serve. https://e2a.dev works because the web front also proxies /v1. The SDKs and the MCP server only ever call /v1 and want the API host alone. Both names existing for "the base URL", with different defaults, hid that distinction. The concrete failures: - README.md and docs/deployment.md taught only E2A_URL, which the SDKs did not read. A self-hoster who followed the docs got their SDK silently pointed at production api.e2a.dev. - The CLI accepted E2A_BASE_URL as an alias for its deployment root, so exporting E2A_BASE_URL=https://api.e2a.dev to configure an SDK silently repointed the CLI at the API host and broke `e2a login`. - tether taught E2A_BASE_URL ("self-host: your API base") and forced the CLI onto api.e2a.dev through that alias. So: - SDKs (TS + Python) read E2A_API_URL, matching the name the server already uses for the same concept (config.go:344 — its externally visible API base). E2A_BASE_URL still works, with a deprecation warning. - MCP moves to E2A_API_URL (E2A_URL/E2A_BASE_URL deprecated) and defaults to the API host; it is a pure API client. - The CLI keeps E2A_URL alone and no longer reads E2A_BASE_URL. Dropping the alias silently would strand tether self-hosters on production, so it warns when E2A_BASE_URL is set and the root is still the default. - tether migrates to E2A_URL, carrying a legacy ~/.e2a-tether.env over with a warning, and defaults to the CLI's own default instead of forcing api.e2a.dev. Also drops the E2A_AGENT_EMAIL fallback claim from both SDK READMEs and the root README: it was never implemented in either SDK (they raise missing_email), though it is real in the CLI and tether. Documents the CLI's env vars, which were undocumented. The MCP one-shot deprecation guard is gone: main() calls loadConfig exactly once, so it deduped nothing and only leaked state across tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…K users Review follow-ups on the E2A_API_URL split. [P1] The deployment guide's audience table and setup example still grouped "CLI / SDK user" together and instructed only E2A_URL — the var the changed SDKs no longer read. A self-hoster following the primary setup path pointed their SDK at production api.e2a.dev, the exact bug this branch fixes. Split the audience row and the walkthrough into a CLI section (E2A_URL + e2a login) and an SDK/MCP section whose example exports E2A_API_URL, in both docs/deployment.md and the README table. Each section now states which var the other audience's tooling ignores. [P2] The CLI's "you set a var I ignore" warning only fired when the resolved URL equalled the default. E2A_BASE_URL used to override ~/.e2a/config.json, so a user with stored host A and a legacy env override for host B now silently connects to A — and the default-only gate stayed quiet because A != default. Warn whenever E2A_BASE_URL is set and E2A_URL is absent, and name the host actually in use so the stored-vs-intended mismatch is visible. Regression test added with a stored non-default api_url. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Both addressed in 6029c08. [P1] Docs no longer misroute SDK users. The
Each section now names the var the other audience's tooling ignores, e.g. "The CLI does not read [P2] Legacy override is no longer silently ignored. You're right that gating on Regression test added with a stored non-default |
Why
The client-side base-URL env vars named one concept badly and two concepts identically, so following our own docs silently misrouted traffic.
E2A_URLand the SDKs'E2A_BASE_URLare not the same thing:api_urlis the deployment root.loginopens a browser against it (cli/src/commands/login.ts:310) and points users at/get-started— a Next.js route (web/src/app/(app)/get-started) the Go backend does not serve.https://e2a.devworks because the web front also proxies/v1(web/Caddyfile:35)./v1, and want the API host alone.Two names for "the base URL", with two different defaults, hid that distinction. The concrete failures:
README.mdanddocs/deployment.mdteachE2A_URL; the SDKs read onlyE2A_BASE_URL. A self-hoster who followed the docs got their SDK silently pointed at productionapi.e2a.dev.e2a loginE2A_BASE_URLas an alias for its deployment root, so exportingE2A_BASE_URL=https://api.e2a.devto configure an SDK silently repointed the CLI at the API host.tether.env.exampletaughtE2A_BASE_URL("self-host: your API base") andlib.sh:51defaulted it toapi.e2a.dev— overriding the CLI's owne2a.devdefault through that alias.What changed
E2A_API_URL, matching the name the server already uses for the same concept (internal/config/config.go:344— its externally visible API base).E2A_BASE_URLstill works, with a deprecation warning (console.warn/DeprecationWarning).E2A_API_URL(E2A_URL+E2A_BASE_URLdeprecated) and now defaults to the API host — it is a pure API client.E2A_URLalone and no longer readsE2A_BASE_URL. Dropping the alias silently would strand tether self-hosters on production, so it warns — gated to the actually-dangerous case (legacy var set,E2A_URLunset, root still at default), so a legitimate SDK user who also configured their CLI gets no noise.E2A_URL, carries a legacy~/.e2a-tether.envover with a warning (rather than reverting to prod), unsets the stale name so the CLI doesn't double-warn, and tracks the CLI's default instead of forcingapi.e2a.dev.E2A_AGENT_EMAILfallback claim from both SDK READMEs and the root README — it was never implemented in either SDK (they raisemissing_email), though it is real in the CLI and tether. Added the CLI's env-var table (it documented none despite reading five) and splitE2A_URLvsE2A_API_URLindocs/deployment.md.Also removed the MCP one-shot deprecation guard:
main()callsloadConfigexactly once, so it deduped nothing and only leaked state across tests.Compatibility
Additive. Every previously-working configuration still works; the old names warn rather than break. The one behavior change is the CLI ignoring
E2A_BASE_URL— loud, not silent, and tether (its main consumer) migrates itself.Verification
Suites: TS SDK typecheck+unit+types, MCP vitest+types, Python 323 passed / 18 skipped, CLI 120 passed, tether
bash -nclean.Driven for real, not just unit-tested:
E2A_API_URL→ deprecatedE2A_BASE_URL+ warning → both set, canonical wins).E2A_URLis set.t_load_configthrough the legacy-migration path: carries over, warns, unsets, and defaults correctly.Follow-ups (not in this PR)
mcp/src/config.tsis dead code (nothing insrc/imports it but a type; nobinfield since npm stdio publishing was retired in GA /v1 readiness: settle API contract, regenerate SDKs, slim CLI, re-curate MCP (hosted-only) #247) and now also contradicts the new canonical name. Deleting it is a separate call.internal/config/config.go:377describes ("web on one host, API/MCP on another") still can't be expressed by the CLI, which holds only one URL. That's the deeper fix.🤖 Generated with Claude Code