Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/deeplethe/forkd/llms.txt

Use this file to discover all available pages before exploring further.

A parent snapshot is the warm VM state that every forked child inherits. It is stored as two files on disk — memory.bin (the full guest RAM image) and vmstate (vCPU registers, device state, and KVM context) — plus an optional rootfs.ext4 and a snapshot.json manifest. The parent boots once, imports your runtime (Python + dependencies, a warmed JVM, a loaded ML model), is paused, and written to disk. Children then mmap memory.bin with MAP_PRIVATE so the kernel implements copy-on-write at the page level: each child shares the parent’s resident memory until it diverges. This guide covers the three paths to create a snapshot and how to manage them locally.

Three paths to a snapshot

forkd from-image

Docker image → ext4 rootfs → boot + warmup → snapshot. Easiest path — one command.

forkd snapshot

Manual path: you supply kernel, rootfs, and tap. Full control over every parameter.

forkd snapshot --from-sandbox

Branch a running sandbox mid-execution. Covered in Branching.

forkd from-image wraps the full pipeline — Docker pull → ext4 build → boot + warmup → pause → register tag — into a single verb. The rootfs is cached after the first build, so re-running with the same image skips the Docker step.
sudo -E forkd from-image python:3.12-slim \
    --tag py-numpy \
    --extra python3-numpy
This typically takes 2–3 minutes on the first run (Docker pull + mkfs.ext4 + warmup) and is nearly instant on subsequent runs because the rootfs is cached at /var/cache/forkd/<image-slug>.ext4.

Flags

FlagDefaultDescription
<image>(required)Docker image reference, e.g. python:3.12-slim, ghcr.io/user/repo:tag
--tag(required)Local snapshot tag: [A-Za-z0-9_][A-Za-z0-9._-]{0,63}
--extra(none)Additional apt packages to bake into the rootfs. Repeatable.
--size-mib1536Rootfs ext4 image size in MiB
--cache/var/cache/forkdDirectory where built rootfs artifacts are cached
--kernelauto-detectedPath to vmlinux kernel image. Searched at ./vmlinux-6.1.141, ./vmlinux, /var/lib/forkd/kernels/vmlinux
--tapforkd-tap0Host tap device for the boot warmup
--boot-wait-secs10Seconds to wait for the guest to settle before snapshotting
--mem-size-mib512Parent VM memory in MiB. Increase for browser or ML model warmups

Full example

# Build a snapshot with multiple apt packages pre-installed
sudo -E forkd from-image python:3.12-slim \
    --tag py-scipy \
    --extra python3-numpy \
    --extra python3-scipy \
    --extra python3-pandas \
    --size-mib 2048 \
    --mem-size-mib 1024 \
    --boot-wait-secs 20
# 2-3 min the first time; uses cached rootfs on re-run.

# Fork children from the snapshot
sudo -E forkd fork --tag py-scipy -n 10 --per-child-netns
After this completes, forkd images will show the new tag.

Path B — forkd snapshot (manual)

Use this path when you have a kernel and rootfs on disk and want direct control over every boot parameter.
sudo -E forkd snapshot \
    --tag pyagent \
    --kernel ./vmlinux-6.1.141 \
    --rootfs ./python-rootfs.ext4 \
    --tap forkd-tap0 \
    --boot-wait-secs 10
The parent VM boots, settles for --boot-wait-secs seconds, is paused, and the memory image + vmstate are written to ~/.local/share/forkd/snapshots/<tag>/.

Flags

