fix: reduce keychain prompts on startup#10669
Conversation
migrateIfNeeded() already reads the anthropic key via `security find-generic-password` to check if migration is needed. Previously, getKey(for:) would discard that result and spawn a second `/usr/bin/security` process to read the same value — each process spawn triggers a separate macOS keychain authorization prompt. Now migrateIfNeeded() returns the key it read, and getKey(for:) reuses it directly. This eliminates one of the three keychain prompts users see on every app launch. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7d29878323
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| ] | ||
| SecItemDelete(deleteQuery as CFDictionary) | ||
|
|
||
| return key |
There was a problem hiding this comment.
Confirm migrated key persisted before returning it
In the migration path, cliSetKey(...) is fire-and-forget, but this function now unconditionally returns key and getKey(for:) short-circuits on that value. If writing the new keychain item fails (for example, the keychain authorization is denied), callers will still see a non-nil API key while the daemon cannot read it from the shared entry, causing an inconsistent "key configured" state that was previously surfaced as nil on read. Re-read the shared entry (or otherwise verify write success) before returning the migrated key.
Useful? React with 👍 / 👎.
Summary
APIKeyManager.migrateIfNeeded()already reads the anthropic key via/usr/bin/securityCLI to check if migration is needed — butgetKey(for:)was discarding the result and spawning a second/usr/bin/securityprocess to read the same value/usr/bin/securityprocess spawn triggers a separate macOS keychain authorization promptmigrateIfNeeded()returns the key it read, andgetKey(for:)reuses it — eliminating one of the three prompts on startup (3 → 2)The three prompts were:
migrateIfNeeded()→cliGetKey("anthropic")→ process feat: initialize Next.js app in /web directory #1getKey(for:)→cliGetKey("anthropic")→ process feat: add platform terraform for GKE deployment #2 (eliminated)loadConfig()→getSecureKey("anthropic")→ process ci: add terraform apply workflow on platform changes #3Test plan
🤖 Generated with Claude Code