ChatGPT OAuth
Authenticate with a ChatGPT account instead of an OpenAI API key. openai-auth signs in through browser OAuth; model calls then use the ChatGPT-authenticated backend.
Configure
In the TUI β add it straight from the provider picker:
/provider # open the picker β Add `openai-auth`; starts the browser OAuth flow inline
/model <id> # pick a model your account allows (run /model list to see them)From the command line β sign in, then select the provider:
yottacode openai-auth loginexport YOTTACODE_PROVIDER=openai-auth
export YOTTACODE_MODEL=<your-model-id> # /model list shows what your account allows
export YOTTACODE_BASE_URL=https://chatgpt.com/backend-api/codexβ¦or pass flags at launch (no --api-key β auth uses the stored OAuth token):
yottacode --provider openai-auth \
--model <your-model-id> \
--base-url https://chatgpt.com/backend-api/codexAvailable models are account-dependent; after login, yottacode probes candidate models and stores the accepted list next to the token store.
Lifecycle commands:
yottacode openai-auth login
yottacode openai-auth status
yottacode openai-auth status --json
yottacode openai-auth logoutTokens and scanned model lists live in ~/.yottacode/auth/ with restrictive file permissions. That directory is denied to model read and write tools.
Context window. The Codex backend enforces a much smaller input limit than the same model ids have on api.openai.com: gpt-5.5 accepts roughly 272k input tokens here (measured 2026-06-10: 264,995 accepted, ~281k rejected) versus the 1.05M the catalog lists for the API-key provider. Window-derived behavior β the usage bar, the compaction watermark, auto-summarize β therefore resolves windows per provider kind: a provider-qualified entry (openai-auth/gpt-5, shipped at the verified-safe 264000) outranks the catalog’s per-model number, so facts from one backend never leak to a namesake model behind another. To pin a different value for an exact model, add an entry like {"prefix": "openai-auth/gpt-5.5", "window": 250000} to ~/.yottacode/context-windows.json β the longest matching prefix wins.
The backend also rejects max_output_tokens (Unsupported parameter), and mid-stream failures arrive as an SSE error event with the detail nested under error.message (followed by a response.failed event); the adapter surfaces that message verbatim, so an input-too-large turn reports context_length_exceeded instead of a generic stream error.
Passive drift correction. Advertised limits and enforced limits drift apart (the 272K-vs-1.05M case above), so yottacode also corrects windows from live traffic, for every provider kind: a turn rejected for context overflow that the local estimator thought would fit shrinks the window pin (estimate Γ 0.9, geometrically on repeat), and a completed turn whose exact provider-reported input exceeds the resolved window raises it to the proven value. Corrections are written as <kind>/<model> entries in ~/.yottacode/context-windows.json with a [window] notice in the transcript, and a shrink immediately re-runs the context check β so an over-window session auto-summarizes in the same turn instead of failing again. config.toml is never touched.