> ## Documentation Index
> Fetch the complete documentation index at: https://microsanbox-staging-toks-cloud-snapshot-contracts.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Snapshots

> Capture a sandbox's writable layer as a portable artifact

A snapshot captures a sandbox's writable filesystem. The local backend stores a
portable on-disk artifact; microsandbox cloud stores it in managed object
storage by default, or in a directory on the organization's host volume when a
destination is supplied.

<Note>
  Snapshots are **disk-only** and require a sandbox that is not running. Stopped and crashed sandboxes can be snapshotted; running, draining, and paused sandboxes are rejected.
</Note>

<Note>
  Snapshot objects now expose a backend-neutral `reference` (and reference kind)
  instead of a host `path` or storage `location`. When upgrading, pass the
  snapshot object directly where supported, or pass its reference to the restore
  API. This keeps the same application code valid for local and cloud backends.
</Note>

## What gets captured

| Captured                           | Not captured      |
| ---------------------------------- | ----------------- |
| Writable filesystem changes        | Memory contents   |
| Pinned image identity              | Running processes |
| Optional labels and integrity hash | Network state     |

Booting from a snapshot is a cold boot of a fresh VM that starts from the captured filesystem changes.

## Quick start

You'll usually reach for the CLI first:

```bash theme={null}
# 1. Boot a sandbox, install state, then stop it
msb run --name baseline --detach python:3.12
msb exec baseline -- pip install requests
msb stop baseline

# 2. Snapshot the stopped sandbox
msb snapshot create after-pip-install --from baseline

# 3. Boot a fresh sandbox from the snapshot
msb run --name worker --from-snapshot after-pip-install \
    -- python -c "import requests; print(requests.__version__)"
```

<Tip>
  On the local backend, the snapshot lives at
  `~/.microsandbox/snapshots/after-pip-install/`. In cloud, omitting a destination
  creates a managed snapshot and returns its stable snapshot reference.
</Tip>

## Snapshot a sandbox

Snapshot under a bare name. Locally, it resolves to
`~/.microsandbox/snapshots/<name>/`. In cloud, it is uploaded to managed storage
and recorded by the control plane. Passing a destination stores an artifact at
`DIR/<name>` locally or at the corresponding path on the organization's host
volume in cloud.

<CodeGroup>
  ```rust Rust theme={null}
  use microsandbox::Sandbox;

  let h = Sandbox::get("baseline").await?;

  // Local: default store. Cloud: managed snapshot storage.
  let snap = h.snapshot("after-pip-install").await?;

  println!("{}", snap.digest()); // sha256:...
  ```

  ```typescript TypeScript theme={null}
  import { Sandbox } from "microsandbox";

  const h = await Sandbox.get("baseline");

  // Local: default store. Cloud: managed snapshot storage.
  const snap = await h.snapshot("after-pip-install");

  console.log(snap.digest); // sha256:...
  ```

  ```python Python theme={null}
  from microsandbox import Sandbox

  h = await Sandbox.get("baseline")

  # Local: default store. Cloud: managed snapshot storage.
  snap = await h.snapshot("after-pip-install")

  print(snap.digest)  # sha256:...
  ```

  ```go Go theme={null}
  h, err := m.GetSandbox(ctx, "baseline")
  if err != nil {
      return err
  }

  // Local: default store. Cloud: managed snapshot storage.
  snap, err := h.Snapshot(ctx, "after-pip-install")

  fmt.Println(snap.Digest()) // sha256:...
  ```

  ```bash CLI theme={null}
  msb snapshot create after-pip-install --from baseline
  msb snapshot create after-pip-install --from baseline --label stage=ready

  # Create the artifact on another volume: lands at /mnt/big/after-pip-install
  msb snapshot create after-pip-install --from baseline --dest-dir /mnt/big
  ```
</CodeGroup>

The sandbox must be stopped or crashed; running sandboxes are rejected.

## Boot from a snapshot

A snapshot already pins its image, so booting from one is mutually exclusive with the image source:

