Summary
Rework Control UI session management: agents become top-level sidebar sections, channel sessions get built-in smart groups with human names, the three create affordances collapse into one plus that opens a draft session with a target bar (agent / where / folder / branch + worktree), and worktree state becomes visible end to end.
Problem to solve
The sessions sidebar has grown three separate create affordances (New session, New chat in worktree, New group prompt), a hidden native agent <select> that teleports navigation on change, and a flat list that mixes channel-originated sessions with dashboard sessions. Channel DMs without a server label render raw peer ids ("Telegram · 123456789") and group sessions render token names ("slack:g-general") even though the store already carries the human title. Custom group catalog/order live in browser localStorage, so groups do not sync across devices and rename/delete page through sessions client-side. The managed-worktree backend is solid but invisible: session rows carry no branch/worktree info, no branch/base picker exists anywhere, every worktree is auto-named off origin/HEAD, and the Worktrees page shows no owner linkage. Session-level exec node bindings (execNode) exist in the data model but have no UI.
Proposed solution
Land as a PR stack:
- Protocol/server foundation: persist
worktree { id, branch, repoRoot } on session entries and expose it (plus execNode) on session rows; sessions.create gains worktreeBaseRef / worktreeName (write scope) and execNode (admin); new worktrees.branches RPC for base-ref pickers; worktrees.remove reports snapshotError; sessions.delete reports preserved dirty worktrees; gateway-owned session group catalog (sessions.groups.list/put/rename/delete, SQLite shared state DB) with server-side member updates; group display names prefer the human chat title.
- Sidebar redesign: agent sections replace the hidden select; built-in channel groups + Work group + custom groups + Chats; naming never shows raw keys/ids; a single plus creates a draft session with a Cursor-style target bar (agent / where / folder / branch + worktree); session rows show branch and node badges.
- Worktrees page upgrades: owner column with open-session links, create action with branch picker,
snapshotError-aware force delete; session delete surfaces preserved worktrees.
Alternatives considered
Keeping grouping browser-local (does not sync, rename requires client-side paging over every session); per-channel default groups server-side (unnecessary — channel structure is already on each row; render-time grouping suffices); running the agent loop on nodes for remote work sessions (contradicts the nodes-are-peripherals architecture; exec-node binding covers the near-term need).
Impact
Operators managing many sessions across agents and channels get a navigable sidebar, human names, one obvious create flow, visible worktree/branch state, and groups that follow them across devices. Existing flows keep working: plain New Chat, /new, and channel sessions are unchanged; new create params are additive.
Evidence/examples
Sidebar affordances and naming fallbacks: ui/src/components/app-sidebar.ts (three create controls, agent scope select), ui/src/lib/session-display.ts (raw peer-id fallback). Group catalog in localStorage: ui/src/lib/sessions/custom-groups.ts. Worktree backend without UI visibility: src/agents/worktrees/service.ts, src/gateway/server-methods/sessions.ts (worktree info returned once at create, not persisted), ui/src/pages/worktrees/worktrees-page.ts (no owner column, error-string matching for snapshot failures). Session exec node binding without UI: execNode in src/config/sessions/types.ts and packages/gateway-protocol/src/schema/sessions.ts.
Additional information
Related: #90757 (poor sidebar titles, inline rename), #99583 (session auto-titling).
Summary
Rework Control UI session management: agents become top-level sidebar sections, channel sessions get built-in smart groups with human names, the three create affordances collapse into one plus that opens a draft session with a target bar (agent / where / folder / branch + worktree), and worktree state becomes visible end to end.
Problem to solve
The sessions sidebar has grown three separate create affordances (New session, New chat in worktree, New group prompt), a hidden native agent
<select>that teleports navigation on change, and a flat list that mixes channel-originated sessions with dashboard sessions. Channel DMs without a server label render raw peer ids ("Telegram · 123456789") and group sessions render token names ("slack:g-general") even though the store already carries the human title. Custom group catalog/order live in browser localStorage, so groups do not sync across devices and rename/delete page through sessions client-side. The managed-worktree backend is solid but invisible: session rows carry no branch/worktree info, no branch/base picker exists anywhere, every worktree is auto-named off origin/HEAD, and the Worktrees page shows no owner linkage. Session-level exec node bindings (execNode) exist in the data model but have no UI.Proposed solution
Land as a PR stack:
worktree { id, branch, repoRoot }on session entries and expose it (plusexecNode) on session rows;sessions.creategainsworktreeBaseRef/worktreeName(write scope) andexecNode(admin); newworktrees.branchesRPC for base-ref pickers;worktrees.removereportssnapshotError;sessions.deletereports preserved dirty worktrees; gateway-owned session group catalog (sessions.groups.list/put/rename/delete, SQLite shared state DB) with server-side member updates; group display names prefer the human chat title.snapshotError-aware force delete; session delete surfaces preserved worktrees.Alternatives considered
Keeping grouping browser-local (does not sync, rename requires client-side paging over every session); per-channel default groups server-side (unnecessary — channel structure is already on each row; render-time grouping suffices); running the agent loop on nodes for remote work sessions (contradicts the nodes-are-peripherals architecture; exec-node binding covers the near-term need).
Impact
Operators managing many sessions across agents and channels get a navigable sidebar, human names, one obvious create flow, visible worktree/branch state, and groups that follow them across devices. Existing flows keep working: plain New Chat,
/new, and channel sessions are unchanged; new create params are additive.Evidence/examples
Sidebar affordances and naming fallbacks:
ui/src/components/app-sidebar.ts(three create controls, agent scope select),ui/src/lib/session-display.ts(raw peer-id fallback). Group catalog in localStorage:ui/src/lib/sessions/custom-groups.ts. Worktree backend without UI visibility:src/agents/worktrees/service.ts,src/gateway/server-methods/sessions.ts(worktree info returned once at create, not persisted),ui/src/pages/worktrees/worktrees-page.ts(no owner column, error-string matching for snapshot failures). Session exec node binding without UI:execNodeinsrc/config/sessions/types.tsandpackages/gateway-protocol/src/schema/sessions.ts.Additional information
Related: #90757 (poor sidebar titles, inline rename), #99583 (session auto-titling).