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

# Sandboxes

> Create, manage, and destroy isolated sandbox environments.

# Sandboxes

## Create Sandbox

<ParamField body="template" type="string" required>
  Base image template. See [Available Templates](#available-templates) below.
</ParamField>

<ParamField body="cpus" type="integer">
  Number of vCPUs (1-8, default: 2).
</ParamField>

<ParamField body="memory_mb" type="integer">
  Memory in MB (128-8192, default: 512).
</ParamField>

<ParamField body="disk_gb" type="integer">
  Disk in GB (1-50, default: 5).
</ParamField>

<ParamField body="network_mode" type="string">
  Network access: `full`, `none`, or `allowlist`.
</ParamField>

<ParamField body="allowlist" type="string[]">
  Allowed hosts when network\_mode is `allowlist`.
</ParamField>

<ParamField body="env" type="object">
  Environment variables as key-value pairs.
</ParamField>

<ParamField body="repo" type="string">
  Git repository URL to clone (HTTPS).
</ParamField>

<ParamField body="repo_token" type="string">
  PAT or OAuth token for private repositories. GitHub: `ghp_...`, GitLab: personal access token.
</ParamField>

<ParamField body="repo_branch" type="string">
  Branch to checkout (default: main/master).
</ParamField>

<ParamField body="repo_commit" type="string">
  Specific commit SHA to checkout (overrides repo\_branch).
</ParamField>

<ParamField body="repo_subdir" type="string">
  Monorepo subdirectory to extract into /workspace.
</ParamField>

<ParamField body="budget" type="number">
  Maximum spend in USD.
</ParamField>

<ParamField body="init_script" type="string">
  Shell command to run after creation.
</ParamField>

<ParamField body="timeout" type="integer">
  Idle timeout in seconds before auto-sleep.
</ParamField>

<ParamField body="packages" type="string[]">
  Packages to pre-install (npm/pip packages).
</ParamField>

<ParamField body="agents" type="string[]">
  AI agents to install: `claude`, `aider`, `codex`.
</ParamField>

```bash theme={null}
curl -X POST https://api.caged.dev/v1/sandboxes \
  -H "Authorization: Bearer caged_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "template": "node-20",
    "cpus": 2,
    "memory_mb": 1024,
    "repo": "https://github.com/user/project",
    "budget": 5.00,
    "init_script": "npm install"
  }'
```

**Private Repository Example**

```bash theme={null}
curl -X POST https://api.caged.dev/v1/sandboxes \
  -H "Authorization: Bearer caged_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "template": "node-20",
    "repo": "https://github.com/your-org/private-repo",
    "repo_token": "ghp_xxxxxxxxxxxx",
    "repo_branch": "develop",
    "agents": ["claude"],
    "budget": 10.00
  }'
```

**Response** `201 Created`

```json theme={null}
{
  "id": "cage-a1b2c3d4",
  "status": "running",
  "template": "node-20",
  "ip": "10.0.1.42",
  "cpus": 2,
  "memory_mb": 1024,
  "disk_gb": 5,
  "network_mode": "full",
  "created_at": "2026-06-08T10:00:00Z"
}
```

## List Sandboxes

```bash theme={null}
curl https://api.caged.dev/v1/sandboxes \
  -H "Authorization: Bearer caged_sk_..."
```

**Response** `200 OK`

```json theme={null}
[
  {
    "id": "cage-a1b2c3d4",
    "status": "running",
    "template": "node-20",
    "cpus": 2,
    "memory_mb": 1024,
    "created_at": "2026-06-08T10:00:00Z"
  }
]
```

## Get Sandbox

```bash theme={null}
curl https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4 \
  -H "Authorization: Bearer caged_sk_..."
```

## Execute a Command

Run a shell command inside a sandbox and get the output back. Supports pipes, redirects, and environment variables. This is how you interact with sandboxes programmatically — including prompting installed AI agents.

`POST /v1/sandboxes/{id}/exec`

<ParamField body="command" type="string" required>
  Shell command to execute. Runs via `/bin/sh -c` inside the sandbox with the sandbox's environment (including any `env` vars set at creation).
</ParamField>

```bash theme={null}
curl -X POST https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4/exec \
  -H "Authorization: Bearer caged_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"command": "python --version"}'
```

**Response** `200 OK`

```json theme={null}
{
  "output": "Python 3.12.3\n",
  "exit_code": 0
}
```

**Prompting an agent** — if the sandbox was created with `"agents": ["claude"]`, you can prompt Claude Code non-interactively:

```bash theme={null}
curl -X POST https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4/exec \
  -H "Authorization: Bearer caged_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"command": "cd /workspace && claude -p \"Summarize what this repo does\""}'
```

**Error semantics** — the three outcomes are distinguishable:

| Case                   | `exit_code` | `error` | Meaning                                |
| ---------------------- | ----------- | ------- | -------------------------------------- |
| Success                | `0`         | empty   | Command ran and succeeded              |
| Command failed         | non-zero    | empty   | Command ran; its stderr is in `output` |
| Infrastructure failure | `1`         | set     | Sandbox unreachable, not running, etc. |

<Note>
  A failed command still returns HTTP `200` — the API call succeeded; the command result is data. Exec requests can run for up to 5 minutes, so long agent prompts are fine.
</Note>

For a fully interactive TTY session (e.g. the Claude Code TUI), use the [terminal WebSocket](/api-reference/sessions) instead: `wss://api.caged.dev/v1/sandboxes/{id}/terminal`.

## Pause Sandbox

Freezes the sandbox in memory. No compute charges while paused. An auto-snapshot is created.

```bash theme={null}
curl -X POST https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4/pause \
  -H "Authorization: Bearer caged_sk_..."
```

## Resume Sandbox

Unfreezes a paused sandbox.

```bash theme={null}
curl -X POST https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4/resume \
  -H "Authorization: Bearer caged_sk_..."
```

## Destroy Sandbox

Permanently destroys a sandbox and all its data.

<Warning>
  This action is irreversible. Create a snapshot first if you need to preserve the state.
</Warning>

```bash theme={null}
curl -X DELETE https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4 \
  -H "Authorization: Bearer caged_sk_..."
```

**Response** `204 No Content`

## Available Templates

Pre-configured sandbox environments with common runtimes and tools.

### JavaScript / TypeScript

| Template  | Runtime          | Includes                    |
| --------- | ---------------- | --------------------------- |
| `node-22` | Node.js 22.x LTS | npm, yarn, pnpm, typescript |
| `node-20` | Node.js 20.x LTS | npm, yarn, pnpm, typescript |

### Python

| Template     | Runtime     | Includes                             |
| ------------ | ----------- | ------------------------------------ |
| `python-312` | Python 3.12 | pip, poetry, virtualenv, black, ruff |
| `python-311` | Python 3.11 | pip, poetry, virtualenv, black, ruff |

### Base

| Template  | Description                                                                      |
| --------- | -------------------------------------------------------------------------------- |
| `minimal` | Ubuntu 24.04 with SSH, git, curl, build-essential. Install any runtime yourself. |

<Tip>
  Using `minimal`? You can install any runtime manually. The sandbox persists your changes until destroyed.
</Tip>
