Skip to main content

Fleet

Arm a set of terminals in one project and drive them as one: live keystroke mirroring, bulk accept, reject, interrupt, restart, and kill, with a ribbon that shows exactly what is armed.

Reviewed

What Is Fleet?

Fleet is Daintree's coordinated multi-terminal mode. You arm a set of terminals, and from then on every action in the primary terminal repeats across all of them: live keystrokes, command submissions, and bulk operations like accept, reject, interrupt, restart, and kill. The armed set is sticky. It stays until you disarm or exit, so Fleet is a mode you enter, not a one-shot shortcut.

Eligibility is about having a writable PTY in a visible slot, not about being an agent. A terminal can join a fleet when it is a terminal panel in the panel grid whose PTY is alive and has not exited or errored. Plain shells qualify: arming reroutes keystrokes, and a shell takes keystrokes as readily as an agent does. Dock terminals are excluded because the collapsed dock has nowhere to draw the armed and follower state that warns you your typing is going somewhere else, and non-terminal panels (browser, dev preview, file viewer) have no PTY to write to. The armed set auto-prunes as panels are trashed, exit, or lose their PTY.

The agent-specific bulk actions are narrower. Accept, reject, interrupt, and restart read agent state, so they only address armed terminals that Daintree recognizes as running an agent. A shell in the fleet receives broadcasts and ignores the agent verbs.

The model is three steps: arm a set, broadcast a draft, review the results.

  • This page covers arming: the surfaces that build an armed set, the ribbon that shows it, and the bulk actions that operate on it.
  • Broadcasting & Runs covers what happens after you type: mirroring, per-target variable resolution, supervised runs, and failure handling.
  • Saved Fleets covers naming an armed set so you can recall it later, as a frozen snapshot or as a live rule.
Note
Fleet works across worktrees. When your armed set spans more than one worktree, switch the grid to the Fleet Deck to see everything that is receiving keystrokes at once.

Fleet vs Pilot

Fleet and Pilot both deal with many agents at once, and they are easy to confuse. They answer different questions.

Fleet is a mode you enter inside one project. You choose a set of terminals, arm them, and act on them together. It is a write surface: the point of arming is that your next keystroke fans out.

Pilot is a read-across view of every agent run in every project, ordered by what needs your attention. You do not arm anything from it and it does not broadcast. Open it when you want to know where to go; use Fleet once you are there.

Starting a Fleet

There are several ways to arm terminals. The arming ribbon appears at the top of the content area once two or more terminals are armed, and that is the moment Fleet becomes visible.

Arming Individual Terminals

The fastest path is to focus a terminal and toggle it into the fleet with a keyboard shortcut. The shortcut works globally, so you can arm terminals from anywhere in the app.

ActionShortcut
Arm or disarm focused terminal Command-J Control-J Control-J
Arm or disarm focused pane Worktree grid only, no modifier X X X
Arm all eligible terminals in current worktree Option-Command-A Control-Alt-A Control-Alt-A
Tip
Arm order matters. Bulk actions run in the order terminals were armed, so the first armed terminal is the primary and its input bar becomes the broadcast source.

The Fleet Picker

The Fleet Picker is the cold-start surface for selecting several terminals at once. Click the Zap icon in the sidebar to open it. A centered palette appears with the heading "Select terminals to arm", a fuzzy search input, and a list of every fleet-eligible terminal grouped by worktree.

Search matches against terminal title, worktree name, branch, file path, and recent scrollback content, so you can find a target by what is happening inside it, not just what it is called. Each worktree group has a parent checkbox, with an indeterminate state when only some of its terminals are selected.

The picker's keyboard model:

KeyAction
TabMove focus from search into the list
SpaceToggle the focused terminal
/ Move between rows
Command-A Control-A Control-A Select all visible matches
Shift-Command-I Control-Shift-I Control-Shift-I Invert the current selection
Shift+ClickRange select from the last clicked row
EscClear search on first press, close on second

Two selection helpers sit below the search box. The first toggles everything currently visible, and its label follows the list rather than the whole selection: Select all or Deselect all with no query, Select all visible or Deselect visible once you have filtered. The second, Select agents, additively adds every visible terminal in a working, waiting, or directing state, leaving your existing picks (including plain shells) alone.

The footer is reserved for committing. A segmented Replace or Append control decides what confirming does: Replace clears the current armed set and arms only the picker's selection, Append adds the selection to what is already armed. Cancel and the confirm button sit together at the trailing edge, and the confirm button counts your picks: Arm 2 selected.

Note
Replace is the default and resets to Replace every time you reopen the picker. Use Append when you want to grow an existing fleet without losing what you already have.

Preset Selections

