Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Package version: see `package.json` (`version` field).
| Plugin orchestration | `index.ts` | OAuth loader, request pipeline, metrics, recovery, `ToolContext` assembly |
| TUI quota status | `tui.ts`, `lib/tui-status.ts`, `lib/tui-quota-cache.ts`, `lib/codex-usage.ts` | prompt quota status, quota details, shared quota cache |
| Tool registry | `lib/tools/index.ts` + `lib/tools/codex-*.ts` | 24 registered `codex-*` tools |
| OAuth flow + PKCE | `lib/auth/auth.ts`, `lib/auth/server.ts`, `lib/auth/device-code.ts`, `lib/auth/login-runner.ts` | browser/device/manual login, token refresh, workspace selection |
| OAuth flow + PKCE | `lib/auth/auth.ts`, `lib/auth/server.ts`, `lib/auth/device-code.ts`, `lib/auth/login-runner.ts`, `lib/auth/loopback-flow.ts` | browser/device/manual login, shared listener lifecycle, token refresh, workspace selection |
| OAuth scopes | `lib/auth/scopes.ts` | connector scope validation and re-auth checks |
| Multi-account rotation | `lib/accounts.ts`, `lib/accounts/`, `lib/rotation.ts` | `rotationStrategy` hybrid/sticky/round-robin, health scoring, cooldowns, token bucket, recovery |
| Account storage | `lib/storage.ts`, `lib/storage/` | V3 facade, per-project/global paths, keychain, backup/import/export |
Expand Down
4 changes: 2 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Standalone read/ops commands (no OpenCode agent loop required): `doctor`, `statu

`index.ts` is the runtime entry OpenCode loads. It owns:

- OAuth login modes: browser callback, device code, and manual URL paste
- OAuth login modes: default-browser callback, open-URL-manually callback, device code, and manual URL/code paste
- account manager lifecycle and local account storage (V3)
- request URL/body/header transformation (native or legacy, plus responses-lite for GPT-5.6)
- health-aware account selection, `rotationStrategy`, and `modelAccountPools`
Expand Down Expand Up @@ -154,7 +154,7 @@ This guarantee is intentionally local-filesystem/same-host. A process that exits
- Multi-turn continuity depends on `reasoning.encrypted_content` and the host-supplied conversation history.
- Account pool limits: max **20** accounts; auth-failure cooldown **30s**; auto-removal after **3** consecutive auth failures.
- Account bootstrap can hydrate from Codex CLI storage under `~/.codex` unless `CODEX_AUTH_SYNC_CODEX_CLI=0`.
- Auth methods exposed to OpenCode are the three OAuth labels only (browser, device code, manual URL). There is no registered API-key login method.
- Auth methods exposed to OpenCode are the four OAuth labels only (default browser, open URL manually, device code, manual URL/code paste). There is no registered API-key login method.
- Credentials and account metadata stay local unless the user exports or migrates them.
- Diagnostic commands redact sensitive account/token details by default.
- The optional keychain backend must fall back without deleting JSON credentials silently.
Expand Down
4 changes: 2 additions & 2 deletions docs/development/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ OpenCode runtime
| loads plugin package
v
index.ts
|- auth loader: browser callback, device code, manual URL paste
|- auth loader: default-browser callback, open-URL-manually callback, device code, manual URL/code paste
|- account manager + V3 storage + optional keychain
|- custom provider fetch pipeline
|- runtime metrics, retry budgets, circuit breaker, recovery hooks
Expand Down Expand Up @@ -95,7 +95,7 @@ tui.ts
| Installer CLI | `scripts/install-oc-codex-multi-auth.js`, `scripts/install-oc-codex-multi-auth-core.js` | npm bin; config merge; cache cleanup; modern/full/legacy catalog selection; standalone doctor/status/list/limits/dashboard/health/diag/warm; TUI plugin enablement |
| OpenCode plugin entry | `index.ts` | auth loader, runtime wiring, custom fetch pipeline, account manager lifecycle, `ToolContext`, OpenCode plugin export |
| TUI plugin entry | `tui.ts`, `lib/tui-status.ts`, `lib/tui-quota-cache.ts`, `lib/codex-usage.ts` | prompt quota status, account-aware quota snapshots, usage refresh, details rendering |
| Auth flow | `lib/auth/auth.ts`, `lib/auth/server.ts`, `lib/auth/browser.ts`, `lib/auth/device-code.ts`, `lib/auth/login-runner.ts`, `lib/auth/scopes.ts` | PKCE OAuth, callback server, device/manual login, workspace/account selection, scope validation |
| Auth flow | `lib/auth/auth.ts`, `lib/auth/loopback-flow.ts`, `lib/auth/server.ts`, `lib/auth/browser.ts`, `lib/auth/device-code.ts`, `lib/auth/login-runner.ts`, `lib/auth/scopes.ts` | PKCE OAuth, callback server, default-browser and open-URL-manually listener flows, device code, manual URL/code paste, workspace/account selection, scope validation |
| Account manager | `lib/accounts.ts`, `lib/accounts/` | account state facade, persistence, rotation, recovery, rate-limit tracking, workspace identity preservation, warm |
| Storage | `lib/storage.ts`, `lib/storage/` | V3 JSON storage, atomic writes, migrations, per-project paths, backups, import/export, keychain opt-in, flagged accounts |
| Request bridge | `lib/request/fetch-helpers.ts`, `lib/request/request-transformer.ts`, `lib/request/response-handler.ts`, `lib/request/retry-budget.ts`, `lib/request/rate-limit-backoff.ts`, `lib/request/helpers/` | URL/body/header shaping, Codex invariants, responses-lite, client identity, SSE conversion, retry budgets, backoff, error mapping |
Expand Down
2 changes: 1 addition & 1 deletion docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Tokens, account state, plugin config, quota cache, and logs are stored locally o

## Is there an API-key login?

No. The plugin registers three OAuth methods only (browser, device code, manual URL paste). A dummy SDK key string is used internally for the OpenAI client; ChatGPT OAuth tokens do the real auth.
No. The plugin registers four OAuth methods (default browser, open URL manually, device code, manual URL/code paste). A dummy SDK key string is used internally for the OpenAI client; ChatGPT OAuth tokens do the real auth.

## What should I do if authentication fails?

Expand Down
20 changes: 12 additions & 8 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,25 +95,29 @@ opencode auth login
Then choose:

1. `OpenAI`
2. One of the **three** plugin OAuth methods:
- `Codex OAuth (ChatGPT Plus/Pro)` — browser callback (default)
2. One of the **four** plugin OAuth methods:
- `Codex OAuth (ChatGPT Plus/Pro)` — opens the default browser; completes through a localhost callback
- `Codex OAuth (Open URL Manually)` - prints the authorization URL after port 1455 is listening; open it in any browser; the callback completes automatically through localhost
- `Codex OAuth (Device Code)` — headless / SSH
- `Codex OAuth (Manual URL Paste)` paste the redirect URL
- `Codex OAuth (Manual URL Paste)` - paste the full callback URL or raw authorization code; the full URL is preferred because it carries the OAuth state parameter and a supplied state mismatch is rejected before token exchange; a raw code is also accepted and PKCE-bound to the current flow

There is **no** registered “Manual API Key” login path for this plugin. The provider still presents a dummy SDK key (`chatgpt-oauth`) internally; real auth is always OAuth.

The browser-based OAuth flow uses the same local callback port as Codex CLI. The authorize redirect is `http://localhost:1455/auth/callback`, while the local callback server binds `http://127.0.0.1:1455/auth/callback` and `[::1]:1455` for dual-stack localhost redirects. Authorization and token exchange go to `auth.openai.com`.
Both browser-based OAuth methods use the same local callback port as Codex CLI. The authorize redirect is `http://localhost:1455/auth/callback`, while the local callback server binds `http://127.0.0.1:1455/auth/callback` and `[::1]:1455` for dual-stack localhost redirects. Authorization and token exchange go to `auth.openai.com`.

