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

# Sandboxes

> What a sandbox is, its statuses and sizes, how stop differs from delete, how commands run, and the limits that apply.

A sandbox is one microVM with its own kernel, disk and memory. It runs Ubuntu 24.04 with Docker and common toolchains. You make it, run commands in it, fork it, snapshot it, stop it, start it and delete it.

## Lifecycle

Create, fork, stop, start and delete return once the change is done. While it is in progress the sandbox shows a transitional status.

| Status | Meaning |
| - | - |
| `creating` | Being placed on a host and booted (create or fork). |
| `running` | Up. You can run commands in it. |
| `stopping` | Hibernating: memory and disk are being saved. |
| `stopped` | Hibernated. No compute billing. |
| `starting` | Waking up, or being restored from a snapshot. |
| `deleting` | Being removed. |
| `deleted` | Gone. Deleted sandboxes are not listed. |
| `error` | A host operation failed. You can delete it, and retry the delete if it fails. |

What each status allows:

| Action | Allowed when |
| - | - |
| Run a command, open a shell | `running` |
| Stop | `running` |
| Start | `stopped` |
| Fork, snapshot | `running` or `stopped` |
| Delete | `running`, `stopped` or `error` |

Anything else returns HTTP 409 with code `invalid_state`, for example "sandbox is stopped; start it to run commands".

## Sizes

| Size | vCPU | RAM | Disk | Compute/hour |
| - | - | - | - | - |
| `small` | 2 | 4 GB | 50 GB | \$0.0175 |
| `default` | 4 | 8 GB | 50 GB | \$0.035 |
| `large` | 8 | 16 GB | 110 GB | \$0.070 |
| `xlarge` | 16 | 32 GB | 250 GB | \$0.140 |

