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

> Python SDK - Snapshot API reference

Capture the disk state of a stopped sandbox as a reusable artifact, then boot fresh sandboxes from it. Snapshots are disk-only and require a sandbox that is not running. See [Snapshots](/sandboxes/snapshots) for concepts and walkthroughs.

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

```python theme={null}
from microsandbox import Sandbox, Snapshot

# Run setup work, then stop the sandbox
async with await Sandbox.create("baseline", image="python:3.12") as sb:
    await sb.exec("pip", ["install", "numpy"])
    await sb.stop()

# Capture its disk state under a name
snap = await Snapshot.create("baseline", name="after-pip-install")
print(snap.digest)

# Boot a fresh sandbox from the artifact
sb2 = await Sandbox.create("worker", snapshot="after-pip-install")
```

## Take a snapshot

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

```python theme={null}
async def snapshot(self, name: str) -> Snapshot
```

<Accordion title="Example">
  ```python theme={null}
  handle = await Sandbox.get("baseline")
  snap = await handle.snapshot("after-pip-install")
  print(snap.digest)
  ```
</Accordion>

Snapshot this sandbox under a bare name in the default snapshots directory (`~/.microsandbox/snapshots/<name>/`). The sandbox must be stopped or crashed. For an explicit filesystem destination, see [`snapshot_to()`](#handle-snapshot_to). Called on a [`SandboxHandle`](/sdk/python/sandbox#sandboxhandle), obtained from [`Sandbox.get()`](/sdk/python/sandbox#sandbox-get).

<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">str</span></div>
    <div className="msb-param-desc">Snapshot name; resolved under 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="#snapshot">Snapshot</a></div>
    <div className="msb-param-desc">The captured snapshot.</div>
  </div>
</div>

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

```python theme={null}
async def snapshot_to(self, path: str | os.PathLike) -> Snapshot
```

<Accordion title="Example">
  ```python theme={null}
  handle = await Sandbox.get("baseline")
  snap = await handle.snapshot_to("/data/snapshots/baseline")
  ```
</Accordion>

Snapshot this sandbox to an explicit filesystem path. The sandbox must be stopped or crashed.

<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">str | os.PathLike</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="#snapshot">Snapshot</a></div>
    <div className="msb-param-desc">The captured snapshot.</div>
  </div>
</div>

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

```python theme={null}
@staticmethod
async def create(
    source_sandbox: str,
    *,
    name: str | None = None,
    path: str | os.PathLike | None = None,
    labels: dict[str, str] | None = None,
    force: bool = False,
    record_integrity: bool = False,
) -> Snapshot
```

<Accordion title="Example">
  ```python theme={null}
  snap = await Snapshot.create(
      "baseline",
      name="after-pip-install",
      labels={"stage": "post-deps"},
      record_integrity=True,
  )
  ```
</Accordion>

Create a snapshot from a stopped or crashed sandbox. Exactly one of `name=` (resolved under the default snapshots directory) or `path=` (explicit filesystem destination) is required.

<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">str</span></div>
    <div className="msb-param-desc">Name of the stopped or crashed sandbox to capture.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>name</code><span className="msb-type">str | None</span></div>
    <div className="msb-param-desc">Snapshot name under the default snapshots directory. Mutually exclusive with <code>path</code>.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>path</code><span className="msb-type">str | os.PathLike | None</span></div>
    <div className="msb-param-desc">Explicit destination directory. Mutually exclusive with <code>name</code>.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>labels</code><span className="msb-type">dict\[str, str] | None</span></div>
    <div className="msb-param-desc">User-supplied labels stored in the manifest.</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">Overwrite an existing destination. Default <code>False</code>.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>record\_integrity</code><span className="msb-type">bool</span></div>
    <div className="msb-param-desc">Record an integrity hash in the manifest so the artifact can be verified later. Default <code>False</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="#snapshot">Snapshot</a></div>
    <div className="msb-param-desc">The captured snapshot.</div>
  </div>
</div>

## Boot from a snapshot

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

```python theme={null}
@staticmethod
async def create(name: str, *, snapshot: str | os.PathLike | None = None, **kwargs) -> Sandbox
```

<Accordion title="Example">
  ```python theme={null}
  # Boot from a snapshot
  sb = await Sandbox.create("worker", snapshot="after-pip-install")

  # Or from an image (existing flow, unchanged)
  sb = await Sandbox.create("worker", image="python:3.12")
  ```
</Accordion>

Boot a fresh sandbox from a snapshot artifact by passing `snapshot=` as a peer of `image=`. The two are mutually exclusive: pass exactly one. See [`Sandbox.create()`](/sdk/python/sandbox#sandbox-create) for the full set of configuration kwargs.

<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">str</span></div>
    <div className="msb-param-desc">Sandbox name, up to 128 UTF-8 bytes.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>snapshot</code><span className="msb-type">str | os.PathLike | None</span></div>
    <div className="msb-param-desc">Snapshot bare name or artifact path to boot from instead of <code>image=</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="/sdk/python/sandbox#instance-methods">Sandbox</a></div>
    <div className="msb-param-desc">Running sandbox.</div>
  </div>
</div>

## Manage artifacts

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

```python theme={null}
@staticmethod
async def open(path_or_name: str) -> Snapshot
```

<Accordion title="Example">
  ```python theme={null}
  snap = await Snapshot.open("after-pip-install")
  print(snap.image_ref)
  ```
</Accordion>

Open an existing artifact by bare name (resolved under the default snapshots directory) or path. Cheap metadata validation only; does **not** read the upper file. Use [`verify()`](#snap-verify) for content checks.

<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">str</span></div>
    <div className="msb-param-desc">Bare snapshot name or artifact directory 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="#snapshot">Snapshot</a></div>
    <div className="msb-param-desc">The opened snapshot.</div>
  </div>
</div>

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

```python theme={null}
@staticmethod
async def get(name_or_digest: str) -> SnapshotHandle
```

<Accordion title="Example">
  ```python theme={null}
  h = await Snapshot.get("after-pip-install")
  print(h.digest)
  ```
</Accordion>

Look up a handle in the local index by name, digest, 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">str</span></div>
    <div className="msb-param-desc">Snapshot name, digest, or 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">Lightweight handle backed by an index row.</div>
  </div>
</div>

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

```python theme={null}
@staticmethod
async def list() -> list[SnapshotHandle]
```

<Accordion title="Example">
  ```python theme={null}
  for h in await Snapshot.list():
      print(h.name, h.digest)
  ```
</Accordion>

List indexed snapshots from the local DB cache.

<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">list\[SnapshotHandle]</a></div>
    <div className="msb-param-desc">Indexed snapshot handles.</div>
  </div>
</div>

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

```python theme={null}
@staticmethod
async def list_dir(dir: str | os.PathLike) -> list[Snapshot]
```

<Accordion title="Example">
  ```python theme={null}
  for snap in await Snapshot.list_dir("/mnt/artifacts"):
      print(snap.path, snap.digest)
  ```
</Accordion>

Walk a directory and parse each subdirectory's manifest. Does not touch the index, useful for inspecting external snapshot collections (e.g. a mounted volume of artifacts that were never imported). Skips entries that don't look like snapshot 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">str | os.PathLike</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="#snapshot">list\[Snapshot]</a></div>
    <div className="msb-param-desc">One snapshot per valid artifact directory.</div>
  </div>
</div>

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

```python theme={null}
@staticmethod
async def remove(path_or_name: str, *, force: bool = False) -> None
```

<Accordion title="Example">
  ```python theme={null}
  await Snapshot.remove("after-pip-install", force=True)
  ```
</Accordion>

Remove a snapshot artifact and its index row. Refuses if the snapshot has indexed children unless `force=True`.

<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">str</span></div>
    <div className="msb-param-desc">Bare snapshot 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">Remove even if the snapshot has indexed children. Default <code>False</code>.</div>
  </div>
</div>

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

```python theme={null}
@staticmethod
async def reindex(dir: str | os.PathLike | None = None) -> int
```

<Accordion title="Example">
  ```python theme={null}
  count = await Snapshot.reindex()
  print(f"indexed {count} snapshots")
  ```
</Accordion>

Walk `dir` (default: configured snapshots dir) and rebuild the local index. Returns the number of artifacts indexed.

<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">str | os.PathLike | None</span></div>
    <div className="msb-param-desc">Directory to scan. Default: the configured snapshots directory.</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">int</span></div>
    <div className="msb-param-desc">Number of artifacts indexed.</div>
  </div>
</div>

#### <span className="msb-recv">Snapshot.</span><span className="msb-hn">export()</span>

```python theme={null}
@staticmethod
async def export(
    name_or_path: str,
    out: str | os.PathLike,
    *,
    with_parents: bool = False,
    with_image: bool = False,
    plain_tar: bool = False,
) -> None
```

<Accordion title="Example">
  ```python theme={null}
  await Snapshot.export(
      "after-pip-install",
      "/tmp/after-pip-install.tar.zst",
      with_parents=True,
  )
  ```
</Accordion>

Bundle a snapshot into a `.tar.zst` archive. The existing snapshot manifest is archived as-is; create the snapshot with recorded integrity when the archive will cross a trust boundary.

<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">str</span></div>
    <div className="msb-param-desc">Snapshot bare name or artifact path to export.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>out</code><span className="msb-type">str | os.PathLike</span></div>
    <div className="msb-param-desc">Output archive path.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>with\_parents</code><span className="msb-type">bool</span></div>
    <div className="msb-param-desc">Include the snapshot's parent chain. Default <code>False</code>.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>with\_image</code><span className="msb-type">bool</span></div>
    <div className="msb-param-desc">Include the pinned base image. Default <code>False</code>.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>plain\_tar</code><span className="msb-type">bool</span></div>
    <div className="msb-param-desc">Write an uncompressed <code>.tar</code> instead of <code>.tar.zst</code>. Default <code>False</code>.</div>
  </div>
</div>

## Move artifacts

#### <span className="msb-recv">Snapshot.</span><span className="msb-hn">import\_()</span>

```python theme={null}
@staticmethod
async def import_(
    archive: str | os.PathLike,
    *,
    dest: str | os.PathLike | None = None,
) -> SnapshotHandle
```

<Accordion title="Example">
  ```python theme={null}
  h = await Snapshot.import_("/tmp/after-pip-install.tar.zst")
  print(h.path)
  ```
</Accordion>

Unpack a snapshot archive (`.tar.zst` or `.tar`) into the snapshots directory, verifying recorded integrity when present. Compression is detected from magic bytes. The trailing underscore is intentional: `import` is a reserved Python keyword.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>archive</code><span className="msb-type">str | os.PathLike</span></div>
    <div className="msb-param-desc">Archive path (<code>.tar.zst</code> or <code>.tar</code>).</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>dest</code><span className="msb-type">str | os.PathLike | None</span></div>
    <div className="msb-param-desc">Destination directory. Default: the configured 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 to the imported snapshot.</div>
  </div>
</div>

## Inspect

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

```python theme={null}
async def verify(self) -> dict[str, Any]
```

<Accordion title="Example">
  ```python theme={null}
  report = await snap.verify()
  if report["upper"]["kind"] == "verified":
      print(f"hash matches: {report['upper']['digest']}")
  else:
      print("no integrity hash recorded")
  ```
</Accordion>

Recompute the upper layer's content hash and compare against the manifest. Walks data extents only, so a 4 GiB sparse file with a few MB of data verifies in milliseconds.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">dict\[str, Any]</span></div>
    <div className="msb-param-desc">Verification report. The <code>upper.kind</code> field is <code>"not\_recorded"</code> when no integrity hash was stored, or <code>"verified"</code> with the recomputed digest.</div>
  </div>
</div>

The report shape:

```python theme={null}
{
    "digest": "sha256:...",
    "path": "/path/to/artifact",
    "upper": {"kind": "not_recorded"}                            # no integrity recorded
        | {"kind": "verified", "algorithm": "...", "digest": "sha256:..."},
}
```

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

```python theme={null}
async def open(self) -> Snapshot
```

<Accordion title="Example">
  ```python theme={null}
  h = await Snapshot.get("after-pip-install")
  snap = await h.open()
  print(snap.fstype)
  ```
</Accordion>

Load the full [`Snapshot`](#snapshot) metadata for this handle. Metadata-validated only; does not read the upper file.

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

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

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

```python theme={null}
async def remove(self, *, force: bool = False) -> None
```

<Accordion title="Example">
  ```python theme={null}
  h = await Snapshot.get("after-pip-install")
  await h.remove(force=False)
  ```
</Accordion>

Remove this snapshot artifact and its index row. Refuses if the snapshot has indexed children unless `force=True`.

<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">Remove even if the snapshot has indexed children. Default <code>False</code>.</div>
  </div>
</div>

## Types

### Snapshot

<p className="msb-backref">Returned by <a href="#handle-snapshot">snapshot()</a> · <a href="#handle-snapshot_to">snapshot\_to()</a> · <a href="#snapshot-create">Snapshot.create()</a> · <a href="#snapshot-open">Snapshot.open()</a> · <a href="#snapshot-list_dir">Snapshot.list\_dir()</a> · <a href="#handle-open">handle.open()</a></p>

A fully-parsed snapshot artifact. Properties are read-only attributes (not async).

| Property / Method       | Type                        | Description                                                                        |
| ----------------------- | --------------------------- | ---------------------------------------------------------------------------------- |
| `path`                  | `str`                       | Path to the artifact directory                                                     |
| `digest`                | `str`                       | Canonical content digest (`sha256:hex`). The snapshot's identity                   |
| `size_bytes`            | `int`                       | Apparent size of the captured upper layer in bytes (sparse on disk)                |
| `image_ref`             | `str`                       | Image reference the snapshot was taken from                                        |
| `image_manifest_digest` | `str`                       | OCI manifest digest of the pinned image                                            |
| `format`                | `str`                       | `"raw"` or `"qcow2"` (always `"raw"` today)                                        |
| `fstype`                | `str`                       | Filesystem type inside the upper (e.g. `"ext4"`)                                   |
| `parent`                | `str \| None`               | Parent snapshot's digest, or `None` for a root                                     |
| `created_at`            | `str`                       | RFC 3339 timestamp                                                                 |
| `labels`                | `dict[str, str]`            | User-supplied labels                                                               |
| `source_sandbox`        | `str \| None`               | Best-effort source-sandbox name                                                    |
| `verify()`              | `Awaitable[dict[str, Any]]` | Recompute and check the upper-layer integrity hash. See [`verify()`](#snap-verify) |

### SnapshotHandle

<p className="msb-backref">Returned by <a href="#snapshot-get">Snapshot.get()</a> · <a href="#snapshot-list">Snapshot.list()</a> · <a href="#snapshot-import_">Snapshot.import\_()</a></p>

Lightweight handle backed by an index row. Properties are read-only attributes (not async).

| Property / Method     | Type                                   | Description                                                             |
| --------------------- | -------------------------------------- | ----------------------------------------------------------------------- |
| `digest`              | `str`                                  | Manifest digest, canonical identity                                     |
| `name`                | `str \| None`                          | Convenience alias                                                       |
| `parent_digest`       | `str \| None`                          | Parent snapshot digest, or `None` for a root                            |
| `image_ref`           | `str`                                  | Image the snapshot was taken from                                       |
| `format`              | `str`                                  | `"raw"` or `"qcow2"`                                                    |
| `size_bytes`          | `int \| None`                          | Apparent upper size at index time                                       |
| `created_at`          | `float`                                | ms since Unix epoch                                                     |
| `path`                | `str`                                  | Local artifact directory path                                           |
| `open()`              | `Awaitable[`[`Snapshot`](#snapshot)`]` | Load full metadata. See [`open()`](#handle-open)                        |
| `remove(force=False)` | `Awaitable[None]`                      | Delete the artifact and its index row. See [`remove()`](#handle-remove) |
