@guard22/opencode-multi-auth-codex
v1.4.2
Published
Multi-account OAuth rotation for OpenAI Codex with auto model discovery
Downloads
634
Maintainers
Readme
opencode-multi-auth-codex
Multi-account OAuth rotation plugin for OpenCode with a local dashboard, force mode, weighted settings, limits probing, and reliability hardening.
Documentation map
README.md-> primary operator and developer documentation for current behavior.docs/ADMIN_MERGE_BRIEF.md-> concise upstream/admin review summary.docs/PHASE_H_VALIDATION.md-> final validation report (current readiness reference).codextesting.md-> live/manual testing runbook.docs/README.md-> full docs index with authoritative vs historical references.
What this project does
- Rotates requests across multiple ChatGPT/Codex OAuth accounts.
- Keeps a local account store with migration, validation, and atomic writes.
- Provides a localhost dashboard to manage accounts and limits.
- Supports force mode (pin one alias), account enable/disable, and re-auth.
- Supports settings-driven rotation strategy (
round-robin,least-used,random,weighted-round-robin). - Probes limits safely and keeps authoritative data quality rules.
- Gates non-core Antigravity features behind a feature flag.
Current implementation status
- Core phases A-G are implemented in this workspace.
- Validation scripts are available for: unit, integration, web-headless, failure, stress, sandbox, soak.
- Web hardening fixes are in place:
- localhost-only bind enforcement
- malformed JSON returns deterministic
400without process crash - dashboard client script parse issue fixed
Behavior guarantees (latest)
- Rate-limit handling sleeps an alias until reset when reset timing is known (
Retry-After, rate-limit window reset, or parsed provider reset text), instead of retrying that alias immediately. - Force mode is strict: when enabled, requests stay pinned to the forced alias and do not silently fall back to other aliases.
- Rotation strategy control is shown next to Force Mode in the dashboard.
- Strategy changes from dashboard settings are applied to runtime selection logic (not just persisted state/UI display).
- Force Mode and strategy interaction is explicit:
- while Force Mode is ON, strategy changes are saved
- saved strategy becomes active when Force Mode is turned OFF
- Dashboard controls include mouseover help text for Force Mode and rotation strategy definitions.
- Account enable/disable toggle is authoritative for eligibility in rotation.
Rotation strategy reference
round-robin-> cycle through healthy enabled accounts in order.least-used-> prefer the healthy enabled account with the lowest usage count.random-> pick randomly from healthy enabled accounts.weighted-round-robin-> split traffic by configured account weights (example:0.70/0.20/0.10≈70%/20%/10%).- Force Mode precedence -> when Force Mode is ON, strategy is paused; strategy changes are saved and become active when Force Mode is OFF.
Repository structure
src/-> TypeScript sourcedist/-> compiled output (tscgenerated)tests/unit/-> unit teststests/integration/-> integration teststests/web-headless/-> headless UI smoke teststests/failure/-> failure-injection teststests/stress/-> stress/concurrency teststests/sandbox/-> sandbox isolation teststests/soak/-> soak scaffoldingdocs/-> QA and phase documentation (seedocs/README.mdfor canonical/historical split)IMPLEMENTATION_PLAN.md-> full plan and contractsTEST_EXECUTION_PLAN.md-> required test order and gatescodextesting.md-> live testing TODO for Codex CLI sessionsauto-login/-> Python script for bulk Outlook-based OAuth login
Requirements
- Node.js 20+
- npm
- OpenCode CLI
- ChatGPT/Codex OAuth accounts
Install and use
Plugin install (recommended)
Install from npm:
opencode plugin @guard22/opencode-multi-auth-codex@latest --globalIf you prefer config-based installation, OpenCode also supports:
{
"plugin": ["@guard22/opencode-multi-auth-codex@latest"]
}Package:
GitHub source install (fallback)
Use this if you want the repo head instead of the latest npm release:
opencode plugin github:guard22/opencode-multi-auth-codex --global{
"plugin": ["github:guard22/opencode-multi-auth-codex"]
}OpenCode support:
- GPT-5.5 may appear in Codex before OpenCode ships built-in model metadata
- the plugin backfills
gpt-5.5andgpt-5.5-fastinto runtime config by default - OpenCode builds that validate model IDs before plugin config is applied may still reject direct
openai/gpt-5.5selection - in that case, keep selecting
openai/gpt-5.4and enable latest-model mapping:
export OPENCODE_MULTI_AUTH_PREFER_CODEX_LATEST=1gpt-5.4remains available and can be selected or used as a rollback target- disable runtime model injection only if you explicitly want that behavior off:
export OPENCODE_MULTI_AUTH_INJECT_MODELS=0Update existing installs:
- npm install: rerun
opencode plugin @guard22/opencode-multi-auth-codex@latest --global - GitHub install: rerun
opencode plugin github:guard22/opencode-multi-auth-codex --global - restart OpenCode after updating the plugin
- if your install is pinned to a specific tag/commit, bump it explicitly before testing new models
From source
git clone https://github.com/guard22/opencode-multi-auth-codex.git
cd opencode-multi-auth-codex
npm ci
npm run buildQuick start
# Add accounts
opencode-multi-auth add personal
opencode-multi-auth add work
# Check status
opencode-multi-auth status
# Start dashboard
opencode-multi-auth web --host 127.0.0.1 --port 3434Open http://127.0.0.1:3434.
Automated Bulk Login (Outlook)
The auto-login/ directory contains a standalone Python script that automates the full OAuth login flow for multiple Outlook-based ChatGPT accounts. Instead of manually running opencode-multi-auth add and clicking through the browser for each account, the script handles everything:
- Opens OpenAI auth page
- Enters email, requests a one-time login code
- Logs into Outlook Web to read the verification code
- Enters the code, clicks through the consent page
- Captures the OAuth tokens and writes them directly into the plugin store
Prerequisites
- Python 3.9+
- Playwright (Python):
pip install playwright playwright install chromium - Outlook.com accounts linked to ChatGPT (the script reads OTP codes from Outlook Web)
Setup
Copy the example credentials file:
cp auto-login/credentials.example.json auto-login/credentials.jsonEdit
auto-login/credentials.jsonwith your real accounts:{ "defaults": { "chatgpt_password": "SharedPasswordIfAny" }, "accounts": [ { "id": "acc-1", "email": "[email protected]", "outlook_password": "your-outlook-password", "chatgpt_password": "your-chatgpt-password", "enabled": true } ] }defaults.chatgpt_passwordis used when an account doesn't specify its own.outlook_passwordis required for reading OTP codes from Outlook inbox.- Set
enabled: falseto skip an account without removing it.
Usage
# Check which accounts need login
python3 auto-login/auto_login.py --check
# Login all enabled accounts (headless)
python3 auto-login/auto_login.py
# Login a specific account by index
python3 auto-login/auto_login.py --account 0
# Login a specific account by email
python3 auto-login/auto_login.py --email [email protected]
# Run with visible browser (for debugging)
python3 auto-login/auto_login.py --visibleHow it works
OpenAI Auth Outlook Web Local Server
| | |
| 1. Enter email | |
| 2. Click "one-time code" | |
| ----sends OTP email-------> | |
| | 3. Login to Outlook |
| | 4. Read OTP from inbox |
| 5. Enter OTP code | |
| 6. Click Continue (consent) | |
| ----redirect callback-----> | ----code via HTTP GET----> |
| | | 7. Capture code
| | | 8. Exchange for tokens
| | | 9. Write to plugin storeThe script generates a PKCE challenge identical to the plugin's own OAuth flow, starts a local HTTP server on port 1455 to capture the callback, and writes tokens in the exact v2 store format the plugin expects.
Microsoft interstitials
Outlook login often shows interstitial pages after password entry:
| Page | Handled by |
|------|-----------|
| "Stay signed in?" | Auto-clicks "Yes" |
| "Let's protect your account" | Auto-clicks "Skip for now" |
| FIDO/Passkey creation (/fido/create) | Auto-clicks "Not now" / "Cancel" |
| Any other blocker | Force-navigates to inbox |
Troubleshooting
--visiblemode shows the browser so you can see exactly where the flow gets stuck.- Debug screenshots are saved as
auto-login/debug_<user>_<step>.pngon failure. - SSL errors on macOS: the script uses
ssl._create_unverified_context()for token exchange requests. This is safe for local automation. - Port 1455 in use: kill any process using that port, or change
REDIRECT_PORTin the script. - Stale OTP codes: if the inbox has old verification emails, the script may pick up an expired code. Clear the inbox or wait for a fresh email.
CLI commands
opencode-multi-auth add <alias>-> add account via OAuthopencode-multi-auth remove <alias>-> remove accountopencode-multi-auth list-> list configured accountsopencode-multi-auth status-> full statusopencode-multi-auth path-> print store pathopencode-multi-auth web --host 127.0.0.1 --port 3434-> run dashboardopencode-multi-auth service install|disable|status-> systemd user service helpers
Dashboard/API endpoints
GET /api/stateGET /api/logsPOST /api/syncPOST /api/auth/startPOST /api/switchPOST /api/removePOST /api/account/metaPOST /api/token/refreshPOST /api/limits/refreshPOST /api/limits/stopGET /api/accountsPUT /api/accounts/:alias/enabledPOST /api/accounts/:alias/reauthGET /api/forcePOST /api/forcePOST /api/force/clearGET /api/settingsPUT /api/settingsGET /api/settings/feature-flagsPUT /api/settings/feature-flagsPOST /api/settings/resetPOST /api/settings/presetPOST /api/antigravity/refresh(feature-flag gated)POST /api/antigravity/refresh-all(feature-flag gated)
Environment variables
Storage and auth
OPENCODE_MULTI_AUTH_STORE_DIR-> override store directoryOPENCODE_MULTI_AUTH_STORE_FILE-> override store file pathOPENCODE_MULTI_AUTH_CODEX_AUTH_FILE-> override Codexauth.jsonCODEX_SOFT_STORE_PASSPHRASE-> encrypt account store at restCODEX_SOFT_LOG_PATH-> override dashboard log path
Rotation and limits
OPENCODE_MULTI_AUTH_ROTATION_STRATEGY(settings source override; runtime rotation follows persisted dashboard settings)OPENCODE_MULTI_AUTH_CRITICAL_THRESHOLDOPENCODE_MULTI_AUTH_LOW_THRESHOLDOPENCODE_MULTI_AUTH_TOKEN_FAILURE_COOLDOWN_MSOPENCODE_MULTI_AUTH_PROBE_EFFORTOPENCODE_MULTI_AUTH_LIMITS_PROBE_MODELS
Model mapping and runtime behavior
OPENCODE_MULTI_AUTH_PREFER_CODEX_LATESTOPENCODE_MULTI_AUTH_CODEX_LATEST_MODELOPENCODE_MULTI_AUTH_INJECT_MODELSOPENCODE_MULTI_AUTH_TRUNCATIONOPENCODE_MULTI_AUTH_DEBUG
Latest Codex Mapping
The plugin can route older Codex selections to the latest Codex backend model when you explicitly opt in.
Default behavior:
- exact model selection is preserved
Environment variables:
OPENCODE_MULTI_AUTH_PREFER_CODEX_LATEST=1enables mapping to the latest backend modelOPENCODE_MULTI_AUTH_CODEX_LATEST_MODEL=gpt-5.4overrides the mapping target, for example to roll back from the defaultgpt-5.5OPENCODE_MULTI_AUTH_DEBUG=1prints model mapping debug logsOPENCODE_MULTI_AUTH_INJECT_MODELS=0disables automatic runtime model backfill
Fast Mode
For OpenCode builds that already accept gpt-5.5 model IDs, the clean way to mirror Codex Fast mode is:
- keep the model as
openai/gpt-5.5 - use a model variant such as
fast - set
serviceTier=priorityin the variant config
Behavior:
- the backend model stays
gpt-5.5 - the plugin forwards the request with
service_tier=priority - the plugin does not automatically lower reasoning or verbosity
Recommended OpenCode config:
{
"provider": {
"openai": {
"models": {
"gpt-5.5": {
"variants": {
"Medium Fast": {
"reasoningEffort": "medium",
"serviceTier": "priority"
},
"High Fast": {
"reasoningEffort": "high",
"serviceTier": "priority"
},
"XHigh Fast": {
"reasoningEffort": "xhigh",
"serviceTier": "priority"
}
}
}
}
}
}
}For OpenCode builds that still reject openai/gpt-5.5, keep selecting openai/gpt-5.4, keep your existing Fast variant, and set OPENCODE_MULTI_AUTH_PREFER_CODEX_LATEST=1. The plugin will send gpt-5.5 to the Codex backend while preserving service_tier=priority.
See docs/gpt-5.4-fast-benchmark.md for a continued-session benchmark summary.
Feature flags
OPENCODE_MULTI_AUTH_ANTIGRAVITY_ENABLED
Notifications
OPENCODE_MULTI_AUTH_NOTIFY=1enables optional completion/retry/error notifications. Notifications are off by default so they cannot delay normalopencode runlifecycle.OPENCODE_MULTI_AUTH_NOTIFY_SOUNDOPENCODE_MULTI_AUTH_NOTIFY_MAC_OPENOPENCODE_MULTI_AUTH_NOTIFY_NTFY_URLOPENCODE_MULTI_AUTH_NOTIFY_NTFY_TOKENOPENCODE_MULTI_AUTH_NOTIFY_UI_BASE_URL
Security rules
- Dashboard host is loopback-only (
127.0.0.1,::1,localhost). - Non-loopback host bind is rejected.
- Sensitive token patterns are redacted in logs.
- Store file permissions are restricted (
0o600). - Antigravity APIs are blocked when feature flag is off.
Build and test
npm ci
npm run lint
npm run build
npx tsc --noEmit
npm run test:unit
npm run test:integration
npm run test:web:headless
npm run test:failure
npm run test:stress
npm run test:sandbox
npm run test:soak:48hCurrent test script surfaces are scaffolded and active. For true long soak, set a long duration and keep the run alive.
Live validation runbook
Use codextesting.md for the Codex CLI live-testing checklist and copy-paste command flow.
Troubleshooting
- If dashboard start fails with localhost error, check
--hostand use loopback only. - If a request returns
INVALID_JSON, verify payload body is valid JSON. - If an alias action returns
ACCOUNT_NOT_FOUND, refresh account list first. - If re-auth is blocked with
ACCOUNT_DISABLED, enable the account before re-auth. - If encrypted store appears locked, export
CODEX_SOFT_STORE_PASSPHRASEbefore launching.
Development notes
- Edit
src/*, never hand-editdist/*. - Run
npm run buildafter source changes. - Keep manual/live tests sandboxed (temp HOME/store/auth paths).
Release flow
- This plugin is now intended to be installed from npm, so every shipped update should bump
package.jsonversion and publish a new package version. Reusing the same version on a new commit will leave users stuck on cached installs. - Prepare the next release by bumping the package version, rebuilding, and publishing:
npm version 1.2.1 --no-git-tag-version
npm install
npm run build
npm publish --access public- After that, cut the git release from
main:
git commit -m "chore: release v1.2.1"
git tag v1.2.1
git push origin main --follow-tags- Users who want a pinned build can install a specific npm version:
{
"plugin": ["npm:@guard22/[email protected]"]
}- Users tracking
latestshould rerun the install command and restart OpenCode after a new package lands.
License
MIT
