Repository navigation
Description
What happened
A Claude provider instance that gets its gateway entirely from the --settings launch argument (an LLM gateway profile: env.ANTHROPIC_BASE_URL, apiKeyHelper and a modelPicker) shows "Claude is not authenticated" in Settings → Providers, and the model picker lists Claude Code's built-in lineup (plus anything left in ~/.claude/settings.json) instead of the profile's modelPicker. Running claude --settings <same file> in a terminal shows the profile's models and authenticates through the helper. Turns in T3 do apply the file (since #22864), so only the status and the picker are wrong.
Diagnosis
Three readers, only one of which applies --settings:
- Turns (
ClaudeAdapterV2.ts,readClaudeLaunchArgSettings): parse--settings(file or inline JSON) and merge it intooptions.settings. Correct. - Capabilities probe (
buildClaudeCapabilitiesProbeQueryOptionsinapps/server/src/provider/ClaudeProvider.ts): starts Claude Code withsettingSources: ["user", "project", "local"]andsettings: { disableAllHooks: true }only.init.models(the picker) andinit.account(the auth verdict) therefore never see the profile'senv,apiKeyHelperormodelPicker. - Custom-endpoint check (
readClaudeSettingsEnvinapps/server/src/provider/Drivers/ClaudeSkills.ts, used bycheckClaudeProviderStatus): readsANTHROPIC_BASE_URLfrom the settings files and the process env only. With the gateway URL only in--settings, it finds none and the empty first-party account yields the "not authenticated" verdict.
#30127 moves readClaudeLaunchArgSettings into ClaudeSkills.ts and forwards enabledPlugins to the probe, and lists "readClaudeSettingsEnv, the probe's account/auth status" as out of scope. This is that gap.
Steps to reproduce
- Use a machine where
~/.claudeis not signed in and has noANTHROPIC_BASE_URL. - Create
~/gateway-settings.json:{ "apiKeyHelper": "echo gateway-test-key", "env": { "ANTHROPIC_BASE_URL": "https://gateway.example", "ANTHROPIC_API_KEY": "", "ANTHROPIC_AUTH_TOKEN": "" }, "modelPicker": { "replaceBuiltInOptions": true, "options": [ { "model": "gateway-opus", "label": "Gateway Opus" }, { "model": "gateway-gpt", "label": "Gateway GPT" } ] } } - In T3 Code, set the Claude instance's Launch Args to
--settings /home/<user>/gateway-settings.json. - Open Settings → Providers, then the model picker.
Expected: the provider is ready ("Custom API endpoint") and the picker lists Gateway Opus and Gateway GPT, as claude --settings ~/gateway-settings.json does.
Actual: "Claude could not authenticate…" / "Claude Code is not authenticated", and the built-in models.
Version
main 5cbdf00481 (0.1.9); Claude Code 2.1.321; macOS arm64.
Environment
Desktop app, local server. Claude provider with an empty CLAUDE_CONFIG_DIR (no login, no settings) and the gateway profile above passed only through --settings.
Evidence
checkClaudeProviderStatus + probeClaudeCapabilities against the real Claude Code CLI, empty config dir, the profile above:
main 5cbdf00481 |
with the fix | |
|---|---|---|
| status | error, auth unauthenticated |
ready, auth authenticated, "Custom API endpoint" |
init.models |
default, opus, fable, sonnet, haiku |
default, gateway-opus, gateway-gpt |
Related issues
#22864 (turns merge --settings), #30094 / #30127 (plugins from --settings; this gap named out of scope there), #26631 (~ in --settings).
Fix applied or workaround
Workaround: point the instance's CLAUDE_CONFIG_DIR at a directory whose settings.json is the profile (it then loads as user settings), at the cost of a separate Claude home.
Fix (ready as a focused PR if wanted): readClaudeSettingsEnv applies the --settings env after the local files and before managed settings (Claude Code's order), and the probe forwards env, apiKeyHelper and modelPicker from --settings, each only when well formed, keeping disableAllHooks: true (the same constraint #30127 handles for enabledPlugins). Both new tests fail on main.
Filed by
astarktc, with Claude Opus 5.5 in Pi under T3 Code.
Activity