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

Capture a stopped sandbox's writable upper layer into a self-describing, content-addressed artifact on disk, then list, verify, export, import, or boot a fresh sandbox from it. See [Snapshots](/sandboxes/snapshots) for concepts and walkthroughs; this page is the Rust SDK reference.

<div className="msb-glance">

  <p className="msb-gl"><span className="msb-dot static"></span>Static · Snapshot<span className="msb-ct">10</span></p>
  <a className="msb-row" href="#snapshotbuilder"><span className="msb-rn">Snapshot::builder()</span><span className="msb-rg">configure a new snapshot</span></a>
  <a className="msb-row" href="#snapshotcreate"><span className="msb-rn">Snapshot::create()</span><span className="msb-rg">create from a config</span></a>
  <a className="msb-row" href="#snapshotopen"><span className="msb-rn">Snapshot::open()</span><span className="msb-rg">open an artifact</span></a>
  <a className="msb-row" href="#snapshotget"><span className="msb-rn">Snapshot::get()</span><span className="msb-rg">handle from the index</span></a>
  <a className="msb-row" href="#snapshotlist"><span className="msb-rn">Snapshot::list()</span><span className="msb-rg">indexed snapshots</span></a>
  <a className="msb-row" href="#snapshotlist_dir"><span className="msb-rn">Snapshot::list_dir()</span><span className="msb-rg">artifacts in a directory</span></a>
  <a className="msb-row" href="#snapshotremove"><span className="msb-rn">Snapshot::remove()</span><span className="msb-rg">delete an artifact</span></a>
  <a className="msb-row" href="#snapshotreindex"><span className="msb-rn">Snapshot::reindex()</span><span className="msb-rg">rebuild the index</span></a>
  <a className="msb-row" href="#snapshotexport"><span className="msb-rn">Snapshot::export()</span><span className="msb-rg">bundle to an archive</span></a>
  <a className="msb-row" href="#snapshotimport"><span className="msb-rn">Snapshot::import()</span><span className="msb-rg">unpack an archive</span></a>

  <p className="msb-gl"><span className="msb-dot instance"></span>Instance · Snapshot<span className="msb-ct">5</span></p>
  <a className="msb-row" href="#snap-digest"><span className="msb-rn">snap.digest()</span><span className="msb-rg">content identity</span></a>
  <a className="msb-row" href="#snap-path"><span className="msb-rn">snap.path()</span><span className="msb-rg">artifact directory</span></a>
  <a className="msb-row" href="#snap-manifest"><span className="msb-rn">snap.manifest()</span><span className="msb-rg">parsed manifest</span></a>
  <a className="msb-row" href="#snap-size_bytes"><span className="msb-rn">snap.size_bytes()</span><span className="msb-rg">upper-layer size</span></a>
  <a className="msb-row" href="#snap-verify"><span className="msb-rn">snap.verify()</span><span className="msb-rg">recheck integrity</span></a>

  <p className="msb-gl"><span className="msb-dot instance"></span>Instance · SnapshotHandle<span className="msb-ct">10</span></p>
  <a className="msb-row" href="#h-digest"><span className="msb-rn">h.digest()</span><span className="msb-rg">manifest digest</span></a>
  <a className="msb-row" href="#h-name"><span className="msb-rn">h.name()</span><span className="msb-rg">name alias</span></a>
  <a className="msb-row" href="#h-parent_digest"><span className="msb-rn">h.parent_digest()</span><span className="msb-rg">parent snapshot</span></a>
  <a className="msb-row" href="#h-image_ref"><span className="msb-rn">h.image_ref()</span><span className="msb-rg">source image</span></a>
  <a className="msb-row" href="#h-format"><span className="msb-rn">h.format()</span><span className="msb-rg">upper format</span></a>
  <a className="msb-row" href="#h-size_bytes"><span className="msb-rn">h.size_bytes()</span><span className="msb-rg">indexed size</span></a>
  <a className="msb-row" href="#h-created_at"><span className="msb-rn">h.created_at()</span><span className="msb-rg">creation time</span></a>
  <a className="msb-row" href="#h-path"><span className="msb-rn">h.path()</span><span className="msb-rg">artifact directory</span></a>
  <a className="msb-row" href="#h-open"><span className="msb-rn">h.open()</span><span className="msb-rg">read the artifact</span></a>
  <a className="msb-row" href="#h-remove"><span className="msb-rn">h.remove()</span><span className="msb-rg">delete this snapshot</span></a>

  <p className="msb-gl"><span className="msb-dot static"></span>Sandbox entry points<span className="msb-ct">3</span></p>
  <a className="msb-row" href="#from_snapshot"><span className="msb-rn">.from_snapshot()</span><span className="msb-rg">boot from a snapshot</span></a>
  <a className="msb-row" href="#h-snapshot"><span className="msb-rn">h.snapshot()</span><span className="msb-rg">snapshot a stopped sandbox</span></a>
  <a className="msb-row" href="#h-snapshot_to"><span className="msb-rn">h.snapshot_to()</span><span className="msb-rg">snapshot to a path</span></a>

  <p className="msb-gl"><span className="msb-dot builder"></span>Builder · SnapshotBuilder<span className="msb-ct">8</span></p>
  <div className="msb-chiprow">
    <a className="msb-chip" href="#destination">.destination()</a>
    <a className="msb-chip" href="#name">.name()</a>
    <a className="msb-chip" href="#path">.path()</a>
    <a className="msb-chip" href="#label">.label()</a>
    <a className="msb-chip" href="#force">.force()</a>
    <a className="msb-chip" href="#record_integrity">.record_integrity()</a>
    <a className="msb-chip" href="#build">.build()</a>
    <a className="msb-chip" href="#create">.create()</a>
  </div>

  <p className="msb-gl"><span className="msb-dot type"></span>Types</p>
  <div className="msb-chiprow">
    <a className="msb-typepill" href="#snapshothandle">SnapshotHandle</a>
    <a className="msb-typepill" href="#snapshotconfig">SnapshotConfig</a>
    <a className="msb-typepill" href="#snapshotdestination">SnapshotDestination</a>
    <a className="msb-typepill" href="#snapshotformat">SnapshotFormat</a>
    <a className="msb-typepill" href="#exportopts">ExportOpts</a>
    <a className="msb-typepill" href="#snapshotverifyreport">SnapshotVerifyReport</a>
    <a className="msb-typepill" href="#upperverifystatus">UpperVerifyStatus</a>
    <a className="msb-typepill" href="#manifest">Manifest</a>
    <a className="msb-typepill" href="#imageref">ImageRef</a>
    <a className="msb-typepill" href="#upperlayer">UpperLayer</a>
    <a className="msb-typepill" href="#upperintegrity">UpperIntegrity</a>
  </div>

