Skip to content

feat(gateway): support Claude Code model discovery - #3310

Merged
steebchen merged 4 commits into
mainfrom
claude-code-model-discovery
Jul 29, 2026
Merged

steebchen merged 4 commits into
mainfrom
claude-code-model-discovery

Conversation

@steebchen

@steebchen steebchen commented Jul 29, 2026 •

Copy link
Copy Markdown
Member

Summary

Investigated whether Claude Code can be preconfigured with a set of models rather than pinning one via ANTHROPIC_MODEL and relaunching on every change. It can, in two ways — one needed a gateway change, and the docs needed a sweep.

Claude Code supports gateway model discovery. With CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 (v2.1.129+), it calls GET /v1/models?limit=1000 on the configured ANTHROPIC_BASE_URL at startup and adds the results to the /model picker, labeled "From gateway". It reads id and the optional display_name off each data entry.

We already served the correct envelope, but had no display_name, so every discovered model rendered as a raw id (claude-sonnet-4-5). This adds it.

Changes

Gateway

  • Emit display_name on /v1/models entries, mirroring name. This is also the field name the Anthropic Models API uses, so it aligns our Anthropic-format surface rather than inventing a field.
  • Test locking in the discovery contract: every entry carries a non-empty display_name, and claude-sonnet-5 resolves to "Claude Sonnet 5".

Docs sweep — the model-config story lived in several places that still presented env vars as the only mechanism, implying a relaunch to switch models:

  • apps/docs/.../guides/claude-code.mdx — new sections for ~/.claude/settings.json (model, availableModels, fallbackModel, env), gateway discovery, and ANTHROPIC_CUSTOM_MODEL_OPTION.
  • apps/ui/.../guides/claude-code.md — the marketing mirror had drifted; ported the same two sections.
  • apps/docs/.../features/anthropic-endpoint.mdx — cross-links the guide instead of growing a third copy of the same instructions.
  • apps/code marketing (page.tsx, SwitchIn60.tsx, claude-code-alternative) — replaced the "flip ANTHROPIC_MODEL" framing, which implied killing and relaunching the session, with /model mid-session switching.

Deliberately left alone: dated changelog and blog entries are published records, so they weren't retroactively rewritten. If we want this announced, the right move is a new changelog entry. Also unchanged: coding-agents, devpass-code, mimocode, agent-skills, and the Copilot migration page — none of them configure Claude Code models.

Verification

Measured against the real catalog through the Hono app:

BYTES=354926 (346.6 KB)  MS=11  TOTAL=248  DISCOVERABLE=15
claude-sonnet-5 => Claude Sonnet 5 | claude-haiku-4-5 => Claude Haiku 4.5 | ...

347 KB served in 11 ms, comfortably inside discovery's hard 3-second timeout.

Known limitation (client-side, not fixable here)

Claude Code discards discovered models whose id does not start with claude or anthropic. So discovery surfaces 15 of our 248 models; GPT-5, Gemini, and the rest are filtered out by the client, not by the gateway. Renaming them to dodge the filter would misrepresent what a model is, so the docs call this out plainly and point at ANTHROPIC_CUSTOM_MODEL_OPTION (one custom picker entry) as the escape hatch.

The settings-file half still solves the original complaint for every model: model in settings.json plus /model switches mid-session without relaunching.

  • pnpm format, pnpm build (17/17), and apps/gateway/src/models/models.spec.ts (22/22) all pass.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added “Model management” documentation, including mid-session model switching via /model.
    • Documented reading model settings from ~/.claude/settings.json and per-project .claude/settings.json.
    • Added guidance for gateway-based model discovery, including local caching and refresh/fallback behavior on lookup failures.
    • Explained how model pickers can be restricted with availableModels/fallbackModel, plus discovery filtering and custom model exposure rules.
  • Enhancements
    • Gateway model listings now include user-friendly display_name values.

Claude Code can populate its /model picker from a gateway's /v1/models
endpoint when CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1, reading `id`
and the optional `display_name` off each entry. We already served the
right envelope but had no `display_name`, so discovered models showed up
as raw ids.

