> ## Documentation Index
> Fetch the complete documentation index at: https://docs.microsandbox.dev/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 is a portable, on-disk capture of a sandbox's writable filesystem. Move it with `scp`, archive it as `.tar.zst`, or boot fresh sandboxes from it.

<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>

## 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 --snapshot after-pip-install \
    -- python -c "import requests; print(requests.__version__)"
```

<Tip>
  By default, the snapshot lives at `~/.microsandbox/snapshots/after-pip-install/`. That whole directory is the snapshot.
</Tip>

## Snapshot a sandbox

Snapshot under a bare name (resolved to `~/.microsandbox/snapshots/<name>/`) or to an explicit path:

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

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

  // Bare name resolves under ~/.microsandbox/snapshots/<name>/
  let snap = h.snapshot("after-pip-install").await?;

  // Or write to an explicit path
  let snap = h.snapshot_to("/tmp/snaps/v1").await?;

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

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

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

  // Bare name resolves under ~/.microsandbox/snapshots/<name>/
  const snap = await h.snapshot("after-pip-install");

  // Or write to an explicit path
  const snap2 = await h.snapshotTo("/tmp/snaps/v1");

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

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

  h = await Sandbox.get("baseline")

  # Bare name resolves under ~/.microsandbox/snapshots/<name>/
  snap = await h.snapshot("after-pip-install")

  # Or write to an explicit path
  snap2 = await h.snapshot_to("/tmp/snaps/v1")

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

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

  // Bare name resolves under ~/.microsandbox/snapshots/<name>/
  snap, err := h.Snapshot(ctx, "after-pip-install")

  // Or write to an explicit path
  snap2, err := h.SnapshotTo(ctx, "/tmp/snaps/v1")

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

  ```bash CLI theme={null}
  msb snapshot create after-pip-install --from baseline
  msb snapshot create ./snaps/v1     --from baseline   # Explicit path
  msb snapshot create after-pip-install --from baseline --label stage=ready
  ```
</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

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

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

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

Booting validates the snapshot, resolves the pinned image, and gives the new sandbox its own writable copy.

## 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("~/.microsandbox/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("~/.microsandbox/snapshots");
  ```

  ```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("~/.microsandbox/snapshots")
  ```

  ```go Go theme={null}
  all, err := m.Snapshot.List(ctx)            // Indexed snapshots
  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, "~/.microsandbox/snapshots")
  ```

  ```bash CLI theme={null}
  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 a local index for fast lookup. If the index gets out of sync, `reindex` rebuilds it from the snapshot artifacts on disk.

## Move snapshots between machines

The snapshot directory is the whole artifact; there is no hidden daemon state. Copy the directory directly, or export 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 import
msb snapshot export after-pip-install /tmp/snap.tar.zst
scp /tmp/snap.tar.zst other-host:
ssh other-host msb snapshot import /tmp/snap.tar.zst

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

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

## Integrity verification

By default, snapshot creation records enough metadata to validate the artifact without hashing the full writable layer. Opt in to a content-integrity hash when crossing a trust boundary:

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

  // Compute and record an integrity hash at create time
  let snap = Snapshot::builder("baseline")
      .name("after-pip-install")
      .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("baseline")
    .name("after-pip-install")
    .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(
      "baseline",
      name="after-pip-install",
      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, "baseline",
      m.SnapshotCreateOptions{
          Name:            "after-pip-install",
          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 export` bundles the snapshot as it exists on disk. `msb snapshot import` verifies recorded integrity when the archive includes it, so create snapshots with `--integrity` before exporting across a trust boundary.

## Use cases

* **Reusable build state.** Install dependencies once, snapshot, then `msb run --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 --snapshot` from the pre-migration artifact.