FlagDescription
--tagSnapshot name. Required.
--kernelPath to vmlinux kernel. Required (unless --from-sandbox). Also reads FORKD_KERNEL.
--rootfsPath to rootfs image (.ext4 for read-write, .squashfs for read-only). Required. Also reads FORKD_ROOTFS.
--tapHost tap device name (e.g. forkd-tap0). Also reads FORKD_TAP.
--rwMount rootfs read-write (auto-enabled for *.ext4 files).
--boot-wait-secsSeconds to settle before snapshot. Default 10.
--mem-size-mibOverride parent VM RAM size in MiB. Default 512.
--keep-workdirKeep /tmp/forkd-parent-<tag>/ after snapshot for post-mortem inspection.
--volume HOST:GUEST[:ro]Attach a persistent volume (see below).
To build a rootfs from a Docker image manually before snapshotting:
sudo bash scripts/build-rootfs.sh python:3.12-slim python-rootfs.ext4 1536 python3-numpy

Volumes

Volumes let you attach persistent ext4 images to a snapshot so every child inherits shared, writable (or read-only) storage. Common uses: pip/npm caches shared across all children, model weights loaded once at parent-boot time, agent scratch space.
# Create a volume image
sudo dd if=/dev/zero of=/var/lib/forkd/vol/pyagent-cache.img bs=1M count=512
sudo mkfs.ext4 -F /var/lib/forkd/vol/pyagent-cache.img

# Attach it when creating the snapshot
sudo -E forkd snapshot --tag pyagent \
    --kernel ./vmlinux-6.1.141 \
    --rootfs ./python-rootfs.ext4 \
    --tap forkd-tap0 \
    --volume /var/lib/forkd/vol/pyagent-cache.img:/opt/cache \
    --volume /var/lib/forkd/vol/models.img:/models:ro
The HOST:GUEST[:ro] format:
  • HOST — absolute path to an existing ext4 image on the host
  • GUEST — absolute mount path inside the VM
  • :ro — optional read-only flag (default is read-write)
Up to 24 volumes are supported per snapshot (virtual drives vdb through vdy). Volume specs are recorded in snapshot.json and automatically inherited by branched snapshots.

Path C — Branch a running sandbox

You can snapshot a running child sandbox mid-execution to create a new parent tag. This is the BRANCH operation — see Branching for the full guide.
# Branch via the CLI
forkd snapshot --from-sandbox <sandbox-id> --tag checkpoint-1 --diff

# Fork grandchildren from the checkpoint
forkd fork --tag checkpoint-1 -n 5 --per-child-netns

Listing and removing snapshots

List local snapshots

forkd images
Example output:
  TAG           SIZE        MEMORY     CREATED  ROOTFS
  py-numpy    22.1 MiB   512.0 MiB    3d ago   yes
  pyagent     14.8 MiB   512.0 MiB    1h ago   yes
  langgraph   14.5 MiB   513.0 MiB    2d ago   yes

  3 snapshots · 51.4 MiB total

Remove a snapshot

forkd rmi py-numpy
forkd rmi py-numpy pyagent   # multiple tags
forkd rmi calls DELETE /v1/snapshots/:tag on the daemon first (clean: removes registry entry + on-disk files atomically) and falls back to direct disk removal if the daemon is not running. In v0.5, removing a snapshot that is the parent_tag of a chained snapshot returns 409 Conflict; use --cascade or --force to override (see Snapshot Chains).

Snapshot directory layout

Every snapshot lives under ~/.local/share/forkd/snapshots/<tag>/ (or $XDG_DATA_HOME/forkd/snapshots/<tag>/):
~/.local/share/forkd/snapshots/py-numpy/
  memory.bin      # Full guest RAM image (CoW source for all children)
  vmstate         # vCPU registers + device state + KVM context
  snapshot.json   # Metadata: volumes, parent_tag, parent_content_hash
  rootfs.ext4     # (optional) guest filesystem image
The snapshot.json manifest records volume mounts and, for v0.5 chained snapshots, the parent_tag and parent_content_hash that pin the chain edge. Children mmap(memory.bin, MAP_PRIVATE) — the kernel handles copy-on-write at the page level with zero explicit copying at fork time.
Run forkd where to print the exact snapshot directory for the current user. Override with the XDG_DATA_HOME environment variable.

Build docs developers (and LLMs) love