</div>

<Note>
  Snapshots are **local-only** and **disk-only** today: they capture a sandbox that is stopped or crashed, and every operation runs against the default local backend. Cloud snapshots and qcow2 backing chains are deferred.
</Note>

<p className="msb-label" id="typical-flow">Typical flow</p>

```rust
use microsandbox::{Sandbox, Snapshot};

// 1. stop the sandbox you want to capture
let sb = Sandbox::get("api").await?;
sb.stop().await?;

// 2. capture its writable upper layer
let snap = Snapshot::builder("api")
    .name("after-pip-install")     // bare name in the default dir
    .record_integrity()            // hash the upper layer
    .create()
    .await?;
println!("{} ({} bytes)", snap.digest(), snap.size_bytes());

// 3. boot a fresh sandbox from it
let restored = Sandbox::builder("api-restored")
    .from_snapshot("after-pip-install")
    .create()
    .await?;
```

## Static methods

---

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

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

Start configuring a new snapshot of `source_sandbox`. The builder lets you set the destination, 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>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>

<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("api")
    .name("baseline")
    .create()
    .await?;
```

</Accordion>

---

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">create()</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 create(config: SnapshotConfig) -> MicrosandboxResult<Snapshot>
```

Create a snapshot artifact from a stopped sandbox. Writes `manifest.json` and the captured `upper.ext4` into the destination directory atomically (the manifest 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">Source sandbox, destination, 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("api").name("baseline").build()?
).await?;
```

</Accordion>

---

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">open()</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 open(path_or_name: impl AsRef<str>) -> MicrosandboxResult<Snapshot>
```

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>

<Accordion title="Example">

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

</Accordion>

