Repository navigation
[Bug]: Claude model picker not synchronized with Claude Code model list, unlike Codex #13875
Description
Activity
- addedbugSomething is broken or behaving incorrectly.Something is broken or behaving incorrectly.needs-triageIssue needs maintainer review and initial categorization.Issue needs maintainer review and initial categorization.
on Sep 26, 2026 Triage: #13875
Verdict: Accept
Type: Feature request
Duplicate: No
Already implemented: No
Confidence: High
Suggested labels:enhancement,accepted
Scope: Medium. The Claude status probe already starts an SDK session and readsinitializationResult(). It has to keep that model list and merge unknown ids into the provider snapshot as built-in rows. Known catalog entries should keep T3's effort, fast-mode, and context-window descriptors. The web picker drops any row marked custom, so gateway ids cannot be stored that way.What was asked
When Claude Code is pointed at an Anthropic-compatible gateway (
ANTHROPIC_BASE_URL) andCLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1is set,/modelin Claude Code lists the gateway's models. T3's Claude picker does not. The ask is to use the model inventory the running Claude Code process already reports, the same way Codex does, and to keep the bundled catalog plus manual custom models when that inventory is missing. Not a CLIProxyAPI-specific client.What the code does today
Confirmed on current
main(d110f98670). The reported commit75d63d64is an ancestor, and nothing since then has changed this path. This is a missing capability, not a regression. The picker is doing what it was built to do.checkClaudeProviderStatusbuilds the picker from the version-filtered bundled catalog pluscustomModels:const models = providerModelsFromSettings( resolveClaudeModelsForVersion(modelCatalog, parsedVersion), claudeSettings.customModels, DEFAULT_CLAUDE_MODEL_CAPABILITIES, );
resolveClaudeModelsForVersiononly drops catalog rows whoseminVersion/maxVersionExclusivedo not matchclaude --version. It never asks Claude Code which models exist.The capability probe does call
initializationResult(), and the instance environment is the env that probe uses (mergeProviderInstanceEnvironmentinClaudeDriver, thenmakeClaudeEnvironment).ANTHROPIC_BASE_URLandCLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERYset on the provider instance are therefore already in the subprocess. The probe then keeps account, slash commands, and usage, and dropsmodels:return { email: account?.email, subscriptionType: account?.subscriptionType, tokenSource: account?.tokenSource, apiProvider: account?.apiProvider, slashCommands: parseClaudeInitializationCommands(init.commands), ...(usage ? { usage } : {}), } satisfies ClaudeCapabilitiesProbe;
The Agent SDK's
SDKControlInitializeResponseincludesmodels: ModelInfo[](value,displayName,description, and optionalresolvedModel,supportsEffort,supportedEffortLevels,supportsFastMode,supportsAdaptiveThinking).supportedModels()is that same init snapshot. T3 does not read either.Codex is the contrast the report describes.
requestAllCodexModelspagesmodel/listand publishes those rows withisCustom: false. Custom slugs are appended afterward.The web picker will not show a Claude row that is marked custom.
getAppModelOptionsandgetAppModelOptionsForInstancetake only!model.isCustomfrom the snapshot, then rebuild custom rows from settings. Gateway ids have to be non-custom snapshot rows or they never appear unless they are also typed into custom models.The manual-custom-model workaround in the report is the path that exists today. It goes stale when the gateway's
/v1/modelslist changes.Not a duplicate
No open issue asks T3 to follow Claude Code's model inventory or gateway discovery. Nearby closed work is different: #9383 maps a gateway-prefixed slug onto an existing catalog entry, #8964 and #4194 are effort controls on custom Claude models, #11369 is OpenRouter docs. #8652 (closed, not merged) would hide org-restricted catalog models. It would not add models the catalog does not already contain.
Implementation notes
On a successful probe, merge
init.modelsinto the snapshot:- Match
valueandresolvedModelto catalog slugs and aliases. Keep T3's descriptors for those rows (effort map, context-window tokens, model suffixes). The SDK flags can fill effort and fast mode only where the catalog row has none. - Append ids that are not in the catalog as
isCustom: false, with capabilities taken fromModelInfowhen present. Runtime resolution already passes unknown slugs through to Claude Code verbatim, which is what custom models do. - If the probe fails or
modelsis empty, keep the current version-filtered catalog pluscustomModels. - Leave the user's custom models as the settings-owned list. Do not write discovered ids back into settings.
Check a cold
CLAUDE_CONFIG_DIR. The probe aborts the subprocess as soon asinitializationResult()resolves, and Claude Code has not always finished gateway/v1/modelsdiscovery before that handshake. A cache warmed by an interactiveclaudesession can hide that race. The capabilities cache also lives for 5 minutes, so a list that arrives late will not show up until the next probe.Discovery stays Claude Code's job. T3 should not call the gateway's
/v1/modelsitself.- Match
- addedenhancementRequested improvement or new capability.Requested improvement or new capability.acceptedfeature request acceptedfeature request acceptedvia-triageFiled through npx t3 triageFiled through npx t3 triageand removedbugSomething is broken or behaving incorrectly.Something is broken or behaving incorrectly.needs-triageIssue needs maintainer review and initial categorization.Issue needs maintainer review and initial categorization.
on Sep 26, 2026 - added 2 commits that reference this issue
on Sep 27, 2026 - added a commit that references this issue
on Oct 1, 2026 - added 4 commits that reference this issue
on Oct 2, 2026
Before submitting
Area
apps/server
Steps to reproduce
ANTHROPIC_BASE_URL./v1/modelsendpoint./model./modelpicker.Expected behavior
T3 Code should show the model inventory reported by the running Claude Code instance / Claude Agent SDK.
When Claude Code gateway discovery is enabled, models discovered from the gateway’s
/v1/modelsendpoint and visible in Claude Code’s/modelpicker should also be selectable in T3 Code.This should be provider-agnostic: T3 should consume the models Claude Code reports rather than implement CLIProxyAPI-specific or gateway-specific discovery.
If live model discovery is unavailable, T3 can continue falling back to its bundled Claude model catalog and manually configured custom models.
Actual behavior
Claude Code correctly discovers the gateway models and shows them in
/model, but T3 Code’s Claude model picker does not show them.T3 currently builds the Claude picker from its bundled/version-filtered Claude model catalog plus
customModels, instead of using the model inventory already returned during Claude Agent SDK initialization.This differs from the Codex integration, where T3 obtains the available models dynamically from Codex.
The mismatch is particularly visible with Anthropic-compatible proxies/gateways. For example, CLIProxyAPI can expose additional model IDs through
/v1/models; Claude Code sees them whenCLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1is enabled, but T3 still presents its static Claude catalog unless every model is added manually in T3 settings.The Claude provider already calls
initializationResult()during its capability probe, so the SDK-reported model list should be available without T3 making a separate request to the gateway.Impact
Cosmetic issue
Version or commit
main @ 75d63d6
Environment
No response
Logs or stack traces
Screenshots, recordings, or supporting files
No response
Workaround
Add every gateway model manually under the Claude provider’s custom models in T3 Code.
This works for a fixed list, but duplicates model discovery that Claude Code already performs and becomes stale when the gateway’s available models change.