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

> Create and restore sandbox snapshots with the Python SDK.

<Tooltip tip="Cloud supports disk capture from stopped persistent sandboxes, lookup, listing, removal, and restore. Live capture, full snapshots, groups, archives, verification, and compaction are local-only."><span className="msb-badge-limited">Limited on cloud <Icon icon="circle-info" size={11} /></span></Tooltip>

See the [snapshot guide](/sandboxes/snapshots) for workflows and examples.

Use snapshot objects or references on cloud. Local operations also accept a group head, `group:member`, or artifact path.

## Guest writeback

Pass `guest_flush=GuestFlush.REQUIRED` to `Snapshot.create`, `Snapshot.create_archive`, `source.fork`, `source.fork_many`, or `source.pause`. Import `GuestFlush` from `microsandbox`. The default `AUTO` flushes live disk-only captures, but adds no optional flush to full captures, forks, or pause. `SKIP` retains mandatory storage barriers. A paused disk capture needs a matching prior flush; cloud rejects non-Auto policies. See [guest flush policy reference](/sandboxes/snapshots#guest-flushing).

## Snapshot

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

<p className="msb-backref">Returned by <a href="#handle-snapshot">snapshot()</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>

Create, open, and manage snapshots. See [properties](#snapshot-properties) for returned metadata.

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

```python theme={null}
@staticmethod
async def create(
    name: str = "",
    *,
    from_sandbox: str,
    group: str | None = None,
    dest_dir: str | os.PathLike[str] | None = None,
    labels: dict[str, str] | None = None,
    force: bool = False,
    record_integrity: bool = False,
    full: bool = False,
    guest_flush: GuestFlush | None = None,
) -> Snapshot
```

Create a disk snapshot, or set `full=True` to include memory and execution state. `name` identifies a member within `group`; an omitted name is generated and an omitted group uses the source sandbox's name. `dest_dir` selects the parent directory containing the group. `from_sandbox` names the sandbox to capture and is required.

<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 member name; generated when omitted.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>from\_sandbox</code><span className="msb-type">str</span></div>
    <div className="msb-param-desc">Name of the source sandbox. Local disk capture supports running, paused, stopped, and crashed sources. Cloud requires a stopped persistent source. Required.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>dest\_dir</code><span className="msb-type">str | os.PathLike\[str] | None</span></div>
    <div className="msb-param-desc">Parent directory containing snapshot groups. Defaults to the snapshots directory.</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 local labels stored outside the identity-bearing descriptor.</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">Must remain <code>False</code> for installed group members. Since v0.7, <code>True</code> raises <code>InvalidConfigError</code> even when the name does not exist. Use a new or generated member name, or explicitly remove the existing member before recreating it. See <a href="/migrations/v0.7#update-snapshot-code">the v0.6 upgrade example</a>. Direct archive capture supports overwriting its output file.</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 className="msb-param">
    <div className="msb-param-key"><code>full</code><span className="msb-type">bool</span></div>
    <div className="msb-param-desc">Local-only when <code>True</code>: capture disk, memory, execution, and device state from a running or paused sandbox. Default <code>False</code> captures disk state; locally, the source can be running, paused, stopped, or crashed. Cloud requires <code>False</code> and a stopped persistent source.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>guest\_flush</code><span className="msb-type">GuestFlush | None</span></div>
    <div className="msb-param-desc">Guest writeback policy. Omitted selects <code>AUTO</code>; see <a href="#guest-writeback">guest writeback</a>.</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>

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

***

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

```python theme={null}
@staticmethod
async def create_archive(
    name: str,
    archive: str | os.PathLike[str],
    *,
    from_sandbox: str,
    group: str | None = None,
    labels: dict[str, str] | None = None,
    force: bool = False,
    record_integrity: bool = False,
    full: bool = False,
    plain_tar: bool = False,
    guest_flush: GuestFlush | None = None,
) -> SnapshotArchive
```

Capture directly into an archive without installing a local snapshot.

```python theme={null}
archive = await Snapshot.create_archive(
    "deps",
    "/tmp/deps.msb",
    from_sandbox="baseline",
)
```

***

#### <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("baseline:deps")
  print(snap.image_ref)
  ```
</Accordion>

Open an existing artifact by group head, `group:member`, or path. This validates metadata without reading the full 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">Group head, <code>group:member</code>, 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("baseline:deps")
  print(h.digest)
  ```
</Accordion>

Look up a handle by group head, `group:member`, stable snapshot ID, descriptor digest, or artifact path. Global IDs and digests must resolve unambiguously.

<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">Group head, <code>group:member</code>, stable snapshot ID, descriptor 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">Lightweight handle returned by the active backend.</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 snapshots visible through the active backend. Local uses its index; cloud
lists managed snapshots. Host-volume artifacts are opened explicitly by
reference.

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

Walk a local directory and parse each subdirectory's manifest. Does not touch
the local index, useful for inspecting external snapshot collections. Skips
entries that don't look like snapshot artifacts. Cloud raises
`UnsupportedError`.

<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("baseline:deps", force=True)
  ```
</Accordion>

Remove a snapshot through the active backend. Locally, removal also updates
the index and refuses 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">Group head, <code>group:member</code>, 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. Cloud raises `UnsupportedError`.

<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">save()</span>

<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

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

<Accordion title="Example">
  ```python theme={null}
  await Snapshot.save(
      "baseline:deps",
      "/tmp/deps.msb",
      with_parents=True,
  )
  ```
</Accordion>

Bundle a snapshot into a `.msb` 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">Group head or <code>group:member</code> or artifact path to save.</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>.msb</code>. Default <code>False</code>.</div>
  </div>
</div>

<Accordion title="Example">
  ```python theme={null}
  await Snapshot.save(
      "baseline:deps",
      "/tmp/deps.msb",
      with_parents=True,
  )
  ```
</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>

```python theme={null}
@staticmethod
async def load(
    archive: str | os.PathLike,
    *,
    dest: str | os.PathLike | None = None,
    base: str | None = None,
    group: str | None = None,
    set_head: bool = False,
) -> SnapshotHandle
```

Unpack a snapshot archive (`.msb` or `.tar`) into the selected or generated group. The returned handle's `group` identifies the group and `head_update` reports the head selection outcome. Structural and archive-entry checks run during import; recorded payload integrity is preserved for explicit [`verify()`](#snap-verify). Compression is detected from magic bytes.

<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>.msb</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 loaded snapshot.</div>
  </div>
</div>

<Accordion title="Example">
  ```python theme={null}
  h = await Snapshot.load("/tmp/deps.msb")
  print(h.path)
  ```
</Accordion>

***

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

```python theme={null}
async def load_many(
    archives: Sequence[str | os.PathLike[str]],
    *,
    dest: str | os.PathLike[str] | None = None,
    base: str | None = None,
    group: str | None = None,
    set_head: bool = False,
) -> list[SnapshotHandle]
```

Import archives as one batch. Returns handles in input order. Dependencies resolve from the batch, the named group, or an explicit base; input order does not matter. All members are validated before publication.

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

```python theme={null}
async def group_head(selector: str) -> dict[str, str | bool | None]
```

Read a group’s head, or select an exact member with `group:member`. Returns the group, previous and current snapshot IDs, reason, and whether the head changed. See [group selection](/sandboxes/snapshots#snapshot-groups).

<span id="snapshot-groups" />

<span id="load-multiple-archives" />

### Import options

Options for `load()` and `load_many()`.

| Option | Purpose |
| - | - |
| `dest` | Parent directory containing groups. Defaults to the local snapshot store. |
| `base` | External snapshot or standalone archive for missing dependencies. |
| `group` | Destination group. Omit to create one group for the import. |
| `set_head` | Select the imported tip, even with divergent ancestry. Defaults to false; requires a unique tip. |

With divergent tips, the existing head stays selected; a new group has no head. Select a member explicitly. Identical members may be reused; conflicting identities fail. See [archive imports](/sandboxes/snapshots#import-archives).

## Snapshot methods

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

```python theme={null}
async def save_to(
    self,
    out: str | os.PathLike,
    *,
    with_parents: bool = False,
    with_image: bool = False,
    plain_tar: bool = False,
    since: str | None = None,
    last_layers: int | None = None,
) -> None
```

Bundle this snapshot through the backend retained when it was created or
opened. This avoids resolving its reference through a possibly different
current default backend. Cloud raises `UnsupportedError`.

<Accordion title="Example">
  ```python theme={null}
  await snap.save_to("/tmp/deps.tar.zst", with_image=True)
  ```
</Accordion>

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

```python theme={null}
def copy_to(self, output_archive_path: str | os.PathLike) -> SnapshotCopyBuilder
```

Create a new archive from this snapshot's disk data while replacing its labels
and integrity metadata. The source snapshot is unchanged. Cloud raises
`UnsupportedError` when `save()` is awaited.

<Accordion title="Example">
  ```python theme={null}
  await (
      snap.copy_to("/tmp/baseline-copy.tar.zst")
      .labels({"environment": "test"})
      .record_integrity(True)
      .save()
  )
  ```
</Accordion>

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

Verify the snapshot's complete state closure. File state recomputes recorded upper-layer integrity. Checkpoint state validates the complete checkpoint closure and returns `checkpoint={"kind": "verified", "root": ...}` in the report.

<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:..."},
}
```

## SnapshotHandle methods

#### <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("baseline:deps")
  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("baseline:deps")
  await h.remove(force=False)
  ```
</Accordion>

Remove this installed snapshot copy and its index row using the handle's stored artifact path. Other groups containing the same snapshot ID or digest remain unchanged. 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>

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

```python theme={null}
async def save_to(
    self,
    out: str | os.PathLike,
    *,
    with_parents: bool = False,
    with_image: bool = False,
    plain_tar: bool = False,
    since: str | None = None,
    last_layers: int | None = None,
) -> None
```

Bundle the referenced snapshot through the backend retained by the handle.
Cloud raises `UnsupportedError`.

<span id="take-a-snapshot" />

## SandboxHandle

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

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

Snapshot this sandbox into its default group with the given member name. Local live disk captures preserve the source's running or paused state. Cloud requires a stopped persistent source. Use the returned artifact path or `sandbox:member` to open it later. 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">Member name within the source sandbox's group.</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>

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

***

<span id="restore-a-sandbox" />

## Restore

Restore into a new detached sandbox. Disk boots fresh; full resumes execution. See [restore examples](/sandboxes/snapshots#disk-snapshots) and [progress](/sandboxes/snapshots#restore-progress).

<Accordion title="Example">
  ```python theme={null}
  child = await Sandbox.restore("api:baseline", name="api-restored", cow_memory=True)
  ```
</Accordion>

| Control | Purpose |
| - | - |
| `cow_memory=True` | Share unchanged full-snapshot memory. |
| `forked=True` | Deprecated alias for the same CoW memory policy; see [migration notes](/sandboxes/snapshots#migrating-restore-options). |
| `disk_only=True` | Boot only the saved disk. |
| `snapshot_base` | Supply an archive dependency. |
| `Sandbox.restore()` | Return the restored sandbox. |
| `Sandbox.restore_with_progress()` | Return a `PullSession`; await its result. |

Image, replacement, and startup-command options are not accepted. Full restore requires matching CPU and memory settings, keeps captured network devices, and cannot apply a new guest security profile. Use disk-only restore to change these.

Full restore rejects missing external filesystems and additional disks by default. Use `allow_missing_resources=True` to resume with unavailable devices and warnings. This is separate from strict/relaxed validation of supplied mappings; inheritance does not waive missing backing. Root and owned storage remain required.

<Accordion title="Destination options">
  | Option | Purpose |
  | - | - |
  | `cpus, memory` | CPU count and memory in MiB. Full restore must match capture. |
  | `network_policy` | Replace host traffic filtering; guest DNS and TLS settings stay unchanged. |
  | `max_connections` | Concurrent TCP limit; zero means unlimited. |
  | `disable_network` | Remove the NIC. Rejected for full snapshots that captured one. |
  | `security` | Guest security profile. Disk boot only, including an explicit default profile. |
  | `max_duration, idle_timeout` | Lifetime and idle limits. Omitted means unlimited; zero expires immediately. |
  | `volumes, captured_volumes` | Map host volumes or select captured private volumes. |
  | `ports` | Bind destination TCP or UDP ports. |
  | `vsock` | Bind destination vsock endpoints. |
  | `user, log_level` | Default user for new execs and host runtime log level. |
  | `dangerously_inherit_resources` | Explicitly inherit host resources. Disabled by default. |
  | `allow_missing_resources=True` | Allow unavailable external filesystems or additional disks, with warnings. Full restore otherwise requires their bindings. |
  | `external_mount_policy` | Validate supplied filesystem mappings: strict (default) or relaxed. Does not grant access. |

  Omitted controls retain destination defaults. Durations are non-negative finite seconds, rounded up. Network policy accepts `NetworkPolicy`, not `Network`. `captured_volumes` contains guest paths.
</Accordion>

<span id="disk-maintenance-and-incremental-export" />

## Compaction

Compact a local sandbox’s root or owned disks. See [compaction](/sandboxes/snapshots#compact-disks) for examples and recovery requirements.

<Accordion title="Options and results">
  | Option | Purpose |
  | - | - |
  | `disk` | Select one owned disk by guest path; `/` selects the root. |
  | `root_disk_only` | Select only the root. Cannot combine with the disk selector. |
  | `layers` | Oldest sealed layers to merge, including the base. Minimum two; omit for all. Excludes the writable layer. |
  | `dry_run` | Preview without changing storage. |

  Defaults to the root and owned data disks; excludes named/external volumes and directories. Requires a running or fully stopped local sandbox. Fewer than two sealed layers means no change; no eligible disks returns an empty result with zero counts.

  Results include aggregate counts and per-disk entries keyed by `guest_path`. `materialized_bytes` counts copied bytes, not reclaimed space. Times are microseconds: per-disk `total_us` covers preparation; aggregate `total_us` also includes switching; `pause_us` measures the shared VM pause.
</Accordion>

## Types

<h3 id="snapshot-properties">
  Snapshot properties
</h3>

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

<p className="msb-backref">Returned by <a href="#handle-snapshot">snapshot()</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 backend-neutral snapshot. Properties are read-only attributes.

| Property / Method | Type | Description |
| - | - | - |
| <span id="snapshot-id" />`id` | `str` | Stable opaque snapshot identity |
| <span id="snapshot-path" />`path` | `str` | Local artifact directory; raises `UnsupportedError` on cloud |
| `reference` | `str` | Stable backend-relative restore reference |
| `reference_kind` | `Literal["id", "path"]` | How the selected backend resolves the reference |
| <span id="snapshot-digest" />`digest` | `str` | Canonical descriptor digest (`sha256:hex`), separate from the stable ID |
| <span id="snapshot-size_bytes" />`size_bytes` | `int \| None` | Backend-reported stored payload size in bytes |
| <span id="snapshot-image_ref" />`image_ref` | `str` | Image reference the snapshot was taken from |
| <span id="snapshot-image_manifest_digest" />`image_manifest_digest` | `str` | OCI manifest digest of the pinned image |
| <span id="snapshot-state_kind" />`state_kind` | [`SnapshotStateKind`](#snapshotstatekind) | File-backed or checkpoint-backed state |
| <span id="snapshot-format" />`format` | [`SnapshotFormat`](#snapshotformat)` \| None` | On-disk format for file-backed state |
| <span id="snapshot-scope" />`scope` | [`SnapshotScope`](#snapshotscope) | Captured state scope |
| <span id="snapshot-fstype" />`fstype` | `str \| None` | Filesystem type for file-backed state (e.g. `"ext4"`) |
| <span id="snapshot-checkpoint_id" />`checkpoint_id` | `str \| None` | Checkpoint identifier for checkpoint-backed state |
| <span id="snapshot-checkpoint_manifest_digest" />`checkpoint_manifest_digest` | `str \| None` | Checkpoint manifest digest for checkpoint-backed state |
| <span id="snapshot-parent" />`parent` | `str \| None` | Parent snapshot's digest, or `None` for a root |
| <span id="snapshot-created_at" />`created_at` | `str` | RFC 3339 timestamp |
| <span id="snapshot-labels" />`labels` | `dict[str, str]` | User-supplied labels |
| <span id="snapshot-source_sandbox" />`source_sandbox` | `str \| None` | Best-effort source-sandbox name |
| `save_to(...)` | `Awaitable[None]` | Bundle through the backend retained by this snapshot |
| `copy_to(path)` | [`SnapshotCopyBuilder`](#snapshotcopybuilder) | Configure a copied archive with replacement metadata |
| `verify()` | `Awaitable[dict[str, Any]]` | Recompute and check the upper-layer integrity hash. See [`verify()`](#snap-verify) |

### SnapshotCopyBuilder

Returned by [`Snapshot.copy_to()`](#snap-copy_to). Setters mutate the builder and
return it so calls can be chained.

| Method | Returns | Description |
| - | - | - |
| `labels(dict[str, str])` | `SnapshotCopyBuilder` | Replace all labels in the copied manifest |
| `record_integrity(bool)` | `SnapshotCopyBuilder` | Compute integrity when true, or omit it when false |
| `save()` | `Awaitable[None]` | Write the configured archive |

### SnapshotHandle

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

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

Lightweight handle returned by the active backend. Properties are read-only.

| Property / Method | Type | Description |
| - | - | - |
| `id` | `str` | Stable opaque snapshot identity |
| `path` | `str` | Local artifact directory; raises `UnsupportedError` on cloud |
| `digest` | `str` | Canonical descriptor digest, separate from the stable ID |
| `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 |
| `state_kind` | [`SnapshotStateKind`](#snapshotstatekind) | File-backed or checkpoint-backed state |
| `format` | [`SnapshotFormat`](#snapshotformat)` \| None` | On-disk format for file-backed state |
| `scope` | [`SnapshotScope`](#snapshotscope) | Captured state scope |
| `fstype` | `str \| None` | Filesystem type for file-backed state |
| `checkpoint_manifest_digest` | `str \| None` | Checkpoint manifest digest for checkpoint-backed state |
| `size_bytes` | `int \| None` | Backend-reported stored payload size, when known |
| `locality` | `str` | Artifact locality reported by the index |
| `availability` | `str` | Artifact availability reported by the index |
| `migration_state` | `str` | Current migration state |
| `migration_error_code` | `str \| None` | Migration error code, when migration failed |
| `created_at` | `float` | ms since Unix epoch |
| `reference` | `str` | Stable backend-relative restore reference |
| `reference_kind` | `Literal["id", "path"]` | How the selected backend resolves the reference |
| `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) |
| `save_to(...)` | `Awaitable[None]` | Bundle through the backend retained by this handle |

### SnapshotStateKind

<p className="msb-backref">Returned by <a href="#snapshot">Snapshot.state\_kind</a> · <a href="#snapshothandle">SnapshotHandle.state\_kind</a></p>

Snapshot state representation.

| Member | Value | Description |
| - | - | - |
| `SnapshotStateKind.FILE` | `"file"` | File-backed upper-layer state |
| `SnapshotStateKind.CHECKPOINT` | `"checkpoint"` | Checkpoint-manifest-backed state |

### SnapshotFormat

<p className="msb-backref">Returned by <a href="#snapshot">Snapshot.format</a> · <a href="#snapshothandle">SnapshotHandle.format</a></p>

On-disk format for file-backed snapshot state.

| Member | Value | Description |
| - | - | - |
| `SnapshotFormat.RAW` | `"raw"` | Raw disk image |
| `SnapshotFormat.QCOW2` | `"qcow2"` | QEMU copy-on-write v2 image |

### SnapshotScope

<p className="msb-backref">Returned by <a href="#snapshot">Snapshot.scope</a> · <a href="#snapshothandle">SnapshotHandle.scope</a></p>

Captured snapshot state scope.

| Member | Value | Description |
| - | - | - |
| `SnapshotScope.DISK` | `"disk"` | Disk-only state |
| `SnapshotScope.FULL` | `"full"` | Disk, memory, and device state |

```python theme={null}
from microsandbox import SnapshotFormat, SnapshotScope, SnapshotStateKind

assert snapshot.state_kind is SnapshotStateKind.FILE
assert snapshot.format is SnapshotFormat.RAW
assert snapshot.scope is SnapshotScope.DISK
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.