Once two or more terminals are armed, the arming ribbon's selection menu offers one-click presets that arm matching terminals additively. Each row carries a live count of how many panes it would arm, and hovering or focusing a row lights up those panes' title bars before you commit, so a preset is a preview before it is an action.

  • All waiting — this worktree: every agent in this worktree currently waiting for input
  • All waiting — all worktrees: every waiting agent anywhere in the project
  • All working — this worktree: every agent currently running a task
  • All working — all worktrees: same, but project-wide
  • All in this worktree: every eligible terminal in the active worktree, shells included

These five are also the built-in predicates behind Saved Fleets, which is where the predicate model is described in full.

Bulk Arming from the Sidebar

An Arm N matching agents button sits at the trailing edge of the worktree sidebar's quick state filter bar. It arms every unarmed agent terminal in the visible worktrees, so you can build a fleet out of whatever filter view you are already looking at. The label tracks the situation: Arm all N agents with no filters, Arm N more matching agents once some are already armed, and a dimmed All matching agents are armed when there is nothing left to add.

Note
This one affordance is deliberately agent-scoped, even though plain shells are otherwise fleet-eligible. It sits beside the sidebar's agent state filters and has to address the same terminals those filters describe, or the count would promise more than a click delivers. Shells stay armable one at a time, through the Fleet Picker, and through All in this worktree.

The Arming Ribbon

The arming ribbon is the amber bar that appears across the top of the content area once the armed count reaches two. It has a 2px amber left-edge stripe and slides in with a short spring entrance. From left to right it holds a disarm-everything button, the count chip with worktree dots, the broadcast progress counter and supervised-run status line, a cancel button (visible only during a large batched broadcast), the selection menu, and an exit button labelled with the exit chord for the current OS.

The Count Chip

The count chip shows how many terminals are armed, an "in fleet" label, and a row of small worktree-color dots marking which worktrees the armed set spans. When the armed set spans more than one worktree the label extends to name it — 3 in fleet · 2 worktrees — so the precise number is in the text and the dots stay a glance signal. The dots themselves cap at three. An exited count appears if any armed terminal is no longer running.

Click the chip to open a popover that lists every armed terminal in arm order under a Fleet terminals heading. A row is the terminal's title, which is itself the button that jumps to that terminal, a live agent-state badge, and a disarm X. A pane that rejected the last broadcast write carries an inline Send failed marker here, so the armed list doubles as the per-target drill-down for a partial failure.

An Add panes… button at the bottom of the popover switches the popover content to an inline picker so you can extend the fleet without leaving the chip. The Escape behavior is layered: the first press clears any search, the second returns the inline picker to list mode, and the third closes the popover.

Exiting Fleet Mode

The exit chord is Command-Escape Control-Escape Control-Escape . The ribbon's Exit button shows the chord for the current OS as a hint. A bare Esc on any ribbon-owned control (the exit button, count chip, or selection menu trigger) also exits, as long as there is no pending confirmation. The X button on the left edge of the ribbon disarms everything immediately.

After exiting, focus returns to the last terminal that was armed, and a brief ring animation pulses around its panel so you can see where you ended up.

Note
The exit chord is held for 350ms before it fires, because a second Command-Escape Control-Escape Control-Escape inside that window is the interrupt gesture instead. The second press has to carry the modifier too: a bare Esc follows the bare-Escape path and lets the pending exit fire. Both chords are handled by a dedicated window listener rather than the keybinding registry, so they cannot be rebound and do not appear in Settings → Keyboard Shortcuts.

Fleet Deck

Fleet Deck is not a separate window. It is the main content grid switched into fleet scope: instead of showing one worktree's panels, the grid shows the armed set. It exists so you can see every terminal that is receiving keystrokes, rather than broadcasting blind to panes that live in worktrees you are not currently viewing.

You enter fleet scope deliberately, with Focus selection in the ribbon's menu, which dispatches fleet.scope.enter. That menu item is the only way in: typing into a primary terminal broadcasts to its peers but does not switch the grid. The action is a no-op unless the Fleet scope mode is at its default of "scoped".

In fleet scope the grid keeps 4px gaps and a 380px minimum panel width — below that an agent TUI wraps and fragments badly. Each panel's title gains a worktree prefix so siblings are distinguishable, joined with an em dash: feature-auth — Claude Code.

Every pane in fleet scope is input-locked, the primary included. Raw xterm keystrokes are blocked for all of them and typing happens in the hybrid input bar, which is the surface that knows about broadcasting. Maximize, minimize, and add-tab are disabled while the scope is active.

Exit with fleet.scope.exit, or by leaving Fleet mode entirely. On exit the content area returns to whichever worktree was active before, using a race-safe token so a mid-flight worktree switch does not strand you on the wrong screen.

