Skip to main content
Aliases: ps/listls · remove/deleterm · worktreeworktrees. dabs --help-full-for-agents prints the full agent-facing guide — the entry point an agent should read before driving dabs.

build

Build a recipe’s box image (once per Dockerfile change). No name → the registry default:; a name → that recipe; a path → a dabs.yaml to load. A boot rebuilds automatically when the Dockerfile or a bundled image’s files change — but not when only COPY . context files changed; run dabs prune then build to pick those up.

recipe

Boot a box from a recipe and run its command, then tear the box down (unless the recipe says keep: true). Trailing tokens are appended to the recipe’s command; appending always confirms first, showing the exact final command.
  • --no-command — boot a NEW box, run nothing, leave it up.
  • --detach — boot a NEW box, start the recipe’s command inside it in the background, and return without waiting for it. The box is left up with its command running; the command’s combined output goes to ~/.dabs/nodes/<id>/tmp/detached.log on the host, and the boot prints the tail -f line for it. The log is reaped with the node. Needs a driver whose box carries a process of its own (docker, apple); it is refused, not degraded, on one that does not.
  • --worktree <wt> — bind an existing worktree to the recipe’s . source and mount its parent .git, so git works in-box.
  • --name <n> — name the node the boot creates instead of a generated id; the name resolves everywhere an id does. See Named nodes.
  • dabs recipe -- <cmd…> — the default recipe with your command appended.

exec

Run a command inside a box: with --, an exact argv (no shell); without, a sh -c line (pipes/globs/&& work). Accepts node ids, instance names, and unambiguous prefixes.

ls

List the active subtrees as a tree; --inactive lists only the hidden empty markers instead. Columns: NODE · KIND · VOL/HELD/TMP · STATE · INFO. A box’s KIND carries the driver that runs it (box (bwrap)), and INFO is per kind — a project’s source repo, a worktree’s checkout, and for a box the dabs exec <instance> bash line that shells into it. Every local driver draws in one flat tree with no heading; a registered server gets a heading of its own.

info

One node’s full model, where ls gives every node a row each. The node resolves like every other handle (exact id, id prefix, then a box instance name), and an ambiguous one is refused.
  • kind and id on the first line.
  • location — the node’s working place, resolved per kind exactly as dabs cd resolves it: a project’s source repo, a worktree’s checkout, and for a box its own node dir.
  • instance — the running box’s own identity (boxes only).
  • appended — the argv dabs recipe <name> <cmd…> appended to the recipe’s command at boot, persisted on the node and shown here only. It is never in dabs ls: an appended command can carry a prompt or a secret, and a listing of everything dabs owns is the wrong place to spill either.
  • spacesholds files / empty per space, by the same predicate ls and the rm confirmation use.
  • recipe — the snapshot captured when the node was provisioned, so it stays truthful after the registry drifts. A node written without one falls back to the current registry definition of its recipe name and says so (sh (current registry definition — no snapshot on this node)); a name the registry no longer knows says that plainly.
Screens verified by walkthroughs/test_info.py.

rm

The single reaper — see Listing and cleaning up for the four consent flags. --keep stops the box but keeps its node record; --clean-worktrees sweeps every worktree with no unreviewed work; --inactive sweeps every inactive subtree.

worktrees

Inspect worktree nodes: state (no-diff / has work / unmerged), branch, recipe, box-liveness; diff shows a review diff that surfaces untracked files. Reaping is dabs rm.

cd

Print a node’s WORKING place as a bare path, resolved per kind — a project to its source repo, a worktree to its checkout (~/.dabs/nodes/<id>/held/worktree), a box to its own node dir (~/.dabs/nodes/<id>). A shell can’t be moved by a child process, so wrap it: cd "$(dabs cd <node>)". Accepts names and unambiguous prefixes; an ambiguous one is refused. A box’s node dir holds its three spaces as the volume/, held/, tmp/ subdirectories. See Named nodes.

recipes

List the known recipes one line each — name, description, and origin (bundled / global / project); --print dumps the merged registry as YAML, each recipe marked with its origin, and --print <name> dumps just that recipe, mounts and all.

prune

Reclaim built box images. --dry lists sizes; --force removes even images a live box uses.

servers

Manage registered remote servers (reached over ssh; a recipe routes to one with target:).

Environment

  • DABS_NAME — set inside every box to the box’s instance name.
  • dabs state lives under ~/.dabs/ (nodes, images, config, shared dirs). Running from inside ~/.dabs never marks a new project: dabs recipe refuses to make a project, worktree, or scratch node there. The one exception is a dabs worktree’s own checkout — a boot from inside one parents the box on that worktree and mounts its parent .git, exactly as --worktree would. See Worktrees.