Skip to content

feat: add Copilot CLI Keychain token discovery and multi-account CLI support#84

Open
Shaglock wants to merge 2 commits intoopgginc:mainfrom
Shaglock:multi-account-and-copilot-cli
Open

feat: add Copilot CLI Keychain token discovery and multi-account CLI support#84
Shaglock wants to merge 2 commits intoopgginc:mainfrom
Shaglock:multi-account-and-copilot-cli

Conversation

@Shaglock
Copy link

@Shaglock Shaglock commented Feb 17, 2026

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

  • Add macOS Keychain (copilot-cli service) as a new GitHub Copilot token discovery source
  • Rewrite CLI's CopilotCLIProvider to use TokenManager for multi-account token discovery, matching the GUI provider's logic
  • Fix CLI table output alignment when multi-account provider names exceed the column width
  • Add quota_snapshots API format support for Copilot plan info
  • Display GitHub login names instead of #1/#2 numbering in the menu
image
Detailed Changes

Token Discovery — Keychain Support (TokenManager.swift)

  • Add copilotCliKeychain case to CopilotAuthSource enum with CustomStringConvertible conformance
  • Implement readCopilotCliKeychainAccounts() using a two-step Keychain query:
    1. Query with kSecReturnAttributes + kSecMatchLimitAll to list all items
    2. Query each item individually with kSecReturnData + kSecMatchLimitOne to get the password
    • This two-step approach is required because kSecMatchLimitAll + kSecReturnData returns errSecParam (-50) on macOS
  • Parse username from the Keychain account field (format: https://github.com:username)
  • Integrate into getGitHubCopilotAccounts() between OpenCode auth and VS Code file discovery
  • Update dedupeCopilotAccounts() priority ordering:
    • OpenCode auth: 3 (highest)
    • Copilot CLI Keychain: 2
    • VS Code hosts.json: 1
    • VS Code apps.json: 0 (lowest)
  • Add diagnostic logging for Keychain discovery in the auth summary

Copilot API — quota_snapshots Format (TokenManager.swift)

  • Add parsing for the new quota_snapshots API response format alongside the legacy monthly_quotas / limited_user_quotas format
  • quota_snapshots contains per-type objects with entitlement, remaining, and unlimited fields
  • Priority: snapshots > monthly > legacy
  • Preserve existing unlimited plan handling (snapshotEntitlement = 0, snapshotRemaining = 0 placeholder)
  • Add error response body logging for failed Copilot API calls

GUI — Display Names (StatusBarController.swift, CopilotProvider.swift)

  • Show GitHub login names (e.g., GitHub Copilot (Shaglock)) instead of generic index numbers (GitHub Copilot #1)
  • Change auth source separator from parentheses to dash: GitHub Copilot (Shaglock) - OpenCode instead of GitHub Copilot #1 (OpenCode)
  • Update CopilotProvider.sourcePriority() to include copilotCliKeychain case with priority 2

CLI — 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:

  • Uses TokenManager.shared.getGitHubCopilotAccounts() for token discovery (OpenCode auth, Keychain, VS Code files)
  • Falls back to browser cookies as an additional source (non-fatal if cookies unavailable)
  • Supports multi-account output via ProviderAccountResult array
  • Uses CandidateDedupe.merge() for cross-source deduplication
  • Fetches user login via GitHub /user API when not available from token metadata
  • Merges plan info from token API with usage data from cookie-based billing API
  • All cookie-based operations (fetchCustomerId, fetchUsageData) return optionals instead of throwing, enabling graceful fallback
  • Removes the local CopilotUsage struct (now uses the shared model from CopilotUsage.swift)

CLI — Table Formatter Alignment Fix (main.swift)

  • Replace hardcoded 20-char provider column width with dynamic computation
  • Add computeProviderWidth() that scans ALL row labels (regular providers, Gemini multi-account, generic multi-account) before rendering
  • Pass computed width to formatHeader(), formatSeparator(), formatRow(), formatGeminiAccountRow(), formatAccountRow()
  • Add shortenAuthSource() to display file paths as just the filename (e.g., /Users/x/.local/share/opencode/auth.json becomes auth.json)
  • Extract accountLabel() and geminiLabel() helpers shared between width computation and rendering
  • JSON formatter already supported multi-account output (added in earlier work)

Build Configuration (project.pbxproj)

  • Add CopilotUsage.swift to the CLI target's Sources build phase so the CLI can use the shared model

Files Changed

File Change
CopilotMonitor/CopilotMonitor/Services/TokenManager.swift Keychain reader, quota_snapshots parser, dedup priorities, diagnostics
CopilotMonitor/CopilotMonitor/Providers/CopilotProvider.swift Add copilotCliKeychain to sourcePriority()
CopilotMonitor/CopilotMonitor/App/StatusBarController.swift Display login names instead of indices
CopilotMonitor/CLI/Providers/CopilotCLIProvider.swift Full rewrite for multi-account TokenManager support
CopilotMonitor/CLI/main.swift Dynamic table column alignment, auth source shortening
CopilotMonitor/CopilotMonitor.xcodeproj/project.pbxproj Add CopilotUsage.swift to CLI target

Testing

  • 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 image
  • JSON output correctly serializes both accounts with all fields

  • GUI menu shows multiple accounts correctly

…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.
@op-gg-ai-devops
Copy link
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 TokenManager to correctly parse the newer quota_snapshots API field.


Code Review Feedback

  • Keychain Integration: The readCopilotCliKeychainAccounts implementation using SecItemCopyMatching is clean and standard for retrieving generic passwords. This is a great addition for users who rely on the official GitHub CLI auth.
  • API Future-Proofing: Excellent catch on the quota_snapshots structure in TokenManager. Relying solely on monthly_quotas or limited_user_quotas was becoming risky as the API evolved, so aggregating entitlements from snapshots makes the logic much more robust.
  • CLI UX: The dynamic width calculation in TableFormatter is a thoughtful improvement; fixed-width tables almost always break when long email addresses are involved.
  • Maintainability: Since CopilotCLIProvider now mirrors the GUI CopilotProvider significantly (deduplication priority, fetching logic), consider extracting shared logic into a common service in a future refactor to prevent logic drift between the two interface modes.

This is just a quick preview.
For a detailed, line-by-line code review (including bug detection and security checks), please comment:
**@opgginc/op-gg-ai-devops** review this

@Shaglock Shaglock changed the title feat: add Copilot CLI Keychain token discovery and multi-account CLI support feat: add Copilot CLI Keychain token discovery and multi-account CLI support #73 Feb 17, 2026
@Shaglock Shaglock changed the title feat: add Copilot CLI Keychain token discovery and multi-account CLI support #73 feat: add Copilot CLI Keychain token discovery and multi-account CLI support Fix #73 Feb 17, 2026
@Shaglock Shaglock changed the title feat: add Copilot CLI Keychain token discovery and multi-account CLI support Fix #73 feat: add Copilot CLI Keychain token discovery and multi-account CLI support Feb 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for Github copilot

1 participant

Comments