diff --git a/src/components/LogoV2/CondensedLogo.tsx b/src/components/LogoV2/CondensedLogo.tsx
index 13419d62c..0e7891200 100644
--- a/src/components/LogoV2/CondensedLogo.tsx
+++ b/src/components/LogoV2/CondensedLogo.tsx
@@ -7,7 +7,7 @@ import { useAppState } from '../../state/AppState.js';
import { getEffortSuffix } from '../../utils/effort.js';
import { truncate } from '../../utils/format.js';
import { isFullscreenEnvEnabled } from '../../utils/fullscreen.js';
-import { formatModelAndBilling, getLogoDisplayData, truncatePath } from '../../utils/logoV2Utils.js';
+import { formatModelAndBilling, getLogoDisplayData, isNotLoggedIn, truncatePath } from '../../utils/logoV2Utils.js';
import { renderModelSetting } from '../../utils/model/model.js';
import { OffscreenFreeze } from '../OffscreenFreeze.js';
import { AnimatedClawd } from './AnimatedClawd.js';
@@ -23,7 +23,10 @@ export function CondensedLogo(): ReactNode {
const { columns } = useTerminalSize();
const agent = useAppState(s => s.agent);
const effortValue = useAppState(s => s.effortValue);
+ // Subscribe to authVersion to re-render after login/logout
+ useAppState(s => s.authVersion);
const model = useMainLoopModel();
+ const notLoggedIn = isNotLoggedIn();
const modelDisplayName = renderModelSetting(model);
const { version, cwd, billingType, agentName: agentNameFromSettings } = getLogoDisplayData();
@@ -92,7 +95,9 @@ export function CondensedLogo(): ReactNode {
{' '}
v{truncatedVersion}
- {shouldSplit ? (
+ {notLoggedIn ? (
+ Not logged in
+ ) : shouldSplit ? (
<>
{truncatedModel}
{truncatedBilling}
diff --git a/src/components/LogoV2/LogoV2.tsx b/src/components/LogoV2/LogoV2.tsx
index 2c998a224..cfec387fc 100644
--- a/src/components/LogoV2/LogoV2.tsx
+++ b/src/components/LogoV2/LogoV2.tsx
@@ -11,6 +11,7 @@ import {
getRecentActivitySync,
getRecentReleaseNotesSync,
getLogoDisplayData,
+ isNotLoggedIn,
} from '../../utils/logoV2Utils.js';
import { truncate } from '../../utils/format.js';
import { getDisplayPath } from '../../utils/file.js';
@@ -82,6 +83,8 @@ export function LogoV2(): React.ReactNode {
const showOverageCreditUpsell = useShowOverageCreditUpsell();
const agent = useAppState(s => s.agent);
const effortValue = useAppState(s => s.effortValue);
+ // Subscribe to authVersion to re-render after login/logout
+ useAppState(s => s.authVersion);
const config = getGlobalConfig();
@@ -136,6 +139,7 @@ export function LogoV2(): React.ReactNode {
}, [showOverageCreditUpsell, showOnboarding, showGuestPassesUpsell, isCondensedMode]);
const model = useMainLoopModel();
+ const notLoggedIn = isNotLoggedIn();
const fullModelDisplayName = renderModelSetting(model);
const { version, cwd, billingType, agentName: agentNameFromSettings } = getLogoDisplayData();
// Prefer AppState.agent (set from --agent CLI flag) over settings
@@ -247,8 +251,8 @@ export function LogoV2(): React.ReactNode {
- {modelDisplayName}
- {billingType}
+ {notLoggedIn ? 'Not logged in' : modelDisplayName}
+ {!notLoggedIn && {billingType}}
{agentName ? `@${agentName} · ${truncatedCwd}` : truncatedCwd}
@@ -269,8 +273,9 @@ export function LogoV2(): React.ReactNode {
}
const welcomeMessage = formatWelcomeMessage(username);
- const modelLine =
- !process.env.IS_DEMO && config.oauthAccount?.organizationName
+ const modelLine = notLoggedIn
+ ? 'Not logged in'
+ : !process.env.IS_DEMO && config.oauthAccount?.organizationName
? `${modelDisplayName} · ${billingType} · ${config.oauthAccount.organizationName}`
: `${modelDisplayName} · ${billingType}`;
// Calculate cwd width accounting for agent name if present
diff --git a/src/utils/logoV2Utils.ts b/src/utils/logoV2Utils.ts
index 4357119d7..861d45200 100644
--- a/src/utils/logoV2Utils.ts
+++ b/src/utils/logoV2Utils.ts
@@ -1,7 +1,8 @@
import { getDirectConnectServerUrl, getSessionId } from '../bootstrap/state.js'
import { stringWidth } from '@anthropic/ink'
import type { LogOption } from '../types/logs.js'
-import { getSubscriptionName, isClaudeAISubscriber } from './auth.js'
+import { getAnthropicApiKey } from './auth.js'
+import { hasCoStrictCredentialsSync } from '../costrict/provider/credentials.js'
import { getCwd } from './cwd.js'
import { getDisplayPath } from './file.js'
import {
@@ -9,6 +10,7 @@ import {
truncateToWidth,
truncateToWidthNoEllipsis,
} from './format.js'
+import { getAPIProvider, getProviderDisplayName } from './model/providers.js'
import { getStoredChangelogFromMemory, parseChangelog } from './releaseNotes.js'
import { gt } from './semver.js'
import { loadMessageLogs } from './sessionStorage.js'
@@ -237,12 +239,33 @@ export function formatReleaseNoteForDisplay(
}
/**
- * Gets the common logo display data used by both LogoV2 and CondensedLogo
+ * Check if user is not logged in
+ * User is considered logged in if they have CoStrict credentials or API key
*/
+export function isNotLoggedIn(): boolean {
+ // 1. CoStrict login (credentials file exists)
+ if (hasCoStrictCredentialsSync()) return false
+
+ const settings = getInitialSettings()
+
+ // 2. Any provider configured via modelType (包括 anthropic/openai/bedrock 等)
+ // 用户通过 /login 选择 provider 后会设置 modelType
+ if (settings.modelType) {
+ return false
+ }
+
+ // 3. Anthropic API Key configured (legacy way without modelType)
+ if (getAnthropicApiKey() !== null) return false
+
+ // None of the above - not logged in
+ return true
+}
+
export function getLogoDisplayData(): {
version: string
cwd: string
billingType: string
+ isLoggedIn: boolean
agentName: string | undefined
} {
const version = process.env.DEMO_VERSION ?? MACRO.VERSION
@@ -253,15 +276,18 @@ export function getLogoDisplayData(): {
const cwd = serverUrl
? `${displayPath} in ${serverUrl.replace(/^https?:\/\//, '')}`
: displayPath
- const billingType = isClaudeAISubscriber()
- ? getSubscriptionName()
- : 'API Usage Billing'
+
+ const loggedIn = !isNotLoggedIn()
+ const provider = getAPIProvider()
+ const providerName = getProviderDisplayName(provider)
+ const billingType = loggedIn ? providerName : 'Not logged in'
const agentName = getInitialSettings().agent
return {
version,
cwd,
billingType,
+ isLoggedIn: loggedIn,
agentName,
}
}
diff --git a/src/utils/model/providers.ts b/src/utils/model/providers.ts
index b5b55444c..45c76d3ca 100644
--- a/src/utils/model/providers.ts
+++ b/src/utils/model/providers.ts
@@ -35,6 +35,32 @@ export function getAPIProviderForStatsig(): AnalyticsMetadata_I_VERIFIED_THIS_IS
return getAPIProvider() as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
}
+/**
+ * Get a human-readable display name for the current API provider
+ */
+export function getProviderDisplayName(provider: APIProvider): string {
+ switch (provider) {
+ case 'firstParty':
+ return 'Anthropic'
+ case 'bedrock':
+ return 'AWS Bedrock'
+ case 'vertex':
+ return 'Google Vertex'
+ case 'foundry':
+ return 'Foundry'
+ case 'openai':
+ return 'OpenAI'
+ case 'gemini':
+ return 'Google Gemini'
+ case 'grok':
+ return 'xAI Grok'
+ case 'costrict':
+ return 'CoStrict'
+ default:
+ return provider
+ }
+}
+
/**
* Check if ANTHROPIC_BASE_URL is a first-party Anthropic API URL.
* Returns true if not set (default API) or points to api.anthropic.com