---

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">get()</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 get(name_or_digest: &str) -> MicrosandboxResult<SnapshotHandle>
```

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>

<Accordion title="Example">

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

</Accordion>

---

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">list()</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 list() -> MicrosandboxResult<Vec<SnapshotHandle>>
```

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>

<Accordion title="Example">

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

</Accordion>

---

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">list_dir()</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 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 `manifest.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>

<Accordion title="Example">

```rust
let snaps = Snapshot::list_dir("/data/snapshots").await?;
println!("{} artifacts", snaps.len());
```

</Accordion>

---

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">remove()</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 remove(path_or_name: &str, force: bool) -> MicrosandboxResult<()>
```

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>

<Accordion title="Example">

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

</Accordion>

---

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">reindex()</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 reindex(dir: impl AsRef<Path>) -> MicrosandboxResult<usize>
```

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">export()</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 export(name_or_path: &str, out: &Path, opts: ExportOpts) -> MicrosandboxResult<()>
```

Bundle a snapshot into a `.tar.zst` archive (or plain `.tar`) at `out`. The head snapshot is verified before bundling. The recorded manifest is archived as-is, so create the snapshot with [`record_integrity()`](#record_integrity) when the archive will cross a trust boundary. See [`ExportOpts`](#exportopts) 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 export.</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="#exportopts">ExportOpts</a></div>
    <div className="msb-param-desc">Bundling options. <code>ExportOpts::default()</code> writes the head snapshot only, zstd-compressed.</div>
  </div>
</div>

<Accordion title="Example">

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

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

</Accordion>

---

#### <span className="msb-recv">Snapshot::</span><span className="msb-hn">import()</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 import(archive_path: &Path, dest: Option<&Path>) -> MicrosandboxResult<SnapshotHandle>
```

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. Recorded integrity is verified as artifacts land. 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::import(Path::new("/tmp/baseline.tar.zst"), None).await?;
println!("imported {}", h.digest());
```

</Accordion>

---

## Instance methods

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

---

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

```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>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

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

Path to the artifact directory holding the canonical `manifest.json` 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>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

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

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>

<Accordion title="Example">

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

</Accordion>

---

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

