# Persistent Volumes

A volume in Lizard (lizard.build) keeps data after a sandbox stops. It mounts at **`/workspace`** and attaches to **one sandbox at a time**. The sandbox runs on the same node as its volume.

## Create and attach by name

Names are unique within a project. Use lowercase letters, digits and dashes, starting and ending with a letter or digit, up to 64 characters.

Use `getOrCreate` to reuse a named volume. Its size applies only when creating a new volume; it never resizes an existing one. `Volume.create` returns a conflict if the name is taken.

```ts
import { Sandbox, Volume } from '@lizard-build/sdk';

await Volume.getOrCreate('proj_123', 'agent-workdir', { sizeGb: 10 });
const sandbox = await Sandbox.create('base', {
  projectId: 'proj_123', volumeName: 'agent-workdir',
});
try {
  await sandbox.fs.write('/workspace/state.json', JSON.stringify({ step: 1 }));
} finally {
  await sandbox.kill();
}

// A later sandbox mounts the same data by name.
const next = await Sandbox.create('base', {
  projectId: 'proj_123', volumeName: 'agent-workdir',
});
try {
  console.log(await next.fs.read('/workspace/state.json'));
} finally {
  await next.kill();
}
```

```python
from lizard import Sandbox, Volume

Volume.get_or_create("proj_123", "agent-workdir", size_gb=10)
sandbox = Sandbox.create("base", project_id="proj_123", volume_name="agent-workdir")
try:
    sandbox.process.exec_("echo hello > /workspace/state.txt")
finally:
    sandbox.kill()
```

## Size and price

New volumes allow **1–50 GB**, in whole GB, with **5 GB** as the default. The server can override the maximum through `VOLUME_MAX_SIZE_GB`; the dashboard and CLI read the current limits from `GET /api/projects/:projectId/volume-limits`. The dashboard also reads the storage price from that endpoint and shows it below the size slider.

You pay for **used space**, not the full allocation. Existing volumes larger than the new maximum keep their size and remain accessible. Creating a new volume requires enough unreserved disk space on a healthy worker in the chosen region. If none has room, the API returns `503` with code `volume_capacity_unavailable`.

## Manage volumes

```ts
await Volume.list('proj_123');
const volume = await Volume.get('proj_123', 'agent-workdir');
await volume.getInfo('proj_123');
await Volume.delete('proj_123', 'agent-workdir'); // detach first
```

| TypeScript | Python | Purpose |
|---|---|---|
| `Volume.getOrCreate(projectId, name, options)` | `Volume.get_or_create(project_id, name, size_gb=5)` | Reuse a volume or create it |
| `Volume.create(projectId, name, options)` | `Volume.create(project_id, name, size_gb=5)` | Create; fail if the name is taken |
| `Volume.list(projectId)` | `Volume.list(project_id)` | List the project's volumes |
| `Volume.get(projectId, nameOrId)` | `Volume.get(project_id, name_or_id)` | Look up a volume |
| `Volume.delete(projectId, nameOrId)` | `Volume.remove(project_id, name_or_id)` | Delete a detached volume |

Generated IDs and the `volumeId` / `volume_id` fields still work for existing callers. Use names in new code.

## CLI

```bash
lizard volume create agent-workdir --size 10 --project proj_123
lizard volume list --project proj_123
lizard sandbox create --volume agent-workdir --project proj_123
# After stopping the sandbox:
lizard volume rm agent-workdir --project proj_123
```

`--size` accepts whole GB and checks the current server limit before creating a volume. `volume list` shows names; use `--json` when you need IDs.

## Dashboard

Open **Sandboxes → Volumes** in a project. The create form checks the name and offers a size slider with the current maximum and price. The list shows used space, allocated space, status, and the attached sandbox. Copy the ID from the volume's details when needed.

## Storage lifecycle

- Killing or expiring a sandbox detaches its volume and keeps the data.
- An attached volume cannot attach to another sandbox or be deleted.
- A paused sandbox keeps its attachment.
- Deleting a volume removes its data. Volumes use node-local storage; export data you need after a node failure. See [storage and recovery](https://lizard.build/docs/platform/storage-and-recovery).

See the [SDK reference](https://lizard.build/docs/sandboxes/sdk-reference) for sandbox options.
