Repository navigation
Description
Motivation
Filling empty Grid Dispatch lanes takes a detour. When a lane is empty and its row is not bound to a project, resolveDispatchSpawnTarget files a new agent under the classic Dispatch focus (the last agent you selected) or activeTabId. So to put a Codex agent for project C into an empty lane, you first have to navigate to some existing agent in project C — only to move the "current project" — then return to the empty lane and run New Agent…. With five fresh lanes that detour happens five times.
The machinery to spawn into an explicit project already exists: createDetachedDispatchAgent(selection, { tabId, anchorSessionId }) is what the Dispatch project header's "+" and the external agents.create capability use, and it still places the agent in the focused lane. What is missing is a keyboard entry point that does not depend on focus.
Intended behavior
A new Dispatch command, New Agent In…:
- Step 1 — pick the agent: the same choices as New Agent… (Claude, Codex, OpenCode, OpenCode Terminal), from
AGENT_PROVIDER_CHOICES. - Step 2 — pick the project: project tabs, labelled with the same
A · titlevocabulary Dispatch uses. Backspace returns to step 1. The initial highlight is the project plain New Agent… would have used, so Enter-Enter is never worse than today. - Commit spawns a detached Dispatch agent in the chosen project, with its working directory borrowed from an existing agent in that project, into the focused lane (same lane semantics as New Agent…).
Decisions:
- Dispatch only (
surface: 'dispatch'). In the grid a project is a tab one keystroke away, and a detached agent spawned from the grid would be invisible there. - If the focused lane's row is bound to projects, step 2 offers only those projects — the binding contract says a row's index only lists its bound projects, so an agent from another project would sit in a lane its own index cannot show. Unbound rows offer every project.
- A project with no agent to borrow a directory from is listed but disabled, with the reason, rather than silently omitted.
- No default keybinding.
Acceptance criteria
-
New Agent In…appears in the command palette only while Dispatch is active. - Choosing an agent then a project creates that agent in that project, in the focused lane, without changing which agent/project you had to be focused on beforehand.
- Row project bindings restrict the project list; unbound rows list all projects.
- Projects without a directory anchor are disabled with an explanation.
- Escape, click-outside and Cancel close the dialog; Backspace on step 2 returns to step 1; a double Enter cannot spawn two agents.
- Behavioral tests cover the project eligibility/anchor rules and the dialog's two-step flow.
Activity
Juliusolsson05 commentedon Sep 11, 2026
Implemented in #860 (branch
feat/new-agent-in-project). Shipped as designed above: Dispatch-only, row bindings restrict the project list, initial highlight is plain New Agent's target, unanchorable projects are listed disabled with the reason, no default keybinding. The row-binding lookup is now one selector (focusedLaneBoundProjectTabIds) shared withresolveDispatchSpawnTargetso the picker and the spawn resolver can't disagree. Not yet exercised in the running app; see the PR's limitations section.fix(dispatch): harden New Agent In keyboard handling after review
fix(dispatch): keep New Agent In rows out of the tab order
test(dispatch): drop resolver tests that restate rowScopedRows coverage