opencode-openai-codex-auth icon indicating copy to clipboard operation
opencode-openai-codex-auth copied to clipboard

feat: add multi-account support with automatic rate limit rotation

Open tiltroom opened this issue 1 week ago • 5 comments

Summary

  • Multi-account authentication: Users can authenticate up to 10 ChatGPT accounts during initial OAuth flow
  • Automatic rate limit rotation: When a 429 response is received, automatically switches to the next available account
  • CLI management tool: New codex-accounts command for add/list/remove operations outside OAuth flow

Problem

Heavy users of the Codex plugin frequently hit ChatGPT's rate limits, causing interruptions. Users with multiple ChatGPT subscriptions (personal, work, etc.) have no way to leverage them for increased throughput.

Solution

This PR implements multi-account management that:

  1. Prompts users to add additional accounts during initial authentication
  2. Persists account metadata separately for runtime state tracking
  3. Automatically rotates to an available account when rate limits are hit
  4. Provides a CLI tool for managing accounts after initial setup

Changes

File Description
lib/accounts/manager.ts New - AccountManager class with round-robin rotation, rate limit tracking
lib/accounts/storage.ts New - Persistent storage to ~/.opencode/openai-codex-accounts.json
lib/accounts/cli.ts New - CLI prompt helper for multi-account setup
scripts/manage-accounts.js New - Standalone CLI tool (codex-accounts add/list/remove)
lib/types.ts Added types: ManagedAccount, AccountStorage, OAuthAuthDetails, RateLimitState
lib/constants.ts Added MAX_ACCOUNTS = 10
lib/auth/auth.ts Added isOAuthAuth() and accessTokenExpired() helpers
index.ts Refactored OAuth flow for multi-account, automatic 429 rotation
test/accounts.test.ts New - Comprehensive test coverage for account management
package.json Added codex-accounts bin entry

How It Works

Authentication Flow

opencode auth login
→ Complete first account OAuth
→ "You have 1 account(s). Add another? [y/N]: y"
→ Complete second account OAuth
→ ... repeat up to 10 accounts

Refresh Token Format

Multiple accounts are encoded in the refresh token field:

refresh1|accountId1||refresh2|accountId2||refresh3|accountId3

Rate Limit Handling

  1. Request sent using current account
  2. If 429 received, parse Retry-After header
  3. Mark current account as rate-limited with reset time
  4. Rotate to next available account
  5. Persist state to storage file

CLI Management

# List all configured accounts
codex-accounts list

# Add another account
codex-accounts add

# Remove account by index
codex-accounts remove 1

Storage Locations

Platform Path
Linux ~/.local/share/opencode/openai-codex-accounts.json
macOS ~/.local/share/opencode/openai-codex-accounts.json
Windows %APPDATA%/opencode/openai-codex-accounts.json

Testing

Added comprehensive test suite in test/accounts.test.ts covering:

  • Multi-account refresh token parsing/formatting
  • AccountManager initialization from storage vs refresh string
  • Rate limit tracking and account rotation
  • Add/remove account operations
  • Auth details conversion

Backwards Compatibility

  • Single-account users are unaffected (no prompt to add more unless they want to)
  • Existing refresh tokens work as-is (parsed as single account)
  • Storage file is only created when multiple accounts are configured

tiltroom avatar Jan 06 '26 11:01 tiltroom

Because of expiring refresh tokens, the rotation could happen in certain intervals, e.g. 5% weekly used, as an idea

dlukt avatar Jan 06 '26 12:01 dlukt

Because of expiring refresh tokens, the rotation could happen in certain intervals, e.g. 5% weekly used, as an idea

Keep in mind that every time we get a 429 it will switch to the next account. I expect pretty much a sort of round robin distribution and "organic" refreshes.

tiltroom avatar Jan 06 '26 16:01 tiltroom

here u go i hope it helps

https://github.com/ndycode/opencode-openai-codex-auth-multi

ndycode avatar Jan 06 '26 20:01 ndycode

Because of expiring refresh tokens, the rotation could happen in certain intervals, e.g. 5% weekly used, as an idea

Keep in mind that every time we get a 429 it will switch to the next account. I expect pretty much a sort of round robin distribution and "organic" refreshes.

Yes but sometimes you leave the other accounts bare for whatever reason. My suggestion is not a good one, in retrospect. If a refresh token is expired for whatever reason, a new JWT should be created aka it needs to prompt the user to log in again, IMHO, if not already the case.

dlukt avatar Jan 06 '26 21:01 dlukt

He's taking his time. @ndycode thanks!

dlukt avatar Jan 10 '26 00:01 dlukt