Account records persist the granted OAuth scope. The required scopes are `openid`, `profile`, `email`, and `offline_access`; an account whose recorded scope is explicitly missing one of them is marked for re-auth instead of being silently reused. An account whose scope is simply unrecorded is left enabled — absent metadata is not treated as a failed grant — and an account previously marked for re-auth is restored automatically once a complete scope is known.

### Remote or Headless Login

If you are on SSH, WSL, or another environment where the browser callback flow is inconvenient:

1. rerun `opencode auth login`
2. choose `Codex OAuth (Device Code)`
3. open the verification link, enter the one-time code, and wait for login to finish
4. if device code is unavailable on your auth server, fall back to `Codex OAuth (Manual URL Paste)`
- **If localhost port 1455 is reachable** (including via `ssh -L 1455:localhost:1455 user@remote`):
1. rerun `opencode auth login`
2. choose `Codex OAuth (Open URL Manually)` - it prints the URL after the listener is ready; open it in any browser; login completes automatically through localhost
- **If localhost is not reachable** (containers, restricted networks):
1. rerun `opencode auth login`
2. choose `Codex OAuth (Device Code)` - follow the verification link and one-time code
3. if device code is unavailable, fall back to `Codex OAuth (Manual URL Paste)` - paste the full callback URL or raw authorization code

## Add the Plugin to OpenCode

Expand Down
12 changes: 7 additions & 5 deletions docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,13 @@ Failed to access Codex API

**Solutions:**

1. **Manual URL paste:**
1. **Alternate login:**
- Re-run `opencode auth login`
- Select **"Codex OAuth (Device Code)"** first if you are on SSH, WSL, or a headless machine
- If device code is unavailable, fall back to **"Codex OAuth (Manual URL Paste)"**
- Paste the full redirect URL after login when using the manual flow
- **If localhost port 1455 is reachable** (including via `ssh -L 1455:localhost:1455 user@remote`):
choose **`Codex OAuth (Open URL Manually)`** - it prints the URL after the listener is ready; open it in any browser; login completes automatically through localhost
- **If localhost is not reachable** (containers, restricted networks):
choose **`Codex OAuth (Device Code)`** - follow the verification link and one-time code;
if device code is unavailable, fall back to **`Codex OAuth (Manual URL Paste)`** - paste the full callback URL or raw authorization code

2. **Check port 1455 availability:**
```bash
Expand All @@ -247,7 +249,7 @@ Failed to access Codex API
**Solutions:**
- Re-run `opencode auth login` to generate a fresh URL
- Open the URL directly in browser (don't use a stale link)
- For SSH/WSL/remote, use **"Device Code"** first, then **"Manual URL Paste"** if needed
- For SSH/WSL/remote: if localhost port 1455 is reachable (including via SSH port forwarding), choose **Open URL Manually**; if localhost is not reachable, choose **Device Code**; use **Manual URL Paste** only as a last resort

</details>

Expand Down
Loading