galaxyproject / galaxyproject/loom
Add Anthropic OAuth (Claude Pro/Max) sign-in to Orbit alongside API-key auth
- Dominant language
- TypeScript
- Stars
- 14
- Forks
- 12
- Avg merge
- 6d 5h
- Merged PRs (30d)
- 17
Description
## Motivation
Orbit currently requires users to paste an Anthropic API key into the welcome screen / Preferences. For Claude Pro / Max subscribers, OAuth-based sign-in (the same flow Claude Code uses) would be a much better first-run experience — no console trip, no key management, no leaked-secret risk. It also opens the door to GitHub Copilot, Google Gemini CLI, and OpenAI Codex sign-ins via the same plumbing.
## Most of the work is already in pi-ai
`@mariozechner/pi-ai/utils/oauth/anthropic.ts` exposes the full PKCE flow:
- `loginAnthropic({ onAuth, onPrompt, onProgress, onManualCodeInput })` — opens a Node HTTP callback server, generates the auth URL, waits for the redirect, exchanges the code for tokens, returns `OAuthCredentials`.
- `refreshAnthropicToken(refreshToken)` — token rotation.
- `anthropicOAuthProvider` — `OAuthProviderInterface` registration helper.
Sibling providers exist for GitHub Copilot, Gemini CLI, Antigravity, and OpenAI Codex — the same surface.
`pi-coding-agent` already wires OAuth into its auth storage:
- `core/model-registry.ts` calls `registerOAuthProvider`.
- `authStorage.getOAuthProviders()` enumerates registered providers.
- `migrations.js` migrates legacy `oauth.json` → `auth.json` with `{type: \"oauth\", ...creds}` records.
- `auth.json` already supports a mixed store of `apiKey` + `oauth` entries.
So the brain side is essentially free. 401 → refresh-and-retry should already be in pi-coding-agent's request pipeline.
## What Orbit needs to add
1. **Main-process auth handler** (~30 lines, new file `app/src/main/auth-handler.ts`):
- Calls `loginAnthropic({ onAuth: ({url}) => shell.openExternal(url), onPrompt: ..., onProgress: ... })`.
- The `onAuth(url)` fires once the local callback server is up; Orbit launches the user's default browser.
- When `loginAnthropic` resolves, persist the credentials via pi-coding-agent's `authStorage`.
- Single in-flight lock so multiple windows don't fight.
2. **Three IPC endpoints** in `ipc-handlers.ts`:
- `auth:login(provider)` — kicks off the flow; resolves on success or error.
- `auth:status()` — returns the current sign-in state per provider (signed in / handle / expiry; or none).
- `auth:logout(provider)` — clear credentials.
- Preload exposure: `window.orbit.signIn(provider)`, `window.orbit.authStatus()`, `window.orbit.signOut(provider)`.
3. **Welcome screen** (`index.html` + `app.ts`):
- Add a primary **\"Sign in with Claude\"** button above the API-key field.
- Keep the API-key input as a fallback (corporate networks, custom endpoints, sandboxed deployments).
- On click, call `signIn(\"anthropic\")`, show a small spinner while waiting, dismiss the welcome on success.
4. **Preferences modal**:
- Show signed-in state (\"Signed in as ``\" or \"Using API key (last 4: …)\") with a \"Sign out\" link.
- Sign-in button below for users who want to swap from API-key to OAuth (or vice versa).
5. **Migration on first run**: invoke `migrations.js`'s legacy-oauth migrator at agent startup so existing pi-coding-agent users on this machine pick up their tokens automatically.
## Pitfalls / things to plan for
- **Random callback port** — `loginAnthropic` picks a free local port; Linux/macOS will prompt for a firewall exception once. On Windows, the first launch shows a firewall dialog. Mention this in the welcome flow if helpful.
- **Corporate networks** that block `claude.ai/oauth` — keep the API-key path as a permanent fallback, do not remove it.
- **\"Only intended for CLI use\"** — pi-ai's note refers to the `http.createServer` callback; Electron's main process is Node-side, so this is fine. Do **not** try to call `loginAnthropic` from the renderer.
- **Token-refresh visibility** — pi-coding-agent should refresh transparently on 401, but if it surfaces an error to the agent shell when the refresh token also expires, Orbit should display \"Sign-in expired — please sign in again\" instead of letting it silently break the next turn.
## Out of scope / future
- GitHub Copilot, Gemini CLI, OpenAI Codex sign-ins — same code path; once Anthropic works, these are 1-line registrations in the auth handler. File as a follow-up issue once the Anthropic flow is shipping.
- An \"Account\" tab in Preferences listing all providers + their statuses. Nice-to-have; not blocking the MVP.
## Estimate
Half a day to a day for a polished MVP — the OAuth callback orchestration is the only \"real\" code, everything else is wiring buttons and state pills.
Happy to put up a PR for this once approved if no one else has it queued.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.