Emit `display_name` (mirroring `name`, and matching the Anthropic Models
API shape) and document the settings.json options that let users switch
models without relaunching, plus the client-side filter that drops ids
not starting with claude/anthropic.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 29, 2026 14:49
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@steebchen, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 25 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5aa4462e-c29a-4fb0-abb9-267e7296836a

📥 Commits

Reviewing files that changed from the base of the PR and between 8f87abb and d5d53f6.

📒 Files selected for processing (3)
  • apps/code/src/app/claude-code-alternative/page.tsx
  • apps/docs/content/guides/claude-code.mdx
  • apps/ui/src/content/guides/claude-code.md

Walkthrough

The gateway now returns display_name for each model. Claude Code documentation and product copy describe startup configuration, /model switching, model restrictions, gateway discovery, caching, filtering, and custom picker entries.

Changes

Model management

Layer / File(s) Summary
Gateway model response contract
apps/gateway/src/models/models.ts, apps/gateway/src/models/models.spec.ts
The /v1/models schema and response now include display_name, derived from name or the model ID, with tests covering response types and model mapping.
Claude Code model management guidance
apps/docs/content/guides/claude-code.mdx, apps/docs/content/features/anthropic-endpoint.mdx, apps/ui/src/content/guides/claude-code.md
The guides document startup settings, /model session switching, availableModels, fallbackModel, gateway discovery and caching, client-side filtering, and custom model entries.
Product model-switching copy
apps/code/src/app/claude-code-alternative/page.tsx, apps/code/src/app/page.tsx, apps/code/src/components/SwitchIn60.tsx
FAQ, landing-page, and setup text now describes setting ANTHROPIC_MODEL or switching models with /model.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: smakosh

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: adding Claude Code model discovery support in the gateway.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude-code-model-discovery

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/docs/content/guides/claude-code.mdx`:
- Around line 113-118: Update the Claude Code settings example by replacing the
hardcoded catalog-derived IDs in availableModels with placeholders, while
preserving the fallbackModel example as appropriate. Add a link or clear
direction to the live models catalog so readers can select current model IDs
instead of relying on documented values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4f33bdca-a548-4e95-94c5-9bbac850ecac

📥 Commits

Reviewing files that changed from the base of the PR and between 2262df1 and 22be8bb.

📒 Files selected for processing (3)
  • apps/docs/content/guides/claude-code.mdx
  • apps/gateway/src/models/models.spec.ts
  • apps/gateway/src/models/models.ts

Comment on lines +113 to +118
```json title="~/.claude/settings.json"
{
"availableModels": ["claude-sonnet-5", "claude-haiku-4-5"],
"fallbackModel": ["claude-haiku-4-5"]
}
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Avoid hardcoding catalog model IDs.

Replace the concrete availableModels list with placeholders and direct readers to the live models catalog. As per coding guidelines, “Do not hardcode catalog-derived lists of models … in documentation; link to live catalog pages instead.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/docs/content/guides/claude-code.mdx` around lines 113 - 118, Update the
Claude Code settings example by replacing the hardcoded catalog-derived IDs in
availableModels with placeholders, while preserving the fallbackModel example as
appropriate. Add a link or clear direction to the live models catalog so readers
can select current model IDs instead of relying on documented values.

Source: Coding guidelines

The Claude Code model-config story lived in several places that still
presented env vars as the only mechanism, implying a relaunch to switch
models.

- ui guide: port the settings.json and gateway-discovery sections so the
  marketing mirror matches apps/docs again
- anthropic-endpoint: cross-link the guide rather than adding a third
  copy of the same instructions
- code marketing: replace the "flip ANTHROPIC_MODEL" framing with /model
  mid-session switching

Dated changelog and blog entries are left as published records.

Co-Authored-By: Claude <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/code/src/app/claude-code-alternative/page.tsx`:
- Line 119: Update the explanatory text around the Claude Code endpoint setup to
clarify that gateway discovery exposes only model IDs beginning with “claude” or
“anthropic” through /model. State that non-Claude models should be selected via
ANTHROPIC_MODEL for startup/default use, with ANTHROPIC_CUSTOM_MODEL_OPTION as
the optional custom picker mechanism.

