Skip to content

Expose every Gateway model to Claude Code with fixed-name and role mapping #77

Closed

Description

@NOirBRight

Part of #73.

Blocked by: #74, #75 (native dependencies). The catalog/protocol contract must be settled before any client UI consumes it.

Objective

Make every Gateway-exported model selectable inside real Claude Code, and define how Claude Code's fixed model names and role aliases map onto those models — with automatic catalog synchronization and fail-closed diagnostics.

Authority

ADR-0014 "Model selection": every model in the existing enabled, Gateway-exported catalog must be selectable inside Claude Code, not merely visible in CodexHub or usable as one custom default. No capability-based filtering, no second editable model list. Claude-compatible IDs must resolve unambiguously to the original Provider/model identity; display labels are not routing identities. Existing clients' discovery must remain compatible. Exact discovery format, role names, and refresh behavior are facts to establish in #74, not assumptions.

Scope

1. Complete, compatible model surface

  • Source set: the existing enabled, Gateway-exported catalog (provider.enabled && model.enabled && model.gateway_exported; ADR-0009/ADR-0011). Do not create a second list, a per-client allowlist, or capability filtering.
  • Every model in that set must be selectable in the pinned real Claude Code picker. Spike Claude Code Messages compatibility through CodexHub #74 records the mechanism the CLI actually supports: Anthropic-shaped discovery, an alias-per-model projection, a custom-model option, or a combination. If the verified CLI constrains discovery IDs (e.g. a claude*/anthropic* prefix rule), project a stable, collision-free alias per exported model rather than dropping models from the list.
  • Projection follows ADR-0011 republish semantics: catalog changes update the Client Projection; display_name is presentation only, and routing identity remains the canonical provider/model selector.
  • Keep the existing OpenAI-shaped GET /v1/models contract compatible for current consumers; a Claude-specific projection must not break them.

2. Identity and round-trip

  • Every projected ID (alias or canonical slug) resolves to exactly one canonical Gateway selector, with no case loss, no prefix ambiguity, and no fuzzy matching.
  • Collisions are impossible by construction, or fail closed at publish time with an actionable diagnostic.
  • Removed/disabled/renamed models: the mapping becomes visibly invalid; never silently fall back to another model. Define migration, deprecation, and historical-session behavior.

3. Fixed names and role mappings

4. Synchronization

Out of scope

The inbound Messages route (#75), client configuration writing, the card and settings dialog (#76), the release matrix (#78), and any ACP/AgentProvider work (#85).

Acceptance criteria

  • Evidence from the pinned real Claude Code shows every exported model present and selectable in the client's own model picker.
  • A model with no capability claim still appears as selectable; requests it cannot serve fail explicitly at Add inbound Anthropic Messages API for Claude Code clients #75's layer rather than disappearing from the list.
  • Each projected ID round-trips to exactly one canonical Gateway selector in tests, including provider-qualified IDs and mixed case.
  • Alias/ID collisions and removed or disabled models fail closed with actionable diagnostics and visible invalid mapping state.
  • Fixed-name and role mappings route as configured in traces, without overriding an explicit model selection.
  • An empty mapping set still yields a working default-model path.
  • Catalog change ⇒ projection republish, covered by a test (added, removed, disabled, renamed).
  • Existing /v1/models consumers and their tests remain green.
  • Discovery/projection stays disabled or inert until the Add inbound Anthropic Messages API for Claude Code clients #75 route is available.

Required verification

Risk class: strict — routing identity, persisted contract, catalog projection. Use the repository launcher; never a bare python/pytest.

.\scripts\codexhub-python.cmd -m pytest tests/test_route_plan_seam.py tests/test_providers_config.py tests/test_maintained_catalog.py -q
.\scripts\codexhub-python.cmd -m pytest -q --ignore=tests/test_real_client_e2e.py
.\scripts\codexhub-python.cmd scripts/report_quality_gates.py

Rust/frontend contract suites when the projection touches exported Rust structures:

Push-Location src-tauri
cargo test --locked
cargo clippy --locked --all-targets -- -D warnings
Pop-Location

Linux: ./scripts/verify-linux.sh for the affected boundaries. Real-CLI picker evidence is recorded with the exact pinned version from #74.

References

  • src-python/gateway_catalog_runtime.py, src-python/providers_config.py, src-tauri/src/gateway/inject.rs (projection helpers), src-python/maintained_catalog.py
  • ADR-0009, ADR-0011
  • docs/research/2026-07-12-claude-code-external-client-support.md (discovery request shape — verify against the pinned CLI)

Document status

ADR-0014 is committed in draft PR #556 at ed76f0a6e22d3188879504638b2943f5bb855d41, not yet merged to main. The pinned link is readable now; the document is accepted direction, not live protocol evidence.

Activity

  1. changed the title [-]Export stable Claude-compatible model aliases and discovery[/-] [+]Expose every Gateway model to Claude Code with fixed-name and role mapping[/+] on Sep 20, 2026
  2. NOirBRight commented on Sep 20, 2026

    @NOirBRight
    OwnerAuthor

    Early version-pinned preparation finding (STATIC source inspection only, not yet runtime acceptance): the installed Claude Code 2.1.278 discovery path is opt-in via CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY and filters returned IDs with /(claude|anthropic)/i (substring, not an anchored prefix). It accepts a data array with id plus optional display_name/description, so a new Anthropic envelope is not automatically required.

    Implication to verify in #74: discovery-based full-catalog selection needs stable Claude-compatible aliases for otherwise nonmatching Gateway IDs. Preserve canonical Provider/model identity and existing clients’ /v1/models behavior. The one-custom-model environment option alone cannot meet the complete-catalog requirement. Other picker configuration mechanisms and alias normalization are still being checked; do not generalize a discovery filter into a claim that every possible picker source rejects arbitrary IDs.

    #74 implementer has the opt-in/filter details for a credential-free loopback test. No live provider calls or user configuration changes occurred.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestneeds-triageMaintainer needs to evaluate this issuewayfinder:taskWayfinder implementation task

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions