6089eb18fa7b5b27cfb908ae444255f20af0a7c7
On a Mac, Claude Code stores its credentials in the login Keychain and never writes ~/.claude/.credentials.json — the only file this proxy knew how to read. The workaround was to copy the Keychain blob into that file by hand, which is a snapshot: a refresh ROTATES the refresh token and revokes the previous one, so the two stores were not redundant copies but competitors, and whichever refreshed second got `401 OAuth access token has been revoked`. That is not hypothetical. On 2026-08-08 it took out every chat turn from the iPad for six hours while the terminal CLI beside it worked fine — the harness spawned, retried for three minutes and wrote the 401 into the transcript, which from the app looks like an agent that simply never answers. So on darwin the Keychain is the authority and the file is a mirror, holding the same token rather than a different rotation of it. Everywhere else — every Linux server — the file is still the authority and nothing changes. Detection is process.platform, and a machine with no `security` binary or no such item falls through to the file rather than failing. Three recoveries, cheapest first: - a watchdog checks every 30 minutes and refreshes when under an hour remains. It checks rather than refreshing on a blind schedule because each refresh rotates the token, so a needless one is another chance for the stores to disagree. - an upstream 401 now RE-READS before refreshing. When a token has genuinely been revoked the machine usually already holds a good one, because Claude Code refreshed it into the Keychain minutes ago; spending our own refresh token there is what caused the divergence in the first place. - only if nobody else has moved do we refresh ourselves. The Keychain write goes through argv, which is the only non-interactive form `security` offers, and matches on the service AND account pair — the account is read off the existing item rather than assumed, or the update would silently create a second entry instead of replacing the one Claude Code reads. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Description
No description provided
42 MiB
Languages
TypeScript
90.9%
Shell
4.7%
JavaScript
4.1%
CSS
0.2%
HTML
0.1%