Skip to content

Models, providers, and auth

This page reverse-engineers the authentication and provider-selection paths that show how Claude Code chooses credentials, providers, and MCP OAuth flows.

Source anchors

Semantic aliasString or symbolMeaning
SdkCredentialInitializerANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKENEmbedded SDK credential initialization path.
RuntimeApiKeyLookupprocess.env.ANTHROPIC_API_KEYRuntime API-key lookup helper.
BearerTokenHeaderPathANTHROPIC_AUTH_TOKENBearer-token authorization header path.
BedrockProviderGateCLAUDE_CODE_USE_BEDROCKProvider classifier branch.
AnthropicAwsProviderGateCLAUDE_CODE_USE_ANTHROPIC_AWSAnthropic AWS provider branch.
MantleProviderGateCLAUDE_CODE_USE_MANTLEMantle provider branch.
VertexProviderGateCLAUDE_CODE_USE_VERTEXVertex provider branch.
MainModelEnvOverrideANTHROPIC_MODELModel selection environment variable.
SmallFastModelOverrideANTHROPIC_SMALL_FAST_MODELSmall/fast model override.
ModelSelectionFlag--model <model>Root model-selection flag.
FallbackModelFlag--fallback-model <model>Print-mode fallback model flag.
XaaEnableGateCLAUDE_CODE_ENABLE_XAACross-app access OAuth flow is gated when server config requests oauth.xaa.
XaaTokenExchangeErrorXaaTokenExchangeError, shouldClearIdTokenFailed XAA token exchange can carry cache-clearing guidance.
McpOAuthStoremcpOAuthMCP OAuth credentials are stored by server-derived key.

Bundle modules in cli.renamed.js

Semantic aliasLoader line(s)Representative renamed exportsAtlas entry
GatewayAuthRefresh110458, 157847withOAuthRefreshLock, validateForceLoginOrg, shouldUseWIFAuth, saveOAuthTokensIfNeeded, saveApiKey, restoreGatewayAuth, resetAwsAuthRefreshCooldown, removeApiKey, refreshGcpCredentialsIfNeeded, refreshGcpAuth, getAnthropicApiKey, hasAnthropicApiKeyAuth, getAuthTokenSource, isAnthropicAuthEnabledBundle module map — auth (multi-cloud)
LoginFlow409636Login, runPostLoginHooksBundle module map — auth (multi-cloud)

Provider selection

The provider classifier visible around Dq() uses environment gates to choose a provider family. Confirmed strings include:

Provider familyHigh-signal env vars
First-party/defaultabsence of provider-specific gates; OAuth/API-key helpers still apply.
BedrockCLAUDE_CODE_USE_BEDROCK
VertexCLAUDE_CODE_USE_VERTEX
FoundryCLAUDE_CODE_USE_FOUNDRY
Anthropic AWSCLAUDE_CODE_USE_ANTHROPIC_AWS
MantleCLAUDE_CODE_USE_MANTLE

The bundle also contains region/base URL surfaces such as AWS_REGION, AWS_DEFAULT_REGION, CLOUD_ML_REGION, and ANTHROPIC_BASE_URL.

Credential sources

flowchart TD
Env[Environment variables] --> Auth[Credential resolver]
KeyHelper[apiKeyHelper / keychain helper] --> Auth
OAuthFd[CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR] --> Auth
ApiFd[CLAUDE_CODE_API_KEY_FILE_DESCRIPTOR] --> Auth
SessionToken[CLAUDE_CODE_SESSION_ACCESS_TOKEN] --> Remote[Remote/session auth]
Auth --> Provider[Provider request]

Confirmed credential surfaces include:

  • ANTHROPIC_API_KEY
  • ANTHROPIC_AUTH_TOKEN
  • CLAUDE_CODE_OAUTH_TOKEN
  • CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR
  • CLAUDE_CODE_API_KEY_FILE_DESCRIPTOR
  • apiKeyHelper
  • enterpriseGateway

MCP cross-app access (XAA)

The decoded OAuth/XAA chunk shows a separate MCP OAuth branch when a server configuration includes oauth.xaa. That branch is hard-gated by CLAUDE_CODE_ENABLE_XAA; without the env gate the runtime tells the user to remove oauth.xaa and use the standard consent flow.

When enabled, the XAA path performs an IdP/client/token-exchange flow and stores resulting MCP OAuth state under mcpOAuth. XaaTokenExchangeError carries shouldClearIdToken, which lets the runtime distinguish ordinary exchange failures from failures that should invalidate a cached identity token. Treat this as an MCP-auth extension path, not as the general Anthropic API-key or provider-selection path.

Model and budget flags

SurfaceRuntime implication
--model <model>Selects a model alias or concrete model for the session.
ANTHROPIC_MODELEnvironment-level default model source.
ANTHROPIC_SMALL_FAST_MODELOverrides the small/fast model used by helper paths.
--fallback-model <model>Enables a print-mode fallback when the default model is overloaded.
--thinking, --thinking-display, --max-thinking-tokensControls thinking mode and legacy thinking-token budget.
--max-budget-usd, --task-budget, --max-turnsEnforces budget/turn constraints in headless or task-like paths.
--betas <betas...>Adds beta headers for API-key users.

