> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vpod.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Snapshots

> Available snapshots, the snapshot API, and managing the local cache.

A snapshot is a saved state that a sandbox boots from. The environment is already
set up inside it, so booting skips installation entirely.

## Available snapshots

| Name         | Id                    | Tag    | Description                                                             | Memory limit (RAM) |
| :----------- | :-------------------- | :----- | :---------------------------------------------------------------------- | :----------------- |
| `alpine`     | `alpine-3.23.0-256mb` | 3.23.0 | Minimal Alpine Linux snapshot                                           | 256 MB             |
| `vsnap-base` | `vsnap-base-256mb`    | 1.0.0  | Alpine-based snapshot with Python pre-installed                         | 256 MB             |
| `vsnap-base` | `vsnap-base-512mb`    | 1.0.0  | Same contents with a larger memory limit                                | 512 MB             |
| `vsnap-data` | `vsnap-data-512mb`    | 1.0.0  | Alpine-based snapshot with `numpy`, `pandas`, and `scipy` pre-installed | 512 MB             |

A name resolves to the first entry carrying it, so `vsnap-base` gives you the
256 MB one. To pin the other, pass its id. Both columns are accepted anywhere a
snapshot is named.

`vsnap-base:latest` is the default. Pass any other:

```ts theme={null}
await using sandbox = await Sandbox.create({ snapshot: "vsnap-base-512mb" });
```

```ts theme={null}
await using sandbox = await Sandbox.create({ snapshot: "vsnap-data" });

await sandbox.code.run("import pandas as pd");
const result = await sandbox.code.run("print(pd.Series([1, 2, 3]).sum())");
console.log(result.text); // 6
```

<Note>
  `uv` is preinstalled in every snapshot, so more Python packages can be added with
  `uv pip install --system <package>`. In a browser that reaches PyPI because PyPI
  sends CORS headers; `apk add` does not work there, because Alpine's mirrors do not.
</Note>

## Snapshot API

```ts theme={null}
import { snapshots } from "@capsule-run/vpod";
```

| Method                      | Description                                      |
| :-------------------------- | :----------------------------------------------- |
| `snapshots.catalog()`       | Fetch the available snapshots                    |
| `snapshots.resolve(name)`   | Resolve one name to a catalogue entry            |
| `snapshots.cached()`        | List what is stored locally, with sizes          |
| `snapshots.clear(options?)` | Delete cached snapshots, returns bytes reclaimed |

```ts theme={null}
for (const entry of await snapshots.catalog()) {
    console.log(entry.name, entry.tag);
}
```

## Where the cache lives

The first `Sandbox.create()` downloads a snapshot and keeps it: on disk in Node,
in origin-private storage in a browser. Later runs boot from the copy.

Snapshots are stored compressed, so a 256 MB snapshot occupies well under a
hundred megabytes. Still enough to be worth showing people.

```ts theme={null}
for (const entry of await snapshots.cached()) {
    console.log(entry.id, entry.byteLength);
}

const reclaimed = await snapshots.clear();
```

`clear()` returns the number of bytes it freed and keeps suspended sandboxes,
which live alongside the snapshots. Pass `{ instances: true }` to drop those too.
The next `Sandbox.create()` downloads again.

<Warning>
  In Node the cache directory is shared with the CLI and the Python SDK. `clear()`
  removes only what it downloaded itself and leaves anything it could not fetch
  again, such as a snapshot you built locally. `cached()` still lists everything
  that is there, so the two can disagree, and that is deliberate.
</Warning>

## Storage in a browser

Origin-private storage is site data rather than the HTTP cache, so the browser's
"clear cached images and files" does not touch it. A browser is also free to
evict it when the disk fills up, which costs a re-download and nothing else.

```ts theme={null}
await snapshots.SnapshotStore.persist();   // ask the browser not to evict
await snapshots.SnapshotStore.persisted(); // whether it agreed
await snapshots.SnapshotStore.quota();     // { usage, quota } or null
```

<Note>
  Firefox prompts the user when you request persistence, so call it from something
  they clicked rather than on page load.
</Note>
