v0.4.0
Added
-
relay-ai ui— Visual launcher web UI — Runrelay-ai uito open a browser-based dashboard for managing providers and launching every supported coding agent from a single interface. Features include:- App launcher cards — one card per tool (Claude Code CLI, Codex CLI, Gemini CLI, Anti-gravity CLI, Antigravity App, Antigravity IDE, Claude Code Desktop, Codex Desktop). Click to expand, pick a provider and model, and launch.
- In-UI model selection — selecting a provider and model before clicking Launch passes
--provider/--modeldirectly to the terminal command, bypassing the interactive picker entirely. The terminal opens straight to the running session with no second selection step. - Real brand icons — every app card shows its actual brand icon: Anthropic orange for Claude Code CLI and Desktop, OpenAI Codex dark for Codex CLI and Desktop, Google gradient for Gemini CLI, Anti-gravity dark for the AGY family, and the relay-ai SVG mark for the sidebar logo.
- General Favorites sidebar — view and manage your saved favorite models with a slot indicator bar (Slots used X/20).
- Antigravity Favorites sidebar — dedicated favorites panel for Antigravity sessions.
- Provider management panel — add providers from templates, delete, and trigger model-list refreshes without leaving the UI.
- Recent launch folders — picker remembers your last-used working directories for CLI launchers.
-
Server tab in
relay-ai ui— run the same API gateway asrelay-ai server, configured and launched entirely from the browser instead of a terminal wizard:- Setup form mirrors the CLI wizard: favorites-only vs. specific providers (searchable multi-select), "Mask gateway model ids" for Claude Desktop / Cowork discovery, and local-only vs. network listen mode with a password field (reuse a saved password or save a new one to the OS keychain).
- Running view shows live, copyable Anthropic and OpenAI endpoint URLs (plus one per network interface in network mode), a reveal/copy API key, and the full exposed model catalog (provider, name, Anthropic ID, OpenAI ID) — with a one-click Stop.
- Runs in-process inside the
relay-ai uiserver (no child process), so it stops automatically when the UI is closed, and shares the same saved settings as the terminal wizard so both stay in sync.
-
Codex Desktop app (
relay-ai codex-app) in the UI launcher — the Codex Desktop app now appears as a launcher card inrelay-ai uiwith correct detection paths for macOS (/Applications/Codex.app,~/Applications/Codex.app) and Windows (Programs/Codex,Programs/OpenAI Codex,openai-codex-electron), the Codex brand icon, and a dark card background. Previouslyrelay-ai codex-appwas a full working CLI command but was invisible in the UI. -
Claude Desktop (
relay-ai claude-app) in the UI launcher — Claude Desktop is now a launcher card inrelay-ai uialongside the CLI tools, with a launch-folder control suppressed (it's a GUI app). Favorites launch resolves the first matching favorite and passes it through so the terminal skips the picker. -
relay-ai server --quick/--savedand one-run override flags — after configuring the server once, start it without prompts viarelay-ai server --quick(or--saved). Any one-run option also skips the wizard:--listen local|network,--providers all|favorites|id1,id2,--free-only/--no-free-only,--mask-gateway-ids/--no-mask-gateway-ids, and--password <value>. Non-interactive shells (scripts, services, CI, pipes) use quick mode automatically; if it resolves to network mode with no--passwordand no saved password, it now exits with a clear error instead of prompting. -
--tracenow covers Codex App WebSocket traffic, plus live generation progress — the Codex App's WebSocket/v1/responseshandler had no debug logging, so--tracewas blind to nearly all Codex App traffic; it now logs incoming requests, context/compaction checks, and resolved effort just like the HTTP path. Generation also reports progress roughly every 3 seconds (running reasoning length and a tail preview), so a stuck or looping generation can be observed live instead of only after the fact. -
relay-ai antigravity/relay-ai antigravity-ide/relay-ai agy— Antigravity launcher support — one of the biggest additions in this release: launch Google's Antigravity CLI, desktop app, or IDE through relay-ai's provider registry, so you can use any configured provider's models — Claude, GPT, DeepSeek, and more — inside Antigravity instead of only Google's own models. Fully supported on both macOS and Windows, including app/IDE detection, launch, and quit on both platforms, plus a dedicated Antigravity Favorites list for quick model switching. -
relay-ai chatgpt— alias forrelay-ai codex-app. OpenAI merged the Codex desktop app into the ChatGPT desktop app on 2026-07-09; the app is now namedChatGPT.appon macOS (bundle id and config format unchanged) and opens in Codex mode for existing Codex users. Detection/launch/quit logic and UI labels updated accordingly. The Windows install path was updated by analogy with the confirmed macOS rename and is not yet verified against a real install. -
Nvidia (build.nvidia.com) provider support — Nvidia's model catalog is now available as a provider template, wired up end-to-end alongside the other native providers.
-
Kilo Code provider support — Kilo Code is now available as a provider template, including its free anonymous-access tier (no API key required to use its free models).
Fixed
-
Codex Desktop / Claude Desktop restart on Windows silently did nothing if the app minimized to the tray instead of exiting — the restart flow's
waitForQuitconsidered the app "closed" as soon as its window handle disappeared, which happens immediately for tray-minimizing apps even though the process (and its old config) is still running. The next launch would then just refocus the stale process, so a newly selected model never took effect.waitForQuitnow polls actual process existence instead of window visibility, so the existing force-kill fallback actually runs when needed. -
Security: Codex Desktop's WebSocket transport now requires the same authentication as its HTTP path — the
/v1/responsesWebSocket upgrade handler had no auth check, unlike the HTTPPOSThandler for the same route, so any local process could open a WebSocket connection to the proxy and get model completions on your configured credentials. It now enforces the identical bearer-token check. -
Security: custom provider display names are now escaped in the UI — a custom endpoint's display name was rendered into the Providers list without HTML-escaping, allowing a crafted name to run arbitrary script in the
relay-ai uipage. -
Security:
allowInsecureLocalno longer permits plaintext HTTP to public hosts — the custom-endpoint URL validator now also requires the resolved address to actually be a loopback or private/LAN address before allowinghttp://, closing a gap where a public IP could be registered with insecure HTTP. -
Security: unsafe app-launch arguments are now rejected instead of shell-escaped — the native terminal launcher's argument quoting didn't fully protect the outer shell command on every platform. Arguments outside the safe identifier character set are now rejected outright rather than escaped.
-
Codex App: non-rate-limit errors no longer show a fake "context too large" message — an invalid API key, a bad request, or an upstream outage was rewritten into a canned "conversation context was too large to summarize" message, hiding the real cause. The actual error message is now shown.
-
OAuth-authenticated Anthropic-format providers no longer break permanently after token expiry, and now work correctly through
relay-ai server— the Anthropic-passthrough path used byrelay-ai claude/codex/gemini/servernow retries once with a refreshed token on a 401, andrelay-ai server's passthrough now applies the same request handling and forwards the same custom provider headers thatrelay-ai claudealready did, instead of dropping them and corrupting streaming responses. -
relay-ai gemini: selecting a non-default model from a backend-routed provider could silently route to the wrong model — a backend-routing rewrite changed the model's internal id but Gemini CLI was still launched with the old one, so requests transparently fell back to a different model than the one selected. -
Windows: Codex CLI could be reported as "not found" even when installed — the binary-verification step didn't account for
.cmd-wrapped installs the way the actual launch step already did, and newer Node.js versions could reject running the check directly. -
relay-ai gemini: non-streaming tool calls no longer lose their arguments — a local proxy mapped tool-call results using an incorrect field name, so a non-streaming request that ended in a tool call reached the client with no arguments at all. -
relay-ai uiServer tab: rapid double-clicking Start could corrupt saved settings — two near-simultaneous start requests could both pass the "already running" check and race through setup, with the losing request's settings silently overwriting the winner's. Start requests are now serialized. -
Codex Desktop: the "keep session running" option on Ctrl+C is back — an unrelated commit had accidentally dropped the confirmation prompt, so Ctrl+C always restored your Codex config immediately with no way to decline. The prompt is restored.
-
Gemini CLI: stale OAuth auth settings no longer block relay-ai launches — if
~/.gemini/settings.jsonhadsecurity.auth.selectedTypeset tooauth-personalfrom a previous direct Gemini CLI login, Gemini CLI preferred that saved setting over relay-ai's injected proxy API key and could fail before reaching the local proxy.relay-ai gemininow launches Gemini with an isolated temporaryGEMINI_CLI_HOME, forcesgemini-api-keyauth for the child process, and cleans up the temporary overlay when Gemini exits. Fixes #13. -
Codex App: WebSocket
/v1/responsesfully implemented — the proxy now accepts WS upgrades, reads the request from the first text frame, runs the sametranslateResponsesRequest+streamResponsesResponsepath as the HTTP POST handler, and streams each SSE event back as a WS text frame (raw JSON, no SSE envelope). Fixes the "Stream error / Reconnecting 5/5" loop seen in newer Codex App versions when the proxy rejected upgrades with HTTP 503. Connection closes cleanly when the stream ends. -
Codex App: context trimming no longer over-trims by 3x — the proxy's internal character limit now matches the caller's token-to-character estimate, preventing oversized sessions from being reduced to a single message before compaction.
-
Codex App: relay-model sessions compact earlier — the app now sets
model_auto_compact_token_limitto 55% of the selected model's context window, giving compaction more headroom across providers with different practical limits. -
Codex App: compaction payloads are protected before upstream — compaction-sized requests now get oversized text/tool-output blobs clipped and are trimmed to a conservative budget before they reach Anthropic, Gemini, xAI, OpenRouter, OpenCode, or other relay providers.
-
Codex App: empty translated input no longer creates invalid Anthropic requests — empty input now becomes a non-empty placeholder message instead of
messages.0with empty content. -
UI → terminal model selection is now end-to-end — selecting a provider and model in
relay-ai uiand clicking Launch previously showed the full interactive provider/model picker in the terminal anyway. Two bugs combined to cause this: (1)claude-appandcodex-apparg parsers used a barefor...ofloop that dumped every arg — including--providerand--model— intoclaudeArgswithout callingtryConsumeRelayLaunchFlag, soparsed.launchProvider/parsed.launchModelwere alwaysundefined; (2) neither command had a boot path that checked those values. Both are now fixed. -
claude-appwith Groq: requests with more than 128 tools no longer fail — Groq's API enforces a hard limit of 128 tools per request. Claude Desktop sends its full tool set on every request — built-in file/bash tools plus every configured MCP tool and injected skill — which easily exceeds 128. The proxy now automatically truncates to 128 when routing via@ai-sdk/groq, loggingtools truncated: N → 128 (provider limit)to the trace log when trimming fires. -
Non-Anthropic providers: null optional parameters no longer cause tool-call validation errors — Open models (GPT OSS 120B, GLM, Z.AI, and similar) sometimes emit
nullfor optional tool-call parameters instead of omitting the key. Claude Desktop's schema validator treatsnullas a type mismatch and shows "Tool call validation failed: parameters for tool X did not match schema". The proxy now strips top-levelnullvalues from all tool-call inputs before returning them to the client. Applies to both streaming and non-streaming response paths. -
--tracelogs now show provider API errors — when a provider returned an error (429 rate limit, 400 bad request, 502 upstream failure, etc.), the proxy's catch block sent the error response but never logged it, so--traceoutput appeared clean even on repeated failures. All SDK-level errors in both the Anthropic-format and OpenAI-format proxy handlers are now logged with the provider npm, upstream model ID, and error message. -
Claude Desktop: direct OpenAI (ChatGPT) OAuth launches keep OAuth routing metadata — selecting an OpenAI OAuth model directly in
relay-ai claude-app, instead of through Favorites, no longer dropsauthType,oauthAccountId, or model reasoning metadata while building the local gateway catalog. This keeps GPT-5.5 and other ChatGPT OAuth models routed through the ChatGPT Codex backend instead of the public OpenAI API. Reported by @lffzdd (#15). -
New OpenAI models newer than GPT-5.5 (e.g. GPT-5.6 Sol/Terra/Luna) could fail outright when using a direct API key — a hardcoded list of "which models require OpenAI's Responses API" only named GPT-5.4 and GPT-5.5 specifically, so any newer model silently fell back to the older Chat Completions endpoint, which OpenAI rejects for these models. Every OpenAI model now defaults to the Responses API (a strict superset of Chat Completions), so this no longer needs a code update for each new model release. Reported by @tonyb760 (#17).
-
Refreshing an OAuth-based provider's model list could silently hide newly released models with no indication anything was wrong — if live model discovery failed for a ChatGPT- or SuperGrok-authenticated provider, the refresh silently overwrote your existing (possibly more current) cached model list with an older, built-in fallback list, and reported success regardless. Refreshing now keeps your existing cached list when live discovery fails, and clearly reports the failure and its cause instead of failing silently.
-
xAI OAuth-authenticated providers failed to refresh their model list — the model-refresh command didn't recognize the
xai-oauthprovider template, so refreshing a Grok OAuth provider's model catalog threw an "unsupported template" error instead of updating it. -
Anonymous/free-access providers (e.g. Kilo Code) failed with "No credential" in Codex CLI, Codex Desktop, and Claude Desktop — the shared credential-resolution logic that already correctly handled these providers in
relay-ai claude/gemini/agyhad drifted out of sync in three other launch paths, which still required a real API key even for providers designed to work without one. -
Non-streaming requests to OpenAI's ChatGPT/Codex OAuth backend failed with a confusing "Stream must be set to true" error — that backend requires streaming for every request, but a non-streaming retry (e.g. after a transient upstream error) was still forwarded as-is. relay-ai now always streams internally for that backend and assembles a complete response itself, regardless of what the client requested.
-
xAI's
grok-4.5wasn't recognized as a reasoning-effort model — the hardcoded model-name check only matchedgrok-4.3, so newer Grok models silently lost the ability to control reasoning effort. -
Reasoning effort was silently dropped for xAI models launched through Favorites/model-switching — the effort-application code looked at the gateway's local alias id instead of the real upstream model id, so the setting never applied whenever a model was chosen via the switch-menu/favorites catalog rather than a direct launch.
-
xAI context window sizing used a stale, hardcoded model-name pattern instead of live data — newer Grok models (e.g.
grok-4.5,grok-4.20) weren't recognized by the old pattern match, causing incorrect context-window sizing and premature or mistimed compaction. -
DeepSeek tool calls could leak as raw text instead of firing — DeepSeek's "DSML" tool-call markup sometimes came through the Codex App path unparsed, showing up as garbled text in the response instead of executing the intended tool call.
-
Upstream streams that died silently could hang a request forever — if an upstream provider connection stopped sending data without an error or a clean end, the request had no timeout and would hang indefinitely; stream errors also weren't being recorded to
--traceoutput. -
Windows Credential Manager silently failed to save long OAuth tokens — Windows' underlying credential store has a roughly 1,280-character limit per entry, so longer tokens (e.g. some OpenAI OAuth JWTs) failed to save without any visible error.
-
GitHub Copilot model listing was broken — the provider hit the wrong API endpoint and was missing a required header, so its model catalog couldn't be fetched even with a valid Copilot subscription.
Known limitations
- Very large pre-existing Codex App sessions may still fail relay-model compaction — sessions that already grew under native GPT-5.5 can exceed a 1 M-token relay model's practical compaction budget when switched to Claude or another relay model. relay-ai now clips oversized text/tool-output blobs and trims as a last resort, but this is best-effort recovery, not a guarantee. The reliable recovery path is to continue or compact once with a native Codex/GPT model when quota is available, or start a fresh relay-model session.