In `@apps/code/src/app/page.tsx`:
- Line 49: Clarify the Claude Code model-switching copy in
apps/code/src/app/page.tsx:49 and apps/code/src/components/SwitchIn60.tsx:53 so
“/model” is described as applying only to discoverable Claude/Anthropic gateway
models, while other gateway models require ANTHROPIC_MODEL or
ANTHROPIC_CUSTOM_MODEL_OPTION; keep both surfaces consistent.

In `@apps/ui/src/content/guides/claude-code.md`:
- Around line 72-82: Update the settings example near the model-switching
guidance so the project-level .claude/settings.json variant does not contain a
literal API token; use a local environment-variable reference there, while
retaining the user-level or shell configuration guidance for
ANTHROPIC_AUTH_TOKEN and documenting that the token must be supplied separately.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d7a65233-d712-4de3-9d2e-640167946869

📥 Commits

Reviewing files that changed from the base of the PR and between 22be8bb and 8f87abb.

📒 Files selected for processing (5)
  • apps/code/src/app/claude-code-alternative/page.tsx
  • apps/code/src/app/page.tsx
  • apps/code/src/components/SwitchIn60.tsx
  • apps/docs/content/features/anthropic-endpoint.mdx
  • apps/ui/src/content/guides/claude-code.md

question: "Can I keep using the Claude Code CLI with DevPass?",
answer:
"Yes. Claude Code accepts a custom endpoint, so switching is two environment variables: set ANTHROPIC_BASE_URL to the DevPass endpoint and ANTHROPIC_AUTH_TOKEN to your DevPass key, then run claude as usual. No reinstall, no SDK changes — and you can flip ANTHROPIC_MODEL to run non-Anthropic models through the same CLI.",
"Yes. Claude Code accepts a custom endpoint, so switching is two environment variables: set ANTHROPIC_BASE_URL to the DevPass endpoint and ANTHROPIC_AUTH_TOKEN to your DevPass key, then run claude as usual. No reinstall, no SDK changes — and you can switch models mid-session with /model, or set ANTHROPIC_MODEL to run non-Anthropic models through the same CLI.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== target file excerpt =="
if [ -f apps/code/src/app/claude-code-alternative/page.tsx ]; then
  sed -n '1,180p' apps/code/src/app/claude-code-alternative/page.tsx | cat -n
else
  echo "target file not found"
fi

echo
echo "== searches for gateway/model discovery symbols =="
rg -n "ANTHROPIC_CUSTOM_MODEL_OPTION|ANTHROPIC_MODEL|llm-gateway|Gateway|discover|gateway|claude|anthropic|model" apps/code/src apps -g '*.ts' -g '*.tsx' -g '*.md' -g '*.mdx' 2>/dev/null | head -n 200

echo
echo "== git diff stat/name =="
git diff --stat HEAD~1..HEAD 2>/dev/null || git diff --stat
git diff --name-only HEAD~1..HEAD 2>/dev/null || git diff --name-only

Repository: theopenco/llmgateway

Length of output: 30046


🌐 Web query:

Claude Code LLM gateway protocol /model custom model option ANTHROPIC_CUSTOM_MODEL_OPTION

💡 Result:

The ANTHROPIC_CUSTOM_MODEL_OPTION environment variable in Claude Code is used to add a custom model entry to the /model picker, allowing users to manually make non-standard or gateway-specific models selectable without replacing the built-in model aliases [1][2][3]. ### Usage and Functionality When you set ANTHROPIC_CUSTOM_MODEL_OPTION to a model ID, that model becomes available in the Claude Code model picker [1][2]. This is particularly useful for deployments using an LLM gateway (configured via ANTHROPIC_BASE_URL) where you want to route requests to specific models not found in Claude Code's default built-in list [4][2]. Additional environment variables are available to customize this entry [1][3]: * ANTHROPIC_CUSTOM_MODEL_OPTION_NAME: The display name for the model in the picker (defaults to the model ID if not set) [1][3]. * ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION: The description text shown in the picker (defaults to "Custom model " if not set) [1][3]. * ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES: A comma-separated list of capabilities (e.g., effort, thinking) the custom model supports [1]. ### Gateway Context For LLM gateway deployments, Claude Code can also automatically populate the /model picker by querying the gateway's /v1/models endpoint if CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 is enabled [4][5][2]. ANTHROPIC_CUSTOM_MODEL_OPTION is primarily needed when this automatic discovery is disabled, or when it fails to return the specific model you wish to use [6][2]. Claude Code does not validate the model ID provided via ANTHROPIC_CUSTOM_MODEL_OPTION, so you can pass any string that your specific API gateway or endpoint accepts [2]. Note that adding a custom option does not automatically update or replace built-in model aliases (like haiku or sonnet); if you intend for those aliases to also use your custom model, you must explicitly set the corresponding ANTHROPIC_DEFAULT_*_MODEL environment variables [7].

