-
Notifications
You must be signed in to change notification settings - Fork 241
fix(claude): reduce keychain prompts even after granting Always Allow #245
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fix(claude): reduce keychain prompts even after granting Always Allow #245
Conversation
CodexBar was prompting for keychain password repeatedly even after the user granted "Always Allow" access to Claude Code credentials. Changes: - Add `allowKeychainPrompt` parameter to `ClaudeOAuthCredentialsStore.load()` - Add `loadFromClaudeKeychainWithoutPrompt()` using LAContext to silently fail - Add `invalidateCacheIfClaudeKeychainChanged()` to detect credential changes - Skip keychain prompts during background refreshes and availability checks - Cache credentials in CodexBar's own keychain after first successful access - Re-migrate Claude credentials when they change to update accessibility
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e2fa96efbe
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR addresses issue #243 where CodexBar repeatedly prompts for keychain password despite "Always Allow" being selected. The fix implements a multi-layered caching strategy and silent keychain access to minimize user prompts.
Changes:
- Added
allowKeychainPromptparameter to control when keychain prompts are shown, preventing unexpected prompts during background operations - Implemented silent keychain access using
LAContext.interactionNotAllowedto read credentials without triggering prompts - Added credential caching in CodexBar's own keychain to reduce access frequency to Claude Code's keychain
- Implemented change detection for both file-based and keychain-based credentials to maintain cache validity
- Enhanced migration logic to re-migrate Claude credentials when they change
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials.swift | Core implementation: added allowKeychainPrompt parameter, silent keychain access methods, cache invalidation logic, and file fingerprinting to detect credential changes |
| Sources/CodexBar/KeychainMigration.swift | Added logic to re-migrate Claude credentials when they change, tracking credentials via fingerprints to maintain proper accessibility settings |
| Sources/CodexBarCore/Providers/Claude/ClaudeUsageFetcher.swift | Updated to use allowKeychainPrompt: false during background refreshes to prevent prompts |
| Sources/CodexBarCore/Providers/Claude/ClaudeProviderDescriptor.swift | Updated availability check to use allowKeychainPrompt: false to prevent prompts during background checks |
| Sources/CodexBar/UsageStore.swift | Updated debug dump to use allowKeychainPrompt: false to prevent prompts during diagnostic operations |
| Sources/CodexBar/UsageStore+Refresh.swift | Added cache invalidation check after fetching to detect credential changes and trigger re-fetch if needed |
| Tests/CodexBarTests/ClaudeOAuthCredentialsStoreTests.swift | Added tests for cache invalidation when credentials file changes, with some test setup improvements |
| Tests/CodexBarTests/KeychainMigrationTests.swift | Added test entries for new keychain items and migration tracking reset functionality |
| CHANGELOG.md | Documented the bug fix with details of the implementation approach |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials.swift
Outdated
Show resolved
Hide resolved
- Remove redundant fingerprint check in cached credentials (already validated by invalidateCacheIfCredentialsFileChanged) - Remove redundant KeychainAccessGate assignment in test - Add comment explaining cache re-store in test
|
While this PR significantly reduces keychain prompts, there's one scenario where prompts may still occur: When Claude Code refreshes expired OAuth tokens (typically every few hours/days), it updates the keychain item which can reset the Access Control List (ACL). This means:
Why this happens:
Mitigation in this PR:
Result: Prompts are reduced from "every access" to "occasionally after token refresh" - a significant improvement but not completely eliminated. Complete fix would require: Claude Code to preserve third-party app ACL entries when updating credentials (feature request to Anthropic). |
|
Does this address the scenario where the user does not wish to grant keychain access at all? I'm not sure why this is a mandatory requirement when just processing .codex/ folder data... |
|
@tylerseymour It wont address that you need permission to token to be able to get your usage from anthropic API what other way you will get your usage ? |
|
can we please merge this at least partial solution instead of waiting for perfect solution and address future issues in the future? |
|
Its not on my hand. Only project owner can merge it. |
|
I'm sorry. The internet is exploding rn. |
|
@elpinguinofrio ./Scripts/compile_and_run.sh |
|
@manikv12 Hi! I'd like to help test this PR but can't build from source - the Tried:
Both fail with: Could you please provide a pre-built binary/DMG so I can test the keychain prompt behavior? |
|
CodexBar-0.18.0-beta.2.zip |
|
dude built clawdbot and probably forgot about codex bar so this VERY MUCH NEEDED pr will never get merged I just don't understand how it's not terribly annoying for him as well love codexbar btw, but PLEASE APPROVE THIS PR @steipete |
|
@manuel-soria Dont worry he is getting back at it. He just have too many things to worry about because of OpenClaw . |
oh it is @manuel-soria it popped up in the middle of one of his recent presentations in London |
|
Tested on macOS 26.2 Tahoe, Apple M4 Max. Build & tests: ✅ Manual testing:
(Note: Debug builds have inconsistent code signatures, so keychain ACL behavior differs from signed releases. Tested the logic path as best as possible in dev environment.) Code review notes: Found two edge cases worth flagging:
// ClaudeUsageFetcher.swift:266-268
let hasCache = ClaudeOAuthCredentialsStore.hasCachedCredentials()
let creds = try ClaudeOAuthCredentialsStore.load(
environment: self.environment,
allowKeychainPrompt: !hasCache)
Neither blocks the main fix. Happy to open a follow-up PR for these if helpful. LGTM 👍 |
|
@odysseus0 Good edge cases you can push changes to this Branch if you would like to i have no problem with that. |
Add automatic token refresh using Anthropic's OAuth token endpoint. When the access token expires, CodexBar now refreshes it using the refresh token and saves the new credentials to its own keychain cache. This eliminates the need for users to run `claude` CLI to refresh tokens. Users will only be prompted for keychain access on: - First time setup (initial read from Claude's keychain) - Account switches Changes: - Add loadWithAutoRefresh() async method that handles token refresh - Add refreshAccessToken() to call Anthropic's /v1/oauth/token endpoint - Add new error cases: refreshFailed, noRefreshToken - Make OAuth client ID configurable via CODEXBAR_CLAUDE_OAUTH_CLIENT_ID - Update ClaudeUsageFetcher to use auto-refresh method
✅ Token Refresh Limitation Now ResolvedThe previous "Known Limitation" about token refresh prompts has been addressed in commit 968e52e. What changed:CodexBar now refreshes OAuth tokens automatically using Anthropic's Flow:When users will still be prompted:
When users will NOT be prompted:
This implementation is inspired by the opencode-anthropic-auth plugin approach. |
rjm11
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested locally (build passes ✅). Code review looks solid:
What this fixes:
- Adds
allowKeychainPromptparameter to prevent unexpected prompts during background refreshes - Uses
LAContext.interactionNotAllowedfor silent keychain reads - Caches credentials in CodexBar's own keychain after first successful access
- Detects credential file/keychain changes via fingerprinting to invalidate stale cache
Why it works:
The root cause is that accessing Claude's keychain item ("Claude Code-credentials") triggers macOS prompts even after "Always Allow" because the ACL changes between app versions or code signatures. By caching in CodexBar's own keychain and only falling back to Claude's keychain when necessary (and only when prompts are allowed), this significantly reduces prompt frequency.
Note: Tests hang in dev builds without proper code signing (expected - they're waiting for keychain prompts). The production build should work fine since it's properly signed.
Ready to merge. 🦞

Fixes #243
Summary
Changes
allowKeychainPromptparameter toClaudeOAuthCredentialsStore.load()to control prompt behaviorloadFromClaudeKeychainWithoutPrompt()usingLAContext.interactionNotAllowedto silently failinvalidateCacheIfClaudeKeychainChanged()to detect credential changes without promptingTest plan