fix(startup): show --model flag override on startup screen (#898)

The startup screen was only reading model from env vars and settings,
ignoring the --model CLI flag since it's parsed by Commander.js after
the banner prints. Now eagerly parses --model from argv before rendering
so the displayed model matches what the session will actually use.
This commit is contained in:
Rayan Alkhelaiwi
2026-04-26 15:24:44 +03:00
committed by GitHub
parent 6dedffe5ff
commit d45628c413
3 changed files with 82 additions and 9 deletions

View File

@@ -14,6 +14,7 @@ const ENV_KEYS = [
'GEMINI_MODEL',
'MISTRAL_MODEL',
'ANTHROPIC_MODEL',
'CLAUDE_MODEL',
'NVIDIA_NIM',
'MINIMAX_API_KEY',
]
@@ -186,3 +187,71 @@ describe('detectProvider — explicit dedicated-provider env flags', () => {
expect(detectProvider().name).toBe('MiniMax')
})
})
// --- modelOverride from --model flag ---
describe('detectProvider — modelOverride from --model flag', () => {
test('modelOverride overrides default Anthropic model', () => {
const result = detectProvider('claude-opus-4-6')
expect(result.name).toBe('Anthropic')
expect(result.model).toContain('opus')
})
test('modelOverride alias is resolved for Anthropic', () => {
const result = detectProvider('opus')
expect(result.name).toBe('Anthropic')
expect(result.model).toContain('opus')
})
test('modelOverride takes priority over ANTHROPIC_MODEL env var', () => {
process.env.ANTHROPIC_MODEL = 'claude-haiku-4-5-20251001'
const result = detectProvider('claude-opus-4-6')
expect(result.name).toBe('Anthropic')
expect(result.model).toContain('opus')
})
test('modelOverride takes priority over CLAUDE_MODEL env var', () => {
process.env.CLAUDE_MODEL = 'claude-haiku-4-5-20251001'
const result = detectProvider('claude-opus-4-6')
expect(result.name).toBe('Anthropic')
expect(result.model).toContain('opus')
})
test('modelOverride works for OpenAI provider', () => {
process.env.CLAUDE_CODE_USE_OPENAI = '1'
process.env.OPENAI_API_KEY = 'test-key'
process.env.OPENAI_MODEL = 'gpt-4o'
const result = detectProvider('gpt-4-turbo')
expect(result.model).toContain('gpt-4-turbo')
})
test('modelOverride works for Gemini provider', () => {
process.env.CLAUDE_CODE_USE_GEMINI = '1'
const result = detectProvider('gemini-2.5-pro')
expect(result.model).toBe('gemini-2.5-pro')
})
test('modelOverride works for Mistral provider', () => {
process.env.CLAUDE_CODE_USE_MISTRAL = '1'
const result = detectProvider('mistral-large-latest')
expect(result.model).toBe('mistral-large-latest')
})
test('modelOverride works for GitHub provider', () => {
process.env.CLAUDE_CODE_USE_GITHUB = '1'
const result = detectProvider('gpt-4o')
expect(result.model).toContain('gpt-4o')
})
test('undefined modelOverride preserves default behavior', () => {
const result = detectProvider(undefined)
expect(result.name).toBe('Anthropic')
expect(result.model).toContain('sonnet')
})
test('no argument preserves default behavior', () => {
const result = detectProvider()
expect(result.name).toBe('Anthropic')
expect(result.model).toContain('sonnet')
})
})

View File

@@ -84,33 +84,33 @@ const LOGO_CLAUDE = [
// ─── Provider detection ───────────────────────────────────────────────────────
export function detectProvider(): { name: string; model: string; baseUrl: string; isLocal: boolean } {
export function detectProvider(modelOverride?: string): { name: string; model: string; baseUrl: string; isLocal: boolean } {
const useGemini = process.env.CLAUDE_CODE_USE_GEMINI === '1' || process.env.CLAUDE_CODE_USE_GEMINI === 'true'
const useGithub = process.env.CLAUDE_CODE_USE_GITHUB === '1' || process.env.CLAUDE_CODE_USE_GITHUB === 'true'
const useOpenAI = process.env.CLAUDE_CODE_USE_OPENAI === '1' || process.env.CLAUDE_CODE_USE_OPENAI === 'true'
const useMistral = process.env.CLAUDE_CODE_USE_MISTRAL === '1' || process.env.CLAUDE_CODE_USE_MISTRAL === 'true'
if (useGemini) {
const model = process.env.GEMINI_MODEL || 'gemini-2.0-flash'
const model = modelOverride || process.env.GEMINI_MODEL || 'gemini-2.0-flash'
const baseUrl = process.env.GEMINI_BASE_URL || 'https://generativelanguage.googleapis.com/v1beta/openai'
return { name: 'Google Gemini', model, baseUrl, isLocal: false }
}
if (useMistral) {
const model = process.env.MISTRAL_MODEL || 'devstral-latest'
const model = modelOverride || process.env.MISTRAL_MODEL || 'devstral-latest'
const baseUrl = process.env.MISTRAL_BASE_URL || 'https://api.mistral.ai/v1'
return { name: 'Mistral', model, baseUrl, isLocal: false }
}
if (useGithub) {
const model = process.env.OPENAI_MODEL || 'github:copilot'
const model = modelOverride || process.env.OPENAI_MODEL || 'github:copilot'
const baseUrl =
process.env.OPENAI_BASE_URL || 'https://api.githubcopilot.com'
return { name: 'GitHub Copilot', model, baseUrl, isLocal: false }
}
if (useOpenAI) {
const rawModel = process.env.OPENAI_MODEL || 'gpt-4o'
const rawModel = modelOverride || process.env.OPENAI_MODEL || 'gpt-4o'
const resolvedRequest = resolveProviderRequest({
model: rawModel,
baseUrl: process.env.OPENAI_BASE_URL,
@@ -166,7 +166,7 @@ export function detectProvider(): { name: string; model: string; baseUrl: string
// Default: Anthropic - check settings.model first, then env vars
const settings = getSettings_DEPRECATED() || {}
const modelSetting = settings.model || process.env.ANTHROPIC_MODEL || process.env.CLAUDE_MODEL || 'claude-sonnet-4-6'
const modelSetting = modelOverride || settings.model || process.env.ANTHROPIC_MODEL || process.env.CLAUDE_MODEL || 'claude-sonnet-4-6'
const resolvedModel = parseUserSpecifiedModel(modelSetting)
const baseUrl = process.env.ANTHROPIC_BASE_URL ?? 'https://api.anthropic.com'
const isLocal = isLocalProviderUrl(baseUrl)
@@ -182,11 +182,11 @@ function boxRow(content: string, width: number, rawLen: number): string {
// ─── Main ─────────────────────────────────────────────────────────────────────
export function printStartupScreen(): void {
export function printStartupScreen(modelOverride?: string): void {
// Skip in non-interactive / CI / print mode
if (process.env.CI || !process.stdout.isTTY) return
const p = detectProvider()
const p = detectProvider(modelOverride)
const W = 62
const out: string[] = []

View File

@@ -134,9 +134,13 @@ async function main(): Promise<void> {
await validateProviderEnvForStartupOrExit()
// Parse --model early so the startup screen can display the override
const { eagerParseCliFlag } = await import('../utils/cliArgs.js')
const earlyModelFlag = eagerParseCliFlag('--model')
// Print the gradient startup screen before the Ink UI loads
const { printStartupScreen } = await import('../components/StartupScreen.js')
printStartupScreen()
printStartupScreen(earlyModelFlag)
// For all other paths, load the startup profiler
const {