Citations:


🌐 Web query:

Claude Code /model command custom model options

💡 Result:

In Claude Code, the /model command is the primary interface for managing and switching between AI models [1][2]. You can use it in several ways: Interactive Picker: Run /model without arguments to open an interactive picker where you can select from available models [1][3]. You can choose to switch the model for the current session only or save your choice as the default for future sessions [1][3]. Switching Models: Run /model <alias|name> to switch immediately to a specific model or alias (e.g., sonnet, opus, haiku, fable) [1][2][4]. Custom Model Options: If you need to use a custom model, such as one via an LLM gateway, Bedrock, or Vertex deployment, you can add it to the /model picker using specific environment variables [5][6]. These allow you to define the model's display name, description, and supported capabilities without replacing the built-in defaults [5]. Key environment variables for this include: ANTHROPIC_CUSTOM_MODEL_OPTION: The model ID to add as a custom entry [5]. ANTHROPIC_CUSTOM_MODEL_OPTION_NAME: The display name shown in the picker [5]. ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION: The description shown in the picker [5]. ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES: A comma-separated list of capabilities (e.g., effort, thinking) the model supports [5]. Additional configuration methods outside of the /model command include: Startup Flags: Use claude --model <alias|name> to set the model for a single session at launch [1][2]. Environment Variables: Set ANTHROPIC_MODEL=<alias|name> to define a permanent default [1][2]. Settings File: Configure the model field in your Claude Code settings file to persist a default across all sessions [1][7]. You can check your currently active model at any time by running the /status command [2]. Note that while standard aliases like sonnet or opus are supported, using a custom endpoint may require providing the full model ID rather than an alias [6].

Citations:


🌐 Web query:

Claude Code LLM gateway protocol filter models claude anthropic

💡 Result:

Claude Code supports an LLM gateway protocol that allows organizations to route traffic through internal infrastructure for auditing, authentication, cost tracking, and provider abstraction [1][2]. Model discovery is a feature of this protocol that enables Claude Code to query a gateway's /v1/models endpoint at startup and dynamically populate the model picker in the terminal [1][3]. Regarding model filtering: When using model discovery, Claude Code applies a filter to the list returned by the gateway. Specifically, only models whose IDs begin with "claude" or "anthropic" are added to the model picker [4]. This filtering ensures that the picker is populated with models compatible with Claude Code's expected capabilities [4]. If a gateway serves other models that you wish to use, you can manually add these aliases to your Claude Code configuration using the relevant model configuration environment variables rather than relying on automated discovery [1][3][5]. Key details for gateway operators include: - Supported API Formats: Anthropic Messages, Amazon Bedrock (InvokeModel), and Google Cloud Agent Platform (:rawPredict) [1][2]. - Discovery Endpoint: Gateways should expose GET /v1/models to allow Claude Code to fetch available models [1][5]. - Configuration: Developers can enable discovery by setting the CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 environment variable [3][5]. - Debugging: You can verify discovery status by checking the debug log (~/.claude/debug/.txt), where the tool records the number of models cached or any errors encountered during the process [3][4]. Anthropic does not endorse, maintain, or audit third-party gateway products and does not provide support for routing Claude Code to non-Claude models through these gateways [6].

Citations:


🌐 Web query:

Claude Code LLM gateway connector /v1/models discovery Claude Code

💡 Result:

