Skip to content

feat(cli): support OAuth login in setup - #4665

Merged
me2seeks merged 11 commits into
apache:mainfrom
hey-mira:feat/cli-setup-oauth
Sep 12, 2026
Merged

feat(cli): support OAuth login in setup#4665
me2seeks merged 11 commits into
apache:mainfrom
hey-mira:feat/cli-setup-oauth

Conversation

@hey-mira

@hey-mira hey-mira commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Add OpenAI OAuth (ChatGPT / Codex) sign-in to the CLI /setup wizard, so terminal and SSH users can configure an openai-codex Connection. The flow reuses the provider picker, editable name/slug fields, and model selector described in #4606.

OAuth entries appear when the Runtime Host enables openai-codex enrollment. OAuth exchange and credential storage remain owned by the Host. The API-key transaction is unchanged.

New OAuth accounts preselect gpt-6-astra, gpt-5.6-sol, gpt-5.6-terra, and gpt-5.6-luna. Existing accounts retain their saved model selections.

Fixes #4606

The blocks below describe keyboard interactions; they are not recordings of a live login.

Complete example: configure Work Codex

This example runs /setup inside an existing TUI session, with OAuth enabled and no existing Codex account. It creates Work Codex with slug codex-work, then enables four models. The device code and model list are illustrative; use the values shown by your Host. <cursor> indicates the active editing position and is not literal terminal text. Colors and borders are omitted.

1. Choose the provider

Run /setup, then type codex to filter the list.

Set Up Provider · 1/4 1
Search providers · ↑↓ select · Enter confirm · Esc cancel

Search codex<cursor>

→ OpenAI OAuth (ChatGPT / Codex)  openai-codex · add account

Press Enter to choose this provider.

2. Edit the account name

Replace the default Name with Work Codex.

Set Up Provider · 2/4 OpenAI OAuth (ChatGPT / Codex)
Name this connection, or keep the defaults to auto-assign · Enter continues · Esc returns

Name Work Codex<cursor>

Slug codex-subscription

Enter to continue

Press Enter to move focus to Slug.

3. Edit the account slug

Replace the default slug with codex-work.

Set Up Provider · 2/4 OpenAI OAuth (ChatGPT / Codex)
Name this connection, or keep the defaults to auto-assign · Enter continues · Esc returns

Name Work Codex

Slug codex-work<cursor>

Enter to continue

Press Enter to start sign-in with this name and slug.

4. Authorize in the browser

Open the displayed URL in a browser and enter the sign-in code.

Set Up Provider · 3/4 OpenAI OAuth (ChatGPT / Codex)
Open the device page and enter the sign-in code · Esc returns

https://auth.openai.com/codex/device

Sign-in code: ABCD-EFGH

⠋ Waiting for browser authorization…

Complete authorization in the browser. The CLI advances automatically after sign-in and model loading finish.

5. Review the discovered models

Set Up Provider · 4/4 OpenAI OAuth (ChatGPT / Codex)
Search models · ↑↓ select · Space toggle · Enter save · Esc back

Search <cursor>

→ ☑ gpt-6-astra
  ☑ gpt-5.6-sol
  ☑ gpt-5.6-terra
  ☑ gpt-5.6-luna

4 selected · Enter to save

Press Enter to save the four selected models.

6. Wait for the save

⠋ Saving…

7. Close the completed setup

After the save completes:

Set Up Provider · Complete OpenAI OAuth (ChatGPT / Codex)
✓ Models enabled: 4

Enter to close

Press Enter (or Esc) to return to the session.

The result is one OAuth Connection named Work Codex, with slug codex-work and the four selected models enabled. To use it in the current session, run /model and select an enabled model belonging to that account. Reopening /setup lists it as an existing account, so selecting it follows the three-step reauthorization flow below.

New OAuth account

Provider selection

Provider 1/4
  Search / ↑↓  → highlight OpenAI OAuth (ChatGPT / Codex)
  Enter        → Identity 2/4
  Esc          → close setup

