feat: add Copilot CLI Keychain token discovery and multi-account CLI support#84
Open
Shaglock wants to merge 2 commits intoopgginc:mainfrom
Open
feat: add Copilot CLI Keychain token discovery and multi-account CLI support#84Shaglock wants to merge 2 commits intoopgginc:mainfrom
Shaglock wants to merge 2 commits intoopgginc:mainfrom
Conversation
…support Add macOS Keychain as a token source for GitHub Copilot, enabling automatic discovery of credentials stored by `copilot-cli`. Rewrite the CLI's CopilotCLIProvider to use TokenManager for multi-account support (matching the GUI provider), and fix table column alignment for long provider names.
Contributor
|
Here is the summary of the changes in this PR: This PR significantly enhances the CLI tool by adding multi-account support for Copilot (including discovery via macOS Keychain), aligns the CLI provider logic with the GUI version, and updates Code Review Feedback
This is just a quick preview. |
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.
Disclaimer
The initial issue (fix #73) I had was that my copilot sub was not detected through opencode auth token.
I have no Swift language knowledge, I tried to guide Claude Opus 4.6 to fix my problem. Then I went into a little rabbit hole trying to support two copilot subs at once. Obviously there is probably a lot of slop here, not sure if the keychain access is implemented correctly, and, but hopefully if it's not merged, at least it's a good starting point for someone.
Summary
copilot-cliservice) as a new GitHub Copilot token discovery sourceCopilotCLIProviderto useTokenManagerfor multi-account token discovery, matching the GUI provider's logicquota_snapshotsAPI format support for Copilot plan info#1/#2numbering in the menuDetailed Changes
Token Discovery — Keychain Support (TokenManager.swift)
copilotCliKeychaincase toCopilotAuthSourceenum withCustomStringConvertibleconformancereadCopilotCliKeychainAccounts()using a two-step Keychain query:kSecReturnAttributes+kSecMatchLimitAllto list all itemskSecReturnData+kSecMatchLimitOneto get the passwordkSecMatchLimitAll+kSecReturnDatareturnserrSecParam(-50) on macOShttps://github.com:username)getGitHubCopilotAccounts()between OpenCode auth and VS Code file discoverydedupeCopilotAccounts()priority ordering:Copilot API — quota_snapshots Format (TokenManager.swift)
quota_snapshotsAPI response format alongside the legacymonthly_quotas/limited_user_quotasformatquota_snapshotscontains per-type objects withentitlement,remaining, andunlimitedfieldssnapshotEntitlement = 0,snapshotRemaining = 0placeholder)GUI — Display Names (StatusBarController.swift, CopilotProvider.swift)
GitHub Copilot (Shaglock)) instead of generic index numbers (GitHub Copilot #1)GitHub Copilot (Shaglock) - OpenCodeinstead ofGitHub Copilot #1 (OpenCode)CopilotProvider.sourcePriority()to includecopilotCliKeychaincase with priority 2CLI — CopilotCLIProvider Rewrite (CopilotCLIProvider.swift)
Complete rewrite from ~276 lines to ~544 lines. The old provider only supported browser cookies and returned a single
ProviderResult. The new provider:TokenManager.shared.getGitHubCopilotAccounts()for token discovery (OpenCode auth, Keychain, VS Code files)ProviderAccountResultarrayCandidateDedupe.merge()for cross-source deduplication/userAPI when not available from token metadatafetchCustomerId,fetchUsageData) return optionals instead of throwing, enabling graceful fallbackCopilotUsagestruct (now uses the shared model fromCopilotUsage.swift)CLI — Table Formatter Alignment Fix (main.swift)
computeProviderWidth()that scans ALL row labels (regular providers, Gemini multi-account, generic multi-account) before renderingformatHeader(),formatSeparator(),formatRow(),formatGeminiAccountRow(),formatAccountRow()shortenAuthSource()to display file paths as just the filename (e.g.,/Users/x/.local/share/opencode/auth.jsonbecomesauth.json)accountLabel()andgeminiLabel()helpers shared between width computation and renderingBuild Configuration (project.pbxproj)
CopilotUsage.swiftto the CLI target's Sources build phase so the CLI can use the shared modelFiles Changed
CopilotMonitor/CopilotMonitor/Services/TokenManager.swiftCopilotMonitor/CopilotMonitor/Providers/CopilotProvider.swiftcopilotCliKeychaintosourcePriority()CopilotMonitor/CopilotMonitor/App/StatusBarController.swiftCopilotMonitor/CLI/Providers/CopilotCLIProvider.swiftCopilotMonitor/CLI/main.swiftCopilotMonitor/CopilotMonitor.xcodeproj/project.pbxprojTesting
Both targets build successfully (
BUILD SUCCEEDED)CLI discovers accounts from both OpenCode auth and Keychain sources
Table output is correctly aligned with dynamic column widths:
Example of new table render
JSON output correctly serializes both accounts with all fields
GUI menu shows multiple accounts correctly