# Sandbox Sessions
Sandbox sessions give you a general-purpose Linux environment inside a dedicated microVM. You get shell access, HTTP command execution, file transfer, port forwarding, and optional persistent storage through workspaces.
## Create a sandbox session
```bash title="CLI"
# Ephemeral
chaser sandbox --ephemeral --json
# With a custom OCI image
chaser sandbox --ephemeral --image ghcr.io/example/dev:latest --json
# Persistent (workspace-backed)
chaser workspaces create --session-type sandbox --name dev --json
chaser sandbox --workspace dev --json
```
```bash title="REST API"
# Ephemeral
curl -sS "$CHASER_API_URL/v1/sessions" \
-H "Authorization: Bearer $CHASER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"session_type": "sandbox", "ephemeral": true}' | jq
# With image
curl -sS "$CHASER_API_URL/v1/sessions" \
-H "Authorization: Bearer $CHASER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"session_type": "sandbox", "ephemeral": true, "image": "ghcr.io/example/dev:latest"}' | jq
# Persistent
curl -sS "$CHASER_API_URL/v1/sessions" \
-H "Authorization: Bearer $CHASER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"session_type": "sandbox", "workspace": "dev"}' | jq
```
## Interactive shell
Open an interactive PTY session:
```bash
chaser shell
```
Run a one-shot command:
```bash
chaser shell -c "node -v && pwd"
```
The PTY endpoint is also available over WebSocket at `GET /v1/sessions/{id}/pty` with mode options: `human` (default), `agent`, or `exec`.
## HTTP command execution
Run commands without managing PTY transport:
```bash
# Auto-provision a sandbox and run a command
curl -sS "$CHASER_API_URL/v1/exec" \
-H "Authorization: Bearer $CHASER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"workspace": "dev", "command": "npm ci && npm test"}' | jq
# Run in an existing session
curl -sS "$CHASER_API_URL/v1/sessions//exec" \
-H "Authorization: Bearer $CHASER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"command": "ls -la /workspace", "cwd": "/workspace"}' | jq
```
See [Command Execution](/docs/sessions/command-execution) for background commands, streaming, and stdin control.
## File transfer
Upload and download files through the API or CLI:
```bash
# CLI
chaser upload ./app.js /workspace/app.js
chaser download /workspace/app.js ./app.js
# REST API upload (multipart)
curl -sS "$CHASER_API_URL/v1/sessions//upload" \
-H "Authorization: Bearer $CHASER_API_KEY" \
-F "path=/workspace/app.js" \
-F "file=@./app.js" | jq
# REST API download
curl -sS "$CHASER_API_URL/v1/sessions//download?path=/workspace/app.js" \
-H "Authorization: Bearer $CHASER_API_KEY" \
--output ./app.js
```
File transfer supports files up to 16 MB per operation.
## Port forwarding
If your application listens on a port inside the sandbox, access it through:
- **Direct URL:** `https://.chaser.sh/forward//`
- **Path style:** `https://api.chaser.sh/s//forward//`
- **Local proxy:** `chaser forward [local_port]`
```bash
# Start a dev server in the sandbox
chaser shell -c "cd /workspace && npm run dev -- --host 0.0.0.0"
# Open a local proxy to it
chaser forward 3000 8080 --open
```
## Runtime self-test
Run the built-in diagnostic to verify the sandbox environment:
```bash
chaser sessions self-test --json
```
This returns structured details about the runtime: working directory, PATH entries, detected tools (Node, Python, Git, etc.), shell configuration, and Chaser environment markers.
## OCI image support
- **Ephemeral sessions** accept an `image` parameter directly on `POST /v1/sessions`.
- **Persistent sessions** inherit the image from their workspace. Set the image when creating the workspace with `POST /v1/workspaces`.
- You cannot pass both `workspace` and `image` on the same request.
## MCP terminal tool
The `terminal` MCP tool is the recommended way for AI agents to interact with sandboxes. It auto-provisions or reuses a session and supports:
- `command` or `cmd` -- run shell commands
- `xml` -- structured file operations (`read_file`, `write_file`, `apply_edit`, `list_files`)
```bash
curl -sS "$CHASER_API_URL/v1/mcp" \
-H "Authorization: Bearer $CHASER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0", "id": 1,
"method": "tools/call",
"params": {
"name": "terminal",
"arguments": {"workspace": "dev", "command": "git status"}
}
}' | jq
```
The response includes the resolved `session_id` and `workspace_id` so follow-up calls can target the same runtime.