Repository navigation
Track Claude Code as an external CodexHub Gateway client #73
Description
Objective
Support Claude Code CLI as an external CodexHub Gateway client: Claude Code speaks Anthropic Messages to the local Gateway, while the Gateway authenticates the client, resolves models, and routes each request to a configured upstream.
This issue is the canonical product specification for that work. Claude Code is a downstream client of CodexHub models. It is explicitly not an ACP plugin, not an upstream AgentProvider runtime (#85), and Claude Code session management inside CodexHub is out of scope.
Authority: ADR-0014 (accepted product direction; implementation and live verification pending). ADR-0014 amends ADR-0001's compatibility policy and adds a narrow activation exception to ADR-0004; read it before changing any body of work here.
Approved product decisions
-
Three upstream protocols, one client surface. Claude Code always speaks Anthropic Messages to the Gateway. The Gateway must route to any of the three configured upstream formats:
anthropic_messages— native Anthropic route, preserved as close to passthrough as the Gateway's own concerns allow (model resolution, credentials, transport safety, redaction); request, semantic headers, JSON response, and incremental SSE must not be round-tripped through a lossy OpenAI representation;responses— Messages ↔ Responses translation;chat_completions— Messages ↔ Chat Completions translation.
All three are production scope, not only the official Codex upstream.
-
Every exported model is selectable inside Claude Code. Every model in the existing enabled, Gateway-exported catalog (
enabled && gateway_exported, ADR-0009/ADR-0011) must be selectable in the real Claude Code model picker — not merely visible in CodexHub, and not only as one custom default. No capability-based filtering and no second editable model list. Models deliberately disabled or not exported are not routable and stay unlisted. Selectability is not a capability claim: if a selected model cannot serve a request, that request fails explicitly (decision 3). -
Best effort with critical-content safety. Prefer equivalent conversion. Where equivalence is unavailable, attempt best-effort adaptation — without a separate opt-in — and record every non-equivalent adaptation as a named policy plus a diagnostic naming the transformed or omitted field and the reason. Never silently remove user text, images, or tool results; never break call identity; never fabricate success or usage; never silently substitute a different model. If no safe adaptation can carry essential content, return an actionable error. Best effort does not authorize blind retry after partial output or possible side effects. Unrepresentable usage detail is disclosed as unavailable, not folded into invented base counts.
-
Fixed-name and role mapping. Mappings from Claude Code's fixed model names and role aliases to Gateway-exported models are separate user choices, and explicit model selection must not be overridden by a role mapping. Removed or disabled mapping targets become visibly invalid and never silently fall back.
-
Dedicated client settings. The Claude Code card keeps connection/status controls and adds its own settings dialog: read-only searchable exported models, default model, searchable mappings, pending changes, conflicts, and accurate restart requirements. Other Clients receive no Claude-specific controls.
-
Current-user configuration with explicit activation. Connecting manages the current user's Claude Code configuration, because Claude Code does not offer the provider-map coexistence shape. An explicit Connect action may change the necessary route/default-model fields after disclosing that scope; it is not a silent side effect, and automatic republish is not permission to activate a disconnected client. Use the existing managed-client coordinator with a Claude-specific adapter: preserve unrelated configuration, back up previous values, publish atomically, detect concurrent edits, verify the owned fields, and restore only those fields on Disconnect. Never modify project configuration or Claude login credentials. Only the local Gateway credential is written (
ANTHROPIC_AUTH_TOKEN), never an upstream API key or subscription credential; secrets are masked in previews and backups are protected. -
Honest compatibility reporting. Request details show sanitized adaptation diagnostics; the Claude Code card shows a concise compatibility state. Neither inserts diagnostic prose into model answers nor records credentials or full prompts.
-
Real-client acceptance. Each upstream path must demonstrate multi-turn text, incremental streaming, tool call/result round trips, cancellation, and error handling with a real pinned Claude Code CLI. The native Anthropic path additionally proves semantic-field and SSE preservation. Deterministic or mock-only evidence does not qualify.
-
Experimental framing. Presented as experimental compatibility with pinned Claude Code versions. Do not claim Anthropic API compatibility, and do not claim Anthropic endorses routing Claude Code to non-Claude models.
Credential boundary
- Claude Code → Gateway:
ANTHROPIC_AUTH_TOKEN=<gateway_client_key>viaAuthorizationbearer. Whetherx-api-key/ANTHROPIC_API_KEYis also accepted is decided from Spike Claude Code Messages compatibility through CodexHub #74 evidence, without weakening Harden local Gateway auth so codex-app context is not spoofable #24. - Gateway → upstream: existing backend-only Codex OAuth or Provider API key.
- Upstream credentials never appear in Claude Code settings, previews, launcher text, logs, telemetry, or exports.
Child workstreams
| Issue | Workstream |
|---|---|
| #74 | Pinned live-wire protocol Spike, compatibility classification, and GO/PARTIAL/NO-GO decision (evidence gate) |
| #75 | Inbound Anthropic Messages surface routing to all three upstream protocols |
| #77 | Complete model surface: every exported model selectable in Claude Code, plus fixed-name/role mapping |
| #76 | Managed Claude Code client: current-user config adapter, card, dedicated settings dialog |
| #78 | Compatibility matrix and release gate |
Dependency order
Native GitHub dependencies are the live gate:
#74 protocol Spike
-> #75 inbound Messages (three upstream protocols)
-> #77 model selection and mapping
-> #76 managed client configuration and UI
-> #78 compatibility matrix and release gate (blocked by #75, #76, #77)
#76 requires #75 and #77; #78 requires #75, #76, and #77. No client configuration UI ships ahead of working Messages text, tools, and streaming.
Tracking acceptance criteria
- A pinned live-wire Spike records GO, scoped PARTIAL, or NO-GO for production
/v1/messages(Spike Claude Code Messages compatibility through CodexHub #74). - ADR-0014 is merged before client configuration ships; it is not evidence that the protocol works.
- No client configuration UI ships before Messages text, tools, and streaming are proven against a real CLI.
- All three upstream protocols pass real-Claude-Code acceptance (Add a Claude Code compatibility matrix and release gate #78).
- Every Gateway-exported model is selectable inside the real Claude Code picker (Expose every Gateway model to Claude Code with fixed-name and role mapping #77).
- Non-equivalent adaptations are declared and diagnosed; nothing critical is dropped silently (Add inbound Anthropic Messages API for Claude Code clients #75).
- Local Gateway credentials remain distinct from every upstream credential (Add a managed Claude Code client config adapter and settings UI #76).
- Connect requires explicit confirmation of its current-user scope and supports surgical restore (Add a managed Claude Code client config adapter and settings UI #76).
- English and Chinese documentation state the experimental scope and verified Claude Code version range (Add a Claude Code compatibility matrix and release gate #78).
- Downstream client support stays distinguished from upstream
AgentProviderwork (Spike Claude Code as a local ACP AgentProvider with API/cloud auth #85).
Primary references
- ADR-0014 — this campaign's authority; not yet verified as merged at the time of writing.
- ADR-0001 — representation seam, ordered content, opaque-field preservation, declared-adaptation outcomes.
- ADR-0004, ADR-0009, ADR-0011.
docs/research/2026-07-12-claude-code-external-client-support.md— historical scoped-PARTIAL evidence; establishes shapes, not readiness.docs/reviews/v0.3-agent-provider-roadmap.md— downstream client vs upstream AgentProvider split.docs/agents/verification-policy.md,docs/agents/real-client-e2e.md,docs/agents/user-feedback.md.- https://code.claude.com/docs/en/llm-gateway and https://code.claude.com/docs/en/model-config
- Source: https://x.com/thsottiaux/status/2076119366647894371, https://x.com/theo/status/2076114415368482854
Related
- Spike Claude Code as a local ACP AgentProvider with API/cloud auth #85 (Claude Code as a local ACP
AgentProvider— separate track, do not fold in) - Implement and qualify Anthropic Messages as a Gateway upstream protocol #246 (outbound Anthropic Messages upstream qualification — separate direction)
- Harden local Gateway auth so codex-app context is not spoofable #24, Spike complete Codex model capability exposure on third-party providers #57, Introduce a typed RoutePlan seam for Gateway routing and mutation policy #61, Introduce curated Provider presets and managed authentication #71
Activity
NOirBRight commentedon Sep 21, 2026
Campaign draft remains PARTIAL at a1c9cdc (PR 556). Offline/implementation slices for #74–#78 are on the branch, plus isolated CLI 2.1.278 loopback (discovery/text/tool/error, egress 0). Live three-protocol evidence is still blocked: no dedicated credential-contract Issue. Not ready. Worktrees retained.