For the detailed runtime model resolver, logical model roles, provider-call shape, retries, rate-limit events, usage accounting, quota probes, and billing/overage UI, see Model selection, calls, usage, quota, and billing.

Error and availability hints

The bundle contains model/provider error strings that point users toward --model or /model when a deployment lacks a requested model. This supports the interpretation that model choice is both a CLI flag and an interactive command surface.

Caveats

  • The bundled Anthropic SDK documentation strings include many API examples. This page only treats strings as runtime evidence when they connect to env-variable lookup, root flags, or provider classifier code.
  • Provider names and env gates are source-anchored for this build; behavior can change across package versions.

OAuth scope model and token lifecycle

The OAuthClient module (cli.renamed.js:47791, 109942-110200) owns Claude Code’s OAuth handshake against claude.ai and the Console. It supports two scope flavors and a long-lived token mode used by claude setup-token.

Scope sets

ConstantEffect
CLAUDE_AI_INFERENCE_SCOPERequired to call inference endpoints with a claude.ai-issued token.
CLAUDE_AI_PROFILE_SCOPERequired for profile/organization metadata reads; gates Remote Control entitlement (see Feature gates reference).
CLAUDE_AI_OAUTH_SCOPESFull default scope set used by claude auth login.
CONSOLE_OAUTH_SCOPESConsole-flavor scope set used when the redirect targets the Console UI.
LONG_LIVED_OAUTH_TOKEN_TTL_SECONDSTTL applied to tokens minted by claude setup-token. The exchange request adds expires_in: <LONG_LIVED_OAUTH_TOKEN_TTL_SECONDS>.
OAUTH_BETA_HEADERBeta opt-in header attached to OAuth flows.

shouldUseClaudeAIAuth(scopes) is the predicate used elsewhere in the runtime: it returns true exactly when scopes contains CLAUDE_AI_INFERENCE_SCOPE. parseScopes(scopeString) splits the server’s space-delimited scope field back into an array.

buildAuthUrl(...)

Builds the authorize URL the browser/manual-paste flow opens:

  • Picks CLAUDE_AI_AUTHORIZE_URL (loginWithClaudeAi: true) or CONSOLE_AUTHORIZE_URL otherwise (both from getOauthConfig()).
  • Appends code=true, client_id, response_type=code, redirect_uri (loopback http://localhost:<port>/callback or MANUAL_REDIRECT_URL for isManual), code_challenge, code_challenge_method=S256, state.
  • Scope = CLAUDE_AI_INFERENCE_SCOPE only when inferenceOnly: true; otherwise the full CLAUDE_AI_OAUTH_SCOPES (or CONSOLE_OAUTH_SCOPES).
  • Optional orgUUID, login_hint, login_method query params for pre-selecting an organization or routing to a specific provider login.

exchangeCodeForTokens(code, state, verifier, port, isManual?, expiresIn?)

POSTs grant_type=authorization_code to getOauthConfig().TOKEN_URL with PKCE verifier, the matching redirect URI, and (optionally) expires_in for long-lived tokens. On 200 it returns the raw token payload and emits tengu_oauth_token_exchange_success. On 401 it tags oauth_exchange_invalid_code; on anything else oauth_exchange_http_error. 30 s axios timeout.

refreshOAuthToken(refreshToken, {scopes?, expiresIn?, clientId?})

  • POSTs grant_type=refresh_token with scope = caller-supplied OR CLAUDE_AI_OAUTH_SCOPES.
  • Always preserves the refresh token (server returns one, but falls back to the input if missing).
  • After success, when the current oauthAccount is missing billing/subscription/profile fields, fetches /profile and atomically updates oauthAccount.displayName, hasExtraUsageEnabled, billingType, accountCreatedAt, subscriptionCreatedAt, ccOnboardingFlags, claudeCodeTrialEndsAt, claudeCodeTrialDurationDays, seatTier.
  • On invalid_grant errors, tags oauth_refresh_invalid_grant so the auth shutdown path can prompt re-login.
  • Returns {accessToken, refreshToken, expiresAt, scopes, clientId, subscriptionType, rateLimitTier, profile?, tokenAccount?}.

fetchAndStoreUserRoles(accessToken)

GETs ROLES_URL with Authorization: Bearer <token>, then atomically updates oauthAccount.organizationRole, workspaceRole, and organizationName. Used by the login flow to make role-gated UI elements available before the first request.

createAndStoreApiKey(accessToken)

POSTs to API_KEY_URL with the OAuth access token to mint a long-lived API key, then writes it through saveApiKey(...). This is the path that claude setup-token uses for sessionless agent installs. On any failure tags oauth_create_api_key / oauth_api_key_request_failed.

isOAuthTokenExpired(expiresAt)

Returns true when the token expires within 5 minutes (300 s grace window). Callers refresh proactively rather than waiting for an inflight 401.

Subscription type mapping

fetchProfileInfo(accessToken) maps the server’s organization.organization_type to the local subscriptionType value:

Server valueLocal subscriptionType
claude_maxmax
claude_propro
claude_enterpriseenterprise
claude_teamteam
anything elsenull

Also returns rateLimitTier, seatTier, hasExtraUsageEnabled, billingType, and the raw profile so callers can stash additional fields.

Created and maintained by Yingting Huang.