Skip to main content

Worktree Cards

The anatomy of a worktree card in the sidebar: the lifecycle status mark, row status signals, alarm salience, the quick state filter, collapsed states, filters, and per-card recovery.

Updated
Reviewed

Worktree Cards

Each worktree shows as a card in the sidebar. This page covers how a card is built: the lifecycle status mark, row status signals, alarm salience, the quick state filter, collapsed states, filters, and per-card recovery. For creating, switching and deleting worktrees (and for what a deleted worktree's card does), see Worktrees.

A card carries:

  • Branch name, with a badge for the main worktree (it moves to the secondary row when an issue is linked)
  • Mood indicator: stable, active, stale or error
  • Issue title as the headline when one is linked, plus PR badges for PR state
  • Git status: changed file count, insertions and deletions
  • Last commit summary
  • Path row: the worktree's folder, written relative to your home directory. Clicking it opens the built-in File Browser as a grid panel rooted there, selecting the card first if it isn't already active; the copy button beside it copies the absolute path.
  • Terminal list: every panel in this worktree with its kind and state
  • Quick actions: launch agents, run recipes, open in an editor

Local git state on cards (commits, branch switches, file changes) comes from file-system event watching rather than polling, so an agent writing files in a background worktree shows up live instead of staying invisible until it commits. A polling fallback covers the case where the OS-level watcher isn't available, which on Linux usually means the inotify watch limit is exhausted.

Tip

On Linux, sidebar updates that lag by tens of seconds usually mean the inotify watch limit is exhausted. Check the log (Settings > Troubleshooting > Open Log File) for a watcher initialization warning, then raise the limit with sudo sysctl -w fs.inotify.max_user_watches=524288. To persist it, add fs.inotify.max_user_watches=524288 to /etc/sysctl.d/99-inotify.conf and run sudo sysctl --system.

Double-click the card header to collapse it. A collapsed card takes less vertical space while still showing status. Double-click again to expand.

Changed files on a card

Expand the changed-files section to inspect local edits without leaving the sidebar. Files are grouped under folder headers, with root-level files grouped as (root); each row shows the filename, status and change counts. Selecting a row opens its diff. The row menu offers the shared file actions, including Insert file reference, the Copy submenu and plugin Extensions. For a complete staging workflow, open Review Hub.

Worktree cards in the sidebar, expanded and collapsed

Lifecycle Status Mark

A small mark in a card's top-left corner names the next action that worktree needs. It only appears when there is something to act on, and it is absent while git data is still resolving.

Since v0.34 the mark is a segmented vertical tick in the grip gutter rather than a corner wedge: a 4px bar in a fixed 16px slot, cut into a different number of pieces per state. It sits flush on the corner of a sidebar card, and 4px in on the overview grid's rounded cell, whose arc would otherwise clip it.

MarkTooltipMeaning
One unbroken amber barAgent waiting for inputAn agent in this worktree is blocked on you.
Two purple segmentsReady for cleanupThe PR is merged. The worktree has served its purpose and can be deleted.
Three blue segmentsComplete: in reviewA linked issue, an open PR, no uncommitted changes, and no active agent. It is ready for review.

The cut count, not the color, is what separates cleanup from complete. Under Windows High Contrast every state repaints to one system color, so geometry is the only channel left; and the previous three corner wedges differed only in how much of a 12×12 box they filled, which does not read at that size. Length would have been the obvious knob and is the wrong one: a short bar is only short beside a longer one, and a card read on its own has no neighbor to compare with. A count of segments is absolute. The ink descends with urgency too, so the solid bar is the state that is blocking on you and the most broken-up one is the state that wants nothing.

Blue, not green, for complete. Across the app green means working and blue means in review or finished; a green "done" mark would compete with the one signal that means work is happening right now.

When several conditions apply the mark shows the highest-priority state: cleanup, then complete, then waiting. A merged PR always wins, because deleting the worktree is the most definitive thing left to do.

Only cleanup is gated to secondary worktrees. Waiting and complete render on the main card too: the main worktree can have an agent waiting on it like any other.

Note
The blue "complete" mark needs both a linked issue and an open pull request. A PR with no linked issue won't trigger it. For linking issues and PRs to worktrees, see Code Forge.

The cleanup mark also adds a trash-icon button to the row toolbar, next to the three-dot menu, so Delete is one click rather than a menu dive. The icon stays muted red until hover. Once a worktree reaches complete, open the Review Hub from its menu to stage, review and push.

Row Status Signals

To the right of the branch name sits a set of small signals. Each is independent and degrades on its own, so a stale freshness pill never hides a fresh commit chip beside it.

SignalWhat it shows
Git state indicatorAn inline label for an in-progress git operation: rebasing, merging, cherry-picking, reverting or detached, amber; conflicted, red. It is a passive label, not a control.
Commit chipAn activity dot and the relative time of the last commit ("2m"). The dot fades from accent to idle as time passes. Hover for author, subject and absolute timestamp.
Upstream sync badge↑N / ↓N against the upstream remote. When upstream and the base branch have diverged from each other, a second pair of counts appears against the base branch.
Freshness pillHow recently the working tree status was read. Hidden under 30 seconds. Between 30 and 60 seconds, a dim relative-time pill; between one and five minutes it brightens; past five minutes it becomes a clickable Refresh.
External badgeA folder-out icon on a worktree git reports from outside the project directory, with the full path in its tooltip. See Worktrees outside the project.
PinA pin icon on a worktree you pinned to the top from the card menu.
EnvironmentThe resource-environment popover, when the worktree runs on non-local compute. See Remote Compute.
Dev serverA dev-preview indicator when one is running for this worktree. See Dev Preview.

The author avatar is deliberately left off the row: a column of identical "you" avatars adds noise and no information. The commit chip's tooltip surfaces the author when you need it.

Row-level status signals sit beside the branch name: branch type, churn, and distance from main

Where mid-rebase recovery lives

The git state indicator names a rebase, merge, cherry-pick, or revert in progress. Open the Review Hub to inspect and resolve conflicted files. The card menu also offers Git > Continue and Git > Abort… for the current operation. Continue routes unresolved conflicts to the review surface; Abort opens a confirmation describing what is restored.

Status still resolving, and the review button

Before git has answered for a worktree, its subtitle reads Checking status… rather than "No recent activity", an all-clear the data can't yet support.

The card's review-opener tracks what the worktree actually needs:

  • Review & Commit when the tree has changes.
  • Review & Push when the tree is clean but commits are unpushed. The next step is still in the Review Hub, so the button stays; only the label shifts.
  • Nothing, when the tree is clean and everything is pushed.

Alarm Salience and the Collapsed Pill

A row can carry a failing CI run, an upstream auth failure, a behind-upstream count and more at once. Salience tiers keep it from becoming a wall of badges: the most important signal renders first, on the left.

TierSignalTone
3 (highest)CI failedRed
2Auth failed (couldn't fetch from upstream)Amber
1Behind upstreamAmber
0No alarmNone

Only a failure CI state climbs above tier 0. Pending and neutral states stay quiet, so a long push session doesn't flicker the row between tiers as checks queue and finish. Detached HEAD is deliberately not an alarm either: the git state indicator already labels it in the title row, and a colored pill would double-label the same fact.

What makes CI "failed"

The CI signal is derived from the PR's required checks, not the raw status rollup, the same derivation the PR dropdown in Code Forge uses, so the two never disagree. Tooltips read like "2 of 5 required checks failing", or "No required checks" when the branch has none configured.

The derivation refuses to invent a green. If the checks page is truncated, if a context arrives in a shape it can't classify, or if no required checks are configured at all, it falls back to the raw rollup state and shows no summary rather than reporting a pass over checks it never saw. A stale required run counts as failing, because it has not resolved to a passing state.

Collapsed, the badge row reduces to a single pill in the header carrying the highest active tier's color and label: "CI failed" in red, "Behind" in amber. Expand the card to get the individual badges back.

Quick State Filter

The filter bar above the worktree list filters by agent state. Four segments: All, Working, Waiting, Finished. "All" keeps its text label; the other three are an icon plus a count, which is what keeps the bar legible in a narrow sidebar.

  • Working: a green spinner. When the count is above zero it turns slowly, gated by prefers-reduced-motion. It is a glance signal, not a change in polling cadence.
  • Waiting: an amber hollow circle.
  • Finished: a blue check circle.

The active chip carries a subtle inset bottom rule in neutral text color, not the accent. Accent stays scarce. Clicking an active chip resets to All. Each chip's accessible name carries noun and count together ("Working, 3 worktrees"), so dropping the visible text label costs screen-reader users nothing.

"Finished" is not "Completed." Finished is a worktree-level label covering complete and cleanup worktrees. Completed is a session-level state: one agent that finished a turn. Both labels appear on the same card: the filter bar counts worktrees, the collapsed card indicators count sessions.

Counts are disjunctive. Each chip's count is what the list would show if only that chip were active, not the count within the current filtered set. With All selected and "Waiting (2)" on the bar, clicking Waiting reliably shows two worktrees, regardless of what you clicked before.

The trailing arm button

A small lightning-bolt button sits at the trailing edge of the bar, past a divider. One click arms every unarmed agent in the currently filtered set and opens the Fleet Arming Ribbon, ready for an Accept, Interrupt or broadcast.

It addresses agents only. Plain shells are excluded (they stay armable individually and through the header fleet picker), which is a different unit from the state filters beside it: those are derived from agent state but count matching worktrees, while the arm button counts the agents it would arm. The tooltip and accessible name track the state:

StateLabel
No filter, nothing armedArm all N agents
Filter active, nothing armedArm N matching agents
Some already armedArm N more agents / Arm N more matching agents
Nothing eligibleNo agents to arm / No agents match the filter
Everything already armedAll agents are armed / All matching agents are armed

The button never disappears (it dims and disables), so its place in the bar stays predictable.

Tip
Filter to the state you want to act on, then arm. Click Waiting, click the arm button, press Command-Y Control-Y Control-Y , and every waiting agent in view is accepted. See Fleet.
Note
The quick filter is session-only. It isn't written to disk and resets on restart, so you never launch Daintree to find worktrees quietly filtered out. The advanced filters below do persist.

PR and Issue Badge Freshness

PR and issue badges come from cached provider responses. The badge's glyph tells you how much to trust the number right now, without opening a panel or reading a tooltip.

GlyphMeaning
NoneFresh: the cached value is recent and no refresh is queued.
ClockStale: older than the freshness threshold, with a refresh in flight or queued.
Cloud-offDisconnected: a rate limit, an open circuit breaker after repeated failures, or PR detection paused. The last known value stays on screen; the glyph says don't treat it as live.

The tooltip carries the relative timestamp ("Updated 4 minutes ago") and, when disconnected, the reason and a retry hint. With no forge token configured the badge grayscales and the tooltip says so.

Note
For tokens, providers and rate-limit behavior, see Code Forge. To force every title, PR and CI badge to re-resolve, use the sidebar's refresh button.

Collapsed Cards

Collapsing a card hides the body (git status, last commit, terminal list, quick actions), leaving the branch name and a row of compact session indicators. Each indicator is an icon plus a count.

StateIconToneAnimated
WorkingSpinner circleGreenYes
DirectingInteracting circleBlueNo
WaitingHollow circleAmberNo
DoneCheck circleSlateNo
ExitedExited circleDimNo

Hovering the group shows the full summary, such as "3 sessions: 2 working, 1 waiting". Idle sessions are never shown: when every session is idle, or there are none, the collapsed card is just the branch name. For what each session state means, see Agent States.

Focused Sub-Line

An expanded card reveals a thin line of context below the branch name when it has focus, from hover or keyboard. It is hidden by default, expands with a short height transition and a brief fade, and collapses again when focus leaves. The animation respects prefers-reduced-motion.

Up to three dot-separated segments, in order: the changed file count when the tree is dirty ("3 files"), the last activity time as a live relative timestamp, and the short status label the header uses. It stays out of the way until you're looking at the card, then gives you enough for a triage call without expanding the body.

Primary Worktree Card

The main worktree's card uses a two-row header that doubles as a project-level overview.

The top row shows the project name rather than the branch, a sprout icon, a collapse button and the actions menu. The second row, visible when expanded, shows the branch label, upstream sync, and an aggregate summary of the secondary worktrees.

  • Upstream sync: ↑N in green for commits ahead, ↓N in amber for commits behind, with the full sentence on hover.
  • Aggregate summary: a branch icon with the total worktree count, then colored counts for working and waiting. The finished count only appears once nothing is working or waiting, so finished work never drowns out work that still needs you.

Expanded, the body adds the same worktree and agent counts, plus a health row with CI status, open PR count and open issue count. That row needs a configured forge token.

The Worktree Sidebar

The sidebar is where you navigate worktrees. It is virtualized and keyboard-first: only the rows in view plus a small overscan buffer render to the DOM, so scroll performance holds on projects with hundreds of worktrees.

The main worktree renders outside the virtual surface and stays at the top. Below it, pinned worktrees, then everything else by the active sort, then external worktrees. Deleted-worktree rows sit at the position they were deleted from.

When rows sit fully offscreen, small pills appear at the top and bottom edges ("Scroll up, 12 more above"), and clicking one jumps to that end of the list.

The search box, filter popover and results list follow the ARIA combobox pattern, so filter changes and result counts are announced. See Search and Filters for what the controls do.

Refreshing

The refresh button in the sidebar header is a true full refresh, not a nudge. It discards cached forge data and re-resolves worktree state, issue and PR titles, and CI badges, re-reading from disk and from the provider. That costs provider round trips against your rate limit, so it is an escape hatch for when something changed outside the app, not a habit to build on top of routine polling.

The pass is watchdogged and each phase is isolated: a slow PR fetch can't sink the worktree refresh, topology re-discovery failing doesn't stop the status pass, and the button always resolves. If the host doesn't respond at all, a Refresh failed toast says so rather than the button quietly doing nothing.

Keyboard navigation

The sidebar has two focus modes. List mode is the default, with focus on a row. Toolbar mode moves focus into the focused row's inline action buttons. The grid holds a single tab stop and tracks the active row through aria-activedescendant.

List mode

KeyAction
↑ / ↓ (or j / k)Move row focus
PgUp / PgDnMove one viewport page
Home / EndFirst / last worktree
Enter or →Enter the focused row's toolbar
SpaceSelect / switch to the focused worktree
Alt+↑ / Alt+↓Reorder the row in the custom sort

Toolbar mode

KeyAction
← / →Move between toolbar buttons (wraps)
Home / EndFirst / last toolbar button
Ctrl+Home / Ctrl+EndReturn to list mode, jump to first / last row
↑ / ↓Return to list mode and move row focus by one
EscReturn to list mode, keeping the active row

Leaving the window drops back to list mode, so re-entering the app never lands inside a toolbar. The Command Control Control modifier is ignored throughout: the grid has no bindings of its own that use it.

Note
For every keybinding across the app, see Keyboard Shortcuts.

Reordering

Alt+↑ and Alt+↓ move the focused worktree in the list. The custom order is per-project and survives restarts, but it only applies when Sort by → Custom order is selected in the filter popover. Reorder under any other sort and the keybinding does nothing.

Reordering is also off while the list is grouped by type or a search query is active. Both controls sit above the worktree list, and with either on the Alt+Arrow keys and drag-to-reorder do nothing. The order itself is kept, you just cannot edit it until you clear the filter.

Focus follows the card as it moves, and the screen-reader announcement reports the new position once the key release settles, so holding the key does not fire an announcement per step.

With the mouse, drag a card and a thin directional line shows where it will land. Escape mid-drag cancels, and the card snaps back with an assertive "drag cancelled" announcement.

Placeholder cards during creation

While a worktree is being created, single or bulk, a placeholder card holds its eventual position so the list doesn't reflow each time a bulk item finishes out of order. Pending placeholders show pulsing skeleton lines with aria-busy="true" and a label like "Creating worktree {branch}". A failure switches the card to an error state titled Couldn't create worktree, carrying the branch name, the error message, and Retry and Dismiss links.

Reconnecting and load errors

When the renderer loses contact with the worktree host (rare, and usually after a sleep/wake cycle or a host crash) the sidebar header shows a spinner and Reconnecting…. Past a short threshold it escalates to Reconnecting… last updated {relative time}, so you can tell fresh data from a stale snapshot. A failed initial load shows a top banner titled Couldn't load worktrees with the error and a Retry button.

Search and Filters

The search bar at the top of the sidebar finds worktrees by name or branch and filters as you type. Press Escape to clear the text and any active filters in one action; press it again on an empty search to blur the input. The X at the right edge does both.

The filter icon inside the search bar opens the advanced popover. A small green dot on the icon marks any active non-search filter.

CategoryOptions
Sort byDate created, Recently updated, Alphabetical, Custom order
Group by typeToggle: groups worktrees by branch-type prefix, plus an "Outside the project" section when external worktrees exist
StatusActive, Dirty, Stale, Idle
Branch TypeFeature, Bugfix, Refactor, Chore, Docs, Test, Release, CI, Deps, Perf, Style, WIP, Main, Detached, Other
Issues & PRsHas Issue, Has PR, PR Open, PR Merged, PR Closed
SessionsHas Terminals, Working, Waiting, Completed, Exited
Activity15m, 1h, 24h, 7d
Dev serverHas server, Running, Starting, Error

The "Issues & PRs" section is provider-neutral: it filters on whatever forge the project is connected to, not on GitHub specifically. "Custom order" is hidden while "Group by type" is on. A Clear all filters button appears at the bottom of the popover whenever anything is active.

Chip counts inside each category use the same disjunctive logic as the quick state filter: the number you see is the number you get if you click.

Activity recency is unified across worktrees, so "Recently updated" and the activity windows mean the same thing everywhere rather than each worktree tracking its own notion of recent.

Every filter category is collapsed until you need it: the popover stays one screen tall however many are open
Note
Advanced filters and the sort order persist across sessions. The quick state filter bar does not.

Visual Hierarchy

With many worktrees open, Daintree dims idle and stale cards so active work stays prominent. A card is muted when it is idle or stale, has no waiting agent, isn't the selected worktree, and isn't hovered or focused. Muted cards use a dimmer text color for the branch name and labels.

One exception matters: a card with a waiting agent is never muted, however idle the worktree otherwise looks. Waiting is the state that needs you.

Lifecycle Failure Recovery

A setup lifecycle script can fail on a missing dependency, a wrong path or a network blip. The failure surfaces in the card footer rather than in a toast you can miss after a context switch, and the worktree holds that state until you act on it.

The footer reads Setup didn't finish. Re-run when you're ready. with two controls:

  • Retry setup: re-runs the failed phase. The label becomes "Retrying…" while it runs, then the footer clears on success. The retry is pinned to the card's own worktree, not whichever one is focused, so you can trigger it from anywhere.
  • Show details: expands the captured error and output in a scrollable monospaced block. Daintree keeps the last 8192 bytes.

The footer survives card collapse and persists across restarts, so a half-set-up worktree never quietly disappears.

Restarting a Session

Restarting an agent session uses a two-click armed pattern, which guards against accidental scrollback loss without putting a modal in the way.

  1. Open the panel's three-dot menu and click Restart Session. The item arms: its background tints amber and the label becomes Confirm Restart (3s) with a ticking countdown.
  2. Click again within three seconds. The menu stays open between the two clicks, so there is no moving target to chase.

Without the second click the item disarms itself. It also resets if you switch panels or if restart eligibility changes mid-countdown. The armed item's accessible name reads "Armed: click again to confirm restart. N seconds remaining", so the countdown isn't visual-only.

The Card Menu

The card's ⋯ button and its right-click menu render the same items, so a command can never be wired into one and missed in the other. As of v0.34 that menu is no longer one flat list of around 25 commands: it is eleven named submenus and a single destructive row, in a fixed order, split into four bands by a separator.

GroupWhat it holds
LaunchYour pinned agents under an Agents heading, then Terminal, Browser and Dev preview, then More agents and panels…, which opens the panel palette. An agent that isn't installed stays on the list, disabled and marked Not installed, rather than disappearing or quietly launching a plain terminal instead.
OpenBrowse files, Open in editor, and Reveal in Finder / Show in Explorer / Show in folder.
ReviewReview worktree (the Review Hub), View uncommitted changes with its changed-file count, and Compare with another worktree….
GitPull and rebase, Push, Fetch, Fetch and prune, then Rebase onto the base branch or Merge the base branch in. During a repository operation, Continue and Abort replace the base-integration commands. A captured push-rejection lease can add Force push with lease…. See Integrating the base branch.
SessionsEverything that acts on every session in the worktree at once. Three labeled sections and a destructive tail; see below.
RecipesEach applicable recipe under a Run heading, then Save current layout as recipe…. Saving needs a live session to snapshot, and the whole group is absent when there is neither a recipe nor a layout to save.
RuntimeTwo labeled sections. Dev server: Start when a stopped server can be restored, Restart and Stop while one is live. Environment: Switch environment, Check status, Connect, Provision, Resume or Pause, and Tear down environment… last. While the worktree is on local compute the section is only the switcher: the six remote commands aren't temporarily unavailable, they don't apply. See Dev Preview and Remote Compute.
Linked workView plan, Open issue #N and Open PR #N, then, below a rule, Attach issue… (or Change linked issue…) and Unlink issue #N.
CopyFull context and Modified files only, then Path and Branch name. See below.
OrganizePin to top / Unpin, Collapse card / Expand card, then Move up and Move down. A move that would run off the end of the list is disabled rather than hidden.
ExtensionsEverything plugins contribute to a worktree. See below.
Delete worktree…The one item that is a row rather than a submenu, alone in the last band. Withheld on the main worktree.

A group with nothing in it is dropped, not shown empty or dimmed: a worktree with no dev server and no configured environment has no Runtime, one with neither a recipe nor a live layout worth saving has no Recipes, and one no plugin contributes to has no Extensions. Linked work is the exception that looks like one. It survives a worktree with no plan, issue or PR, because Attach issue… is still something to offer — the group is dropped only when there is nothing to open and nothing to attach. So a fresh secondary worktree opens on Launch, Open, Review, Git, Sessions, Linked work, Copy, Organize and Delete alone. The separators are computed after that decision rather than owned by each optional group, so the menu can never open on a leading rule, end on a trailing one, or show two in a row.

The order ends on the destructive row deliberately. Destruction ends a menu, so nothing renders past it.

Plugin items under Extensions

Plugin contributions used to trail the root menu after Delete worktree…. Nesting them under Extensions keeps the root the same shape however many plugins are installed, and makes it impossible for a third party to render past deletion.

A single contributing plugin gets no group heading: the submenu's own title is enough. Once two or more contribute, each plugin's items sit under its display name (falling back to its manifest name or id), separated by a rule, so you can tell whose command you are about to run.

Filtering happens before the menu sees the list. An item whose when clause doesn't hold is never passed in, and an empty list produces no Extensions trigger at all.

Copy path and Copy branch name

Copy gathers every clipboard route in one place. Full context and Modified files only hand the worktree to CopyTree; below a rule, Path copies the worktree's absolute path and Branch name, new in v0.34, copies the branch it is checked out on.

Branch name sits directly under Path so the two copy targets read together. It is hidden, not disabled, when there is no branch name to give: a worktree on a detached HEAD has none, even while the card still shows the branch it was on before detaching, and copying that string would hand you a branch you are not on.

Sessions Submenu

The menu's Sessions submenu fans one action across every session in the worktree. Most items carry their eligible count and disable at zero, and the count is part of the accessible name ("Dock all panels, 2") rather than only a muted number at the end of the row.

SectionItemWhat it does
LayoutDock all panelsMove every grid-resident session into the dock.
LayoutMove all to gridRestore every docked session to the grid.
Fleet selectionSelect all terminalsArm every agent terminal here and open the Fleet Arming Ribbon.
Fleet selectionSelect waiting agentsArm only the sessions currently waiting.
Fleet selectionSelect working agentsArm only the sessions currently working.
MaintenanceRedraw all terminalsForce-reload the terminal renderer for every session here, useful after a GPU driver hiccup or a font-loading glitch.
Below the ruleClear session history…Drop this worktree's resumable session journal.
Below the ruleTrash all sessions…Close every active session.
Below the ruleTerminate all sessions…Send SIGTERM to every agent process, for when trashing them would wait too long.

Layout, Fleet selection and Maintenance each disappear when their subject does: no live panels, no Layout or Maintenance section; nothing armable, no Fleet selection. Clear session history… stays whatever else is on screen, and carries no count — availability isn't cached, and opening a menu must not go and read the journal to find out. It sits with the destructive pair rather than beside renderer maintenance because it is deletion, not repair: the journal records are gone permanently.

All three items below the rule confirm from every dispatch source, including the action palette and agent-initiated calls, not only from the menu.

Tip
Select waiting agents then Command-Y Control-Y Control-Y accepts every waiting agent in a worktree in two clicks and a chord.

WSL Git Banner

On Windows, when a worktree lives inside a WSL distribution, Daintree probes whether git can be routed through the interop layer and shows a banner on the card describing what it found.

The WSL git banner does not appear on macOS. Daintree always runs git natively.

The banner has four states.

Eligible: git is installed in the distribution and reachable. The title reads Speed up git on this WSL worktree:

This worktree lives in WSL ({distro}). Routing git through wsl git avoids the Windows–Linux filesystem boundary and can make status polling 5–10× faster.

Two buttons: Enable WSL git switches this worktree to WSL-native git; Not now dismisses. You can flip the setting back later.

Ineligible: the distro is stopped, isn't the default distro, or has no git. The title reads Git runs via Windows:

This worktree is in {distro}, which isn't the default WSL distro. Git can't be routed through this distro automatically: it will run from Windows and may be slower than usual.

Two buttons here too: Re-check (which reads Re-checking… while it runs, and adds "Couldn't re-check. Try again." if it errors) and Got it.

Unreadable: the default distro couldn't be read at all, so routing is undetermined. The title reads Couldn't check WSL distro, git runs from Windows in the meantime, and a Re-check button is the only control. You are never stranded on a spinner.

Probing: a short skeleton while the probe resolves. It appears only if the probe is slow enough to be worth acknowledging.

The WSL git banner does not appear on Linux. Daintree always runs git natively.

Note
For WSL setup notes and other platform-specific git tips, see Troubleshooting.

Worktrees Outside the Project

Git will happily report worktrees that live outside the project directory. Daintree identifies those and sorts them apart: they sink below everything the project owns, ahead of the pin check, so a stale pin can't lift one back to the top. In grouped mode they get their own Outside the project section.

On the card, a FolderOutput icon carries the tooltip "Outside the project directory" and the full path. External worktrees can't be pinned, and the pin entry is ignored if one exists.

Containment is only asserted on an explicit answer from the workspace host. When the host can't resolve the boundary, the worktree is treated as internal: a transient path-resolution failure shouldn't demote every worktree in the project at once.

Pinning is the counterpart: Pin to Top / Unpin on any non-main, non-external card's menu. Pinned worktrees sit directly under main and every sort honors that.