---
title: Snapshots
description: Rust SDK - Snapshot API reference
---

Create and manage disk-only snapshots of stopped sandboxes. See [Snapshots](/sandboxes/snapshots) for usage and lifecycle concepts.

## Snapshot

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">builder()</span>

```rust
fn builder(name: impl Into<String>) -> SnapshotBuilder
```

Start configuring a new snapshot named `name`, resolved under the default snapshots directory (`~/.microsandbox/snapshots/<name>/`) or under [`dest_dir()`](#dest_dir) when set. The source sandbox is set with [`from_sandbox()`](#from_sandbox), which is required; the other setters cover labels and whether to record content integrity before capturing. See [`SnapshotBuilder`](#snapshotbuilder) for all options.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Bare snapshot name. Must not be empty, contain <code>/</code>, or start with <code>.</code>.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#snapshotbuilder">SnapshotBuilder</a></div>
    <div className="msb-param-desc">Builder for configuring the snapshot.</div>
  </div>
</div>

<Accordion title="Example">

```rust
let snap = Snapshot::builder("baseline")
    .from_sandbox("api")
    .create()
    .await?;
```

</Accordion>

---

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">create()</span>

```rust
async fn create(config: SnapshotConfig) -> MicrosandboxResult<Snapshot>
```

Create a snapshot artifact from a stopped sandbox. Writes the `snapshot.json` descriptor and the captured `upper.ext4` into the artifact directory atomically (the descriptor is renamed into place last), then best-effort upserts a row into the local index. Index failures are logged but do not fail the call; the artifact is the source of truth. Most callers use the [builder](#snapshotbuilder)'s [`create()`](#create) instead of constructing a [`SnapshotConfig`](#snapshotconfig) by hand.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>config</code><a className="msb-type" href="#snapshotconfig">SnapshotConfig</a></div>
    <div className="msb-param-desc">Name, source sandbox, labels, and integrity flag.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#instance-methods">Snapshot</a></div>
    <div className="msb-param-desc">The created artifact handle.</div>
  </div>
</div>

<Accordion title="Example">

```rust
let snap = Snapshot::create(
    Snapshot::builder("baseline").from_sandbox("api").build()?
).await?;
```

</Accordion>

---

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">open()</span>

```rust
async fn open(path_or_name: impl AsRef<str>) -> MicrosandboxResult<Snapshot>
```

<Accordion title="Example">

```rust
let snap = Snapshot::open("baseline").await?;
println!("{}", snap.manifest().image.reference);
```

</Accordion>

Open an existing artifact by path or bare name. Bare names (no path separator, not starting with `.` or `~`) resolve under the default snapshots directory; anything else is treated as a path. This is a fast metadata operation: it verifies the manifest structure, recomputes the manifest digest, and checks that the upper file exists with the recorded size. It does **not** read the full upper contents; use [`verify()`](#snap-verify) for that.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>path_or_name</code><span className="msb-type">impl AsRef&lt;str&gt;</span></div>
    <div className="msb-param-desc">Bare snapshot name or filesystem path to an artifact directory.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#instance-methods">Snapshot</a></div>
    <div className="msb-param-desc">The opened artifact handle.</div>
  </div>
</div>

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">get()</span>

```rust
async fn get(name_or_digest: &str) -> MicrosandboxResult<SnapshotHandle>
```

<Accordion title="Example">

```rust
let h = Snapshot::get("after-pip-install").await?;
println!("{} from {}", h.digest(), h.image_ref());
```

</Accordion>

Look up a lightweight [`SnapshotHandle`](#snapshothandle) in the local index by name, digest (`sha256:`/`sha512:` prefix), or path.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name_or_digest</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Snapshot name, manifest digest, or artifact path.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#snapshothandle">SnapshotHandle</a></div>
    <div className="msb-param-desc">Handle backed by the matching index row.</div>
  </div>
</div>

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">list()</span>

```rust
async fn list() -> MicrosandboxResult<Vec<SnapshotHandle>>
```

<Accordion title="Example">

```rust
for h in Snapshot::list().await? {
    println!("{:?} - {}", h.name(), h.digest());
}
```

</Accordion>

List indexed snapshots from the local DB cache, newest first. External-path artifacts booted by full path aren't in the index and won't appear here; use [`list_dir`](#snapshotlist_dir) to enumerate artifacts on disk directly.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#snapshothandle">Vec&lt;SnapshotHandle&gt;</a></div>
    <div className="msb-param-desc">Indexed snapshot handles, ordered by creation time descending.</div>
  </div>
</div>

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">list_dir()</span>

```rust
async fn list_dir(dir: impl AsRef<Path>) -> MicrosandboxResult<Vec<Snapshot>>
```

Walk a directory and parse each subdirectory's manifest. Does not touch the index. Skips entries that don't look like snapshot artifacts (no `snapshot.json`) and malformed artifacts.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>dir</code><span className="msb-type">impl AsRef&lt;Path&gt;</span></div>
    <div className="msb-param-desc">Directory to scan for artifacts.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#instance-methods">Vec&lt;Snapshot&gt;</a></div>
    <div className="msb-param-desc">One handle per valid artifact found.</div>
  </div>
</div>

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">remove()</span>

```rust
async fn remove(path_or_name: &str, force: bool) -> MicrosandboxResult<()>
```

<Accordion title="Example">

```rust
Snapshot::remove("after-pip-install", false).await?;
```

</Accordion>

Remove a snapshot artifact (by digest, name, or path) and its index row. Refuses if the snapshot has indexed children unless `force` is set. The artifact directory is deleted on success and the parent's child count is decremented.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>path_or_name</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Snapshot digest, name, or artifact path.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>force</code><span className="msb-type">bool</span></div>
    <div className="msb-param-desc">When <code>true</code>, remove even if the snapshot has indexed children.</div>
  </div>
</div>

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">reindex()</span>

```rust
async fn reindex(dir: impl AsRef<Path>) -> MicrosandboxResult<usize>
```

<Accordion title="Example">

```rust
let n = Snapshot::reindex("/data/snapshots").await?;
println!("indexed {n} snapshots");
```

</Accordion>

Rebuild the local index from the artifacts in `dir`. Upserts an index row for every artifact found, then recomputes parent-edge child counts in one pass so the cache stays honest about the current set of artifacts.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>dir</code><span className="msb-type">impl AsRef&lt;Path&gt;</span></div>
    <div className="msb-param-desc">Directory of artifacts to index.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">usize</span></div>
    <div className="msb-param-desc">Number of artifacts indexed.</div>
  </div>
</div>

<Accordion title="Example">

```rust
let n = Snapshot::reindex("/data/snapshots").await?;
println!("indexed {n} snapshots");
```

</Accordion>

---

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">save()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn save(name_or_path: &str, out: &Path, opts: SaveOpts) -> MicrosandboxResult<()>
```

Bundle a snapshot into a `.tar.zst` archive (or plain `.tar`) at `out`. Recorded payload integrity is preserved but not executed implicitly; call [`verify()`](#snap-verify) when an independent content scan is part of your workflow. See [`SaveOpts`](#saveopts) to also include ancestors and the OCI image cache.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name_or_path</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Snapshot name or artifact path to save.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>out</code><span className="msb-type">&amp;Path</span></div>
    <div className="msb-param-desc">Output archive path. Parent directories are created if missing.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>opts</code><a className="msb-type" href="#saveopts">SaveOpts</a></div>
    <div className="msb-param-desc">Bundling options. <code>SaveOpts::default()</code> writes the head snapshot only, zstd-compressed.</div>
  </div>
</div>

<Accordion title="Example">

```rust
use microsandbox::snapshot::SaveOpts;
use std::path::Path;

Snapshot::save(
    "baseline",
    Path::new("/tmp/baseline.tar.zst"),
    SaveOpts { with_parents: true, with_image: true, ..Default::default() },
).await?;
```

</Accordion>

---

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">load()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn load(archive_path: &Path, dest: Option<&Path>) -> MicrosandboxResult<SnapshotHandle>
```

<Accordion title="Example">

```rust
use std::path::Path;

let h = Snapshot::load(Path::new("/tmp/baseline.tar.zst"), None).await?;
println!("loaded {}", h.digest());
```

</Accordion>

Unpack a snapshot archive (`.tar.zst` or `.tar`, detected from magic bytes) into the snapshots directory (or `dest`), routing any bundled image-cache entries into the global cache and registering everything found in the index. Structural and archive-entry checks remain mandatory, while recorded payload integrity is preserved for explicit [`verify()`](#snap-verify). Returns a handle for the head snapshot.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>archive_path</code><span className="msb-type">&amp;Path</span></div>
    <div className="msb-param-desc">Archive to unpack.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>dest</code><span className="msb-type">Option&lt;&amp;Path&gt;</span></div>
    <div className="msb-param-desc">Destination directory. <code>None</code> uses the default snapshots directory.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#snapshothandle">SnapshotHandle</a></div>
    <div className="msb-param-desc">Handle for the head (last-listed) snapshot.</div>
  </div>
</div>

<Accordion title="Example">

```rust
use std::path::Path;

let h = Snapshot::load(Path::new("/tmp/baseline.tar.zst"), None).await?;
println!("loaded {}", h.digest());
```

</Accordion>

---

<p className="msb-member-group">Instance methods</p>

Methods on an opened [`Snapshot`](#snapshotopen) artifact.

#### <span className="msb-recv">snap.</span><span className="msb-hn">digest()</span>

```rust
fn digest(&self) -> &str
```

Canonical content digest of this snapshot's manifest (`sha256:hex`). This is the snapshot's identity.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Manifest digest in <code>sha256:hex</code> form.</div>
  </div>
</div>

#### <span className="msb-recv">snap.</span><span className="msb-hn">path()</span>

```rust
fn path(&self) -> &Path
```

Path to the artifact directory holding the canonical `snapshot.json` descriptor and the captured upper file.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">&amp;Path</span></div>
    <div className="msb-param-desc">Artifact directory path.</div>
  </div>
</div>

#### <span className="msb-recv">snap.</span><span className="msb-hn">manifest()</span>

```rust
fn manifest(&self) -> &Manifest
```

<Accordion title="Example">

```rust
let snap = Snapshot::open("baseline").await?;
let m = snap.manifest();
println!("{} @ {}", m.image.reference, m.image.manifest_digest);
```

</Accordion>

The parsed [`Manifest`](#manifest): schema, format, fstype, image reference, parent, creation time, labels, and upper-layer metadata.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#manifest">&amp;Manifest</a></div>
    <div className="msb-param-desc">Parsed snapshot manifest.</div>
  </div>
</div>

#### <span className="msb-recv">snap.</span><span className="msb-hn">size_bytes()</span>

```rust
fn size_bytes(&self) -> u64
```

Apparent size of the captured upper layer in bytes (the ext4 virtual size; sparse on disk).

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">u64</span></div>
    <div className="msb-param-desc">Upper-layer apparent size in bytes.</div>
  </div>
</div>

#### <span className="msb-recv">snap.</span><span className="msb-hn">verify()</span>

```rust
async fn verify(&self) -> MicrosandboxResult<SnapshotVerifyReport>
```

<Accordion title="Example">

```rust
use microsandbox::snapshot::UpperVerifyStatus;

let snap = Snapshot::open("baseline").await?;
match snap.verify().await?.upper {
    UpperVerifyStatus::Verified { algorithm, .. } => println!("ok via {algorithm}"),
    UpperVerifyStatus::NotRecorded => println!("no integrity hash recorded"),
}
```

</Accordion>

Recompute the upper layer's recorded content integrity and compare it against the descriptor. Current BLAKE3 Merkle integrity skips known all-hole subtrees and hashes allocated leaves in batches. Released SHA algorithms retain their exact verifier and may still cost O(logical size). Returns `NotRecorded` without reading payload contents when the descriptor has `integrity: null`; errors with `SnapshotIntegrity` on mismatch.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#snapshotverifyreport">SnapshotVerifyReport</a></div>
    <div className="msb-param-desc">Digest, path, and upper-layer verification status.</div>
  </div>
</div>

## SnapshotHandle

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div>

<p className="msb-backref">Returned by <a href="#snapshotget">Snapshot::get()</a> · <a href="#snapshotlist">Snapshot::list()</a> · <a href="#snapshotload">Snapshot::load()</a></p>

A snapshot handle backed by the local index.

#### <span className="msb-recv">h.</span><span className="msb-hn">digest()</span>

```rust
fn digest(&self) -> &str
```

Manifest digest (`sha256:hex`), the canonical identity.

#### <span className="msb-recv">h.</span><span className="msb-hn">name()</span>

```rust
fn name(&self) -> Option<&str>
```

Name alias, or `None` for digest-only entries.

#### <span className="msb-recv">h.</span><span className="msb-hn">parent_digest()</span>

```rust
fn parent_digest(&self) -> Option<&str>
```

The parent snapshot's digest, or `None` for a root. Always `None` today; populated once chained snapshots land.

---

#### <span className="msb-recv">h.</span><span className="msb-hn">scope()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```rust
fn scope(&self) -> SnapshotScope
```

Snapshot payload scope: [`SnapshotScope::Disk`](#snapshotscope) for a disk-only snapshot, `Resumable` once resumable snapshots land. Always `Disk` today.

---

#### <span className="msb-recv">h.</span><span className="msb-hn">image_ref()</span>

```rust
fn image_ref(&self) -> &str
```

Image reference the snapshot was taken from.

#### <span className="msb-recv">h.</span><span className="msb-hn">format()</span>

```rust
fn format(&self) -> SnapshotFormat
```

On-disk format of the upper layer.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#snapshotformat">SnapshotFormat</a></div>
    <div className="msb-param-desc">Upper-layer format (<code>Raw</code> today).</div>
  </div>
</div>

#### <span className="msb-recv">h.</span><span className="msb-hn">size_bytes()</span>

```rust
fn size_bytes(&self) -> Option<u64>
```

Apparent size of the upper file at index time, if recorded.

#### <span className="msb-recv">h.</span><span className="msb-hn">created_at()</span>

```rust
fn created_at(&self) -> chrono::NaiveDateTime
```

Snapshot creation time, parsed from the manifest.

#### <span className="msb-recv">h.</span><span className="msb-hn">path()</span>

```rust
fn path(&self) -> &Path
```

Local artifact directory path.

#### <span className="msb-recv">h.</span><span className="msb-hn">open()</span>

```rust
async fn open(&self) -> MicrosandboxResult<Snapshot>
```

<Accordion title="Example">

```rust
let h = Snapshot::get("baseline").await?;
let snap = h.open().await?;
snap.verify().await?;
```

</Accordion>

Open the underlying artifact metadata, upgrading this lightweight handle to a full [`Snapshot`](#instance-methods). Equivalent to [`Snapshot::open(self.path())`](#snapshotopen).

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#instance-methods">Snapshot</a></div>
    <div className="msb-param-desc">The opened artifact.</div>
  </div>
</div>

#### <span className="msb-recv">h.</span><span className="msb-hn">remove()</span>

```rust
async fn remove(&self, force: bool) -> MicrosandboxResult<()>
```

<Accordion title="Example">

```rust
let h = Snapshot::get("baseline").await?;
h.remove(false).await?;
```

</Accordion>

Remove this snapshot. Delegates to [`Snapshot::remove(self.digest(), force)`](#snapshotremove).

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>force</code><span className="msb-type">bool</span></div>
    <div className="msb-param-desc">When <code>true</code>, remove even if the snapshot has indexed children.</div>
  </div>
</div>

## SandboxBuilder

Snapshot-related methods that live on the sandbox builder and handle. See [Sandbox](/sdk/rust/sandbox) for the full sandbox API.

#### <span className="msb-recv">sandbox.</span><span className="msb-hn">from_snapshot()</span>

```rust
fn from_snapshot(self, path_or_name: impl Into<String>) -> Self
```

<Accordion title="Example">

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

</Accordion>

`SandboxBuilder` setter. Boot a fresh sandbox from a snapshot artifact. The snapshot already pins the image reference and digest, so this is mutually exclusive with [`image()`](/sdk/rust/sandbox#image) and [`image_with()`](/sdk/rust/sandbox#image_with). The artifact is structurally opened at [`create()`](/sdk/rust/sandbox#create) time; persistent payload integrity is checked only through explicit [`Snapshot::verify()`](#snap-verify).

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>path_or_name</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Bare name resolved under the default snapshots directory, or a path to an artifact directory.</div>
  </div>
</div>

## SandboxHandle

#### <span className="msb-recv">h.</span><span className="msb-hn">snapshot()</span>

```rust
async fn snapshot(&self, name: &str) -> MicrosandboxResult<Snapshot>
```

`SandboxHandle` method. Snapshot this sandbox under a bare name in the default snapshots directory (`~/.microsandbox/snapshots/<name>/`). The sandbox must be stopped or crashed; running sandboxes are rejected with `SnapshotSandboxRunning`. Local handles only. To place the artifact elsewhere, use [`Snapshot::save()`](#snapshotsave) / [`Snapshot::load()`](#snapshotload) or move the self-contained artifact directory.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Bare snapshot name.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#instance-methods">Snapshot</a></div>
    <div className="msb-param-desc">The created artifact handle.</div>
  </div>
</div>

#### <span className="msb-recv">h.</span><span className="msb-hn">snapshot_to()</span>

```rust
async fn snapshot_to(&self, path: impl AsRef<Path>) -> MicrosandboxResult<Snapshot>
```

<Accordion title="Example">

```rust
let h = Sandbox::get("api").await?;
h.stop().await?;
let snap = h.snapshot_to("/data/snapshots/baseline").await?;
```

</Accordion>

---

## SnapshotBuilder

Builder for snapshot configuration.

---

#### <span className="msb-recv">snapshot_builder.</span><span className="msb-hn">from_sandbox()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn from_sandbox(self, source_sandbox: impl Into<String>) -> Self
```

Set the sandbox to capture. Required; [`build()`](#build) and [`create()`](#create) fail without it.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>source_sandbox</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Name of the source sandbox. Must be stopped or crashed, and rooted on an OCI image.</div>
  </div>
</div>

---

#### <span className="msb-recv">snapshot_builder.</span><span className="msb-hn">dest_dir()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn dest_dir(self, dest_dir: impl Into<PathBuf>) -> Self
```

Create the artifact under this parent directory instead of the default snapshots store. The artifact directory is `dest_dir/<name>`; the name stays the snapshot's identity either way.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>dest_dir</code><span className="msb-type">impl Into&lt;PathBuf&gt;</span></div>
    <div className="msb-param-desc">Parent directory to create the artifact in (e.g. a larger volume).</div>
  </div>
</div>

#### <span className="msb-recv">snapshot_builder.</span><span className="msb-hn">label()</span>

```rust
fn label(self, key: impl Into<String>, value: impl Into<String>) -> Self
```

Add a user label. Can be called multiple times. Labels are sorted by key in the manifest's canonical form.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>key</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Label key.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>value</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Label value.</div>
  </div>
</div>

#### <span className="msb-recv">snapshot_builder.</span><span className="msb-hn">force()</span>

```rust
fn force(self) -> Self
```

Overwrite an existing artifact with the same name. Without this, creation fails with `SnapshotAlreadyExists` if the artifact directory exists.

#### <span className="msb-recv">snapshot_builder.</span><span className="msb-hn">record_integrity()</span>

```rust
fn record_integrity(self) -> Self
```

Compute and record sparse-aware BLAKE3 Merkle integrity during creation. [`verify()`](#snap-verify) checks it explicitly; ordinary open, boot, save, load, and upgrade preserve the value without adding an independent payload pass.

---

#### <span className="msb-recv">snapshot_builder.</span><span className="msb-hn">resumable()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

```rust
fn resumable(self) -> Self
```

Request a resumable snapshot (disk plus VM state). Accepted by the builder, but [`create()`](#create) currently fails with `Unsupported`; resumable snapshots have not landed yet.

#### <span className="msb-recv">snapshot_builder.</span><span className="msb-hn">build()</span>

```rust
fn build(self) -> MicrosandboxResult<SnapshotConfig>
```

Materialize the [`SnapshotConfig`](#snapshotconfig) without creating the snapshot. Errors with `InvalidConfig` if [`from_sandbox`](#from_sandbox) was not called. For capturing, use [`create`](#create) instead; it calls `build` internally.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#snapshotconfig">SnapshotConfig</a></div>
    <div className="msb-param-desc">Validated snapshot configuration.</div>
  </div>
</div>

#### <span className="msb-recv">snapshot_builder.</span><span className="msb-hn">create()</span>

```rust
async fn create(self) -> MicrosandboxResult<Snapshot>
```

Build and execute the snapshot in one step. Equivalent to [`Snapshot::create(self.build()?)`](#snapshotcreate).

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#instance-methods">Snapshot</a></div>
    <div className="msb-param-desc">The created artifact handle.</div>
  </div>
</div>

## Types

### SnapshotConfig

<p className="msb-backref">Used by <a href="#snapshotcreate">Snapshot::create()</a> · returned by <a href="#build">build()</a></p>

Inputs to create a snapshot. A type alias for `SnapshotSpec`. Usually built via [`SnapshotBuilder`](#snapshotbuilder) rather than constructed directly.

| Field | Type | Description |
|-------|------|-------------|
| name | `String` | Bare snapshot name; always the artifact directory's basename |
| dest_dir | `Option<PathBuf>` | Parent directory for the artifact; `None` = the default snapshots directory |
| source_sandbox | `String` | Name of the source sandbox; must be stopped |
| labels | `Vec<(String, String)>` | User-supplied labels |
| force | `bool` | Overwrite an existing artifact with the same name |
| record_integrity | `bool` | Compute and record upper-layer integrity at creation |
| resumable | `bool` | Request a resumable snapshot; returns an unsupported-feature error today |

### SnapshotFormat

<p className="msb-backref">Used by <a href="#h-format">format()</a> · <a href="#manifest">Manifest.format</a></p>

On-disk format of the captured upper layer. Today only `Raw` is produced; the variant exists so qcow2 chains drop in later without a schema migration.

| Value | Description |
|-------|-------------|
| `Raw` | Raw ext4 image, sparse on disk |
| `Qcow2` | qcow2 with optional backing chain (future) |

### SnapshotScope

<div className="msb-tags"><span className="msb-tag is-type">enum</span></div>

<p className="msb-backref">Used by <a href="#h-scope">scope()</a> · <a href="#manifest">Manifest.scope</a></p>

Snapshot payload scope. Parsing accepts every known scope so older runtimes can still list and inspect artifacts they cannot restore; create and restore paths enforce support. Re-exported as `microsandbox::snapshot::SnapshotScope`.

| Value | Description |
|-------|-------------|
| `Disk` | Disk-only snapshot; captures the writable filesystem state |
| `Resumable` | Reserved for future memory/device-state capture |

### SaveOpts

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div>

<p className="msb-backref">Used by <a href="#snapshotsave">Snapshot::save()</a></p>

Options for [`Snapshot::save()`](#snapshotsave). Implements `Default`; `SaveOpts::default()` writes the head snapshot only, zstd-compressed.

| Field | Type | Description |
|-------|------|-------------|
| with_parents | `bool` | Walk the parent chain and include each ancestor in the archive |
| with_image | `bool` | Bundle the OCI image artifacts (EROFS layers, fsmeta, VMDK descriptor) from the global cache so the archive boots offline |
| plain_tar | `bool` | Skip zstd compression and write a plain `.tar`. Default: zstd |

### SnapshotVerifyReport

<p className="msb-backref">Returned by <a href="#snap-verify">verify()</a></p>

Result of explicit snapshot verification.

| Field | Type | Description |
|-------|------|-------------|
| digest | `String` | Snapshot manifest digest |
| path | `PathBuf` | Artifact directory |
| upper | [`UpperVerifyStatus`](#upperverifystatus) | Upper-layer content verification result |

### UpperVerifyStatus

<p className="msb-backref">Used by <a href="#snapshotverifyreport">SnapshotVerifyReport.upper</a></p>

Upper-layer content verification result.

| Variant | Fields | Description |
|---------|--------|-------------|
| `NotRecorded` | - | No content integrity descriptor was recorded in the manifest |
| `Verified` | - `algorithm: String` <br/> - `digest: String` | Recorded integrity matched the computed digest |

### Manifest

<p className="msb-backref">Returned by <a href="#snap-manifest">manifest()</a></p>

The snapshot artifact manifest, the source of truth for an artifact, serialized as the `snapshot.json` descriptor (`DESCRIPTOR_FILENAME`). Re-exported as `microsandbox::snapshot::Manifest`. Its SHA-256 digest over the canonical byte form is the snapshot's identity. Field order is load-bearing (it determines the canonical byte layout) and must not be reordered.

| Field | Type | Description |
|-------|------|-------------|
| schema | `u32` | Manifest schema version; readers reject unknown values |
| artifact | `String` | Artifact kind; always `"snapshot"` |
| scope | [`SnapshotScope`](#snapshotscope) | Payload scope; only disk snapshots are created today |
| format | [`SnapshotFormat`](#snapshotformat) | On-disk format of the upper layer |
| fstype | `String` | Filesystem type inside the upper (e.g. `ext4`) |
| image | [`ImageRef`](#imageref) | Image the snapshot was taken from |
| parent | `Option<String>` | Parent snapshot digest, or `None` for a root |
| created_at | `String` | RFC 3339 creation timestamp |
| labels | `BTreeMap<String, String>` | User-supplied labels, sorted by key in canonical form |
| upper | [`UpperLayer`](#upperlayer) | The captured upper layer |
| source_sandbox | `Option<String>` | Best-effort name of the source sandbox (informational) |

### ImageRef

<p className="msb-backref">Used by <a href="#manifest">Manifest.image</a></p>

Reference to the OCI image the snapshot was taken from. Re-exported as `microsandbox::snapshot::ImageRef`.

| Field | Type | Description |
|-------|------|-------------|
| reference | `String` | Human-readable image reference (e.g. `docker.io/library/python:3.12`) |
| manifest_digest | `String` | Digest of the OCI manifest, in `sha256:hex` form |

### UpperLayer

<p className="msb-backref">Used by <a href="#manifest">Manifest.upper</a></p>

Captured upper-layer file metadata. Re-exported as `microsandbox::snapshot::UpperLayer`.

| Field | Type | Description |
|-------|------|-------------|
| file | `String` | Filename inside the artifact directory (e.g. `upper.ext4`) |
| size_bytes | `u64` | Apparent size in bytes (ext4 virtual size; sparse on disk) |
| integrity | `Option<`[`UpperIntegrity`](#upperintegrity)`>` | Optional content integrity descriptor; `None` on local hot paths |

### UpperIntegrity

<p className="msb-backref">Used by <a href="#upperlayer">UpperLayer.integrity</a></p>

Content integrity descriptor for the captured upper layer.

| Field | Type | Description |
|-------|------|-------------|
| Variant | Serialized algorithm | Fields | Purpose |
|---------|----------------------|--------|---------|
| `Sha256` | `sha256` | `digest` | Exact released compatibility |
| `SparseSha256V1` | `msb-sparse-sha256-v1` | `digest` | Exact released sparse-SHA compatibility |
| `FileMerkleBlake3V1` | `msb-file-merkle-blake3-v1` | `root`, `logical_size`, `leaf_size` | Current opt-in sparse-aware integrity |
