Add opt-in read-only claude-swap adapter for Claude multi-account usage#1909
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed July 5, 2026, 10:11 AM ET / 14:11 UTC. Summary Reproducibility: yes. for the review finding. Source inspection shows that with more than one Claude token account, stacked layout, and more than one claude-swap snapshot, the token-account branch returns before claude-swap cards can render. Review metrics: 2 noteworthy metrics.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Mantis proof suggestion Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Land the accepted read-only adapter after resolving stacked-source rendering and adding redacted real behavior proof; keep account switching and per-account status items in later phases. Do we have a high-confidence way to reproduce the issue? Yes for the review finding. Source inspection shows that with more than one Claude token account, stacked layout, and more than one claude-swap snapshot, the token-account branch returns before claude-swap cards can render. Is this the best way to solve the issue? No for the current patch. The accepted adapter direction is sound, but the implementation should resolve the stacked-source conflict and include redacted real behavior proof before merge. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against cda65e7000d1. Label changesLabel justifications:
Evidence reviewedWhat I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (2 earlier review cycles)
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 52d7b54bf0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| if provider == .claude, self.shouldFetchClaudeSwapAccounts() { | ||
| await self.refreshClaudeSwapAccounts(generation: generation) |
There was a problem hiding this comment.
Run claude-swap without blocking Claude refresh
When the opt-in adapter is enabled and the configured cswap executable is slow, locked on Keychain, or hangs until its timeout, this await delays the regular Claude provider fetch from even starting. That makes the optional adapter affect the ambient Claude card’s freshness/loading state despite the feature contract saying adapter failures should not affect ambient Claude usage; run it after or independently from the required Claude refresh path so a bad external executable cannot stall normal Claude updates.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed: the adapter now runs as a detached task that is never awaited by the ambient Claude refresh (scheduleClaudeSwapAccountRefresh in d5253e2, with state isolation and cancellation handling in 6430cd4/b8469c1c). As a follow-up, 139a752 also stops override account cards from inheriting the provider-level ambient error, so a broken ambient Claude credential can no longer render inside per-account claude-swap cards (covered in MenuCardOverrideIsolationTests).
…hots Phase 1 of docs/claude-multi-account-and-status-items.md: execute exactly 'cswap --list --json' (no shell, bounded runtime and output), strictly parse schema v1 with its error envelope and sentinel statuses, and project rows into ProviderAccountUsageSnapshot keyed by claude-swap:<slot>. CodexBar reads no claude-swap or Claude Code credential storage. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Opt-in via Preferences > Providers > Claude: a claude-swap toggle plus executable path field. When enabled, each Claude refresh also runs the adapter and renders one card per account (active first) using the Kilo multi-scope pattern; adapter failures keep last-good rows as stale data and surface in settings without touching the ambient Claude card. Hide Personal Info redacts account emails as usual. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
52d7b54 to
b8469c1
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
Extend the override-card isolation from 6430cd4 to the lastError fallback: the ambient Claude error (e.g. OAuth credentials unavailable) was rendering inside every claude-swap account card. Apply the same surface scoping as the snapshot, token-cost, and source-label fallbacks, with coverage in MenuCardOverrideIsolationTests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 00e1a83be0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return false | ||
| } | ||
|
|
||
| if context.currentProvider == .claude, self.store.claudeSwapAccountSnapshots.count > 1 { |
There was a problem hiding this comment.
Render claude-swap cards even with stacked token accounts
When Claude already has more than one configured token account and the global multi-account layout is stacked, the earlier tokenAccountDisplay.showAll branch returns before this claude-swap branch can run. In that configuration, enabling claude-swap and successfully fetching multiple snapshots still silently shows only the token-account cards, so the new opt-in adapter does not render the accounts it just fetched; either combine the sources or make claude-swap precedence explicit for this case.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed in 9738b10: active claude-swap accounts now take explicit precedence over Claude token-account presentation — the claude-swap branch renders first in addMenuCards, and tokenAccountMenuDisplay(for:) returns nil for Claude while adapter rows are active, so the segmented switcher can't mix with adapter cards either. Covered in ClaudeSwapMenuPrecedenceTests (suppression for Claude, no effect on other providers) and documented in docs/claude.md.
There was a problem hiding this comment.
Correction: 9738b10e missed the squash cut-off, so this is still open on main. The fix (plus ClaudeSwapMenuPrecedenceTests and the packaged synthetic proof) is now #1913.
|
Landed after maintainer hardening and exact-head proof. Thanks @optimiz-r!
The final adapter is opt-in and read-only, cannot delay ambient Claude refreshes, rejects stale/config-mismatched results, preserves cancellation, strictly validates schema/identity invariants, and keeps account cards isolated from ambient costs, identity, source labels, and provider errors. |
|
Packaged synthetic proof added in 9738b10 (fake @clawsweeper re-review |
|
🦞🧹 Reason: re-review requires an open issue or PR. |

Summary
Implements Phase 1 of the accepted Claude multi-account design: an opt-in, read-only claude-swap adapter that shows every account's session and weekly usage as stacked Claude cards.
Addresses the Claude-subscription portion of #1756 and #1268. Account switching and per-account status items remain out of scope.
User experience
cswap --list --json.Maintainer hardening
Security boundary
claude-swap:<slot>, never an email or credential value.Validation
Fake executables and model/state seams only; no real credentials or Keychain access:
swift test --filter 'ClaudeSwap|ClaudeProviderRuntimeTests|StatusMenuHostedSubmenuRefreshTests|MenuCardOverrideIsolationTests'make check— SwiftFormat clean; SwiftLint 0 violations; docs/locales/repository checks pass.make test— full 47-shard suite.Focused coverage includes strict parsing, fixed argv, error envelopes, timeout/output bounds, cancellation-before-launch, stale/config result rejection, disabled-provider lifecycle, projection ordering, privacy redaction, open-menu readiness, and ambient account-data isolation.