Claude Code supports automatic model discovery via an LLM gateway's /v1/models endpoint, which allows the tool to populate its internal model picker with models provided by your gateway [1][2]. To enable this feature, you must set the environment variable CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 [3][4]. This functionality is disabled by default to prevent leaking all models accessible to a shared API key to every user [4]. Key details regarding this process include: 1. Protocol: When enabled, Claude Code performs a GET request to /v1/models?limit=1000 at startup [2]. The gateway must respond using the Anthropic Messages API format [1][2]. 2. Authentication: The request uses the configured ANTHROPIC_AUTH_TOKEN (or an x-api-key header if an API key helper is in use) [2]. It is essential that the gateway handles this request directly, as redirects are treated as failures for security reasons [2]. 3. Filtering and Caching: Discovered models are filtered (only models with IDs starting with "claude" or "anthropic" are typically added, unless otherwise configured) and then cached to a local file (~/.claude/cache/gateway-models.json) to be refreshed at each startup [2][5]. 4. Interaction: Once discovered, these models appear in the Claude Code /model picker, labeled as "From gateway" [2]. If discovery is disabled or fails to return specific models, you can manually add custom entries to the picker using the ANTHROPIC_CUSTOM_MODEL_OPTION environment variable [3][4][6]. This process requires Claude Code version 2.1.129 or later for the opt-in discovery behavior [3].

Citations:


Clarify gateway model discovery before /model.

Line 119 can make it sound like every GPT/Gemini/other gateway model is directly selectable via /model after just setting ANTHROPIC_BASE_URL. Claude Code’s gateway discovery only exposes models IDs starting with claude or anthropic; non-Claude models use ANTHROPIC_MODEL for startup/default switching, with optional custom picker entry via ANTHROPIC_CUSTOM_MODEL_OPTION.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/code/src/app/claude-code-alternative/page.tsx` at line 119, Update the
explanatory text around the Claude Code endpoint setup to clarify that gateway
discovery exposes only model IDs beginning with “claude” or “anthropic” through
/model. State that non-Claude models should be selected via ANTHROPIC_MODEL for
startup/default use, with ANTHROPIC_CUSTOM_MODEL_OPTION as the optional custom
picker mechanism.

Source: MCP tools

icon: AnthropicIcon,
description:
"Two env vars and Claude Code routes through LLM Gateway. Use any model — Claude, GPT-5, Gemini, GLM — with a single ANTHROPIC_MODEL flip.",
"Two env vars and Claude Code routes through LLM Gateway. Use any model — Claude, GPT-5, Gemini, GLM — and switch mid-session with /model.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## Locate relevant files"
fd -a 'page\.tsx|SwitchIn60\.tsx' apps/code/src 2>/dev/null || true

echo
echo "## Relevant lines"
if [ -f apps/code/src/app/page.tsx ]; then
  nl -ba apps/code/src/app/page.tsx | sed -n '40,55p'
fi
if [ -f apps/code/src/components/SwitchIn60.tsx ]; then
  nl -ba apps/code/src/components/SwitchIn60.tsx | sed -n '45,58p'
fi

echo
echo "## Search for /model and model env/config copy"
rg -n -- '-- /\bmodel\b|ANTHROPIC_MODEL|ANTHROPIC_CUSTOM_MODEL_OPTION|custom .*model|non-cclaude|claude|anthropic|gateway' apps/code/src README.md docs lib . 2>/dev/null | head -200

Repository: theopenco/llmgateway

Length of output: 1938


🌐 Web query:

Claude Code LLM Gateway protocol /model discovery filter claude anthropic custom picker

💡 Result:

Claude Code supports an LLM Gateway protocol that allows it to interact with Anthropic-compatible gateways for model discovery and inference [1][2][3]. Model Discovery Model discovery enables Claude Code to automatically populate its internal /model picker with models returned by a gateway's /v1/models endpoint [1][2]. This feature is opt-in and disabled by default to prevent gateways from surfacing unauthorized models to users [1][4]. Configuration To enable gateway model discovery, you must set the environment variable CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 in your shell or settings file [1][2]. This requires Claude Code version 2.1.129 or later [1][5]. Protocol Details - Endpoint: The client makes a GET request to /v1/models (with a limit parameter of 1000) [1][6]. - Response Format: Gateways must return an Anthropic-style JSON object containing a list of models, specifically using IDs that begin with "claude" or "anthropic" (e.g., claude-family-major-minor) [6][7]. - Filtering: Only models whose IDs match these prefix requirements are added to the picker; others are filtered out [7]. - Caching: Discovered results are cached in the local ~/.claude/cache/gateway-models.json file (or equivalent based on OS) and refreshed at startup [1]. - Troubleshooting: You can verify discovery status by running claude --debug and checking the log file for [gatewayDiscovery] entries [2][7]. Custom Picker Alternatives If discovery is disabled or a specific model is not returned, you can manually add a model to the picker using the ANTHROPIC_CUSTOM_MODEL_OPTION environment variable [4][8]. Additionally, the availableModels managed setting can be used to restrict which models are visible in the picker, even if they are discovered [1][9]. Note on Edge Cases: As of mid-2026, there are known interactions where other settings, such as CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, may unintentionally block the gateway discovery process if not configured correctly [10].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## Relevant lines in app/page.tsx"
awk 'NR>=42 && NR<=54 {printf "%5d  %s\n", NR, $0}' apps/code/src/app/page.tsx

echo
echo "## Relevant lines in SwitchIn60.tsx"
awk 'NR>=48 && NR>=60 {printf "%5d  %s\n", NR, $0}' apps/code/src/components/SwitchIn60.tsx

echo
echo "## Search for Claude Code /model and env-var mentions"
rg -n -- '-- /\bmodel\b|ANTHROPIC_MODEL|ANTHROPIC_CUSTOM_MODEL_OPTION|ENABLE_GATEWAY_MODEL_DISCOVERY|custom .*model|switch mid-session|model-switching|/model' apps/code/src README.md docs . 2>/dev/null | head -200

echo
echo "## Python source-string probe for exact copy at cited lines"
python3 - <<'PY'
from pathlib import Path
paths = ["apps/code/src/app/page.tsx", "apps/code/src/components/SwitchIn60.tsx"]
for path in paths:
    lines = Path(path).read_text().splitlines()
    target = 49 if path.endswith("app/page.tsx") else 53
    print(f"{path}:{target}: {lines[target-1]!r}")
PY

Repository: theopenco/llmgateway

Length of output: 29326


Clarify Claude Code’s /model availability.

Claude Code discovery only adds gateway models whose IDs start with claude or anthropic; other gateway models should be selected via ANTHROPIC_MODEL or ANTHROPIC_CUSTOM_MODEL_OPTION.

  • apps/code/src/app/page.tsx#L49: qualify “switch mid-session with /model” so it does not apply to arbitrary gateway IDs.
  • apps/code/src/app/claude-code-alternative/page.tsx#L119: apply the same qualification here if this surface is still part of the consolidated concern.
📍 Affects 2 files
  • apps/code/src/app/page.tsx#L49-L49 (this comment)
  • apps/code/src/components/SwitchIn60.tsx#L53-L53
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/code/src/app/page.tsx` at line 49, Clarify the Claude Code
model-switching copy in apps/code/src/app/page.tsx:49 and
apps/code/src/components/SwitchIn60.tsx:53 so “/model” is described as applying
only to discoverable Claude/Anthropic gateway models, while other gateway models
require ANTHROPIC_MODEL or ANTHROPIC_CUSTOM_MODEL_OPTION; keep both surfaces
consistent.

