fix: support current Claude Code keychain auth#110
fix: support current Claude Code keychain auth#110andycostintoma wants to merge 3 commits intogriffinmartin:mainfrom
Conversation
|
Thanks for the PR. |
|
@andycostintoma checks out, just get lint/build to pass and I can get this through. |
|
@griffinmartin done |
griffinmartin
left a comment
There was a problem hiding this comment.
Hey, nice work on this — the overall approach is solid and the discriminated union design is the right call. A couple things I'd want addressed before merging though:
Must fix
authType should be required, not optional
Right now ClaudeCredentials.authType is optional (authType?: "api" | "oauth"), but syncToPath and refreshIfNeeded both branch on it. The problem is writeBackCredentials constructs newCreds from creds.accessToken/refreshToken/expiresAt without propagating authType — so any credentials flowing through that path lose their type discriminator and silently fall through to the OAuth branch. Making it required forces all construction sites to be explicit and eliminates a whole class of silent misbehavior.
Guard writeBackCredentials against API key entries
writeBackCredentials is exported but has no check for API key credentials. If it's ever called with an API key source (raw sk-ant-... string), updateCredentialBlob will try to JSON.parse it, fail, and return false silently. I know refreshIfNeeded has the early return so this won't happen through that path today, but the function should protect itself. Something like if (creds.authType === "api") return false at the top would do it.
Other things worth noting
- The test file mirrors
parseCredentialsandextractServicesFromDumplocally rather than importing the actual exports — works fine now but it's a drift risk over time Number.MAX_SAFE_INTEGERas the expiry sentinel is clever but a comment explaining the intent would help future readers- The
sk-ant-prefix check is a reasonable heuristic but worth a comment acknowledging the assumption - No test coverage for
syncToPathwith API key credentials — that's the most user-visible behavior change in this PR - Minor:
authTypeon the interface vstypein auth.json serve the same purpose but have different names, a cross-reference comment would help

Summary
Claude Code-credentials*andClaude Codekeychain entries when discovering Claude auth sourcesClaude Codekeychain entry stores a raw managedsk-ant-...key instead of OAuth JSONClaude Codeentry into OpenCode astype: \"api\"and add tests covering both keychain formatsTesting
node --test --experimental-strip-types src/**/*.test.ts