The host accepts only these four. A sandbox made without a size is `small`, in the API, the SDK, the CLI and the MCP server. The size named `default` is not the default: you get 4 vCPU only when you ask for `default`. On the CLI, pass `--size`. In the API and SDK, pass `vcpus` (2, 4, 8 or 16); RAM and disk follow. Any other combination returns 400 with the list of available sizes. A sandbox made from a [custom image](https://docs.zode.dev/concepts/images.md) has the image's size, and a fork has its parent's.

A sandbox's size does not change after it is made.

## Names and ids

Every sandbox has an id like `sbx_d54teouhd5f4lf52` and a name. Names are 1 to 63 characters of `a-z`, `0-9` and `-`, and cannot start or end with `-`. Leave the name out and Zode picks a two-word one such as `brave-hopper`.

Names do not have to be unique. The CLI accepts a name or an id; when two sandboxes share a name it asks you for the id. The API and SDK take ids only.

```bash theme={null}
zode ls
```

```
NAME            STATUS     SIZE    REGION       CREATED    ID
docs-qs         stopped    small   eu-central   18m ago    sbx_5a4hldojl5lpjwlk
docs-sdk        running    small   eu-central   1m ago     sbx_d54teouhd5f4lf52
```

## Regions

Sandboxes run in `eu-central`, on Google Cloud in europe-west1 (Belgium). It is the only region today. US East is coming soon. The API takes an optional `region`; an unknown region returns 400. A sandbox made from a custom image runs in the image's region.

## Stop or delete

Stopping hibernates the sandbox. Its memory and disk are saved, running processes resume where they were when you start it again, and compute billing stops. Storage is still billed while it is stopped.

Deleting removes the sandbox, its disk and its snapshots. Billing for it ends. You cannot undo a delete. Forks of a deleted sandbox keep working.

```bash theme={null}
zode stop demo      # demo is stopped
zode start demo     # demo is running
zode rm demo        # demo deleted
```

Storage is free for the first 48 hours of every sandbox, forks included. After that it is billed at $0.10 per GB-month until delete, whether the sandbox is running or stopped. It is measured on the sandbox's full disk size, so a `small` sandbox (50 GB) costs $5 a month in storage on top of its compute once it is two days old. Delete sandboxes you no longer need. See [Pricing](https://docs.zode.dev/pricing.md).

A stopped sandbox starts again on the same host. If that host has no free memory at that moment, start returns 409 `node_full`; try again shortly.

## Exec and attach

There are two ways to run something in a sandbox.

**Buffered exec**, `POST /v1/sandboxes/{id}/exec`, runs one command and returns `exit_code`, `stdout`, `stderr` and `duration_ms` in one response. Pass `command` (a string, run under `bash -lc`) or `argv` (run as is). The working directory defaults to `/workspace`. `env` entries are added to the default environment and the sandbox's environment; on a clash yours win. Limits: 30 seconds by default and 55 seconds at most (`timeout_ms`), 16 KB of command, 1 MiB of `stdin`, and 1 MiB each of `stdout` and `stderr` (beyond that the response sets `stdout_truncated` or `stderr_truncated`).

**Attach**, `GET /v1/sandboxes/{id}/attach`, is a WebSocket that streams output both ways, supports a TTY and has no time limit. See [Attach](https://docs.zode.dev/api-reference/attach.md).

The CLI uses attach for both `zode exec` and `zode ssh`. `zode exec` streams output and exits with the command's exit code. With exactly one argument after `--`, the command runs through `bash -lc`, so quote shell syntax as one argument. With several arguments, they run as is, with no shell:

```bash theme={null}
zode exec demo -- npm test
zode exec demo -- 'ls /workspace | wc -l'
zode exec -t demo -- top     # -t for a TTY
```

The SDK's `exec()` uses the buffered route and switches to attach when you stream output, ask for a TTY, pass a timeout over 55 seconds or more than 1 MiB of stdin. A bare `exec()` with no timeout is killed after 30 seconds.

If the kernel kills a command for running out of memory, the result says so (`oom_killed` and `peak_rss_mb` in the API; "killed: out of memory" from the CLI).

## Repo, branch and PR labels

You can label a sandbox with the git repo, branch and pull request it works on. Zode does not clone anything: the labels are for cost breakdowns. `zode cost --by repo` (or `branch`, `pr`) groups spend by them, as does the console's Usage page.

```bash CLI theme={null}
zode new fix-login --repo github.com/acme/web --branch fix/login --pr 412
```

```ts TypeScript theme={null}
const sbx = await Sandbox.create({
  name: "fix-login",
  gitRepo: "github.com/acme/web",
  gitBranch: "fix/login",
  prNumber: 412,
});
```

```bash curl theme={null}
curl -sS -X POST https://api.zode.dev/v1/sandboxes \
  -H "Authorization: Bearer $ZODE_API_KEY" -H "Content-Type: application/json" \
  -d '{"name":"fix-login","git_repo":"github.com/acme/web","git_branch":"fix/login","pr_number":412}'
```

The API fields are `git_repo` (up to 512 characters), `git_branch` (up to 255) and `pr_number` (positive). The CLI flags are `--repo`, `--branch` and `--pr`. A fork keeps its parent's repo; you can give it a new `git_branch` and `pr_number` (`zode fork --branch B --pr N`). Labels cannot be changed after the sandbox is made.

## Per-sandbox spend cap

`max_cost_micros` caps a sandbox's AI provider spend, in millionths of a dollar (`5000000` is \$5). It counts only model calls the sandbox makes through Zode's AI proxy that are paid by an API key. Compute, storage and calls made through a signed-in subscription are not counted.

When the cap is reached, further model calls from that sandbox get HTTP 402 with code `zode_spend_cap`, and a `spend.cap_reached` alert fires. The sandbox keeps running, and its compute and storage are not counted against this cap.

* Leave it out and the sandbox gets the workspace's default per-sandbox cap from **Billing**, if one is set. `0` or no default means no cap.
* A fork inherits its parent's cap unless you pass a new one.
* The cap is set at create or fork and cannot be changed afterwards.
* The host keeps the running total in memory, so a host restart resets it.

On the CLI, pass `--max-cost` in dollars to `zode new` or `zode fork`; in the SDK, `maxCostMicros`. Workspace-wide daily caps are on [Spend and caps](https://docs.zode.dev/concepts/spend-and-caps.md).

## Limits

* **Running at once**: Free 2, Pro 15, Team 50; a Pro trial gets Pro's 15. Sandboxes that are `creating`, `running` or `starting` count; stopped ones do not. Over the limit, create, fork and start return 409 `concurrency_limit`.
* **Credit**: a workspace with no card on file and no credit left cannot create, fork or start sandboxes (402 `credit_exhausted`), and its running sandboxes are stopped. See [Pricing](https://docs.zode.dev/pricing.md#when-credit-runs-out).
* **Create rate**: creates and forks are limited to 30 an hour per user, 60 an hour per workspace and 60 an hour per client IP. Over it you get 429 `rate_limited` with `Retry-After` and `X-RateLimit-*` headers.
* **Daily cap**: if your workspace has a daily spend cap and today's spend (UTC) has reached it, create, fork and start return 409 `daily_cap_reached`.
* **Same host**: a fork runs on its parent's host, and a stopped sandbox starts on its own host. When that host has no free memory you get 409 `node_full`.
* **Free plan**: a sandbox that averages 90% CPU or more for an hour, or that looks like it is scanning the network, is stopped. So are the workspace's running sandboxes once it sends more than 10 GiB out in a UTC day.


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