Source: MCP tools

Comment on lines +72 to +82
Environment variables are read once at startup, so changing `ANTHROPIC_MODEL` means restarting Claude Code. To switch models mid-session instead, put the configuration in `~/.claude/settings.json` (user-wide) or `.claude/settings.json` (per project) and use `/model` to switch on the fly:

```json
{
"env": {
"ANTHROPIC_BASE_URL": "https://api.llmgateway.io",
"ANTHROPIC_AUTH_TOKEN": "llmgtwy_your_api_key_here"
},
"model": "claude-sonnet-5"
}
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Repository files matching claude-code.md:"
fd -a 'claude-code\.md$' . || true

file="$(fd 'claude-code\.md$' . | head -n 1 || true)"
if [ -n "${file:-}" ]; then
  echo "Selected file: $(realpath "$file")"
  wc -l "$file"
  echo "---- Relevant section ----"
  sed -n '60,95p' "$file" | cat -n
fi

echo "---- Search for project/user settings examples in repo ----"
rg -n '\.claude/settings\.json|~\/\.claude/settings\.json|ANTHROPIC_AUTH_TOKEN|ANTHROPIC_BASE_URL' . --glob '!node_modules' --glob '!dist' --glob '!build' | head -n 200

echo "---- Package/config references (if any) ----"
git ls-files | rg 'package(-lock)?\.json|pnpm-lock|yarn.lock|bun.lock|\.claude/settings\.json$|claude-code\.md$' || true

Repository: theopenco/llmgateway

Length of output: 11233


🌐 Web query:

Claude Code settings env model token project settings .claude settings.json

💡 Result:

Claude Code uses a hierarchical configuration system based on settings files and environment variables to manage its behavior, model selection, and project-specific settings [1][2][3]. Configuration Files and Precedence Settings are applied in order of precedence, from highest to lowest: 1. Managed Settings: System or organization-wide policies (e.g., managed-settings.json) [2][3]. 2. Command Line: Flags used when launching the claude command [2][4]. 3. Local Project Settings (.claude/settings.local.json): Personal, project-specific settings that are git-ignored [1][5][3]. 4. Shared Project Settings (.claude/settings.json): Project-level settings that are committed to source control and shared with the team [1][3]. 5. User Settings (~/.claude/settings.json): Global settings that apply to all projects [1][5][3]. Important: The file ~/.claude.json is a separate configuration file used for OAuth sessions, MCP server configurations, per-project state, and caches; do not include these settings in your settings.json files [1][2]. Model Configuration You can configure the model used by Claude Code through several methods: - During a session: Use the /model command [6]. - At startup: Use the --model flag [6]. - Environment Variable: Set ANTHROPIC_MODEL (or specific variables like ANTHROPIC_DEFAULT_SONNET_MODEL) [7][6]. - Settings File: Define the model field within your settings.json [6][8]. Environment Variables Environment variables can be set in your shell or defined under the env key within any settings.json file [9][10]. When both a shell environment variable and a settings file env block exist, the settings file value generally takes precedence [9]. Changes to the env block in settings files take effect when saved (or upon the next launch, depending on the specific variable) [9]. Project Settings Implementation For project-specific needs, use the.claude directory at the root of your repository [1][3]. -.claude/settings.json: Use this for team-shared configurations that should be version-controlled [1][5]. -.claude/settings.local.json: Use this for your personal preferences. Claude Code will automatically add this to your git excludes file if it is created by the tool, but you should manually add it to your.gitignore if you create it yourself [1][9][3].

Citations:


🌐 Web query:

Claude Code /model command precedence local.project settings.json model env

💡 Result:

In Claude Code, model selection is determined by a hierarchy of precedence. When resolving which model to use, the system evaluates configurations from the most immediate session-specific overrides down to default settings [1][2]. The standard precedence for the active session model is [1][2]: 1. During-session change: The /model command [1][2]. 2. Startup flag: The claude --model command-line argument [1][2]. 3. Environment variable: ANTHROPIC_MODEL [1][2]. 4. Settings: The model field in your configuration files [1][2]. 5. Default: The system's built-in default [1][2]. Settings Precedence For the model setting itself (and other configurations), Claude Code processes settings files based on the following scope precedence, where higher-level files override lower-level ones [3][4][5]: 1. Managed settings (highest priority, cannot be overridden) [3][4]. 2. Local project settings (.claude/settings.local.json) [3][4][5]. 3. Project settings (.claude/settings.json) [3][4][5]. 4. User settings (~/.claude/settings.json) (lowest priority) [3][4][5]. Important Caveats - Frontmatter Overrides: Slash commands and agents can define a model: field in their YAML frontmatter [6]. This pinned model takes precedence over the active session model, and there is currently no native session-level override to force these commands to use the session's active model instead of their pinned model [6]. - Environment Variables in Settings: If you define environment variables (such as ANTHROPIC_MODEL) within the env block of a settings file, those values take precedence over a model setting defined in the same file [7][8]. Furthermore, environment variables set directly in your shell process override values defined in settings files [5]. - Organization Overrides: If an administrator has configured an organization-level default model, that setting will take precedence over user, project, and local settings [1].

Citations:


Do not put the API token in the project settings alternative.

ANTHROPIC_AUTH_TOKEN belongs in user settings or shell environment variables. Keep .claude/settings.json as a shared/project example without exposed credentials, e.g. by pointing ANTHROPIC_AUTH_TOKEN to a local variable and documenting the token separately.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/ui/src/content/guides/claude-code.md` around lines 72 - 82, Update the
settings example near the model-switching guidance so the project-level
.claude/settings.json variant does not contain a literal API token; use a local
environment-variable reference there, while retaining the user-level or shell
configuration guidance for ANTHROPIC_AUTH_TOKEN and documenting that the token
must be supplied separately.