Identity — Name field

Identity 2/4 · Name focused
  Name + Enter → focus Slug
  Name + Esc   → Provider 1/4

Identity — Slug field

Identity 2/4 · Slug focused
  Slug + Enter → validate identity, then start OAuth 3/4
  Slug + Esc   → focus Name

Browser authorization

OAuth 3/4
  Open the displayed URL in a browser:
    https://auth.openai.com/codex/device
    Sign-in code: ABCD-EFGH (example)

  Browser authorization completes
    → Signed in → load models → Models 4/4

Model selection

Models 4/4
  Search / ↑↓ / Space → find and toggle models
  Enter              → save the selected models → Complete
  Esc                → signed-in OAuth 3/4

Completion

Complete
  Enter / Esc → close setup

Name and slug can be edited or left at their defaults. Invalid input stays in the identity step. A requested slug that is already taken also returns to that step for correction. The authenticated account and the model selection belong to the same Connection.

Existing OAuth account

Select an existing account

Provider 1/3
  Enter on an existing account → OAuth 2/3

Reauthorize that account

OAuth 2/3
  Browser authorization completes → load models → Models 3/3

Choose its enabled models

Models 3/3
  Enter → save model selection for the same account
  Esc   → signed-in OAuth 2/3

The name/slug step is skipped. Reauthorization preserves the Connection's identity, and model selection starts from its enabled models that are still available.

Enter / Esc while authorization is pending

Preparing or waiting for authorization

OAuth: preparing sign-in or waiting for browser authorization
  Enter → keep waiting; authorization happens in the browser
  Esc   → request cancellation → Cancelling…

Waiting for cancellation

Cancelling…
  Enter / Esc → keep waiting for the Host's result

The Host's result determines the next screen:

  • Cancellation confirmed: return to Identity with Slug focused for a new account, or Provider selection for an existing account.
  • Authentication completed before cancellation took effect: continue to the signed-in state and load models.
  • Failure confirmed: show the sign-in error.
  • Result cannot be confirmed: show the unconfirmed-result state.

Esc requests cancellation; it does not assume cancellation won a race with a completed login.

Sign-in failure or an unconfirmed result

Confirmed failure

Sign-in failed
  Enter → retry sign-in with the same account identity
  Esc   → Identity for a new account; Providers for an existing account

Unconfirmed result

Sign-in result is not confirmed
  Enter → check the same sign-in attempt again
  Esc   → close setup

After checking again:

  • Authenticated: load models.
  • Cancelled: return to Identity for a new account, or Providers for an existing account.
  • Failed: show the sign-in error.
  • Unconfirmed: keep offering status check / close.

An unconfirmed result does not imply that the account was never created. Checking again retains the sign-in attempt's identity so a lost response does not create a second independent login.

Enter / Esc after authentication

Model loading in progress

Signed in · Loading models…
  Enter → keep waiting for model loading
  Esc   → Provider selection

Model loading failed

Signed in · Model loading failed
  Enter → retry model loading for the authenticated account
  Esc   → Provider selection

Return from model selection

Models
  Esc → Signed in

Already signed in

Signed in
  Enter → reload models → Models
  Esc   → Provider selection

Back at provider selection

Provider selection after returning
  Refresh completes → the saved account appears as an existing account
  Enter on it       → reauthorize it through the existing-account flow
  Esc               → close setup

Returning keeps the saved Connection and credentials. Enter on the signed-in page only reloads models; selecting an existing account from the provider list starts reauthorization. Reloading models within the same flow preserves selections for models that remain available.

The provider list remains usable while refreshing and retains its cached entries if refresh fails. Late model-loading or catalog results do not interrupt subsequent navigation.

Model validation, save failure, and leaving during a save

Empty selection

Models: no models selected
  Enter → show validation error; stay on Models

Save failure

