Conversation
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & Why
On macOS,
readAllClaudeAccounts()treats the keychain and~/.claude/.credentials.jsonas either/or: if any keychain service matchingClaude Code-credentials*parses, the credentials file is never included in the account list. A stale keychain entry (for example one left behind by an older Claude Code version that no longer maintains it) can therefore hide a perfectly healthy file store completely.In that state the fallback machinery has nothing to work with. When the stale entry's refresh gets rate-limited,
tryFallbackAccountfinds no sibling account, the refresh-cooldown path returnscredentials_unavailable, and a long-lived process (such as anopencode serveinstance) fails every request with "Claude token refresh is rate-limited; retry shortly" while a valid token sits unused in the file, indefinitely. Observed in production:plugin_initshowed a single suffixed keychain account, the file store held a token valid for hours, and the process wedged until manually restarted.This PR includes the file store as its own account alongside keychain entries, so the existing borrow/fallback paths can rescue a wedged keychain account with the file token. Keychain-first ordering is unchanged, and the file account is skipped when a keychain account already carries the same access token, which keeps the account list identical in the common case where Claude Code writes both stores.
Changes
readAllClaudeAccounts()appends asource: "file"account (with its config dir and email) after keychain accounts, unless a keychain account already holds the same access token.