Source: MCP tools

Gateway discovery only surfaces ids starting with claude/anthropic, and
the guide sent readers to ANTHROPIC_CUSTOM_MODEL_OPTION, which holds one
entry. availableModels is the better answer: it accepts arbitrary
gateway model ids and renders each as its own /model picker row.

Verified against Claude Code v2.1.220 with a local probe endpoint: an id
listed in availableModels is forwarded verbatim, while an unlisted one
is silently swapped for the default model. Documented that swap, since
it fails quietly.

Co-Authored-By: Claude <noreply@anthropic.com>
@steebchen
steebchen enabled auto-merge July 29, 2026 15:10
The FAQ answer implied /model lists every model. It lists the Claude
ones; ANTHROPIC_MODEL reaches the rest.

Co-Authored-By: Claude <noreply@anthropic.com>
@steebchen
steebchen disabled auto-merge July 29, 2026 15:17
@steebchen
steebchen merged commit 7e5c37f into main Jul 29, 2026
11 checks passed
@steebchen
steebchen deleted the claude-code-model-discovery branch July 29, 2026 15:17
pull Bot pushed a commit to soitun/llmgateway that referenced this pull request Jul 30, 2026
## Summary

Corrects guidance shipped in theopenco#3310. That PR claimed `availableModels`
adds non-Claude models to the `/model` picker. **It does not.**
`availableModels` filters the rows Claude Code already has; it never
creates new ones.