<CodeGroup>
  ```rust Rust theme={null}
  use microsandbox::Sandbox;

  let sb = Sandbox::builder("worker")
      .from_snapshot("after-pip-install")
      .create()
      .await?;
  ```

  ```typescript TypeScript theme={null}
  import { Sandbox } from "microsandbox";

  const sb = await Sandbox.builder("worker")
      .fromSnapshot("after-pip-install")
      .create();
  ```

  ```python Python theme={null}
  from microsandbox import Sandbox

  # `from_snapshot=` is a peer of `image=` and mutually exclusive with it
  sb = await Sandbox.create("worker", from_snapshot="after-pip-install")
  ```

  ```go Go theme={null}
  sb, err := m.CreateSandbox(ctx, "worker",
      m.WithFromSnapshot("after-pip-install"),
  )
  ```

  ```bash CLI theme={null}
  msb run --name worker --from-snapshot after-pip-install -- python -V
  ```
</CodeGroup>

Booting validates the snapshot, resolves the pinned image, and gives the new
sandbox its own writable copy. When you already have a `Snapshot` or
`SnapshotHandle`, pass its stable reference rather than its local path. The
Python, TypeScript, and Go accept the snapshot object directly.

## List, inspect, and remove

<CodeGroup>
  ```rust Rust theme={null}
  use microsandbox::Snapshot;

  let all = Snapshot::list().await?; // Indexed snapshots
  let h = Snapshot::get("after-pip-install").await?; // By name, digest, or path
  println!("{} ({})", h.name().unwrap_or("-"), h.digest());

  Snapshot::remove("after-pip-install", false).await?;
  Snapshot::reindex("/data/snapshots").await?;
  ```

  ```typescript TypeScript theme={null}
  import { Snapshot } from "microsandbox";

  const all = await Snapshot.list();                       // Indexed snapshots
  const h = await Snapshot.get("after-pip-install");       // By name, digest, or path
  console.log(`${h.name ?? "-"} (${h.digest})`);

  await Snapshot.remove("after-pip-install");
  await Snapshot.reindex();                               // Default snapshots directory
  ```

  ```python Python theme={null}
  from microsandbox import Snapshot

  all = await Snapshot.list()                              # Indexed snapshots
  h = await Snapshot.get("after-pip-install")              # By name, digest, or path
  print(f"{h.name or '-'} ({h.digest})")

  await Snapshot.remove("after-pip-install")
  await Snapshot.reindex()                                 # Default snapshots directory
  ```

  ```go Go theme={null}
  all, err := m.Snapshot.List(ctx)            // Indexed snapshots
  fmt.Printf("%d snapshots\n", len(all))
  h, err := m.Snapshot.Get(ctx, "after-pip-install") // By name, digest, or path
  name := "-"
  if h.Name() != nil {
      name = *h.Name()
  }
  fmt.Printf("%s (%s)\n", name, h.Digest())

  err = m.Snapshot.Remove(ctx, "after-pip-install", false)
  _, err = m.Snapshot.Reindex(ctx, "/data/snapshots")
  ```

  ```bash CLI theme={null}
  msb snapshots                  # Also: msb snaps, msb snapshot ls
  msb snapshot inspect after-pip-install
  msb snapshot rm after-pip-install

  # Also if it has indexed children
  msb snapshot rm after-pip-install --force

  # Rebuild the index from artifacts on disk
  msb snapshot reindex
  ```
</CodeGroup>

`list` and `get` use the active backend. `reindex`, `list_dir`, `save`, `load`,
direct artifact-file operations, and full payload verification keep the same
SDK surface on every backend but currently return a typed `Unsupported` error
in cloud. Snapshot path references themselves are supported in cloud and are
resolved relative to the organization's host volume.

## Move local snapshots between machines

The snapshot directory is the whole artifact; there is no hidden daemon state. Copy the directory directly, or save it as an archive:

```bash theme={null}
# Copy the directory directly with scp (image must be cached or pullable on the target)
scp -r ~/.microsandbox/snapshots/after-pip-install \
    other-host:~/.microsandbox/snapshots/

# Bundle into a .tar.zst, transport, then load
msb snapshot save after-pip-install /tmp/snap.tar.zst
scp /tmp/snap.tar.zst other-host:
ssh other-host msb snapshot load /tmp/snap.tar.zst

# Fully offline: include the OCI image cache so the target needs no network
msb snapshot save after-pip-install /tmp/snap.tar.zst --with-image
ssh other-host msb snapshot load /tmp/snap.tar.zst
```

Archives default to `.tar.zst`. Pass `--plain-tar` for a plain `.tar`. SDKs expose the same save and load operations as the CLI.

## Integrity verification

By default, snapshot creation records structural metadata without hashing the writable layer. Opt in when you need a persistent content check. Current snapshots use a fixed 64 KiB-leaf BLAKE3 Merkle tree: known sparse holes collapse into precomputed zero subtrees, while allocated bytes are read and hashed.

<CodeGroup>
  ```rust Rust theme={null}
  use microsandbox::Snapshot;

  // Compute and record an integrity hash at create time
  let snap = Snapshot::builder("after-pip-install")
      .from_sandbox("baseline")
      .record_integrity()
      .create()
      .await?;

  // Verify a snapshot's recorded integrity on demand
  let report = snap.verify().await?;

  ```

  ```typescript TypeScript theme={null}
  import { Snapshot } from "microsandbox";

  // Compute and record an integrity hash at create time
  const snap = await Snapshot.builder("after-pip-install")
    .fromSandbox("baseline")
    .recordIntegrity()
    .create();

  // Verify a snapshot's recorded integrity on demand
  const report = await snap.verify();
  ```

  ```python Python theme={null}
  from microsandbox import Snapshot

  # Compute and record an integrity hash at create time
  snap = await Snapshot.create(
      "after-pip-install",
      from_sandbox="baseline",
      record_integrity=True,
  )

  # Verify a snapshot's recorded integrity on demand
  report = await snap.verify()
  ```

  ```go Go theme={null}
  // Compute and record an integrity hash at create time
  snap, err := m.Snapshot.Create(ctx,
      m.SnapshotCreateOptions{
          Name:            "after-pip-install",
          FromSandbox:     "baseline",
          RecordIntegrity: true,
      },
  )

  // Verify a snapshot's recorded integrity on demand
  report, err := snap.Verify(ctx)
  ```

  ```bash CLI theme={null}
  # Compute and record an integrity hash at create time
  msb snapshot create after-pip-install --from baseline --integrity

  # Verify a snapshot's recorded integrity on demand
  msb snapshot verify after-pip-install
  msb snapshot inspect after-pip-install --verify
  ```
</CodeGroup>

`msb snapshot save` and `msb snapshot load` preserve recorded integrity but do not silently execute it. They still enforce the archive grammar, path confinement, entry sizes, descriptor identities, and ordinary archive-entry hashes. Run `msb snapshot verify` explicitly after receiving a snapshot when your workflow requires an independent payload scan. Released `msb-sparse-sha256-v1` descriptors remain readable and verifiable, but ordinary open, boot, save, load, and upgrade paths do not pay their full logical-size SHA cost.

## Use cases

* **Reusable build state.** Install dependencies once, snapshot, then `msb run --from-snapshot ...` repeatedly without paying the install cost. Common pattern for CI, agent workloads, and reproducible dev environments.
* **Portable scratch state.** Capture a sandbox after a long setup, hand the artifact to a teammate or push it to shared storage, and let them boot from the same starting point.
* **Local fork-by-copy.** Multiple sandboxes from one snapshot are independent; each copy of the upper layer diverges on its own.
* **Disaster recovery.** Snapshot a sandbox before a risky migration; if it goes wrong, `msb rm` the broken one and `msb run --from-snapshot` from the pre-migration artifact.
