Model Gateway
Model Gateway adds subscription-backed GPT and Grok models to Claude Code. Claude Code v2.1.129+ can show those gateway models in its /model picker. Claude models keep using Anthropic normally.
Install
Section titled “Install”Run these in Claude Code:
/plugin marketplace add Eigenwise/eigenwise-toolshed/plugin install model-gateway@eigenwise-toolshed --scope projectReload the plugin, then start the Model Gateway skill:
Set up Model Gateway for me.
The skill runs setup with project-local wiring, installs and starts the local gateway, checks your subscription login, and confirms the current project’s .claude/settings.local.json. If setup asks for login, complete the browser sign-in, then let Claude run setup again to finish and confirm the project wiring.
After the wiring is confirmed, fully restart the Claude Code process for that same project. A plugin reload alone does not reload the picker cache or the settings in the new process. Select a gateway model only after that restart.
Model Gateway writes ANTHROPIC_BASE_URL to .claude/settings.local.json, never the committed .claude/settings.json. That keeps your local gateway endpoint out of other people’s checkouts. You can opt into one shared fallback URL in ~/.claude/settings.json, but a project’s local setting wins. model-gateway doctor marks the effective source and calls out conflicting gateway modes.
A Claude alias pin applies to every project already registered as wired. Model Gateway updates only gateway-owned pin values, tells you about any user-owned value it skipped, and prunes missing project directories from the registry. Restart each affected open Claude Code session before its /model alias reflects the new pin.
For a direct recovery command, use node ~/.claude/model-gateway/model-gateway.js <command>. SessionStart writes this version-independent launcher from Claude Code’s installed-plugin registry, so it follows upgrades and uses the highest remaining installed version after an uninstall or downgrade.
A process ANTHROPIC_BASE_URL has higher precedence than either settings file. If doctor or SessionStart says it shadows a wired file, Model Gateway is bypassed. If you control the Claude Code CLI launch, correct or unset that value, then restart. If the host replaces it, use the supported Claude Code CLI on the wired project instead. Model Gateway does not support Desktop routing under forced overrides on Windows or macOS, and settings, parent, or User-scope edits cannot be promised to win.
You may need to complete a browser sign-in or restart Claude Code. Claude will ask only when either step is actually needed.
Pick a model
Section titled “Pick a model”Setup now requires the proxy release’s checksum file and stops before extraction if verification fails. Keep that refusal in place and report the error rather than running the downloaded archive manually.
Gateway restart and drain commands use a private local control token automatically. Do not share the ~/.claude/model-gateway/control-token file. After an update, fully restart Claude Code so it uses the current lifecycle protocol. A hot worker update is limited to the same plugin cache; switching between a development checkout and an installed copy requires stopping the old supervisor through its bundled CLI first. These protections apply to gateway lifecycle operations, not to the separate proxy’s inference endpoint.
In Claude Code v2.1.129+, open /model and choose a row labeled From gateway. Claude Code only refetches gateway discovery
with an API-key credential. Model Gateway writes its discovery cache for OAuth subscriptions, and
new rows appear after a full Claude Code restart. /reload-plugins does not reload the picker cache.
claude-gpt-*[1m]uses your ChatGPT/Codex subscription.MODEL_WINDOW_POLICYin Model Gateway’s runtime is the authority for every gateway picker row. GPT-5.6 Sol, Terra, Luna, and GPT-6 Astra are measured rows; other Codex proxy rows use its explicit unmeasured 920k default until measured.- A
[1m]alias gives Claude Code a 1M client window, but a lower explicitautoCompactWindowstill wins. The optional325000setting is a cap, and with that cap the client compacts around292000. The alias is removed before forwarding to the backend and does not promise a 1M backend input limit. Use/contextto inspect the selected model and effective cap. claude-grok-4.5[1m]uses your Grok subscription when the Grok CLI is installed and signed in. Its measured backend window is 500k. The shared synthetic-413 sentry returns Claude Code’s compaction signal 40k tokens before that backend limit if the client has not compacted first. The alias is removed before requests reach the backend.- Claude models keep using Anthropic.
Codex rejects some JSON Schema regex Unicode property escapes, including \p{Cc} and \P{Cf}. When a deferred tool resolves, Model Gateway can make a narrow Codex-only compatibility copy of its input_schema. It supports a missing dialect or Draft 2020-12, and only a pattern on the documented positive paths: properties, compatible patternProperties values, additionalProperties, items, prefixItems, allOf, anyOf, dependentSchemas, propertyNames, and unevaluatedProperties or unevaluatedItems. Each real property atom has to be a standalone member of a negated character class, with no range, set syntax, capture, backreference, or negative regex context. The lexer consumes every allowed escape as one token, so escaped parentheses, brackets, and backslashes stay literal data rather than group or class structure. The copy removes only that atom and keeps every other regex byte. Unsupported affected schemas return a local 400 with the tool name, JSON Pointer, and reason code, before any request is forwarded or sent to another provider. Claude Code still holds the original tool schema and Anthropic requests stay byte-identical.
Route a subagent to a gateway model
Section titled “Route a subagent to a gateway model”Claude Code’s Agent tool takes an optional model override, but that parameter only accepts sonnet, opus, haiku, or fable — a fixed list on the host, independent of any gateway or installed plugin. Passing a gateway id there (for example claude-gpt-5.6-luna[1m]) is refused.
To send one subagent through a specific gateway model, skip that parameter and give the subagent its own definition file instead. Claude Code reads model: frontmatter from a subagent definition and accepts a full model id there (see Claude Code’s subagent docs):
---name: luna-reviewerdescription: Reviews code changes using the GPT-5.6 Luna gateway model.model: claude-gpt-5.6-luna[1m]tools: Read, Grep, Glob---
Review the diff for correctness and report findings.Save that as .claude/agents/luna-reviewer.md, then start a new Claude Code session before invoking it — definitions are read at session start, so a session already running won’t see a file you just added. Invoke it with subagent_type: "luna-reviewer" and no model argument in the call: the invocation param takes precedence over frontmatter when set, so leaving it out is what lets the frontmatter’s gateway id apply.
This works with Model Gateway alone; Sidequest isn’t required. Sidequest’s own execution subagents use this same frontmatter path internally, pinned to its claude-codex-auto id, which is reserved for Sidequest’s own dispatch marker system. A concrete gateway id like the one above needs no such marker. The frontmatter contract above and Model Gateway’s routing for a concrete id are both confirmed; spawning a custom agent end-to-end through this path hasn’t been separately verified here, so treat it as documented, not guaranteed.
Claude Desktop
Section titled “Claude Desktop”Claude Desktop has its own native Gateway configuration, separate from the Claude Code CLI settings above. You can point it at Model Gateway’s endpoint, but installed Desktop 1.49585.0 validates every Gateway model ID on the client side and rejects any gpt, codex, or other non-Anthropic family marker before it reaches the picker or a session. This applies to both an explicit model entry you add yourself and an ID Desktop discovers automatically; a trailing [1m] is stripped first and does not change the outcome. Only a genuinely Anthropic-backed route, such as a real Claude alias, is usable there.
This is a Desktop-side restriction, not a Model Gateway bug, and there is no supported workaround: no Anthropic-named alias to disguise a Codex or Grok route, no binary patch, no credential or auth substitution, no TLS interception, no global env or hosts trick. The Claude Code CLI remains the verified way to use gateway models. VS Code success has been reported by users but is not independently verified here. This limitation is specific to the installed Desktop version and can be revisited if a future release removes the model-family filter.
Daily use
Section titled “Daily use”There are no routine Model Gateway commands to remember. The shim supervisor checks the proxy’s /v1/models endpoint while it runs and confirms a failed probe through a fresh connection before recovering an unavailable proxy with bounded backoff. It leaves a healthy proxy alone. If a session survives a plugin update, its older plugin copy leaves the newer shim running and asks you to reload plugins or restart Claude Code. Claude handles setup, updates, authentication checks, model discovery, and settings repair through the skill.
SessionStart launches a missing supervisor outside the hook’s process tree, then waits no more than 12 seconds inside its 30-second hook budget. A slow proxy keeps starting in the background. Claude asks you to retry the Codex model in a few seconds instead of holding the session-start hook open.
When the gateway disappears or restarts, ask Claude to run doctor. It names ~/.claude/model-gateway/logs/lifecycle.jsonl and says whether it found an observed supervisor, worker, or proxy exit. The bounded records include PIDs, orderly setup/stop/restart requests, signals, and recovery outcomes. A force-killed supervisor or OS termination can leave no final record, so a missing exit entry does not prove an orderly shutdown. If the Claude CLI alias resolves an older native model than the shipped fallback, doctor and pin name the newer id and the exact persistent override command; detection stays unchanged until you choose it.
doctor can report upstream-unavailable for 60 seconds after a final Codex inference fails. It is passive evidence, independent of telemetry consent: a completed successful Codex response clears it. An attributed OpenAI 401, 403, or 429 rejection enters upstream-blocked. An attributed 429 has no TTL: setup or a completed successful Codex response clears it, and a later rejected request can latch it again. That persistent 429 blocking is a known limitation (issue #190); a retry or expiry does not cure it. Sidequest reads a cached catalog, so its readiness can lag this state by up to five minutes.
SIDEQUEST_DISCOVERY_DIRS accepts comma-separated extra catalog roots. Sidequest always keeps ~/.claude in discovery, so adding a root does not hide the installed Model Gateway catalog. Only that installed catalog has a refresh command. Fixture or shared catalogs at extra roots keep using their recorded contents without a five-minute expiry.
That refresh command is catalog --refresh --json, and Sidequest runs it whenever the installed catalog has expired. If it cannot write a fresh catalog it exits non-zero and says why on stderr: the shim is not answering /healthz, /v1/models returned an error, or the model list held no gateway ids. It keeps the stored catalog and its timestamp as they were, so Sidequest treats the attempt as a failure instead of accepting an expired file. If your gateway models disappear from a board a few minutes after each shim start, run that command yourself and read its exit code and stderr.
Running Model Gateway’s own suite uses a separate test home and never touches the installed gateway. Codex sessions dropping while tests ran was a supervisor cleanup bug, fixed in this version. Cleanup uses this home’s recorded PIDs and targeted ownership checks only: the recorded command or start time must match the live process. Windows hides the command line of a process running at a higher privilege level than the session asking, so a record whose start time still matches is accepted on that alone, and a record is discarded only when a command line it can read contradicts it. A reused PID is never stopped. When the command line is unavailable, doctor says so and names elevation as the likely cause: stop and setup then have to run from a session with the same privileges as the one that started the gateway. If startup, restart, or drain cannot confirm who owns a listener, it leaves that listener alone and startup records owner-unknown; confirmed foreign listeners are refused too. On POSIX, process probes pin their child locale to C so they can read start times without requiring a global locale settings change.
If something breaks, describe the symptom:
My gateway models disappeared from
/model. Diagnose and fix it.
Codex fails, but Claude models still work. Repair Model Gateway.
Troubleshooting model visibility
Section titled “Troubleshooting model visibility”If GPT-6 Astra is missing from /model, check the installed and serving claude-code-proxy version before diagnosing account access. Astra requires version 0.1.36 or newer. Version 0.1.35 does not include its backend allowlist, and the current doctor check can still report PASS when Astra is the missing row. Ask Claude to rerun setup, which fetches the latest GitHub release, then fully restart Claude Code. A models.json edit cannot add a backend that the proxy does not allow.
Authentication recovery has a different boundary. Complete login and let Claude run setup again; the refreshed credential can serve the already-running proxy, so a process restart is not required just for auth. Settings, discovery-cache, plugin, or model-row changes do require a full restart of the affected project process. /reload-plugins alone is not enough.
Local gateway records
Section titled “Local gateway records”The shim writes request-route metadata to ~/.claude/model-gateway/logs/request-routes.jsonl by default. Records contain the time, backend, model, request path, route and effort when present, and safe session or agent correlation fields. They do not contain request bodies, prompts, messages, tools, authentication, or arbitrary headers. Set CODEX_GATEWAY_REQUEST_LOG=0 before the shim starts, then restart the shim through setup or ensure, to disable this route log. The setting is read by the shim process at startup. CODEX_GATEWAY_REQUEST_LOG_PATH changes the file location.
Usage observability also keeps one high-water JSON file per valid session under ~/.claude/model-gateway/request-body/. It records only the largest forwarded request-body byte count seen for that session and an observation timestamp. It does not contain the request body. No retention period is promised for either local record.
When project telemetry is already enabled, route traces carry the terminal request status and status code. A failed inference cannot fabricate usage, so it does not create token-usage or limit records.
Remote Control gives each project two choices.
Use RC-compatibility mode
Section titled “Use RC-compatibility mode”RC-compatibility keeps the project’s HTTP Model Gateway transport configured. It maps api.anthropic.com to loopback in the hosts file and needs the gateway shim to bind port 80. A detected hosts entry or bound listener proves that local HTTP transport only. It also makes Claude Code treat the gateway as first-party, which can enable experimental message threading. Model Gateway refuses Codex and Grok thread continuations locally with HTTP 400 because neither backend has conversation state. Nothing is forwarded or rerouted. A client version that recognizes the refusal drops the threading beta and retries the turn with full message history. The experiment and client version can change that behavior, so do not promise a single refusal per session. On inspected Claude Code 2.1.267, Remote Control session creation uses HTTPS while the compatibility listener is HTTP; the reported 2.1.259 client and the inspected client have no verified end-to-end RC result. Normal gateway mode remains the verified inference path.
At 2.1.267, the api.anthropic.com hostname also disables client gateway discovery, so gateway rows disappear from /model in RC-compatibility mode and a cache refresh cannot restore them. Claude Code can accept and persist an explicit id such as /model claude-gpt-5.6-terra[1m], but that client-side action does not prove its later request reaches the gateway. The current cache cleaner preserves canonical [1m] ids; it is not a proposed fix for a reported request error.
Tell Claude you want to enable, disable, or diagnose RC-compatibility. After you directly confirm remote-control enable --confirm, Model Gateway creates a backup and writes its marked hosts block. Its read-only diagnosis reports the current serving supervisor as bound, bindable, unavailable (CODE), or unknown, never an untested availability claim. Start the normal-user gateway supervisor before enabling unless it reports bound or bindable. Enable checks that serving process before any backup or hosts-file write, then asks the same process to open the compatibility listener without restarting the main gateway or worker. If activation, verification, or wiring fails, it restores the exact original hosts bytes only when the file still has the bytes it wrote. Later external edits stay in place, and the command names the backup for manual recovery. A bound result permits adoption of an existing unmarked loopback mapping, including when the serving supervisor already owns the compatibility listener. An unavailable result can name another port holder and enable refuses before any hosts-file write. Docker Desktop is a common holder. Enabling also refuses before any backup, hosts write, gateway startup, or reconciliation when effective process ANTHROPIC_BASE_URL is HTTPS api.anthropic.com (including port 443), because the loopback mapping would send TLS traffic to an unsupported endpoint. If you control the Claude Code CLI launch, correct or unset that value, then restart. If the host replaces it, use the supported Claude Code CLI on the wired project instead. Desktop routing is unsupported under forced overrides on Windows and macOS, and settings, parent, or User-scope edits cannot be promised to win. Enabling synchronizes and verifies an existing writable settings target for future sessions. Existing env-only compatibility remains env-only and applies only to processes that inherit that environment. Enable never claims to change the current process environment. Disabling stays available without a bindability preflight and uses the normal safe recovery path to remove the compatibility listener.
Turn the gateway off for this project
Section titled “Turn the gateway off for this project”To get Remote Control without RC-compatibility, remove only ANTHROPIC_BASE_URL from the env object in that project’s .claude/settings.local.json. Keep every other gateway setting, then restart Claude Code. The project talks to api.anthropic.com directly and Remote Control becomes available.
That project has no gateway models after the restart: gateway rows disappear from /model and typed gateway ids do not work either. A process-exported ANTHROPIC_BASE_URL still wins over the file edit. If you control the Claude Code CLI launch, correct or unset that value, then restart. If the host replaces it, use the supported Claude Code CLI on the wired project instead. Desktop routing is unsupported under forced overrides on Windows and macOS, and settings, parent, or User-scope edits cannot be promised to win.
The generated Model Gateway reference records the agent-facing commands and configuration details used by the skill.