Models: save failed
  Selection remains available
  Enter → retry saving
  Esc   → Signed in

Save in progress

Models: saving
  Enter → keep waiting
  Esc   → Signed in

Leaving during a save does not undo a write that the Host has already accepted. A late result cannot pull the wizard back to an abandoned screen. A successful save refreshes the running TUI's model choices without switching the current session's account/model. If that refresh fails, setup reports that the account was saved and the model list needs reloading.

Closing setup and first-run onboarding

Close from any step

Any setup step
  Ctrl+C → close setup; request cancellation of any pending sign-in

Return to an existing session

/setup in an existing TUI session
  Close setup → return to the session

First-run onboarding

First-run onboarding
  Save succeeds → close onboarding → load the configured default
  Close setup   → close the onboarding TUI
                  Startup continues only if a default is configured

Verification

For the latest commit, 72ad69ea4 (including the merge of origin/main):

  • Core, Storage, Runtime, Runtime Host, and CLI builds passed.
  • 519 tests passed across the CLI onboarding and TUI suites, core model catalog and metadata suites, Runtime Host protocol, OAuth, session bundle and external-agent setup suites, and Storage runtime policy suites.
  • Added regression cases for Esc during model loading, after model-loading failure, and after returning from model selection. They also exercise refreshed-account selection, late results, refresh failure, and first-run closure.
  • Biome checks, TUI copy checks, locale hygiene, staged commit checks, and the protocol compatibility check against origin/main passed. The merged protocol uses compatibility epoch 146.

The full workspace suite was not rerun for the main-branch merge and default-model update. The earlier validation recorded in this PR reported one Runtime Host failure in production Host executes Bash against the current live sandbox boundary, outside the changed implementation. A recording of a real OpenAI device login remains pending; the interaction blocks above are illustrative.

AI use

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex assisted with implementation, tests, localized copy, review, and verification.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected CLI suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@github-actions github-actions Bot added the effort/XL Under 2500 readable lines label Sep 3, 2026
@hey-mira
hey-mira force-pushed the feat/cli-setup-oauth branch 2 times, most recently from 23053f0 to 33ccb3b Compare September 4, 2026 06:59
@hey-mira
hey-mira force-pushed the feat/cli-setup-oauth branch from 33ccb3b to 6f5f23f Compare September 4, 2026 09:13
# Conflicts:
#	packages/cli/src/runtime-host-tui-command.ts
#	packages/runtime-host/src/protocol/index.ts
Bound cancellation and shutdown observation, retain the Host attempt for reconciliation, and republish OAuth presentation capabilities before a retried start on each physical connection.

Generated-by: Codex
Resolve the OAuth setup copy against the current TUI catalog and advance the Runtime Host compatibility epoch to 142.

Generated-by: Codex
Resolve the Runtime Host compatibility epoch collision by assigning the OAuth create-target protocol epoch 143 and repinning the compatible Base64 allocation declaration.

Generated-by: Codex
Return authenticated setup to provider selection while keeping the saved connection. Refresh providers without blocking navigation, and ignore superseded model discovery and catalog results. Cover loading, failure, and model-selection return paths.
@hey-mira
hey-mira marked this pull request as ready for review September 11, 2026 15:47
@github-actions github-actions Bot added effort/XXL Over 2500 readable lines and removed effort/XL Under 2500 readable lines labels Sep 11, 2026
Resolve the independent epoch-143 changes by retaining session bundle support at 143 and advancing the OAuth identity extension to 144.

Generated-by: Codex
Preselect gpt-6-astra, gpt-5.6-sol, gpt-5.6-terra, and gpt-5.6-luna from the shared provider baseline. Preserve existing accounts' saved model selections.

Generated-by: Codex
Retain the Antigravity and session bundle protocol additions from main and advance the OAuth identity extension to compatibility epoch 146.

Generated-by: Codex

@me2seeks me2seeks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found no blocking correctness issue in the reviewed implementation.

