Skip to main content
A worktree source cuts a fresh git branch off HEAD (dabs/<id>), checks it out into its own node, and mounts it live — the agent works on an isolated, reviewable copy while your working tree stays untouched.
Screens verified by tests/test_worktrees.py.

Cut one

From inside a git repo:
dabs recipe wt        # a worktree, no box
✓ worktree repo-________ branch dabs/________ · …/.dabs/nodes/repo-________/held/worktree
(wtbox does the same and boots a shell box over it in one step.)

Judge it at a glance

dabs worktrees ls shows every worktree with a three-value STATE:
NAME           WORKTREE                                              STATE    DETAIL
repo-________  …/.dabs/nodes/repo-________/held/worktree             no-diff  branch dabs/________ · recipe wt · uncommitted=false ahead=0 · no box
statemeaning
no-diffclean — or squash-merged: commits ahead whose content the base already has
has workuncommitted or untracked changes, nothing unmerged ahead
unmergedcommits ahead carrying content the base lacks (wins over has-work)
The judgment is content, not commit count — landed work never reads as unreviewed.

Point a box at it

--worktree <wt> binds an existing worktree to a recipe’s . source — and also mounts the parent repo’s .git, so git works inside the box and commits reconcile straight into your shared object store (no push):
dabs recipe sh --worktree repo-________ --detach
dabs exec sh-________ 'cd /work && git add -A && git commit -qm improve && git --no-pager log --oneline'
_______ (HEAD -> dabs/________) improve
_______ (main) first
A static worktree: . source (plain wt/wtbox) does not mount the parent .git — git is blind inside such a box. The agent edits; you commit on the host. Use --worktree when a job needs in-box git.
After an edit the state flips to has work; after an in-box commit, to unmerged:
repo-________  …  has work  branch dabs/________ · recipe wt · uncommitted=true ahead=0 · box shell-____________ live
repo-________  …  unmerged  branch dabs/________ · recipe wt · uncommitted=false ahead=1 · box shell-____________ live

Review, then reap

See exactly what the agent changed — the diff surfaces untracked files too:
dabs worktrees diff repo-________
diff --git a/app.txt b/app.txt
--- a/app.txt
+++ b/app.txt
@@ -1 +1,2 @@
 line one
+edit
rm refuses to discard work nobody reviewed:
dabs: repo-________ has unreviewed work (uncommitted=false, 1 commit(s) ahead) — review with `dabs worktrees diff repo-________`, then rm --force to discard
Once reviewed (or truly unwanted), --force is the explicit “discard git work” consent — a different risk than the -y prompt, so it is a different flag. Reaping a worktree also takes any box standing on it:
dabs rm repo-________ -y --force
✓ shell-____________ stopped
✓ sh-________ removed
✓ repo-________ removed

Sweep the clean ones

--clean-worktrees reaps every worktree with no unreviewed work, in one shot — the tidy-up after a day of agent runs:
dabs rm --clean-worktrees
✓ repo-________ removed
✓ repo-________ removed
no worktrees
Add --dry to preview, or --force to include the ones that do hold work.