Repository navigation
feat(accounts): add native accounts and in-place Claude account switching - #919
Open
Adam-Dalloul wants to merge 25 commits into
Open
Adam-Dalloul wants to merge 25 commits into
Adam-Dalloul wants to merge 25 commits into
Conversation
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
force-pushed
the
native-built-in-agent-accounts
branch
from
October 11, 2026 05:23
4c9548b to
9ee89cc
Compare
…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.
A tab that starts as a draft keeps a virtual runtime key, so its detail is never fetched. After the first send it read its account as Default and held auto-connect and reconnects for good, for every user. The account now comes from the binding the view set itself, then the newer of the workspace list and detail copies, and auto-connect waits only while none is known. The in-chat switcher stays disabled until then. The conversation list gets the in-flight ordering folders already have: an older snapshot is discarded, and a row an upsert changed while a refresh was in flight keeps the upsert's copy.
Connecting or sending to a conversation of another agent was refused with "This conversation belongs to a different agent account", which sends the user looking for an account problem. The refusal now names the other agent; a different account of the same agent keeps the account message.
Removing an account keeps its folder and its conversations, but adding that folder back created a new account. The conversations stayed bound to the removed one, so none of them could continue. Adding the folder of a removed account of the same agent now brings that account back, under the name entered, with its conversations. The removal dialog names the folder and says so, and a conversation of a removed account tells which folder to add again.
… it left A Claude account switch copies the session into the target account and leaves the source account's copy in place. The import scan listed that copy as new in the source account, and importing it created a stale duplicate whose row then blocked switching the conversation back. A copy is now treated as already imported when a live conversation under another account holds everything in it: its transcript as a prefix, and its sub-agent and tool result folder and file history as older trees, the switch's own test for a copy it may replace. The scan shows it as imported, an import of it is skipped, and the folder sweep leaves it out. A copy with anything of its own, or one that appears in two project folders, stays importable.
Every open conversation tab, hidden ones included, fetched the account list for itself and refetched it on every agent registry change, so one change sent a request per tab. The list is now kept once per agent and shared, the way the agent registry is: one request per agent on each change, and a refetch after a web client reconnects, since changes made while it was disconnected are lost. A failed refresh keeps the last list instead of emptying every tab at once, which made a draft's chosen account look gone.
…them A custom agent set up as a second account of a built-in agent (an extra slot) and a native account of that agent now do the same job, but their sign-ins had drifted apart. The slot ran the bare login command, which fails when the CLI is only installed by codeg (the OpenCode binary, say), and kept credentials the terminal exports, which can stand in for the login it is meant to create. Both now build the command the same way: the vendor CLI is resolved like codeg resolves it, and inherited credentials are cleared unless the slot sets them itself. The slot's card also points to the built-in agent's accounts, which keep that agent's features, and names the folder to add there. OpenCode is the exception, since its slot names only a config folder.
Collaborator
|
codeg work task |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Extra subscriptions currently require custom agents, which lose behavior tied to the built-in agent type. This adds named accounts under the built-in agents, so separate sign-ins can run concurrently while keeping native steering, controls, history and resume behavior.
Stacked on #471 and #470. Default continues to use the existing sign-in. Settings can create a profile or adopt an existing account folder, rename it, remove it without deleting files, and open the official sign-in flow. The browser keeps a copyable command when a terminal cannot be opened.
The account is saved on the conversation. Reconnect, config restart, fork, same-family delegation, transcript readers, imports, title refresh and selector preferences retain that binding. Removed or missing accounts fail explicitly. Identical native session IDs in different accounts remain distinct; adopting the same physical session through an old custom slot cannot create a second active writer.
Existing Claude conversations now have an account picker in the chat. Switching keeps the conversation, tab and native session id, with the full transcript, tool results and file-history. The target must acknowledge restoring the session before the saved account changes. Active turns and background work are refused; failed loads roll back, conflicting destination history is preserved, and a disconnected caller cannot interrupt the commit or rollback. Switching back carries the newer history forward. Other agents retain their saved account until equivalent native transfer is verified.
Supported: Claude Code, Codex, Gemini, OpenCode, Grok, Hermes, CodeBuddy, Cline, Kimi Code, Pi, DeepSeek, Qoder, Antigravity and Cursor. OpenClaw continues to use the account on its configured gateway. Cursor also isolates its credential store, since moving its chat folder alone does not move authentication. Shared MCP changes and skills reach account homes while preserving account-local entries and authentication files. Existing per-agent MCP limitations still apply.
Pi project-trust decisions and their acknowledgements also follow the selected account, including the restart after approval. Windows skill links are removed without touching the shared directory. Connection discovery retains the existing
nullresponse for a missing conversation and cannot use that absence to attach to Default.Validation:
Named profiles also clear OpenCode API-key overrides from the default launch environment. The account-isolation regression test covers those keys. All seven CI jobs pass on
cef21c9b: frontend and desktop/server checks on Linux, macOS and Windows.