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
| state | meaning |
|---|
no-diff | clean — or squash-merged: commits ahead whose content the base already has |
has work | uncommitted or untracked changes, nothing unmerged ahead |
unmerged | commits 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.