Account re-login over HTTP — `POST /accounts/login-capture`
The HTTP twin of the account panel's general Log In button: how an agent starts an Anthropic account re-login through Omniscio's local control server, polls until the flow finishes, and confirms which account was captured. Covers the two routes, the full headless sequence, every error status, and the credential-safety gates wrapped around it.
What it is
How an agent completes an Anthropic account re-login end to end over the CLI control server, without a human driving the desktop UI. This is the HTTP twin of the account panel's general "Log In" button.
Where to find it
The thing being driven here is the account panel's general "Log In" action, which sits in the footer of the account indicator — the small account strip in the app's chrome — and not the per-account orange re-auth buttons beside it. Everything else on this page is addressed to an agent working over HTTP rather than to someone clicking in the desktop UI.
How it behaves
What the "Log In" button actually does (and which browser it signs into)
The account panel's general "Log In" action — the account-agnostic one in the AccountIndicator footer, NOT the per-account orange re-auth buttons — starts a PKCE OAuth flow via authService.login():
- It opens the system default browser (through
shell.openExternal) to Anthropic's authorize URL, and starts a loopback HTTP server to catch the OAuth redirect. - It is account-agnostic: whichever Anthropic account finishes the sign-in is the one captured — Omniscio identifies the account from the tokens the callback returns.
- It signs into the system default browser — not a managed login window, and not the Real Chrome bridge / the user's real Chrome over CDP. So step 2's magic link must be opened in that same system-default-browser OAuth flow.
- It imports a completed OAuth callback, never browser cookies. There is no "paste cookies to sign in" path.
That last point is why the endpoint below must be started before the magic link is opened — the OAuth callback can only complete a flow that is already running.
For agents
The endpoint
POST /accounts/login-capture
- Auth: bearer, global
amc-clitoken only (cliTokenOnly). A scoped agent-session token is refused401— this route mutates credentials. - Body:
{ "loginHint"?: "<email>" }— an optional email prefilled into the OAuth page. The route captures whichever account actually signs in, regardless of the hint. - Behaviour: invokes the same
authService.login()capture the button uses, then the same post-login side-effects (other windows refreshed, CLI caches cleared, refresh cooldown reset, usage primed, rate-limited sessions auto-restored). - NON-BLOCKING (fire-and-forget): it starts the OAuth flow and returns immediately — it does NOT wait for the callback. Start it before opening the sign-in / magic link, then poll for the result.
- Response
202:{ ok: true, data: { started: true } }— that is the WHOLE body. There is noaccountId,account,health, oraccountSwitchedhere; the OAuth outcome is written only to the app log.
The poll target
GET /accounts/login-capture/status
- Auth: bearer (read preamble).
- Response
200:{ ok: true, data: { inProgress, activeAccount } }inProgress—truewhile a sign-in is still in flight; it flips tofalsewhen the flow finishes (captured, timed out, or cancelled).activeAccount—{ id, email }of the app-wide active account, ornull. After a successful capture this is the account that was captured, which is how you confirm which account landed.
- It reports liveness + the active account, not success:
inProgress: falsealone does not mean the login worked. Confirm withGET /accounts(below).
The full headless re-login sequence
- Start the capture —
POST /accounts/login-capture(optionally{ "loginHint": "<email>" }). This opens the system browser to the OAuth page and returns202 { started: true }right away. Do NOT hold the connection open, and do NOT try to read an account off this response. - User enters their email in the login browser (human step — may include a CAPTCHA).
- Agent opens the magic link from the account's Gmail so that same browser/flow completes the OAuth redirect → the loopback callback fires.
- Poll
GET /accounts/login-capture/statusuntildata.inProgressisfalse. The OAuth flow allows up to ~5 minutes, so poll on that budget and treat exhausting it as a failure. - Confirm:
GET /accountsshows the expected account athealth: "ok". This is the authoritative check —inProgress: falseonly means the flow ended, not that it succeeded. Cross-checkdata.activeAccount.emailfrom step 4 to see WHICH account was captured.
Errors
| Status | Meaning |
|---|---|
202 |
Success — the capture STARTED (not "completed"). Body is { started: true }; poll /accounts/login-capture/status. |
403 |
Managed pathway unavailable on this install (F038 fail-closed owner gate). On a public build with no managed accounts, no tier floor and no dev override, the route refuses before opening any browser. Not retryable — add your own Anthropic API key, or use your own claude login, instead. |
409 |
A login is already in progress, or the user cancelled it — a caller-state conflict (humanized message), not a server fault. |
400 |
Malformed body. |
401 |
Missing/invalid token, or an in-app session token (this route is global-token-only). |
5xx |
Token-exchange / network failure — humanized for the caller, raw logged server-side. |
Safety notes
- Desktop-only capability surfaced over loopback HTTP; because it mutates credentials it requires the global
amc-clitoken, never a spawned agent's scoped token. - The route returns no account data at all — the
202body is just{ started: true }, so no credential can leak through it. The stripped account view is served byGET /accounts. - Fail-closed managed-pathway gate (F038). Before anything else the route checks
isManagedPathwayAvailableForSpawn(); when the managed pathway is unavailable it answers403and never opens a browser. This mirrors theACCOUNT_ADD_LOGINIPC handler and exists because this route is reachable with a bearer token that lives on the customer's own disk — without the gate, a public build could bootstrap the managed account pool. Owner / dev installs are unaffected. See auth-pathways-contract.md. - The capture path is identical to the desktop button's, so a CLI capture and a button login leave the app in the same state.
Related
The wider account and sign-in picture — the account indicator, switching accounts, and what the orange per-account re-auth buttons do — is on the account indicator and account re-login pages. How a session's credential actually gets chosen, and what the managed-versus-own-key gate means, is on the auth pathways page. For driving Omniscio over HTTP in general, rather than this one route, start from CLI control.
Last verified 2026-09-23