Skip to main content

resolve_access_token

Function resolve_access_token 

Source
pub async fn resolve_access_token(
    config_dir: &Path,
    allow_keychain_fallback: bool,
) -> Option<String>
Expand description

Resolve the Claude OAuth access token to use for the model-catalog fetch, trying multiple sources in order before giving up (→ caller falls back to the bundled curated catalog, unchanged from before this existed). Order:

  1. read_oauth_access_token — the .credentials.json file written by the Claude Code CLI. Covers Linux/Windows with zero behavior change.
  2. The CLAUDE_CODE_OAUTH_TOKEN env var — the long-lived token a user gets by running claude setup-token themselves in a real terminal (Anthropic’s documented recipe for headless/CI use of Claude Code) and exporting before launching AgentMux. This is how macOS — where Claude Code keeps its token in the Keychain, not a plain file — gets a token at all. When found, it is persisted into AgentMux’s own OS-keychain-backed secret store (identity::secret_store) under CLAUDE_OAUTH_TOKEN_ACCOUNT so a later run still has it even without the env var set (e.g. the app relaunched from the Dock rather than from the terminal that had it exported).
  3. AgentMux’s own secret store — a token persisted by a previous run of step 2.

Callers should use this instead of calling read_oauth_access_token directly. Never logs the token.

allow_keychain_fallback gates the two operations in steps 2/3 that actually touch the OS keychain (via identity::secret_store, which wraps blocking keyring syscalls): persisting a freshly-read env-var token, and reading back a previously-persisted one. Either can trigger an interactive macOS “App wants to use your confidential information” password prompt whenever a stored entry exists under a code signature the OS doesn’t already trust (e.g. a rebuilt local dev binary). That’s fine for a flow the user explicitly triggered, but this function’s only caller today (providers.models) is a silent, fire-and-forget background refresh fired on every app launch (frontend/app-init.ts) — a keychain prompt appearing unprompted at startup, for a purely cosmetic model-label refresh, is not acceptable.

Reading the CLAUDE_CODE_OAUTH_TOKEN env var itself is a plain process-env read with no keychain interaction, so it’s always attempted regardless of this flag (Codex P2, PR #2654) — only the persist-on-find and read-the-stored-copy operations are skipped when false. Pass false from any automatic/background caller; pass true only from a path the user explicitly initiated.