Worktrees
How to create, navigate, compare, and delete Git worktrees in Daintree, plus the virtualized sidebar and fleet arming.
Worktrees
Daintree runs several agents on one repo at once by giving each its own Git worktree. A worktree has its own branch and its own working directory, so two agents can edit the same project without touching each other's files.
This page covers the worktree lifecycle: creating, switching, comparing, and deleting worktrees, plus the sidebar that navigates them. The rest of the worktree surface is documented on its own pages:
- Worktree Cards: the anatomy of a card in the sidebar: lifecycle chips, row status signals, badges, the quick state filter, collapsed states, and per-card recovery actions.
- Worktrees Overview: the full-bleed modal for multi-select and bulk actions across every worktree in the project.
- Remote Compute: per-worktree remote resource environments that provision and tear down external compute as part of the worktree lifecycle.
Creating a Worktree
Open the New Worktree dialog from the + button in the sidebar, or right-click any worktree card and select New Worktree. The dialog has three creation modes: start a new branch, use an existing local branch, or check out a PR branch from GitHub.
New Branch (Default)
This is the default mode. A New Branch / Existing Branch toggle sits at the top of the dialog (hidden when you open it from a PR). New Branch mode has the following fields:
- Link Issue (optional): a searchable issue selector. Pick an issue and Daintree generates the branch name in
{type}/issue-{number}-{slug}format, with the type prefix taken from the issue's labels or title keywords. - Base Branch: a searchable dropdown with fuzzy matching. Branches are split into "Recent" and the rest. A branch already checked out in another worktree shows an in use badge, and clicking it navigates to that worktree rather than selecting it. Defaults to the current branch when the dialog opens, or
main/masterif there is no current branch. - New Branch Name: a freeform input. As you type, an autocomplete popover suggests known type prefixes:
feature/,bugfix/,chore/,docs/,refactor/,test/,release/,ci/,deps/,perf/,style/, andwip/. Common aliases are normalized for you:featbecomesfeature, andfixorhotfixbecomesbugfix. If the name already exists, Daintree adds a numeric suffix (for examplefeature/login-1) and shows a green hint. - Worktree Path: generated from the branch name using your configured path pattern. Edit it by hand or use the folder picker button. If the path already exists on disk, it gets the same numeric suffix treatment.
- Create from remote branch: a checkbox that bases the new worktree on the remote tracking branch. Checked automatically when the chosen base branch is remote.
- Assign to me: shown when a GitHub issue is linked and a GitHub account is configured. Assigns the issue to you on creation. The setting is remembered across sessions.
- Run Recipe (optional): a dropdown that picks a recipe to run once the worktree exists. Shows your project's default recipe if one is set.
. or -, can't end with a space or ., and can't contain \, :, or ... The prefix is validated separately from the rest of the name.Existing Branch
Click the Existing Branch tab in the mode toggle. Use this mode for a branch that already exists locally, such as resuming interrupted work or picking up a branch created outside Daintree.
The dialog gets simpler: the base branch picker and the branch name input collapse into a single Select Branch dropdown. The dropdown lists local branches that aren't already checked out in another worktree. Remote-only branches and branches in use are left out. A search box at the top of the dropdown filters by name.
Once you select a branch, Daintree generates the worktree path (with the same numeric suffix if the path already exists). The Create button stays disabled until you pick something. On submit, Daintree uses the existing branch as-is rather than creating a new one.
Switching between New Branch and Existing Branch mode resets the branch selection, the search query, and any validation errors.
PR Checkout
You can create a worktree straight from a pull request with the Create Worktree button in the Code Forge panel's PR list. The dialog opens in PR Checkout mode: the title changes to Checkout PR Branch, the mode toggle is hidden, and a banner at the top shows the PR number and title.
On open, Daintree resolves the PR's branch through the following sequence:
- Looks for the branch as a remote tracking branch (
origin/{headRefName}). If it's there, selects it. - Looks for the branch locally. If it's there, selects it.
- If neither exists, runs
git fetch origin pull/{number}/head:{headRefName}to fetch the branch from GitHub. - Once the fetch finishes, re-checks for the local branch and selects it if it's now available.
If the branch still can't be resolved after the fetch, the Create button stays disabled and an amber warning banner appears:
{headRefName} from the remote. Try running git fetch origin manually and reopening this dialog.Fetch the branch yourself, then reopen the dialog to create the worktree.
Branch Prefix
Daintree can prepend a namespace prefix to every new branch name. Set it in Project Settings > Worktree Setup > Branch Prefix. There are three options:
- None (default): no prefix.
- Username: reads your
git config user.name, slugs it to lowercase (for examplealice), and prepends it asalice/. - Custom: any string you want, such as
myteam/orfeature/.
A live preview shows what the branch name looks like with the prefix applied. The configured prefix is filled into the branch name input when the dialog opens. When an issue is linked, the prefix sits in front of the branch name generated from the issue.
This namespace prefix is separate from the type prefix (feature/, bugfix/, and so on) that comes from issue labels or the autocomplete popover. The two stack. With a username prefix of alice/ and a type prefix of feature/, the branch name comes out as alice/feature/issue-42-add-login.
The prefix is a per-project setting. There is no global option.
Error States
When worktree creation fails, Daintree shows a banner in the dialog with a plain-language message. The common cases:
| Condition | Message |
|---|---|
| Branch already checked out elsewhere | "This branch is already open in another worktree." An Open Worktree button appears so you can navigate directly to it. |
| Directory creation failed | "Cannot create directory — check permissions or available disk space." |
| Invalid branch name | "The branch name contains invalid characters." |
| Worktree path conflict | "A worktree already exists at this path." |
For any other git error, Daintree shows the raw output directly. When the plain-language message differs from the raw error, a collapsible "Show details" section holds the full git output.
Bulk Worktree Creation
Bulk creation makes a worktree for each of several GitHub issues or pull requests in one pass. Select the items, and Daintree creates a worktree for every one. It tracks each item's progress, retries transient errors on its own, and recovers at the step level when something fails partway through.
Open the Issues or Pull Requests panel from the toolbar. Hover a row to reveal its checkbox, then check the items you want. Once the first checkbox is set, every row shows its checkbox for the rest of the session. A floating action bar slides up from the bottom with the selection count and a Create Worktrees button. See Code Forge for more on the Code Forge panel.
Selection shortcuts
Shift-click extends the selection as a range from the last checked item to the clicked one. A Select all button appears in the header while a search is active, and issues also get a Select unassigned option. Press Escape to clear the selection. Otherwise it survives reopening the panel within the same project, and clears when you switch projects.
#42 for one issue, #42,#43,#44 for several, or #40-45 for a range. Select what you want from the results, then click Create Worktrees.The plan view
Clicking Create Worktrees opens a dialog listing every selected item with its proposed branch name. Before execution starts, there are two optional settings:
- Assign to me (issues only): assigns each issue to your GitHub account as it's created. The toggle is remembered across sessions.
- Run Recipe: picks a recipe to run on each new worktree after it's created. Defaults to your project's configured default recipe, or the last recipe you picked for bulk creation if you changed it. See Recipes for more.
Items that can't be created appear at reduced opacity with a skip badge that says why:
- Closed or Merged: the issue or PR is no longer open
- Has worktree: a worktree already exists for this item
- No branch info: the PR has no branch metadata, usually a fork PR
If every selected item is skipped, Daintree shows a toast and the execution view never opens.
Branch naming
For issues, Daintree builds a branch name from the issue's labels and title. Labels like bug or hotfix map to a bugfix/ prefix, feature or enhancement map to feature/, and docs maps to docs/. When no label matches, Daintree scans the title for keywords and falls back to feature/. The full pattern is {prefix}/issue-{number}-{slug}, for example feature/issue-42-add-dark-mode. An existing name gets a numeric suffix.
For pull requests, Daintree uses the PR's existing source branch directly.
Execution and progress
When you click the confirm button, each item moves through a set of stages: creating the worktree, spawning terminals (if a recipe is selected), assigning the issue (if enabled), and verifying terminal health. The dialog shows a spinner, checkmark, or warning icon per item as it goes, with a progress bar for the batch as a whole.
Daintree runs up to three items at once. The old limit was two. It went up once git worktree add --no-track sidestepped the .git/config.lock contention that used to block parallel operations. Non-transient git errors still fail fast, so lock collisions don't turn into silent retries.
Automatic retry
Transient errors retry on their own, up to twice per item, with exponential backoff that starts at 3 seconds and caps at 30 seconds. A small retry badge appears on the item row while this happens. Git lock file conflicts, rate limits, and network timeouts all trigger a retry. Non-transient errors, such as validation failures or missing resources, fail straight away with no retry.
Post-batch verification
When a recipe is selected, Daintree waits a moment after every item completes, then checks whether any spawned terminals crashed right after launch. An item with a crashed terminal is downgraded from succeeded to failed, so Retry Failed can re-spawn the terminal without recreating the worktree.
Completion
When the batch finishes, a toast shows the result: every worktree created, or a count of successes and failures. The dialog footer carries a Done button that closes the dialog and switches to the last worktree that was created. If any items failed, a Retry Failed button sits next to it.
Moving an Agent to a New Worktree
If you're working with an agent in the main worktree and decide the work belongs on its own branch, you can create a new worktree and move the agent there in one step. The agent restarts fresh in the new worktree with your recent terminal output injected as context, which gives it enough background to carry on without you re-explaining the task.
This option is on agent panels only (Claude Code, Gemini CLI, Codex CLI, OpenCode). Cursor agent panels, plain terminals, browser panels, and dev-preview panels don't have it.
How to access
- Right-click the agent panel header and select Move to New Worktree… from the context menu
- Open the three-dot menu (•••) in the panel header and select Move to New Worktree…
What happens
- Daintree captures the terminal's visible output buffer, up to 20,000 characters, with escape sequences stripped.
- The standard New Worktree dialog opens. Choose a base branch and enter a new branch name, the same as creating any worktree.
- On confirm, the panel moves to the new worktree. Its working directory and worktree association update, and the agent restarts fresh in the new directory.
- Once the agent goes idle, the captured history is injected as an opening prompt so it knows what was done before.
The transferred history is whatever was visible in the terminal output, not structured session data. It's a best-effort handoff: the agent gets enough context to continue, but it may not have full recall of earlier reasoning. If the terminal buffer is empty when you trigger the action, such as on a panel that was just launched or restarted, no history is injected and the agent starts completely fresh.
The new worktree also starts without node_modules and other untracked files. Re-run your setup steps by hand, or use lifecycle scripts to automate it.
Switching Worktrees
Click a worktree card in the sidebar to switch to it, or use Cmd+Alt+1 through 9 to switch by position. When you switch worktrees:
- The panel grid shows the terminals that belong to that worktree
- Terminals in the active worktree get higher refresh rates
- Terminals in background worktrees drop to 1 FPS to save resources
Deleting a Worktree
Open the delete dialog by right-clicking a worktree card and choosing Delete Worktree, or from the three-dot menu in the card header, or from the action palette. The main worktree, your repository root, is protected and can't be deleted.
The "What will happen" list
Before you confirm, the dialog spells out what the delete will do under a small What will happen heading. The list always shows the same four rows. Toggling the dialog's options strikes through the rows that no longer apply, so you can see the effect of each option without reading the fine print twice.
- Worktree directory will be deleted. Always active.
- N terminal(s) will be closed. Struck through when Close all terminals is off, or when the worktree has no open terminals.
- Uncommitted changes will be lost. Renders in red when Force delete is on and the working tree is dirty. Struck through otherwise.
- Branch
{branch-name}will be deleted. Active when Delete branch is checked. Struck through when you keep the branch, or when the branch can't be safely deleted.
Below the list, the dialog reads "This cannot be undone." in dim text, then shows the worktree's full path in a monospaced block, an advisory banner for dirty trees, and three checkboxes: Force delete, Close all terminals, and Delete branch {branch}. Checking Delete branch reveals the hint "Safe delete — fails if branch has unmerged changes", unless force is also on.
The confirm button
The confirm label changes with the option set, so you always read what you're about to do:
- Delete worktree: the default, safe path.
- Force delete worktree: when Force delete is on but the action is still low-risk.
- Force delete '{target}': when force is on and the target is risky enough to warrant typing the name. The typed-name input appears above the button, and confirm stays disabled until you match the worktree name exactly.
Inline progress and errors
Once you confirm, the dialog closes and the card takes over. The recipe/launch row in the card body is replaced by a small spinner labeled Deleting…, the card dims to roughly 50% opacity, and it stops accepting clicks. The card stays mounted until the delete completes, so you watch the worktree disappear rather than having it vanish the moment you confirm.
If the delete fails, because a process is holding a file, a hook script errors, or the remote teardown times out, the card shows an inline banner titled Couldn't delete worktree with the error text and Retry and Dismiss buttons. The banner sits outside the collapsible details section, so collapsing the card doesn't hide the error.
Force Delete from the context menu
The card context menu adds a separate Force Delete entry when a worktree has running processes, an in-flight teardown, or a previous deletion that timed out. It opens the same dialog with the Force delete checkbox pre-checked, plus a shorter timeout on the teardown step.
To delete more than one worktree at once, see Worktrees Overview.
Comparing Worktrees
When several agents are working in parallel across different worktrees, you'll want to see how their changes diverge. The cross-worktree diff opens a side-by-side comparison between any two worktrees. It shows every file that differs between their branch tips, based on each branch's latest commit. Uncommitted changes are not included.
There are a few ways to open it:
- Right-click a worktree card in the sidebar and select Compare Worktrees...: the worktree you clicked is pre-selected as the left (base) side
- Three-dot menu on any worktree card header: same behavior, same pre-selection
- Action palette: search for "Compare Worktrees" to open the modal with nothing pre-selected
Selecting worktrees
The modal has two dropdowns at the top: Left (base) and Right (compare), separated by a "vs" label. The main worktree comes first in both lists, then the rest alphabetically. Each dropdown disables whichever worktree is already selected on the other side, so you can't compare a worktree against itself. The comparison runs as soon as both sides are set.
File list
A sidebar on the left lists every changed file with a count header (for example "12 files changed"). Each file carries a single-letter status badge:
| Badge | Color | Meaning |
|---|---|---|
| A | Green | Added: file exists only in the right worktree |
| D | Red | Deleted: file exists only in the left worktree |
| M | Amber | Modified: file changed between the two branches |
| R | Blue | Renamed: file was moved or renamed |
| C | Purple | Copied: file was duplicated from another path |
Click any file in the list to load its diff in the main panel.
Diff panel
The right side of the modal shows a split diff view with syntax highlighting. Additions on the right (compare) branch appear in green; deletions appear in red. Binary files and files larger than 1 MB show a placeholder message instead of the diff.
The left side is the base for the comparison. To see what another agent added, put your worktree (or main) on the left and the agent's branch on the right. Anything that exists only on the right side shows up as green lines.
The comparison is a direct branch-tip diff, not a merge-base comparison, so it shows the full difference between the two snapshots regardless of shared history. For staging and committing changes within a single worktree, see Review Hub.
The Worktree Sidebar
The sidebar is where you navigate worktrees. It's virtualized and keyboard-first, and it stays responsive on projects with hundreds of worktrees. Only the rows in view, plus a small overscan buffer, render to the DOM, so scroll performance holds up as the list grows.
The main worktree and any integration branch are pinned outside the virtual list, so they stay at the top of the sidebar no matter where you scroll. Everything else lives in the virtualized region below them.
Keyboard Navigation
The sidebar has two focus modes. List mode is the default: focus sits on a worktree row. Toolbar mode moves focus into the inline action buttons of the focused row, the small buttons that appear on hover or focus. The grid holds a single tab stop and tracks the active row through aria-activedescendant, so screen readers stay coherent.
List mode
| Key | Action |
|---|---|
| ↑ / ↓ (or j / k) | Move row focus |
| PgUp / PgDn | Move one viewport page at a time |
| Home / End | First / last worktree |
| Enter or → | Enter the focused row's toolbar |
| Space | Select / switch to the focused worktree |
| Alt+↑ / Alt+↓ | Reorder the row in the custom sort (see below) |
Toolbar mode
| Key | Action |
|---|---|
| ← / → | Move between toolbar buttons (wraps at the ends) |
| Home / End | First / last toolbar button |
| Ctrl+Home / Ctrl+End | Return to list mode, jump to first / last row |
| ↑ / ↓ | Return to list mode and move the row focus by one |
| Esc | Return to list mode (keeps the active row) |
Leaving the window drops back to list mode, so re-entering the app never lands inside a toolbar. The Cmd modifier is ignored throughout. The sidebar grid has no Cmd-based bindings of its own.
Reordering Worktrees
In list mode, Alt+↑ and Alt+↓ move the focused worktree up or down in the sidebar. The custom order is per-project and survives restarts, but it only takes effect when Sort by → Custom order is selected in the advanced filter popover. Reorder while any other sort is active (alphabetical, recently updated, date created) and the keybinding does nothing. Switch to Custom order first, then reorder.
Placeholder Cards During Creation
While a worktree is being created, single or bulk, Daintree drops a placeholder card into the sidebar at the worktree's eventual position. The placeholder holds the slot, so the list doesn't reflow each time an item in a bulk batch completes out of order, and you can see what's still in flight at a glance.
The placeholder has two visual states.
Pending: pulsing skeleton lines with aria-busy="true" and an accessible label like "Creating worktree {branch}". The proposed branch name shows above the skeleton.
Error: if creation fails, the card switches to an error state with a red-tinted background, an alert icon, and the title Couldn't create worktree. Below the title sit the intended branch name, the full error message, and two text-link buttons: Retry, which re-runs the same creation request from the start, and Dismiss, which removes the placeholder.
Reconnecting and Load Errors
When the renderer loses contact with the worktree service, which is rare and usually follows a sleep/wake cycle or a host crash, the sidebar header shows a small refresh spinner and the label Reconnecting…. If reconnection drags past a short threshold, the label escalates to Reconnecting… last updated {relative time}, so you can tell fresh data from a stale snapshot.
If the initial load fails outright, from a corrupt repo, a missing .git, or a permissions error, the sidebar shows a top banner titled Couldn't load worktrees with the error message and a single Retry button.
Fleet Arming
Fleet arming lets you act on several agent terminals at once. You arm a set of terminals, then every Accept, Reject, Interrupt, Restart, Kill, or Trash, plus anything you broadcast, fans out to all of them. The armed set holds until you disarm it, so it spans the worktree workflows on this page.
The full reference lives at Fleet: the arming ribbon, live keystroke mirroring, per-target variable resolution, broadcast safety gates, the Fleet Deck, saved fleets, and the complete shortcut table. The Cluster Attention Pill, which arms a group of agents sharing a state in one click, is documented there too.