Merge note — assign a new Runtime Host compatibility epoch when updating to current main

packages/runtime-host/src/protocol/index.ts:104

This branch assigns epoch 146 to the OAuth wire change: create targets may now carry a caller-selected Connection name and slug, and slug collisions add a closed typed result. Current main independently assigns epoch 146 to the Code Mode settings and Session tool-mode contract. The combined protocol cannot continue advertising 146, because a Client or Host that implements only one of those contracts could pass the compatibility handshake with a peer that implements the other.

I reproduced the conflict by merging current origin/main (3cfcb09fd903bfbf94cbc4684b78c67be616342a) into the reviewed head (72ad69ea41d10d110a6546c377a56f09a7a76e0e). Resolving the combined declaration to epoch 147 makes the repository guard pass:

Protocol epoch guard: Protocol changed and the epoch moved: 146 -> 147.

When updating the currently conflicting branch, please set RUNTIME_HOST_COMPATIBILITY_EPOCH to 147, retain the epoch-146 Code Mode note, add the OAuth contract as the epoch-147 note, and rerun CI on the new exact head.

I found no other blocking correctness issue. The design follows the Desktop boundary: the CLI presents the device login and drives interaction, while the Runtime Host owns authorization exchange, credential persistence, Connection commit, cancellation races, and durable recovery. The CLI additionally covers terminal-specific loss and reconnect cases, including re-observing the same attempt after an SSH disconnect and refusing to attach it to a different Host root.

The reviewed head passed clean install, full workspace build/typecheck/format, and 432 focused CLI, OAuth protocol/coordinator, and Runtime Policy storage tests.

中文说明

已审查的功能实现没有发现阻塞正确性问题。

合并提示 — 更新到当前 main 时为组合后的 Runtime Host 协议分配新 epoch

packages/runtime-host/src/protocol/index.ts:104

该分支把 epoch 146 用于 OAuth 协议变化:创建 Connection 时可以携带用户选择的 name/slug,slug 冲突也新增了闭合的类型化结果。当前 main 又独立把 epoch 146 用于 Code Mode 设置和 Session tool mode。合并后的协议不能继续使用 146,否则只实现其中一套协议的 Client 与 Host 可能通过兼容握手,却在实际请求时使用不同的 wire contract。

我在精确 head 72ad69ea41d10d110a6546c377a56f09a7a76e0e 上合并当前 origin/main 3cfcb09fd903bfbf94cbc4684b78c67be616342a 复现了冲突。把组合结果改为 epoch 147 后,仓库协议守卫通过并报告:

Protocol epoch guard: Protocol changed and the epoch moved: 146 -> 147.

更新当前有冲突的分支时,请将兼容 epoch 改为 147,保留 146 的 Code Mode 说明,并把 OAuth identity/slug contract 记录为 147,然后在新的精确 head 上重跑 CI。

除此之外没有发现阻塞正确性问题。设计沿用了 Desktop 的边界:CLI 展示设备登录信息并承载交互,Runtime Host 负责授权交换、凭据持久化、Connection 提交、取消竞态和持久恢复。CLI 还覆盖了终端特有的断线与重连,包括 SSH 断开后继续查询同一个 attempt,以及拒绝把旧 attempt 接到不同的 Host root。

已审查 head 通过干净安装、全仓 build/typecheck/format,以及 432 个 CLI、OAuth 协议/协调器和 Runtime Policy 存储测试。

Retain the Code Mode protocol contract at epoch 146 and advance the OAuth identity extension to compatibility epoch 147. Allow required unified-diff context markers in the imported patch files during whitespace checks.

Generated-by: Codex
@me2seeks
me2seeks merged commit 8af5612 into apache:main Sep 12, 2026
2 checks passed
@hey-mira
hey-mira deleted the feat/cli-setup-oauth branch September 12, 2026 09:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/XXL Over 2500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CLI] Support account OAuth login in /setup

3 participants