Skip to content

feat(accounts): add native accounts and guided sign-in - #919

Open
Adam-Dalloul wants to merge 59 commits into
spacering-net:mainfrom
Adam-Dalloul:native-built-in-agent-accounts
Open

Adam-Dalloul wants to merge 59 commits into
spacering-net:mainfrom
Adam-Dalloul:native-built-in-agent-accounts

Conversation

@Adam-Dalloul

@Adam-Dalloul Adam-Dalloul commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Add named accounts to built-in agents while retaining their native identity, model controls, history, imports, @ targeting and delegation behavior. A chat keeps its selected account when reopened; missing, removed or wrong-family accounts cannot silently become Default.

Settings > Agents offers a name and supported connection method. Claude Code and Codex offer native account sign-in or an API key; other supported agents use their own setup. Existing-folder adoption preserves sign-in and history. Desktop starts official sign-in, and web provides the command to run on the host.

Native Claude account switches retain the transcript, session sidecars, file history, session task lists and legacy todos. Mutable task updates/deletions carry over, with replaced task files retained for recovery. The target must acknowledge native restoration and the requested model after its selectors finish loading. An unavailable model or custom shared task list refuses the switch. Account settings and memory remain account-specific. Explicit switching also works after a viewer reattach; implicit viewer teardown still only detaches.

Named accounts cover 14 families on Windows/Linux and 13 on macOS. Cursor uses Default on macOS. Kiro, ZCode, TRAE CLI and Command Code do not support named accounts; OpenClaw uses its gateway account. Existing-chat native account transfer is Claude-only. Cross-agent/context handoff is in #669.

Validation: server/MCP all-target Clippy with warnings denied, TypeScript, picker/hook tests, and the combined-stack account/API/MCP/browser regressions. Fixtures verify task round trips, model refusal, rollback, account-specific routing, imports, credentials isolation and preserved drafts. Provider sign-in and generation have not been exercised live for every vendor/OS. See docs/agent-accounts.md for the supported flow and backup scope.

Includes the compatibility work from #470 and #471; maintainer edits are enabled.

Settings MCP still targets the built-in family row. Extra custom
agents whose spec.env sets CLAUDE_CONFIG_DIR, CODEX_HOME, GROK_HOME,
GEMINI_CONFIG_DIR, or OPENCODE_CONFIG_DIR now receive the same server
on upsert and lose it on remove.

Claude extra homes only get enabledPlugins; server defs stay in the
shared ~/.claude.json. Auth files are never copied.
Custom agents whose spec.env sets a family isolator now have a Sign in
card on the Agents page. That opens the official CLI login
(claude/codex/grok/gemini/opencode) with the isolator env set.

No tokens are copied. Account 1 stays on the built-in home. Headless
and unit-test paths return the command instead of spawning a terminal.
@Adam-Dalloul
Adam-Dalloul marked this pull request as ready for review October 11, 2026 04:40
Settings MCP still targets the built-in family row. Extra custom
agents whose spec.env sets CLAUDE_CONFIG_DIR, CODEX_HOME, GROK_HOME,
GEMINI_CONFIG_DIR, or OPENCODE_CONFIG_DIR now receive the same server
on upsert and lose it on remove.

Claude extra homes only get enabledPlugins; server defs stay in the
shared ~/.claude.json. Auth files are never copied.
Custom agents whose spec.env sets a family isolator now have a Sign in
card on the Agents page. That opens the official CLI login
(claude/codex/grok/gemini/opencode) with the isolator env set.

No tokens are copied. Account 1 stays on the built-in home. Headless
and unit-test paths return the command instead of spawning a terminal.
@Adam-Dalloul
Adam-Dalloul force-pushed the native-built-in-agent-accounts branch from 4c9548b to 9ee89cc Compare October 11, 2026 05:23
@Adam-Dalloul Adam-Dalloul changed the title feat(accounts): keep extra accounts on built-in agent types feat(accounts): add native accounts and in-place Claude account switching Oct 11, 2026
Adam-Dalloul and others added 4 commits October 11, 2026 08:35
…tches

