Chapter · filesystem

Filesystem isolation: worktrees, reflinks, overlays and snapshots

Two different things need cloning: the sandbox's own root filesystem, and your project. They do not have to use the same mechanism, and getting this right is what makes fanning one task out to five agents cost almost nothing.

The rule that matters

Never give an autonomous agent your original working tree Give it a writable derivative. The original should either be invisible, or mounted read-only for reference. "Keep the changes?" then becomes a controlled host-side operation — a diff you review and apply — rather than trusting the sandbox to undo whatever happened. This one decision eliminates the entire class of "the agent rewrote my Git history" and "the agent deleted the backup along with the database" incidents that keep appearing in practitioner threads.
YOUR PROJECT read-only, or not visible HEAD @ commit hash worktree · reflink · overlay workspace A · agent 1 37 ms · 1.8 MB allocated workspace B · agent 2 independent writes workspace C · agent 3 disposable REVIEW diff per lane tests, transcript a human reads it APPLY selected files or hunks or export as project-box2/
Cheap fan-out plus an explicit review step. Every design that does this well separates "the agent can write" from "the original changes".

The five ways to clone a workspace

Order-of-magnitude figures, gathered from the primary sources behind this guide rather than measured here; treat them as indicative of magnitude, not as promises for your hardware.
StrategyDisk at N lanesSetup timeCarries node_modules and caches?PlatformWhere it wins
Git worktree ~N × working tree (objects shared) 180–350 ms on SSD; minutes on a huge monorepo No — every new worktree starts cold Windows, Linux, macOS The default whenever the folder is a Git repo. Least surprising, reviewable as a branch, no new tooling.
Reflink / CoW copy ~1× (blocks shared until written) Near-constant — a 2 GB tree in ~130 ms on APFS Yes, including build output and caches APFS, Btrfs, XFS, bcachefs. Not ext4 or NTFS. Non-Git directories, and any tree whose value is in untracked artifacts. This is the single biggest practical win for monorepos.
OverlayFS (lower + per-lane upper) Minimal upper per lane Mount plus empty upper Yes, via the lower layer Linux (native kernel or fuse-overlayfs) Non-Git trees inside a Linux container or VM. Note the rename footgun: moving a file from lower into upper fails with EXDEV, which is known to break node_modules/.vite/deps.
qcow2 backing file Delta only per VM Instant (qemu-img create -b base.qcow2) Yes — it is the whole disk Anywhere QEMU runs VM and microVM disk images. This is how you get five near-instant VMs from one base without inventing a format.
Snapshot / clone (Incus, ZFS, Btrfs) Near zero for snapshots Sub-second on a CoW backend Yes — it is the whole instance Linux hosts Persistent agent machines you fork per task. Storage driver decides whether it is free or expensive.
Plain recursive copy N × size O(size) Yes Everywhere The reliable fallback. Fine for one lane, wasteful for ten.
The numbers that make the case
  • A Git upstream patch for copy-on-write worktrees measured a Linux kernel fork (93k files, ~33 GB) needing ~0.9 GB of real disk per worktree on Btrfs, growing linearly, versus ~0 at any lane count with reflinks — and the reflink version also carries the untracked build tree.
  • Eight isolated views of a 300 MiB tree: 2.4–2.6 GB with plain worktrees versus 301 MB with CoW views, at 2.1× the cold setup time.
  • A Firefox-scale build cache: two worktrees summed to 47.2 GB naively, saved 27.4 GB via reflinks, measured 19.9 GB on disk — and restoring 13.5 GB of compiled artifacts into a second worktree wrote zero new bytes.
  • Per-turn snapshots of 5,000 small files: cp -r 1,970 ms, a CoW clone 487 ms.
Worktrees are not a filesystem trick

A worktree shares the object database, refs and config — not the working tree. Each one still materialises every tracked file, so a repo with large generated assets or a heavyweight node_modules gets expensive at ten lanes. The practical fixes, in order: reflink the ignored directories after creating the worktree; use a warm pool of pre-provisioned worktrees so acquisition is milliseconds instead of a two-minute install; use cone-mode sparse checkout plus partial clone for enormous monorepos; and share compiled artifacts through a content-addressed cache rather than duplicating them.

The strategy picker

Is it a Git repo? and is the tree modest? yes git worktree + reflink ignored dirs + warm pool huge tree sparse checkout cone mode + partial clone no reflink copy APFS, Btrfs, XFS overlayfs Linux, non-Git tree qcow2 backing VM / microVM disks plain copy (fallback) WHATEVER YOU PICK original stays read-only each lane fully isolated apply is a host action snapshot before fan-out show the clone cost in the UI 37 ms · 1.8 MB allocated
Pick per project, not per application. A good tool detects the repository, asks the filesystem what it supports, and reports which mechanism it used — instead of making the user learn four of them.

Cloning the sandbox itself

The second half of the problem is the environment the agent runs in. Here the mechanisms are different and usually already built into your runtime.

Containers: image layers are already copy-on-write

Ten containers from one image share the immutable layers and each write only their own upper layer. You get cheap fan-out for free — right up until you bind-mount your project, at which point the bind mount deliberately exposes the host directory and all that layering stops applying to your source.

Implication: keep "the sandbox root filesystem" and "the project workspace" as separate concepts, because they use different mechanisms.

VMs and microVMs: qcow2 backing files and snapshots

qemu-img create -f qcow2 -b base.qcow2 -F qcow2 lane1.qcow2 gives you five lanes from one base with delta-only writes. Incus snapshots do the same at the instance level. This is the "instant five copies" mechanism people reinvent badly — it already exists, and it is not a format you need to design.

Checkpoints are not memory

Filesystem checkpoints capture files. They do not rewind processes, pending network requests or open file handles, and they do not capture what a running agent had in RAM. If a lane has credentials written into it, the checkpoint contains those credentials — a detail at least one local sandbox tool documents plainly, and one that most do not mention at all.

The sharp edge to avoid

git clone --shared is described by Git's own documentation as a possibly dangerous operation: it sets up object alternates referencing the source repository, and if those source objects later become unreferenced and are pruned, the dependent clone can be corrupted. There is no reason to put that in a product when git worktree exists.

Snapshots are not backups A snapshot lives on the same storage as the thing it snapshots. If the agent fills the disk, corrupts the filesystem or deletes the pool, your snapshot goes with it. Snapshots make fan-out and rollback cheap; they do not make anything safe. Keep an actual backup somewhere the agent cannot reach — which, by definition, means outside every mount you gave it.

The apply-back workflow

This is the part most tools get wrong, and it is mostly a user-interface problem rather than a plumbing one. A good workflow has four verbs, and they should be visible as verbs:

VerbWhat it doesWhat it must never do
KeepApply selected files or hunks from a lane onto the host working tree, as a commit, a cherry-pick or a patch.Apply everything silently because the agent said it was done.
ExportProduce project-box2/ next to the original, so you can diff two results side by side without touching your tree.Overwrite an existing directory of the same name.
DiscardDelete the lane and its workspace, freeing the copy-on-write blocks.Discard the checkpoint you would need to recover something you later wanted.
Keep laneLeave the sandbox and its workspace alive for another round of instructions.Leave it running and billing, or leave it discoverable only if you remember its container ID.
The UI detail that makes this trustworthy Tell the user what they got. "Workspace clone: 37 ms, 1.8 MB initially allocated, source protected" is a sentence that teaches more about the system than any amount of documentation, and it makes the cost of trying something fearless. The same is true of the inverse: an interface that says "writes directly to the original" instead of displaying a bare RW has done more for safety than a dozen warnings in a settings file.