This came from a user report: custom gateway model IDs added to
`availableModels` never appeared in `/model` on Claude Code 2.1.220.
They were right.

## What I got wrong

In theopenco#3310 I tested that `availableModels` makes an arbitrary ID
*selectable* (a listed `gpt-5` was forwarded verbatim; an unlisted one
was silently swapped for the default) and inferred from the docs that it
would therefore render a picker row. I flagged the row rendering as the
one thing I couldn't verify, because the picker is an interactive TUI.
That inference was wrong.

## Verification

Drove the real TUI through a pty against a local gateway serving three
models — `claude-sonnet-5`, `gemini-3.5-flash`, `gpt-5`.

Claude Code called `GET /v1/models?limit=1000`, then wrote this cache:

```json
{"baseUrl":"http://127.0.0.1:8124","models":[{"id":"claude-sonnet-5","display_name":"Claude Sonnet 5"}]}
```

Only the Claude model survived — the other two were dropped at ingest,
before the picker. Adding them to `availableModels` produced no rows
either. The picker header states the rule outright:

> "Switch between Claude models… For other/previous model names, specify
with `--model`."

`ANTHROPIC_CUSTOM_MODEL_OPTION=gemini-3.5-flash` **did** render, as row
7 — so it's now documented as the single-row mechanism.

| Mechanism | Non-Claude row in `/model`? |
|---|---|
| Gateway discovery | No — filtered at ingest |
| `availableModels` | No — filters existing rows only |
| `ANTHROPIC_CUSTOM_MODEL_OPTION` | Yes, exactly one |
| `ANTHROPIC_MODEL` / `--model` | Selects it, no row |

## Changes

- `guides/claude-code.mdx` + `ui/content/guides/claude-code.md` —
replaced the `availableModels` section with the verified mechanisms;
added a "Selecting Any Other Model" section for `ANTHROPIC_MODEL` /
`--model`.
- `features/anthropic-endpoint.mdx` — the cross-link callout repeated
the same wrong claim.

The gateway `display_name` change from theopenco#3310 is unaffected and still
correct: it's what labels discovered Claude models.

`pnpm format` and `pnpm build` (17/17) pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Clarified how Claude Code’s model picker handles Claude and non-Claude
models.
* Explained that `availableModels` filters existing Claude model entries
and does not add new models.
* Documented how to add a custom picker option or select other models
directly using environment variables or command-line options.
* Updated gateway discovery guidance to reflect Claude-only model
filtering and caching behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants