---
title: "Sandboxes on exe.dev"
description: "Create a sandbox VM with new --sandbox, run a CI job or an agent in it, pause and resume it, delete it, and see how per-second billing compares to pools."
url: https://exe-staging.dev/deploy/sandbox
category: "AI agents"
updated: 2026-11-02
---

# Sandboxes on exe.dev

A VM with its own CPU and memory, billed by the second while it runs.

- **Software:** Sandboxes (https://exe.dev/docs/standalone-vms)
- **Time:** 5 minutes
- **Machine-readable:** https://exe-staging.dev/deploy/sandbox/manifest.json

## What you get

- A sandbox VM created with one command, ready for SSH in about a second
- Work run in it from your computer, a script, or an agent
- A paused sandbox that keeps its memory and processes and isn't billed for CPU or memory
- Scripted creation for CI and agent jobs, each deleted when it ends
- A sweep that finds and deletes sandboxes left running

Running on the VM:

- **Standalone VM**: exeuntu (Ubuntu 24.04), 2 vCPU / 4 GiB by default, reserved for this VM alone, data in `its own disk, kept while paused`
- **Meter**: $0.105 per 2 vCPU / 4 GiB unit-hour, by the second, while it runs
- **Egress policy**: all by default; integrations to cut it off from the internet

How it is reached:

- ssh my-sandbox.exe.xyz (private): a shell in the sandbox, for the SSH keys on your account
- https://my-sandbox.exe.xyz/ (private): port 8000 of the sandbox, behind your exe.dev login, for previews

A sandbox is an exe.dev VM with its own reserved vCPU and memory. An
ordinary VM shares your plan's capacity with your other VMs; a sandbox
doesn't take from it or add to it, and is metered by the second instead,
from when you create it until you delete it, except while it's paused.
That suits work you start, finish, and throw away: a CI job, an agent's
task, code an LLM wrote, a preview of a branch.

It's still a whole VM, not a container: its own kernel, `sudo`, Docker, Go,
Python and `uv`, an HTTPS address behind your exe.dev login, and the
integrations attached to it. In our tests `new --sandbox` returned in about
a second and the VM took commands right away. This page creates one, runs
something in it, pauses and resumes it, deletes it, then does the same in
bulk, and ends with what it costs next to a pool.

## Create a sandbox

On your computer:

```bash
ssh exe.dev new --sandbox --name=my-sandbox
```

`--sandbox` is an alias for `--standalone`; the two are the same flag.
Pick any free name (VM names are global, so `my-sandbox` may be taken), or
leave `--name` off and exe.dev makes one up. The other `new` flags work as
usual:

```bash
ssh exe.dev new --sandbox --name=my-sandbox --cpu=4 --memory=8GB --tag=sandbox --egress=integrations
```

- **Size.** The default is 2 vCPU and 4 GiB. A sandbox can have up to 2
  GiB of memory per vCPU, up to your plan's vCPUs on Personal and 32 vCPU
  on Work. `ssh exe.dev resize my-sandbox --cpu=N --memory=M` changes it
  later, and billing follows the new size.
- **Tags** let you find and clean up sandboxes later.
- **`--egress=integrations`** cuts the sandbox off from the internet except
  for the [integrations attached to it](/docs/integrations-attach). Use it
  for any sandbox an agent or untrusted code works in.
- **`--no-email`** skips the email exe.dev sends about a new VM, which you
  want when a script makes hundreds.

Check that it's a sandbox:

```bash
ssh exe.dev ls --group=type
```

`my-sandbox` is listed under "Standalone VMs".

> [!NOTE]
> Personal accounts can create sandboxes. On a Work team an admin turns
> them on first, with `ssh exe.dev team settings standalone all-users` (or
> `admins-only`) or at [exe.dev/team](https://exe.dev/team). Until then
> `new --sandbox` is refused.

## Run work in it

A sandbox answers SSH for the keys on your account. On your computer:

```bash
ssh my-sandbox.exe.xyz 'nproc && free -m && python3 -c "print(6 * 7)"'
```

It prints `2`, the memory table, and `42`. For an interactive shell, `ssh
my-sandbox.exe.xyz`. Everything else works as on any VM: `scp` files in
and out, run Docker, start a server on port 8000 and open
`https://my-sandbox.exe.xyz/` (private to you until you
[share it](/docs/sharing)), or point an agent at it. Claude Code, Codex,
and Shelley are preinstalled.

An existing VM can become a sandbox too. `ssh exe.dev cp my-vm
my-sandbox-2 --sandbox` copies it into a new sandbox, and `ssh exe.dev pool
detach --vm=my-vm` turns a pool VM into one. A sandbox can't move into a
pool.

## Pause and resume

When a sandbox has nothing to do but you'll want it again, pause it. On
your computer:

```bash
ssh exe.dev pause my-sandbox
```

`pause` snapshots the VM's memory to its disk and frees its CPU and
memory. It took about 2 seconds in our tests. `ssh exe.dev ls my-sandbox`
now says `paused`. Commands sent to it through exe.dev fail with `VM
"my-sandbox" is not running`, so resume it before you connect:

```bash
ssh exe.dev resume my-sandbox
```

About 3 seconds later the VM is back where it was, not rebooted: processes
that were running are still running, and files in `/tmp` are still there.
To see it, start something before you pause and look for it after:

```bash
ssh my-sandbox.exe.xyz 'nohup sleep 100000 >/dev/null 2>&1 &'
ssh exe.dev pause my-sandbox
ssh exe.dev resume my-sandbox
ssh my-sandbox.exe.xyz 'pgrep -a sleep'
```

It prints the same `sleep 100000` process.

While it's paused, a sandbox isn't billed for its vCPU and memory. It keeps
its disk, which counts toward your plan's disk allowance, and it still
counts toward your VM limit (50 on [Personal](/docs/billing/personal)).

`restart` is not a pause: it reboots the VM, so processes are gone and
files that hadn't reached the disk can be lost.

## Delete it

```bash
ssh exe.dev rm my-sandbox
```

The VM, its disk, and its capacity are gone, and so is the meter. `rm`
takes several names at once: `ssh exe.dev rm sbx-1 sbx-2 sbx-3`.

> [!WARNING]
> A sandbox you forget about keeps running, and keeps costing $0.105 an
> hour for every 2 vCPU, until you pause or delete it. An 8 vCPU sandbox
> left up for a week is about $70. Pause what you'll come back to; delete
> the rest. [Clean up](#clean-up-whats-left-running) shows how to find
> them.

## Many sandboxes: CI and agent jobs

Most sandboxes live for one job: seconds for a test run, minutes or hours
for an agent's task. Create one per job, let exe.dev pick the name, and
delete it however the job ends. This script runs a command in a fresh
sandbox and passes its exit code through:

```bash
#!/usr/bin/env bash
# run-in-sandbox.sh 'cd /tmp && echo hello'
set -euo pipefail
vm=$(ssh exe.dev new --sandbox --tag=ci --no-email --json | jq -r .vm_name)
trap 'ssh exe.dev rm "$vm" >/dev/null' EXIT
ssh -o StrictHostKeyChecking=accept-new "$vm.exe.xyz" "$1"
```

`--json` makes `new` print the VM's details, `vm_name` among them, and the
`trap` deletes the sandbox when the script exits, whether the command
passed, failed, or was interrupted. Let exe.dev choose names: a name like
`ci-1234` is global and may belong to someone else.

To run several at once, start them in the background and wait. Three
sandboxes created in parallel were all ready in under 2 seconds in our
tests:

```bash
for i in 1 2 3 4 5; do ./run-in-sandbox.sh "echo job $i on \$(hostname)" & done; wait
```

### Start each job from a prepared base

Installing the same packages for every job is slow. Prepare a base once,
pause it, and copy it for each job. Copying a paused sandbox took under
half a second:

```bash
ssh exe.dev new --sandbox --name=my-sandbox-base --tag=ci
ssh my-sandbox-base.exe.xyz 'sudo apt-get update -q && sudo apt-get install -yq build-essential && sync'
ssh exe.dev pause my-sandbox-base

vm=$(ssh exe.dev cp my-sandbox-base --sandbox --json | jq -r .name)
```

- Keep `--sandbox` on `cp`. Without it the copy goes into your pool,
  even when the source is a sandbox.
- Run `sync` before you pause the base. A copy gets the base's disk, not
  its memory, and in our tests a file written just before the pause was
  empty in the copy until we added `sync`.
- `cp --json` names the new VM in `name`, where `new --json` uses
  `vm_name`. The copy keeps the base's tags.
- The paused base costs nothing for CPU and memory while it waits.

### From code, without SSH keys

The same commands work over the [HTTPS API](/docs/https-api), which suits
CI runners and agent platforms that shouldn't hold an SSH key. Make a token
that can only touch VMs tagged `ci`. On your computer:

```bash
ssh exe.dev ssh-key generate-api-key --label=ci --tag=ci --exp=90d --cmds=new,ls,rm,ssh,cp,pause,resume
```

Every VM the token creates gets the `ci` tag, and it can see and touch no
other VM. Then, wherever the job runs:

```bash
vm=$(curl -fsS -X POST https://exe.dev/exec -H "Authorization: Bearer $EXE_TOKEN" \
  -d 'new --sandbox --no-email' | jq -r .vm_name)
curl -sS -X POST https://exe.dev/exec -H "Authorization: Bearer $EXE_TOKEN" -d "ssh $vm uname -a"
curl -fsS -X POST https://exe.dev/exec -H "Authorization: Bearer $EXE_TOKEN" -d "rm $vm"
```

The API always answers in JSON. A command's exit code comes back in the
`X-Exe-Exit` trailer; see
[Run commands on VM](/docs/https-api-run-on-vm). The SDKs wrap all of
this: `exe.new(standalone=True)` in [Python](/deploy/python-sandboxes) and
`exe.new({ sandbox: true })` in [TypeScript](/deploy/typescript-sandboxes),
with pause, resume, and copy as methods. An agent can drive sandboxes
itself through the [exe.dev MCP server](/deploy/exe-mcp).

## Clean up what's left running

Scripts crash and agents forget. List the sandboxes that are running now,
with when they were made and their tags:

```bash
ssh exe.dev ls --json | jq -r '.vms[] | select(.type == "standalone" and .status == "running")
  | "\(.vm_name)\t\(.created_at)\t\(.tags // [] | join(","))"'
```

Pause the ones you'll want again and delete the rest. This deletes running
sandboxes tagged `ci` that are more than an hour old, leaving paused ones,
like a base, alone:

```bash
ssh exe.dev ls --json | jq -r '.vms[] | select(.type == "standalone" and .status == "running"
    and (.tags // [] | index("ci")) and (.created_at | fromdateiso8601) < now - 3600) | .vm_name' \
  | xargs -r ssh exe.dev rm
```

Run it from cron, or before each batch of jobs. With a `--tag=ci` token,
`ls` already lists only `ci` VMs, so the sweep can't touch anything else.

## What it costs

exe.dev sells capacity two ways.

- **Pools** are capacity you subscribe to, shared by your VMs.
  [Personal](/docs/billing/personal) is $15, $35, $75, or $155 a month for
  2, 4, 8, or 16 vCPU (with 2 GiB of memory per vCPU), for up to 50 VMs.
  [Work](/docs/billing/work) is $75 a month for the team, including 2 vCPU
  and 4 GiB across its pools; more pool capacity is $0.105 per unit-hour
  for as long as the pool has it. A VM in a pool costs nothing extra,
  running or idle, but it shares the pool's CPU with your other VMs.
- **Sandboxes** are metered on their own: $0.105 per unit-hour, where a
  unit is 2 vCPU and 4 GiB, by the second, with no minimum. On Personal
  that's on top of your subscription. On Work, sandboxes and pools share
  the included 2 vCPU and 4 GiB, and the rest is metered at the same rate.
  Paused or stopped, a sandbox isn't billed for its CPU and memory.

| Sandbox size | Units | Per hour | If it runs all month |
| --- | --- | --- | --- |
| 2 vCPU / 4 GiB | 1 | $0.105 | $76.70 |
| 4 vCPU / 8 GiB | 2 | $0.21 | $153.40 |
| 8 vCPU / 16 GiB | 4 | $0.42 | $306.80 |
| 16 vCPU / 32 GiB | 8 | $0.84 | $613.60 |

A month is 730.5 hours, as on [exe.dev/pricing](https://exe.dev/pricing).
Some worked examples:

- **CI.** 500 test jobs a day, 15 seconds each, on 2 vCPU sandboxes:
  `500 × 15 s ≈ 2.08 unit-hours` a day, about $0.22 a day or $6.56 over 30
  days, and the jobs never slow down your other VMs.
- **Agent workers.** 20 agent tasks a day, 30 minutes each, on 4 vCPU (2
  units): `20 × 0.5 h × 2 = 20 unit-hours` a day, $2.10 a day or $63 over
  30 days.
- **A worker you pause.** One 2 vCPU sandbox that works 2 hours a day and
  is paused the rest: `2 h × 30 = 60 unit-hours`, $6.30 a month. Left
  running, it would be $76.70.
- **A box that stays up.** A 2 vCPU sandbox running all month is $76.70.
  The same capacity on Personal is $15 and holds up to 50 VMs. A 2 vCPU
  sandbox costs more than $15 after about 143 hours in a month, roughly
  4¾ hours a day.
- **The one you forgot.** An 8 vCPU sandbox (4 units) left running for a
  week: `4 × 168 h × $0.105 ≈ $70.56`. Paused for that week, its CPU and
  memory cost nothing.

## Sandbox or pool?

Use a **sandbox** when the work is short or bursty and you'll throw the VM
away: CI jobs, agent tasks, untrusted code, load tests, previews. You pay
only while it runs, it can't slow down your other VMs, and on Work it
doesn't need room in a pool.

Use a **pool VM** for what stays up: a dev box, an app, a bot, a database,
an agent you talk to every day. Sharing a pool you already pay for is
far cheaper than metering the same VM around the clock. Make it with plain
`ssh exe.dev new`.

Between the two, a sandbox you pause when it's idle keeps its state for
when you come back, and costs only its disk in between.

## Troubleshooting

- **`new --sandbox` is refused on a Work team:** sandboxes are off until
  an admin runs `ssh exe.dev team settings standalone all-users` (or
  `admins-only`). The legacy Individual and Team plans don't include them.
- **`VM "…" is not running`:** the sandbox is paused. `ssh exe.dev resume
  <name>`, then try again.
- **A copy is missing files the base had:** they hadn't reached the base's
  disk when it was paused. Resume the base, run `sync`, pause it, copy
  again.
- **A copy isn't a sandbox:** `cp` without `--sandbox` puts the copy in
  your pool. Check with `ssh exe.dev ls --group=type`.
- **`--standalone cannot be combined`:** drop `--pool` or `--no-pool`.
- **Can't reach GitHub or a package registry:** the sandbox was created
  with `--egress=integrations`. Use the
  [GitHub integration](/docs/integrations-github), or `ssh exe.dev egress
  <name> all` if the job needs the internet.
- **Manage your billing:** `ssh exe.dev billing usage` shows your usage
  against your plan (`ssh exe.dev team usage` on Work, or
  [exe.dev/team/usage](https://exe.dev/team/usage)). To bring it down,
  find running sandboxes as in [Clean up](#clean-up-whats-left-running),
  then pause the ones you'll come back to and delete the rest. See
  [Billing](/docs/billing/overview) for plans and invoices.

## Frequently asked questions

### Is --sandbox the same as --standalone?

Yes. `--sandbox` is an alias for `--standalone` on both `new` and `cp`, and the docs call these VMs [standalone VMs](/docs/standalone-vms). Neither can be combined with `--pool` or `--no-pool`.

### How much does a sandbox cost?

$0.105 per unit-hour, where a unit is 2 vCPU and 4 GiB of memory, measured by the second with no minimum. A 2 vCPU sandbox that lives 15 seconds costs about $0.0004; one that runs all month costs about $76.70. On Personal it's on top of your subscription; on Work it shares the included 2 vCPU / 4 GiB with your pools. See [What it costs](#what-it-costs).

### Am I billed while a sandbox is paused?

Not for its vCPU and memory: metering stops when it's paused or stopped and starts again when you resume it. Its disk stays, so disk beyond your plan's allowance is still billed as [usage](/docs/billing/usage), and it still counts toward your VM limit. `rm` stops everything.

### What survives a pause?

Everything. `pause` snapshots the VM's memory to disk, so running processes, open files, and the disk are all there after `resume`, which in our tests took about 3 seconds and didn't reboot the VM. `restart` is different: it reboots, and processes are gone.

### When should I use a pool VM instead?

For anything that stays up. A Personal plan's 2 vCPU / 4 GiB costs $15 a month and is shared by up to 50 VMs; the same capacity as a sandbox running all month is $76.70. A sandbox wins for short or bursty jobs you want to run without taking CPU from your other VMs: below about 143 unit-hours a month, it costs less than $15.

### Can my Work team use sandboxes?

Yes, once an admin allows it: `ssh exe.dev team settings standalone all-users` (or `admins-only`), or at [exe.dev/team](https://exe.dev/team). It's off until then. Personal accounts can create them right away; the legacy Individual and Team plans can't.

### Can a sandbox reach the internet?

Yes, by default. `new --sandbox --egress=integrations` limits it to exe.dev metadata and the [integrations](/docs/integrations) attached to it, which is what you want for code you don't trust. See [egress policy](/docs/internet-access).


## Related

- [Create sandboxes from Python](https://exe-staging.dev/deploy/python-sandboxes.md): Full VMs as sandboxes. A with block creates one, runs your code, and deletes it.
- [Create sandboxes from TypeScript](https://exe-staging.dev/deploy/typescript-sandboxes.md): Full VMs as sandboxes. Create, control, and destroy them from your code.
- [Host a Claude Agent SDK app on its own VM](https://exe-staging.dev/deploy/claude-agent-sdk.md): Claude Code as a library, with a whole computer to run on.
- [Running a self-hosted GitHub Actions Runner](https://exe-staging.dev/deploy/github-actions-runner.md): Log in easily into your CI environment
- [Give any agent a sandbox over MCP](https://exe-staging.dev/deploy/exe-mcp.md): One URL gives your agent real VMs to run code on, host apps from, and hand work to.
- [Run AI-generated code safely](https://exe-staging.dev/deploy/code-interpreter.md): The model writes Python. A VM of its own runs it, keeps its variables, draws the charts.