Note
Fleet scope only engages in the default scoped mode. In legacy mode (the fleetScopeMode setting), Focus selection does nothing: broadcasts still reach armed terminals in other worktrees, but the content area does not switch, so you will not see them updating. Scoped mode makes broadcasting safer by removing invisible receivers.

Quick Actions

Once a fleet is armed, a set of bulk action shortcuts operates on every eligible armed terminal at once. Each action reads the agent state of each target, so it only applies to terminals in a state to receive it.

ActionShortcutActs OnConfirmation
AcceptCommand-Y Control-Y Control-Y Waiting armed agentsNever
RejectShift-Command-Y Control-Shift-Y Control-Shift-Y Waiting armed agentsFive or more waiting
InterruptEscape, then Escape Escape, then Escape Escape, then Escape (double-tap)Working or directing armed agentsThree or more targets
RestartShift-Command-R Control-Shift-R Control-Shift-R All live armed agentsAlways (with session-loss warning)
KillShift-Command-K Control-Shift-K Control-Shift-K All live armed terminalsAlways
TrashShift-Command-Backspace Control-Shift-Backspace Control-Shift-Backspace All live armed terminalsFive or more targets

Reject sits on Shift-Command-Y Control-Shift-Y Control-Shift-Y as the shifted twin of Accept, and deliberately not on a reflexive "new" key: an action that sends n and Enter to every armed agent must not live on a chord whose meaning flips with transient ribbon state.

Interrupt is bound as a 350ms double-tap on Esc rather than a standard chord. A chord would collide with the escape stack the rest of the app relies on for closing popovers and dialogs, so the double-tap handler runs separately to avoid that interference. The first tap still passes through untouched, so a single Escape reaches the agents for menu dismissal.

Confirmation prompts replace the ribbon body with a single-line strip: a description like Reject 6 prompts? or Restart 4 agents?, plus Enter to confirm and Esc to cancel. Each verb names what it acts on — prompts for reject, agents for interrupt and restart, terminals for kill and trash. Restart adds a second sentence when a session is at stake: Restart 4 agents? 3 agents will lose their session. Confirmation will not fire while focus is in a text input or an xterm surface, so an active typing session never gets a confirmation prompt stolen out from under it.

Tip
If you press Reject and nothing happens, check the count chip. The action is a no-op when none of your armed targets are in a waiting state — the agent verbs read state before they act.

Fleet over MCP

Fleet's arming surface is exposed to Daintree's MCP server, but narrowly, and there is no tool that broadcasts to a fleet.

ToolTierWhat it does
terminal.arm / terminal.disarm / terminal.disarmAllSystemChange the armed set. Each echoes the resulting set back.
fleet.getRunStatusWorkbenchRead-only snapshot of the supervised broadcast run in flight.
agent.listToolbarWorkbenchRead-only list of the agents available to launch.

Arming is at the system tier and is absent from the external API-key allowlist, so a remote client cannot reach it at all. Even at that tier, an agent or MCP dispatch of terminal.arm raises a real host confirmation dialog. The reason is specific: arming reroutes your next keystrokes to every armed terminal, so a caller that silently repoints the armed set could fan a reflexive Ctrl+C out to terminals in worktrees you are not watching. The gate is a host prompt rather than a boolean the client can supply.

fleet.getRunStatus is read-only and available to both internal and external clients. An agent that wants to drive its own fan-out sends one terminal.sendCommand per terminal and watches with batched status calls — see Supervised Runs.

Keyboard Shortcuts

The Fleet shortcut reference:

ActionShortcut
Arm or disarm focused terminal (global) Command-J Control-J Control-J
Arm or disarm focused pane Worktree grid only, no modifier X X X
Arm all eligible in current worktree Option-Command-A Control-Alt-A Control-Alt-A
Accept waiting Command-Y Control-Y Control-Y
Reject waiting Shift-Command-Y Control-Shift-Y Control-Shift-Y
Restart all Shift-Command-R Control-Shift-R Control-Shift-R
Kill all Shift-Command-K Control-Shift-K Control-Shift-K
Trash all Shift-Command-Backspace Control-Shift-Backspace Control-Shift-Backspace
Interrupt (350ms window) Double-tap Not rebindableEscape, then Escape Escape, then Escape Escape, then Escape

Exiting Fleet mode is the one Fleet shortcut missing from that table: it is Command-Escape Control-Escape Control-Escape .

Note
Neither Escape chord is a registry keybinding: not the interrupt double-tap, and not the exit chord. Both are handled by a dedicated window listener so they can sidestep the escape stack, which means they are not rebindable and do not appear in Settings → Keyboard Shortcuts. Every other shortcut on this page is, and the full reference for the rest of Daintree lives at Keyboard Shortcuts.