dispatch
Sessions waiting on you:0finished:0· all quiet
Sign inStart the trial

Docs Core

Branches and worktrees

Put two tiles on one repository without them fighting over one checkout: each on its own branch, in its own folder, with the ones that have gone wrong saying so.

Two terminals open on one repository have always shared one working copy. A session that starts on main and a session that runs git switch fix-the-thing are the same checkout, so the second one moves the first, and the way that ends is a session committing to a branch nobody pointed it at.

That is not a hypothetical once an agent is doing the switching. Pin a tile to a branch and it gets a git worktree instead: a second checkout of the same repository, on its own branch, sharing one object store with the original. Two tiles, two folders, one repo, no collision.

The branch chip

Every tile header carries the branch its folder is on, with a clean/dirty dot and ↑/↓ ahead-behind. Click it and the menu lists, in this order:

  • The worktrees this repo already has, the main checkout first, each saying which it is and whether it is the one this tile is on. A folder somebody deleted in Explorer says folder missing; one git has finished with says prunable; a detached head shows the commit rather than an empty name.
  • Branch with no worktree: every local branch that has nowhere to work in yet, plus the ones that exist only on a remote. Picking one makes the worktree and repoints the tile in a single go.
  • New branch from main creates the branch from whatever the main checkout is on, and a worktree for it.
  • Another branch by name… is for a branch that exists here or on a remote but is too far down the list to scroll to.

The shell already running does not move

Picking a branch changes where the next terminal for this tile opens. It does not relocate the shell that is in it.

A running build, a Claude session mid-turn, a REPL with state in it all stay where they are, and the menu says so before you pick. The tile keeps reporting where its shell actually is, shell in dispatch-main, until you restart it, and Restart the shell in… is in the same menu.

A worktree is not a second project

The distinction that has to stay straight:

The project
Which repository this tile belongs to. What the sidebar highlights, what a startup command is keyed by, what a Studio link hangs off.
The folder
Which checkout this tile is about. Where a new terminal opens, and whose git status the header paints.

Pinning a tile moves the second and leaves the first alone. So four tiles on four branches of one repo are still one row in the sidebar, one entry in recents, and one project startup command.

Where the folders go

By default, beside the repository they came from, named <repo>-<branch>. So a dispatch checkout with a tile pinned to content-completeness grows a dispatch-content-completeness next to it.

Where new worktrees go… at the bottom of the menu changes that: name a folder and every new worktree lands there instead, under the same names. Leave it empty to go back to beside the repo.

When something has gone wrong with a pin

A pinned tile is a claim about a folder on disk, and folders move. Three ways that claim goes stale, each of which the chip says out loud rather than quietly falling back:

The worktree folder was deleted
worktree gone, and the tile has fallen back to the project’s own checkout
Something switched that checkout to a different branch
pinned to fix-the-thing, with the branch it is actually on in the full message
The shell in the tile is still in the old folder
shell in dispatch; restart it to move it

Read that before telling a session to commit. It is the same sentence dispatch_list returns as branchWarning, so a lead session laying work out across branches hears it too rather than finding out from the reflog.

Removing one

Remove this worktree… deletes the folder. A worktree with uncommitted changes in it is refused first and the message says what is in there; agreeing to it anyway removes only the working copy: the branch is kept, and everything committed to it is still in the repository.

Every tile pointed at that folder is detached, not only the one you did it from, so no tile is left holding a cwd that no longer exists.

Detach (back to dispatch) does the smaller thing: the tile goes back to the project’s own checkout and the worktree stays where it is.

From a plan

dispatch_plan takes a branch per tile, so a lead session can lay four tickets out across four branches in one call:

Take BUG-114 and BUG-118 in vantage, each on its own branch off main, and open the plan next to them.

Every branch is resolved in the same all-or-nothing pass as the projects: a plan that cannot place one tile on its branch opens none of them. Within that pass, reuse comes before creation: an existing worktree for that branch is used, a branch with none gets one, and a branch that exists nowhere is created from the main checkout’s current branch. So the same plan run twice does not leave eight folders behind.

dispatch_list reports branch and, on a pinned tile, the worktree it was pinned to. See Planning.

This is git’s own worktrees, not a copy of your repo. One object store, one set of refs, several working copies. git worktree list in any of them shows the same set Dispatch is showing you, and removing one by hand is a thing Dispatch notices rather than a thing it breaks on.