A connection whose task ends on its own (the agent failed to load or
exited, or the task panicked) now parks its child in the manager's
draining list, as every explicit teardown does, so a missing map entry is
never taken as proof that the process stopped. The deferred cleanup is
spawned on the connection's runtime handle, because the guard drops
outside any runtime context. Account switches wait for every writer of the
session before copying it and before rolling a target back, and a child
parked after its task finished leaves the list as soon as it is reaped.

A switch's staging copies are removed once the switch is committed, a
rollback completes, or staging itself fails. They are kept only when a
rollback fails.
Launching a named account re-applies the shared MCP servers to config
files that the account's own CLIs rewrite too. The config writers now
leave a file alone when its content would not change, and the config
staleness check no longer syncs account folders at all.

Pi accounts mirror pi's own server list instead of the empty ACP
forwarding view, which removed their servers again on every launch. A
missing account folder no longer fails the import scan or every MCP
change; that account is skipped until its folder is restored.
…ount

A conversation switched to another account keeps its session in that
account's folder. Work-task retries, returns and merges, their
fresh-session fallback, and chat-channel resumes now launch with the
conversation's saved account instead of the Default one, which the prompt
gate then refused.
@Adam-Dalloul

Copy link
Copy Markdown
Contributor Author

@xintaofei, the account and usage PRs (#470, #471, #919, and #472) are refreshed on v0.36.0, with conflicts resolved and desktop/mobile checks passing locally. Could you take another look when the remaining CI checks finish?

The account migration is now m20261017_000001_agent_account and is
registered last, after the four migrations v0.36.0 shipped.

A backup records only the last registered migration, and a release
restores any backup whose last migration it knows. With the account
migration in the middle of the list, a backup from this build named
m20261016_000002_conversation_assistant, so v0.36.0 restored it and
then failed to start, since it has no file for the account migration.
Now v0.36.0 refuses such a backup as coming from a newer version.

A database that already ran a build with the old name must have its
seaql_migrations row renamed to the new one.
The locale files now differ from main only by this branch's own
strings. Merging v0.36.0 had moved four of main's blocks to the end of
their sections in all ten locales: MentionPanelSettings,
WindowAttentionSettings, and AcpAgentSettings' kiro and distribution.
No string was lost, but every locale conflicted with later changes next
to those blocks, and keeping main's side of a conflict listed kiro
twice.
Kiro's and ZCode's settings showed the server's English reason, "Named
accounts are not yet supported for this agent.", in every locale. The
accounts card now shows a translated note for any built-in agent
without accounts, and keeps the OpenClaw gateway note.
@xintaofei

Copy link
Copy Markdown
Collaborator

@Adam-Dalloul thanks for refreshing the stack on v0.36.0. The conflict resolutions hold up: I went through git show --remerge-diff for every hand-resolved file in a385417e6 and the earlier merges, and both sides' changes survived, including the review fixes from the last round. Dropping the duplicate /acp_login_extra_agent route in 86c087cb7 was a good catch too, since axum panics on an overlapping method route when the router is built.

I pushed three commits on top of 412f570b1. The first fixes a problem that would otherwise ship in the next release, and the other two are small. Below that are three open items I'd like to settle with you before merging.

1. The account migration now runs after v0.36.0's (2d79f6a10)

After the merge, m20261011_000001_agent_account was registered before the four migrations v0.36.0 already shipped. A backup's manifest names only the last registered migration (latest_migration_name), and that name is what a release checks to decide whether a backup comes from a newer version (evaluate_compat). With that order, a backup from a build of this branch named m20261016_000002_conversation_assistant. v0.36.0 knows that name, so it would accept the backup. Once the restored database was swapped in at startup, v0.36.0's migrator would stop on an applied migration it has no file for, and Codeg would not start.

The migration is now m20261017_000001_agent_account, registered last, so backups made with this build name it, and v0.36.0 refuses them as coming from a newer version. account_migration_runs_after_every_released_migration checks its position against v0.36.0's newest migration and fails with the old order. The migration's content is unchanged, and your account_migration_can_follow_newer_release_migrations test still covers upgrading a v0.36.0 database.

One step for a database that ran an earlier build of this branch: it will no longer start, and the error is

Migration file of version 'm20261011_000001_agent_account' is missing, this migration has been applied but its file is missing

The failed start migrates nothing. Quit every Codeg process that uses that database, then rename the recorded migration. The file is codeg-dev.db for a debug desktop build and codeg.db otherwise, in Codeg's data directory. Keep the quotes, since that path can contain spaces:

sqlite3 "/path/to/codeg-dev.db" "UPDATE seaql_migrations SET version = 'm20261017_000001_agent_account' WHERE version = 'm20261011_000001_agent_account'; SELECT changes();"

It prints 1 when it renamed the row, and 0 when no row currently has the old name, including when it was already renamed. The account tables are already there, so the account migration doesn't run again, and any v0.36.0 migration the database hadn't applied yet runs on the next start.

Backups taken with earlier builds of this branch keep the old name as well. Don't restore one taken after the v0.36.0 merge into v0.36.0. If you restore one into this build, Codeg stops with the same error after the restore, and the same rename fixes it. Backups taken before the merge name the old migration in their manifest, so this build refuses them as coming from a newer version.

2. The locale files add strings without moving main's (e20e93723)

The merge had moved four blocks that v0.36.0 added, MentionPanelSettings, WindowAttentionSettings, AcpAgentSettings.kiro and AcpAgentSettings.distribution, to the end of their sections in all ten locales. No string was lost, but the moves make later edits near those blocks likely to conflict in every locale. The files now differ from main only by this PR's strings.

3. Kiro and ZCode show a translated note (21cd032ac)

Their accounts card showed the server's English reason, "Named accounts are not yet supported for this agent.", in every locale. It now shows AgentAccounts.notSupported, translated in all ten locales. OpenClaw keeps its gateway note.

Checks

On 21cd032ac, all of these pass on macOS: tsc --noEmit, eslint ., vitest run with 9,725 tests, next build, the server lib tests with 5,388 passing, the desktop tests with test-utils with 5,727 passing, and clippy -D warnings for the desktop, server and codeg-mcp targets.

Open before merging

The refresh didn't change these, and I'd like your view on them:

  1. OpenCode, and Cursor on macOS, get the account folder as HOME (OpenCode, Cursor). OpenCode's account also gets its own XDG folders. The tools the agent runs in a named-account session inherit those values, so unless something points them elsewhere, git looks for the user's ~/.gitconfig, npm for ~/.npmrc and gh for its login inside the account folder instead. Is there a way to keep these two agents' credentials per account without replacing HOME? If not, one option is to leave them without named accounts for now, as Kiro and ZCode are.
  2. Real sign-ins. The tests check the isolation against fixture folders. Have you signed in with two real accounts on any of these agents? A short list of which agents you checked, and on which OS, would help us decide what to enable first.
  3. Backups. With "include conversation content" on, a backup packs the transcript folders Codeg resolves from its own environment (external_transcript_sources). It doesn't look at saved account folders, and Codeg's own agent-accounts folder isn't one of the backup sections either. A restore onto another machine therefore brings back the named-account conversations and their account bindings, but not the account folders or their transcripts. That seems fine as a documented limitation for now; I'm noting it so it's tracked.

If any of this misreads the code or your intent, please push back.

@Adam-Dalloul

Copy link
Copy Markdown
Contributor Author

Thanks @xintaofei, I've addressed the isolation and backup points and carried your fixes into #472. The updated description includes the exact validation, including two existing Claude sign-ins on Windows.

@Adam-Dalloul Adam-Dalloul changed the title feat(accounts): add native accounts and in-place Claude account switching feat(accounts): native accounts with guided setup and in-place Claude switching Oct 17, 2026
@Adam-Dalloul Adam-Dalloul changed the title feat(accounts): native accounts with guided setup and in-place Claude switching feat(accounts): add native accounts and guided sign-in Oct 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants