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.

Building a parent snapshot — Docker pull → rootfs build → boot + warmup — takes 2–3 minutes. Once built, the snapshot is a portable artifact: pack it into a .forkd-snapshot.tar.zst bundle, upload it to any S3-compatible storage, and pull it on any forkd host in seconds. No Docker round-trip, no re-importing numpy. The Snapshot Hub is intentionally simple: a registry.json file in the main repo maps <owner>/<name> to a download URL + SHA-256, and GitHub Releases provides free, unlimited public asset hosting.

Packing a snapshot

forkd pack compresses a local snapshot tag into a single .tar.zst bundle with a TOML manifest that contains per-file SHA-256 digests:
forkd pack --tag pyagent --out pyagent.forkd-snapshot.tar.zst
# ==> packing snapshot 'pyagent' → pyagent.forkd-snapshot.tar.zst
# ✓ wrote 22.1 MiB (512.0 MiB uncompressed; 23.2× compression) in 4.3s
#   next: scp/upload, then `forkd unpack pyagent.forkd-snapshot.tar.zst` on the target host
Typical compression ratio is 23× for Python + numpy snapshots (zstd against mostly-zero guest RAM pages). The coding-agent-fork pack that carries a 50 MiB synthetic binary blob of random bytes compresses to 67.6 MiB — zstd cannot compress random data.

Pack flags

FlagDescription
--tagLocal snapshot tag to pack. Must exist under ~/.local/share/forkd/snapshots/<tag>/.
--outOutput file. Default: ./<sanitized-tag>.forkd-snapshot.tar.zst.
--descriptionHuman-readable description recorded in manifest.toml.
--base-imageUpstream Docker image (e.g. python:3.12-slim). Informational, for audit.

Pack format

v1 packs (single snapshot, pre-v0.5 or flat base):
manifest.toml     # forkd_pack_version=1, per-file sha256 digests
snapshot.json
vmstate
memory.bin
rootfs.ext4       # optional
v2 packs (chained snapshot, v0.5+): forkd pack automatically detects a chain and bundles all ancestor links. See Snapshot Chains for the full format.

Pushing a snapshot

