Agents & automation
Fleet & Background Sessions
Fleet lets you run agent sessions in isolated git worktrees while you keep working - either one at a time or fanned out in parallel. When a session finishes, you review the diff and apply it on your terms.
What Fleet is
Fleet is the background execution layer. You drive it from the Agent panel in Code mode, but the Fleet list also adopts any session that got detached to the background (see What actually puts a session in Fleet below). It has three modes that share the same infrastructure:
- Fleet Sessions - individual agent sessions, each isolated in its own git worktree on a throwaway branch. Your working copy is untouched while the session runs. Sessions survive tab-switching and app restarts.
- Fleet Parallel - fans a single prompt out to N independent sessions simultaneously. When they finish, you compare diffs side by side and pick a winner.
- Start in background - in the composer's Send as… menu (the caret beside Send) or
Ctrl+Enter(⌘+Enteron macOS). Dispatches the current task headlessly, clears the composer once the run has started, and notifies you when the agent is done.
A run in its own worktree writes its output to a branch and you review the diff before anything touches your main working copy. A run in this folder writes straight to your working copy with no diff step. A background run starts in its own worktree unless you changed that for the project (see Background defaults below).
What actually puts a session in Fleet
Fleet is not a classifier. Nothing reads your message and decides it looks like a background job. A session becomes a Fleet item in exactly four ways - three you click, and one you should know about:
The three explicit ones:
- Start in background from the composer's Send as… menu or
Ctrl+Enter(⌘+Enteron macOS; Code mode and Chat mode), or New → Background run… in the Runs header. - Start in parallel… from Send as…, or New → Parallel run… in the Runs header.
- Moving a session - Send as… → Move this session to a worktree, or right-click → Open in fleet in the Sessions drawer.
The one that can surprise you - stream drop: if you send a message and the connection carrying that response closes while the agent loop is still running, and you didn't press Stop, Bodega keeps the loop running rather than killing your work - and marks that session as a background session. It then shows up in Fleet. This applies to Chat mode sends too, not just Code mode. Switching sessions or panels mid-run, closing the panel, or reloading the window can all trigger it.
Two guards keep a brief blip from counting as a real detach: a disconnect within the first 15 seconds of the turn is never flagged as backgrounding (too early to mean anything), and any disconnect gets a 5-second reconnect grace - reattaching within that window cancels the pending flag before the session is ever marked background.
A session detached this way has no worktree and no diff, because it was never an isolated run. It still reaches the Ready to apply state when the loop finishes, so you can get an "apply"-labelled card with nothing to apply. If a Chat mode message you expected an answer to turns up as a Fleet card instead, this is why - open the card to read the response rather than looking for a diff.
Open the Fleet panel
- Switch to Code mode (
Ctrl+2). - Open Runs (the tray icon in the left activity bar, or
Ctrl+Shift+U), find the lane, and choose Open in Fleet from its right-click menu.Ctrl+Shift+Fstill toggles the Fleet panel directly.
The Fleet panel is a dockable tab in the Dockview layout. If your project is not a git repository, the panel shows a "Initialize git" tile instead of session cards - Fleet requires git.
Run a task in the background
Requires: a project folder. In Code mode a session is created for you if the panel has none yet.
- Type your task in the composer.
- Press
Ctrl+Enter(⌘+Enteron macOS; the first time in a project it opens the defaults sheet once, becauseCtrl+Enterused to send; Save and start remembers your choice), or open the ▾ beside Send (Alt+R) and choose Start in background. The row under it says what it will do with this project's defaults, for exampleOwn worktree · Act · notifies when done. - The composer clears once the run has started, and a line under it says what it used and links to Runs, for example Started in background · own worktree · Act · Open in Runs. The run is a new session in the project: the chat or session you are typing in is never taken over, and this works from Chat mode too. There is no toast; the run is a row in Runs, which is also where it asks for you if it needs an approval.
- When the agent finishes, the run moves to Done in Runs (and sends a desktop notification if you turned that on). Open it, review the diff in the Fleet panel and apply it when you are ready.
Background defaults. By default a background run gets its own worktree and runs in Act, so nothing touches your working copy until you apply it. Send as… → Background defaults: change… opens a small sheet for this project: In its own worktree or In this folder, and Act or Plan. It is remembered per project (a user setting, never part of a repository's .bodega/config.json). Ask is not offered: nobody is watching an unattended run to answer. If the project is not a git repository, the line under the composer says a worktree cannot be created and offers Run in this folder instead, which also becomes this project's default.
Without a project folder the background, parallel and loop rows are greyed out and say why.
Fleet card states and actions
Cards are sorted action-required first.
| State | Left border | Actions |
|---|---|---|
| Running | Blue | Open · Discard |
| Awaiting approval | Amber (pulsing) | View · Approve |
| Ready to apply | Green | View diff · Apply ▾ |
| Interrupted / Error | Red | Resume in foreground · Discard |
| Idle | Grey | Open · Discard |
While a session is running, the card shows a live activity row: Iter 5/13 - read style.css Last active 12s ago. The timer ticks every 5 seconds. If the session goes quiet for more than 60 seconds the timer turns amber; over 180 seconds it turns red.
Sessions idle for 7+ days show an Idle 7d - Close? badge.
Review and apply a finished session
- In the Fleet panel, find the Ready to apply card.
- Click View diff to open the full colored unified diff with
+/-statistics per file. - When you're ready, click Apply ▾ to open the Apply dialog.
- The dialog runs a dry-run conflict check against your working copy. If there are merge conflicts or uncommitted changes, the Apply button is disabled and the conflicting files are listed. Buttons next to each file open the main-project copy and the agent's worktree copy side by side as labeled tabs. Uncommitted changes in your working copy route you to the Git panel.
- Once the check is clear, choose merge or squash strategy and confirm.
The dry-run is non-destructive - it never writes to disk.
Discard a session
Click Discard on any card. A confirmation dialog appears (with a Don't ask again checkbox). Confirming calls DELETE and removes the worktree from disk.
To suppress the confirmation in future, check Don't ask again in the dialog - or there is no switch to turn it on from Settings (general.dont_ask_again_discard is only set by that checkbox); Settings → General → Startup & confirmations → Reset confirmation prompts turns it back off.
Apply has the same bypass (beta.27): check Don't ask again in the apply dialog and future applies run immediately with the merge strategy (failures surface as toasts). Re-enable both confirmations with Reset confirmation prompts in Settings → General → Startup & confirmations.
Promote a foreground session to Fleet
You can move an already-running foreground session to Fleet without dispatching a new prompt:
- From the composer: open Send as… (the ▾ beside Send, or
Alt+R) and choose Move this session to a worktree. This provisions a worktree and moves the session to the background. It needs a project folder and a Code mode session that has already started (a Chat mode chat cannot be moved; use Start in background to run its draft in a new session). - From the Sessions drawer: open the Sessions drawer (top-bar hamburger → Sessions), right-click any session, and choose Open in fleet.
The session header no longer carries a button or a Foreground/Background pill; it names the project and says Working in this folder or In worktree ….
Fleet Parallel - fan out to multiple sessions
Fleet Parallel runs the same prompt in N independent isolated sessions simultaneously. When they finish, you compare diffs side by side and pick one to apply.
Each session gets its own worktree branch. The ParallelDiffCompare view shows up to 3 sessions as columns (4+ sessions get a scrollable tab strip), with:
- Branch name and
+/-stats - Full colored unified diff
- QEL score badge
- Pick this winner button
Sessions are sorted highest-QEL-score first. If the top session passed QEL verification, it shows a purple Verified before review badge. If none passed, a banner warns you before you pick.
Picking a winner opens a confirm sheet with a commit message field and merge/squash strategy, then applies that session's worktree.
Launch a parallel run
Requires: a project folder.
- In the composer, open Send as… and choose Start in parallel… (or New → Parallel run… in the Runs header, which starts with an empty task).
- In the Parallel run sheet:
- Task - pre-filled from your composer draft; edit as needed.
- Lanes - 2 to 4. The server also checks the VRAM ceiling for your hardware and refuses a set of models it can tell will not fit together.
- Compare models (default) gives each lane its own model and harness (Bodega, or an installed coding agent such as Claude Code, Gemini CLI or Codex, which runs its own model). Same model ×N repeats one model and harness in every lane.
- Permission - Act or Plan only. Ask is not offered because several lanes asking at once is an approval storm.
- Two or more local lanes show a note that they share one GPU. Bodega adds up the different local models and refuses a set it can tell will not fit in the free VRAM (two different llama.cpp models are refused, since it serves one at a time). A lane whose provider Bodega cannot work out is flagged and blocks Start until you pick the model again.
- Click Start N lanes. The sheet closes and a line under the composer says Started N lanes · Open in Runs.
When all lanes finish the run asks you to choose the winner in Runs; Compare All in the Fleet Monitor group header opens the side-by-side view. Picking the winner automatically by verification score is not part of this release.
Air-gap: while air-gap is on (globally, or for a project with an Air-Gap Vault), only local models and Bodega lanes can start. A cloud lane or an external coding agent is refused for the whole run (it is never quietly dropped), and a cloud lane runs the spend-cap check like any other cloud run.
In the CLI, bodega fleet "<task>" --split N fans one task out across N worktrees with a single model; per-lane models there are a follow-up (the server accepts them, the CLI does not send them yet).
Fleet Monitor panel
The Monitor tab (second tab in the Code mode left sidebar) shows all active Fleet sessions in a compact table: Branch/Project, Status, Iter, Files changed, Elapsed, Tokens, and action buttons.
- Running sessions appear first.
- Parallel runs are grouped into collapsible rows with a per-session mini progress bar and QEL score indicator.
- The table polls live status every 5 seconds.
From the Monitor you can: Focus a session (bring it to the foreground), Kill a running session, Restart a stopped session, or Compare All on a completed parallel run group.
Where the Fleet and Loops indicators went
The Fleet pill, the Loops pill and the Runs Inbox pill that used to sit in the top bar are gone: Runs replaces all three. A running lane shows under Working, a lane that needs approval or review shows under Needs you with the reason in words (Approve shell, Review diff), and a finished lane you have not opened shows under Done. The Runs icon in the activity bar carries one count: how many runs need you. Fleet and Loops are not removed: a lane's menu has Open in Fleet and a loop's has Open in Loops, and both panels keep their place in your layout.
Runs: everything waiting on you, working, or finished
The Needs you section of Runs lists every run that is blocked on a person, across Fleet, Loops and your own chats: an approval waiting, a question to answer, a diff ready to review, a parked loop, a lane waiting for you to choose a winner. Each row says why in words. The decision lives where it always did (the Agent panel, the Fleet panel, the Loops panel); the row is the notification and the way there. Nothing pops up as a toast: a finished run is a row, and an optional desktop notification if you turned Settings → General → Notifications → Notify when a background run finishes on. When a background run finishes, that notification carries the run's recap (for example Fix the parser: Changed 4 files · Verification passed); if it has none, it says the run is complete.
Open the Runs page of this hub for the sections, the keys and the menu.
Fleet settings (Settings → Automations → Background runs)
Fleet settings live under Settings → Automations → Background runs, except the notification rows (fleet.notify_os, quiet hours, and fleet.notify_in_app under Advanced), which are on Settings → General → Notifications. Background runs has no Save button: each row saves as you change it.
| Setting | Default | Notes |
|---|---|---|
agent.max_background_sessions |
4 | Max concurrent sessions (range 2–12). Exceeding this returns an error toast. |
agent.worktree_max_age_days |
30 days | Auto-GC age threshold (range 7–90 days). |
fleet.notify_in_app |
ON | In-app notice for scheduled Drift Radar checks. Fleet and Loops runs no longer toast: their row in Runs is the in-app notification. |
fleet.notify_os |
OFF | OS desktop notification on completion (requires system permission). |
fleet.worktree_path |
<userData>/bodega-worktrees/ |
Custom storage base directory for worktrees. |
fleet.quiet_hours_start / fleet.quiet_hours_end |
empty | HH:MM 24h strings. OS notifications are suppressed in this window. |
followups.background_worktree |
ON | A Background follow-up gets its own worktree. Global only. |
recap.polish |
OFF | Reword the recap in up to three plain sentences. Greyed out while air-gap is on or your active provider is not a cloud provider (stricter than the backend, which only skips a model on this computer). Global only. |
ACP agents in Fleet
External ACP agents (Claude Code, Gemini CLI, Codex) can run as Fleet sessions or as participants in a parallel run. Two things to know:
- They are labeled external - not QEL-verified in Fleet cards and in the parallel compare view, because they bypass Bodega's QEL verification layer.
- They cannot use Ask permission mode in parallel runs (disabled to prevent an approval storm across N sessions). Act and Plan are available.
- ACP requires network - all ACP agents are disabled when air-gap mode is ON.
Error messages you may see
| Message | Cause |
|---|---|
Type the task first. |
The composer was empty when you pressed Ctrl+Enter or chose Start in background. Shown under the composer, not as a toast. |
Too many background sessions - close or apply one first |
You've hit the agent.max_background_sessions ceiling (default 4). |
This session is already running |
You tried to launch a background run on a session already in flight. |
This project has no commits yet. Make an initial commit to run in a worktree. |
A worktree needs at least one commit in the project. Run in this folder instead, or commit first. |
This folder isn't a git repository, so a worktree can't be created. |
The open project is not a git repo. The line offers Run in this folder instead. |
What happens on app restart
Fleet sessions are persisted. When you relaunch Bodega, any sessions that were running or interrupted reappear in the Fleet panel as Interrupted with a Resume in foreground button. You don't lose track of in-flight work across restarts.
In-place vs isolated - when to use each
In this folder (Background defaults → In this folder): the agent writes directly to your working copy. No diff review, no apply step - changes land immediately. Good for low-risk single-file tasks where you want to see results fast and can use git to undo if needed.
In its own worktree (the default): changes go to a throwaway worktree branch. You get a full diff review and a conflict-checked apply step. Use this for multi-file changes, refactors, or anything where you want to review before the code lands.
Things that aren't obvious
- "Ready to apply" doesn't always mean there's a diff. The state means the loop finished, not that a worktree is waiting to merge. A session detached by a dropped stream reaches it with nothing to apply. Check for a worktree branch on the card before you go hunting for changes.
- Pressing Stop is meaningfully different from navigating away. An explicit Stop aborts the run. Closing the panel or switching away does not - the loop keeps going in the background and the session lands in Fleet. If you actually want a run dead, Stop it.
- A dropped connection gets 20 seconds to come back. If the stream to the app drops mid-turn, Bodega waits 20 seconds before treating it as a background session. Reconnect inside that window and the turn carries on as a normal turn, with no Fleet card. The agent keeps working and approvals keep waiting for you either way.
- The concurrency cap counts live work, not cards.
agent.max_background_sessions(default 4, range 2–12) counts only sessions actually occupying a slot - running or awaiting your approval - for every way of starting background work, parallel runs included. A finished, ready-to-apply, idle, or errored card sits in the strip for free; hitting the cap means N sessions are genuinely still running, not that you have stale cards to clear. - Quiet hours only silence the OS notification. In-app toasts still fire inside the quiet window - the setting suppresses the desktop notification, not the completion signal.
- Worktrees are garbage-collected by age.
agent.worktree_max_age_days(default 30, range 7–90) reaps old worktrees. A session you meant to keep for a month is on the edge of that default.
In the CLI
Two separate CLI features cover this page. bodega fleet "<task>" --split 3 fans one task out across N isolated worktrees, then fleet status / attach / apply / discard picks the winner - the CLI's equivalent of a Fleet parallel split. For a single background run, bodega run --bg detaches and returns a task ID; runs lists them, logs <id> streams NDJSON, and attach <id> blocks until it finishes and exits with its code. There's no Runs Inbox or quiet-hours setting - background status is whatever runs/logs/attach report when you ask.
Follow-ups run as background sessions
The Background button on a recap's follow-up starts a new session in the same project, in its own worktree by default (turn that off in Settings → Automations → Background runs → Recaps and follow-ups, key followups.background_worktree; it is a global setting, a project cannot switch it off for you). When that setting is on, it starts from the parent's branch if the parent works in a worktree. It runs in the same permission mode as the session it came from, so nothing is approved just because it is in the background. A background follow-up stops at its first approval and shows under the parent in Runs as needing you; it cannot be approved from there, so re-run the item in the foreground (Here) to approve it. The same background limit applies; if it is full you see the limit message on the follow-up row and nothing is started.
Keyboard shortcuts
| Keys | Action |
|---|---|
| Ctrl+2 | Switch to Code mode (where Fleet lives) |
This page mirrors the in-app docs hub for app version 1.0.0-beta.46. Found something unclear or out of date? Tell us on Discord. New here? Download the free beta and follow along.