```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>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

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

Recompute the upper layer's content hash and compare it against the manifest. Walks data extents only, so a multi-GiB sparse file with a little data verifies in milliseconds. Returns `NotRecorded` when the manifest has no integrity descriptor; 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>

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

---

## SnapshotHandle methods

Accessors and lifecycle on a [`SnapshotHandle`](#snapshothandle) (an index row). Returned by [`Snapshot::get()`](#snapshotget), [`Snapshot::list()`](#snapshotlist), and [`Snapshot::import()`](#snapshotimport).

---

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

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

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

---

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

```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>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```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">image_ref()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```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>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```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>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```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>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```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>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

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

Local artifact directory path.

---

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

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

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>

<Accordion title="Example">

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

</Accordion>

---

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

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

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>

<Accordion title="Example">

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

</Accordion>

---

## Sandbox entry points

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">.</span><span className="msb-hn">from_snapshot()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

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

`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 opened and its integrity verified at [`create()`](/sdk/rust/sandbox#create) time, not here.

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

<Accordion title="Example">

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

</Accordion>

---

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

```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. For an explicit destination see [`snapshot_to()`](#h-snapshot_to).

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

<Accordion title="Example">

```rust
let h = Sandbox::get("api").await?;
h.stop().await?;
let snap = h.snapshot("baseline").await?;
```

</Accordion>

---

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

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

`SandboxHandle` method. Snapshot this sandbox to an explicit filesystem path. The sandbox must be stopped or crashed. Local handles only. For the common case of writing under the default snapshots directory see [`snapshot()`](#h-snapshot).

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>path</code><span className="msb-type">impl AsRef&lt;Path&gt;</span></div>
    <div className="msb-param-desc">Destination 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 created artifact handle.</div>
  </div>
</div>

<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 a [`SnapshotConfig`](#snapshotconfig). Obtained via [`Snapshot::builder(source_sandbox)`](#snapshotbuilder). A destination is required ([`name`](#name) or [`path`](#path)); the other setters are optional. Every setter returns `Self`, so calls chain.

```rust
let snap = Snapshot::builder("api")
    .name("after-pip-install")     // bare name in default dir
    .label("stage", "post-deps")
    .force()                       // overwrite if it exists
    .record_integrity()            // hash the upper layer
    .create()
    .await?;
```

---

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

```rust
fn destination(self, dest: SnapshotDestination) -> Self
```

Set the artifact destination explicitly. The [`name`](#name) and [`path`](#path) setters are convenience wrappers over this.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>dest</code><a className="msb-type" href="#snapshotdestination">SnapshotDestination</a></div>
    <div className="msb-param-desc">Name- or path-based destination.</div>
  </div>
</div>

---

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

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

Convenience: use a bare name resolved under the default snapshots directory. Sets the destination to [`SnapshotDestination::Name`](#snapshotdestination).

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

---

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

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

Convenience: write the artifact to an explicit path. Sets the destination to [`SnapshotDestination::Path`](#snapshotdestination).

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>path</code><span className="msb-type">impl Into&lt;PathBuf&gt;</span></div>
    <div className="msb-param-desc">Destination artifact directory.</div>
  </div>
</div>

---

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

```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">.</span><span className="msb-hn">force()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>

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

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

---

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

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

Compute and record an upper-layer content-integrity hash during creation. Recorded integrity is what [`verify()`](#snap-verify) checks and what import/export rely on when crossing a trust boundary.

---

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

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

Materialize the [`SnapshotConfig`](#snapshotconfig) without creating the snapshot. Errors with `InvalidConfig` if no destination was set. 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">.</span><span className="msb-hn">create()</span>
<div className="msb-tags"><span className="msb-tag is-builder">builder</span><span className="msb-tag is-async">async</span></div>

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

### 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="#snapshotimport">Snapshot::import()</a></p>

A lightweight handle backed by a local index row. Use [`open()`](#h-open) to read the artifact metadata, and [`Snapshot::verify()`](#snap-verify) for explicit content verification. All accessors are listed under [SnapshotHandle methods](#snapshothandle-methods).

| Method | Type | Description |
|--------|------|-------------|
| digest() | `&str` | Manifest digest (`sha256:hex`) |
| name() | `Option<&str>` | Name alias; `None` for digest-only entries |
| parent_digest() | `Option<&str>` | Parent snapshot digest, or `None` for a root |
| image_ref() | `&str` | Source image reference |
| format() | [`SnapshotFormat`](#snapshotformat) | On-disk upper format |
| size_bytes() | `Option<u64>` | Upper file size at index time |
| created_at() | `chrono::NaiveDateTime` | Creation time from the manifest |
| path() | `&Path` | Local artifact directory |
| open() | `Result<`[`Snapshot`](#instance-methods)`>` | Open the underlying artifact |
| remove(force) | `Result<()>` | Remove this snapshot |

### SnapshotConfig

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

<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 |
|-------|------|-------------|
| source_sandbox | `String` | Name of the source sandbox; must be stopped |
| destination | [`SnapshotDestination`](#snapshotdestination) | Where to write the artifact |
| labels | `Vec<(String, String)>` | User-supplied labels |
| force | `bool` | Overwrite an existing artifact at the destination |
| record_integrity | `bool` | Compute and record upper-layer integrity at creation |

### SnapshotDestination

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

<p className="msb-backref">Used by <a href="#destination">destination()</a> · <a href="#snapshotconfig">SnapshotConfig.destination</a></p>

Where to place a new snapshot artifact. The builder's [`name()`](#name) and [`path()`](#path), and the handle's [`snapshot()`](#h-snapshot) / [`snapshot_to()`](#h-snapshot_to), construct this enum internally so callers rarely import it.

| Variant | Fields | Description |
|---------|--------|-------------|
| `Name` | `String` | Bare name resolved under the default snapshots directory |
| `Path` | `PathBuf` | Explicit absolute or relative path to the artifact directory |

### SnapshotFormat

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

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

### ExportOpts

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

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

Options for [`Snapshot::export()`](#snapshotexport). Implements `Default`; `ExportOpts::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

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

<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

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

<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

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

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

The snapshot artifact manifest, the source of truth for an artifact. 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 |
| 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

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

<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

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

<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

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

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

Content integrity descriptor for the captured upper layer.

| Field | Type | Description |
|-------|------|-------------|
| algorithm | `String` | Digest algorithm name (e.g. `msb-sparse-sha256-v1`) |
| digest | `String` | Algorithm output, in `sha256:hex` form for current algorithms |