Upload a pack to any S3 or R2 bucket via a presigned PUT URL:
# Generate a presigned PUT URL (AWS CLI)
PRESIGNED_URL=$(aws s3 presign --method PUT s3://your-bucket/pyagent.forkd-snapshot.tar.zst)

# Pack and upload in one step
forkd push --tag pyagent "$PRESIGNED_URL"
# ==> packing snapshot 'pyagent' → /tmp/forkd-push-<pid>-pyagent.tar.zst
#     packed 22.1 MiB (23.2× compression) in 4.3s
# ✓ pushed 22.1 MiB in 2.1s (10.5 MiB/s)
forkd push packs the snapshot to a temp file, uploads via HTTP PUT, and removes the temp file whether the upload succeeds or fails.

Pulling a snapshot

Full URL

forkd pull https://your-bucket.r2.cloudflarestorage.com/pyagent.forkd-snapshot.tar.zst

Short form — public registry

forkd pull deeplethe/python-numpy
# → resolves via https://raw.githubusercontent.com/deeplethe/forkd/main/registry.json
# ✓ downloaded 15.8 MiB
# ✓ sha256 verified (b356ee89...)
# ✓ unpacked tag 'python-numpy' at ~/.local/share/forkd/snapshots/python-numpy/
#   next: forkd fork --tag python-numpy -n <N>
Override the registry URL with --hub <url> or FORKD_HUB_URL for private mirrors:
FORKD_HUB_URL=https://internal.example.com/forkd-registry.json forkd pull myorg/my-snapshot

Version pinning

forkd pull deeplethe/python-numpy@v1   # pin to a specific registry version

The public registry

The public registry is a registry.json file at the root of deeplethe/forkd on GitHub. It maps <owner>/<name> to download URLs hosted on GitHub Releases with the tag scheme hub-<name>-v<N>.

Currently published snapshots

NameDescriptionMemoryPack size
deeplethe/python-numpyPython 3.12 + numpy. Default fork target for README quickstart and bench scripts.1536 MiB15.8 MiB
deeplethe/playwright-browserNode.js + Playwright 1.50 + pre-warmed Chromium. ~56 ms fork vs ~2-3 s cold container.2048 MiB105.5 MiB
deeplethe/postgres-fixturePostgreSQL 16 with initdb done + postmaster pre-launched. ~10 ms fork per test.1024 MiB38.0 MiB
deeplethe/coding-agentPython 3.12 + git + gh CLI + pytest. SWE-bench-style parallel evals.1024 MiB15.2 MiB
deeplethe/nodejsNode.js 22 slim runtime preloaded. Generic JS workload base.512 MiB10.5 MiB
deeplethe/e2b-codeinterpreterE2B code-interpreter image (Python + Node + Jupyter + ML libs). Drop-in for E2B SDK.2048 MiB21.6 MiB
deeplethe/jupyter-kernelJupyter scipy-notebook with IPython + numpy + scipy + pandas + matplotlib pre-imported.2048 MiB15.5 MiB
deeplethe/langgraph-reactReAct agent for the branch-and-fan-out demo (Python 3.12 + requests).513 MiB14.5 MiB

Publishing your own snapshot

1

Build the snapshot locally

# From a Docker image (easiest)
sudo -E forkd from-image python:3.12-slim --tag mything --extra python3-mylib

# Or manual path
sudo -E forkd snapshot --tag mything \
    --kernel ./vmlinux-6.1.141 \
    --rootfs ./mything.ext4 \
    --tap forkd-tap0
2

Pack it

sudo HOME=$HOME forkd pack \
    --tag mything \
    --description "What this is" \
    --base-image python:3.12-slim \
    --out /tmp/mything.forkd-snapshot.tar.zst
3

Get the SHA-256 and size

sha256sum /tmp/mything.forkd-snapshot.tar.zst
wc -c /tmp/mything.forkd-snapshot.tar.zst
4

Create a GitHub Release

gh release create hub-mything-v1 \
    /tmp/mything.forkd-snapshot.tar.zst \
    --target main \
    --title "Hub: yourorg/mything v1" \
    --notes "Python 3.12 + mylib pre-installed."
5

Open a PR to add your entry to registry.json

Add an entry to registry.json in the deeplethe/forkd repo:
{
  "schema_version": 1,
  "packages": {
    "yourorg/mything": {
      "description": "What this is",
      "versions": {
        "latest": {
          "url": "https://github.com/yourorg/forkd-snapshots/releases/download/hub-mything-v1/mything.forkd-snapshot.tar.zst",
          "sha256": "<hex digest from step 3>",
          "size_bytes": 12345678,
          "memory_mib": 512,
          "base_image": "python:3.12-slim",
          "recipe_path": "recipes/mything"
        }
      }
    }
  }
}
Once the PR is merged, forkd pull yourorg/mything works for anyone.

Listing local snapshots

forkd images
  TAG                SIZE        MEMORY     CREATED  ROOTFS
  python-numpy     22.1 MiB   512.0 MiB    3d ago   yes
  playwright-browser  106.2 MiB   2048.0 MiB    1w ago   yes
  pyagent          14.8 MiB   512.0 MiB    1h ago   yes

  3 snapshots · 143.1 MiB total

Security model

Pulling a snapshot and forking from it means running guest kernel + rootfs code under KVM on your host. Trust the publisher to the same degree you would trust a Docker image from that registry — KVM is the isolation boundary, not a stronger one.
  • Integrity — every pack carries per-file SHA-256 digests in manifest.toml. forkd pull verifies the downloaded pack’s SHA-256 against the registry entry before unpacking. forkd unpack verifies every file inside the pack against the manifest digests.
  • Path-traversal protectionmanifest.toml tags are validated against [A-Za-z0-9_][A-Za-z0-9._-]{0,63} before any file is extracted. A malicious bundle declaring tag = "../etc/x" is rejected at manifest-parse time.
  • No signing yet — the SHA-256 in registry.json is integrity, not authenticity. v0.x is single-trust-domain (the deeplethe/forkd repo). v1.0 will add Sigstore / cosign signatures.

Chain packs (v0.5)

When forkd pack is invoked on a chained snapshot (one with parent_tag set in snapshot.json), it automatically produces a v2 pack that bundles every ancestor link:
# Pack the 3-link chain py-base → py-numpy → py-pandas
forkd pack --tag py-pandas --out py-pandas-chain.tar.zst
# ✓ wrote 28.4 MiB (... uncompressed; 19.2× compression)  (3 chain links)
forkd unpack restores all links to their respective snapshot directories and preserves the parent_tag edges so the daemon can walk the chain at spawn time:
forkd unpack py-pandas-chain.tar.zst
# ✓ link 'py-base'   → 'py-base'   at ~/.local/share/forkd/snapshots/py-base/
# ✓ link 'py-numpy'  → 'py-numpy'  at ...  (chain parent: py-base)
# ✓ link 'py-pandas' → 'py-pandas' at ...  (chain parent: py-numpy)
# ✓ unpacked 3 chain link(s), head = 'py-pandas'
#   next: forkd fork --tag py-pandas -n <N>
Each link’s SHA-256 is verified independently against the manifest before it is moved into place.
Hub chain packs include the full base bytes — a 3-link chain with a 1.5 GiB base ships ~1.7 GiB total even though the deltas are only ~100 MB. This is a known limitation of v0.5; v0.6 will add a CAS-layered Hub that deduplicates the base across multiple +delta tags on the server side.

Build docs developers (and LLMs) love