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:
read_oauth_access_token— the.credentials.jsonfile written by the Claude Code CLI. Covers Linux/Windows with zero behavior change.- The
CLAUDE_CODE_OAUTH_TOKENenv var — the long-lived token a user gets by runningclaude setup-tokenthemselves 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) underCLAUDE_OAUTH_TOKEN_ACCOUNTso 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). - 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.