Skip to content

feat(onboarding): in-app OAuth login for Codex and Claude (currently terminal-only) #1362

@nesquena-hermes

Description

@nesquena-hermes

Feature request

Add an in-app OAuth login flow for OpenAI Codex (ChatGPT subscription) and Anthropic Claude (Claude Pro/Max subscription) so users don't have to drop into the terminal to add these providers.

Reported by AvidFuturist, April 30 2026:

I'm confused on how to add the new Codex model (I'm using OAuth) and Claude models through the app. I feel I must be missing something. (Or should I still be using the terminal for that?) - OAuth model flows via web and Mac

Nathan is correct that he's not missing anything — there is no in-app path today. The current behavior is intentional but documented as a known gap.

Current state — verified in v0.50.248

In api/onboarding.py:158–161:

_UNSUPPORTED_PROVIDER_NOTE = (
    "OAuth and advanced provider flows such as Nous Portal, OpenAI Codex, and GitHub "
    "Copilot are still terminal-first. Use `hermes model` for those flows."
)

The list of OAuth-capable providers in hermes_cli/auth_commands.py:36:

_OAUTH_CAPABLE_PROVIDERS = {"nous", "openai-codex", "qwen-oauth", "google-gemini-cli", "minimax-oauth"}

Plus anthropic (handled separately via _run_anthropic_oauth_flow in hermes_cli/main.py:4740).

The detection side already works in the WebUI:

  • _provider_oauth_authenticated() in api/onboarding.py:327 checks auth.json for valid OAuth tokens
  • The wizard renders an "OAuth provider ready / pending" card via static/onboarding.js:140–170
  • The provider model picker correctly auto-detects OpenAI Codex when ChatGPT OAuth credentials exist (api/config.py:1683–1687)

What's missing is the login half — the user-facing button or flow that actually walks the user through the OAuth handshake from the web UI.

What "terminal-first" means today

To add Codex OAuth or Anthropic OAuth, the user has to:

  1. Open a terminal
  2. SSH or local-shell into the same machine the WebUI is running on
  3. Run hermes auth login openai-codex (or hermes auth login anthropic)
  4. Follow the device-code flow in the terminal
  5. Come back to the WebUI and refresh

For a Mac app user (especially one using the bundled WKWebView), step 2 is non-obvious and step 3 requires knowing the exact provider ID. This is friction Nathan has been hitting daily.

Proposed fix shape

The OAuth flows are device-code based — they generate a URL the user visits in a browser, the user approves, and the CLI polls for a token. That's perfectly portable to a web UI:

  1. Add an "OAuth login" button to the onboarding wizard's OAuth-pending card (static/onboarding.js:170 area). Click handler hits a new endpoint /api/onboarding/oauth/start?provider=openai-codex (and anthropic).
  2. Server endpoint (api/onboarding.py or a new api/oauth.py) wraps the existing CLI helpers:
    • openai-codex: reuse the device-code flow that already lives in hermes_cli/auth_commands.py
    • anthropic: reuse run_hermes_oauth_login_pure() from hermes_cli/auth_commands.py:224
    • Returns {verification_url, user_code, polling_token} to the front-end
  3. Front-end displays the verification URL and code in a modal, opens the URL in a new tab (or system browser via the Swift app's bridge), and polls a /api/onboarding/oauth/poll?token=... endpoint every 2s until the token is saved or times out.
  4. On success, the existing detection path (_provider_oauth_authenticated()) picks up the new credential automatically — no other plumbing needs to change.

The provider list to enable in the UI: openai-codex, anthropic, nous (already partially supported via the wizard), qwen-oauth, google-gemini-cli, minimax-oauth. GitHub Copilot is similar but uses a different auth model — it can be a separate follow-up.

Mac app considerations

The Mac app is a thin WKWebView wrapper, so once the WebUI side works, the Mac app gets the feature for free. One small caveat: opening the OAuth verification URL should use window.open() to escape WKWebView and hit the user's default browser (so they can sign in with their existing browser session). The Swift app may need a decidePolicyForNavigationAction hook to intercept verification URLs and route them to NSWorkspace.shared.open(_:) — but that's a Swift-side polish item, not a blocker.

Severity

M2 enhancement. Not a bug, but a real friction point for a power user — and a credibility gap (the app is "GUI-first" but punts to terminal for the most common premium auth flows). The fix is well-scoped because all the underlying CLI helpers already exist; it's purely a frontend + thin endpoint wrapper.

Suggested ordering

  1. Anthropic OAuth first — Claude Pro/Max users are the largest underserved group and the helper (run_hermes_oauth_login_pure) is already a clean pure-Python function.
  2. OpenAI Codex second — same shape, slightly different polling semantics. Nathan specifically called this out as one of his pain points.
  3. Other OAuth providers (Nous, Qwen, Gemini, MiniMax) third — same flow scaffold, just different provider IDs.

Marking sprint-candidate.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestsprint-candidateStrong candidate for next sprintuxUser experience / visual polish

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions