# Daytona User Guide

Daytona is a cloud development sandbox platform that creates isolated, on-demand environments for running code, automating GUI interactions, managing files, and integrating with AI agents. It provides multi-language SDKs (Python, TypeScript, Go, Java, Ruby), a full-featured CLI, and an MCP server for LLM tool integration. Sandboxes spin up in seconds, run any Docker image, and support features like code interpretation, computer use (VNC-based GUI automation), Git operations, LSP intelligence, PTY sessions, snapshots, and persistent volumes.

---

## 1. Quick Start

### 1.1 Create Your First Sandbox (Python)

```python
from daytona import Daytona

daytona = Daytona()
sandbox = daytona.create()

response = sandbox.process.exec("echo 'Hello from Daytona!'")
print(response.result)
# Output: Hello from Daytona!

daytona.delete(sandbox)
```

### 1.2 Create Your First Sandbox (TypeScript)

```typescript
import { Daytona } from '@daytona/sdk'

async function main() {
  const daytona = new Daytona()

  const sandbox = await daytona.create()

  const response = await sandbox.process.executeCommand('echo "Hello from Daytona!"')
  console.log(response.result)
  // Output: Hello from Daytona!

  await sandbox.delete()
}

main().catch(console.error)
```

### 1.3 Create Your First Sandbox (CLI)

```bash
# Authenticate
daytona login

# Create a sandbox
daytona create

# List your sandboxes
daytona list
```

> [!NOTE]
> Before using any SDK, set the `DAYTONA_API_KEY` environment variable. You can generate an API key from the [Daytona dashboard](https://app.daytona.io). For the CLI, run `daytona login` to authenticate via browser.

### 1.4 Run Python Code in a Sandbox

```python
from daytona import Daytona

daytona = Daytona()
sandbox = daytona.create()

result = sandbox.code_interpreter.run_code("print('2 + 2 =', 2 + 2)")
print(result.stdout)
# Output: 2 + 2 = 4

daytona.delete(sandbox)
```

---

## 2. Installation

### 2.1 Python SDK

**Requirements:** Python 3.9 or later.

```bash
pip install daytona
```

The package is also published under the alias `daytona_sdk`:

```bash
pip install daytona_sdk
```

### 2.2 TypeScript SDK

**Requirements:** Node.js 18 or later.

```bash
npm install @daytona/sdk
```

Or with yarn:

```bash
yarn add @daytona/sdk
```

### 2.3 Go SDK

**Requirements:** Go 1.21 or later.

```bash
go get github.com/daytonaio/daytona/libs/sdk-go
```

### 2.4 Java SDK

**Requirements:** Java 11 or later with Maven or Gradle.

Add the dependency to your `pom.xml`:

```xml
<dependency>
  <groupId>io.daytona</groupId>
  <artifactId>sdk</artifactId>
  <version>LATEST</version>
</dependency>
```

### 2.5 Ruby SDK

**Requirements:** Ruby 3.0 or later.

```bash
gem install daytona
```

### 2.6 CLI Installation

Download the Daytona CLI binary for your platform from the [Daytona releases page](https://github.com/daytonaio/daytona/releases) or install via your package manager. After installation, verify:

```bash
daytona version
```

Expected output:

```
Daytona CLI version v0.x.x
```

> [!TIP]
> Set up shell autocompletion immediately after installing the CLI. Run `daytona autocomplete bash` (or `zsh`, `fish`, `powershell`) to enable tab-completion for all commands and flags.

### 2.7 Shell Autocompletion

The CLI supports autocompletion for **bash**, **zsh**, **fish**, and **powershell**.

```bash
# Bash
daytona autocomplete bash
# Then: source ~/.bashrc

# Zsh
daytona autocomplete zsh
# Then: source ~/.zshrc

# Fish
daytona autocomplete fish
# Then: source ~/.config/fish/config.fish

# PowerShell
daytona autocomplete powershell
# Then: . ~/Documents/WindowsPowerShell/Microsoft.PowerShell_profile.ps1
```

The completion script is automatically injected into your shell profile. Restart your terminal or source the profile file to activate.

> [!NOTE]
> For bash, ensure `bash-completion` is installed on your system. See the [Daytona docs on autocomplete](https://www.daytona.io/docs/tools/cli/#daytona-autocomplete) for platform-specific instructions.

---

## 3. Configuration

### 3.1 SDK Authentication

All SDKs authenticate via API key or JWT token. The simplest approach is to set environment variables:

| Variable | Purpose |
|---|---|
| `DAYTONA_API_KEY` | API key for authentication (primary method) |
| `DAYTONA_API_URL` | API endpoint (default: `https://app.daytona.io/api`) |
| `DAYTONA_JWT_TOKEN` | JWT token (alternative to API key) |
| `DAYTONA_ORGANIZATION_ID` | Required when using JWT authentication |
| `DAYTONA_TARGET` | Target region for sandbox placement |

**Python explicit configuration:**

```python
from daytona import Daytona, DaytonaConfig

config = DaytonaConfig(
    api_key="your-api-key",
    api_url="https://app.daytona.io/api",  # default
    target="us",                            # optional region
    connection_pool_maxsize=250,            # default; set None for unlimited
)
daytona = Daytona(config)
```

**TypeScript explicit configuration:**

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona({
  apiKey: 'your-api-key',
  apiUrl: 'https://app.daytona.io/api',
  target: 'us',
})
```

**Go explicit configuration:**

```go
import "github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"

client, err := daytona.NewClient(daytona.WithAPIKey("your-api-key"))
```

> [!IMPORTANT]
> The `server_url` configuration field is **deprecated**. Always use `api_url` instead. If both are provided, `api_url` takes precedence. `server_url` will be removed in a future release.

### 3.2 JWT Authentication

For service-to-service flows, use JWT tokens with an organization ID:

```python
from daytona import Daytona, DaytonaConfig

config = DaytonaConfig(
    jwt_token="your-jwt-token",
    organization_id="your-organization-id",
)
daytona = Daytona(config)
```

### 3.3 CLI Configuration

The CLI stores configuration in a JSON file at:

- `$DAYTONA_CONFIG_DIR/config.json` (if `DAYTONA_CONFIG_DIR` is set)
- `$XDG_CONFIG_HOME/daytona/config.json` (Linux/macOS default)
- `%APPDATA%/daytona/config.json` (Windows default)

The configuration file contains profiles with API URLs and authentication tokens:

```json
{
  "activeProfile": "default",
  "profiles": [
    {
      "id": "default",
      "name": "Default",
      "api": {
        "url": "https://app.daytona.io/api",
        "key": "dc_your_api_key"
      },
      "activeOrganizationId": "org-id-here"
    }
  ]
}
```

**Environment variable overrides:** Setting both `DAYTONA_API_URL` and `DAYTONA_API_KEY` as environment variables bypasses the config file entirely, creating an ephemeral "env" profile.

### 3.4 CLI Authentication

```bash
# Interactive browser-based login (Auth0 OAuth)
daytona login

# Logout and clear stored tokens
daytona logout
```

The login flow opens your browser for Auth0 authentication, then stores the access and refresh tokens in your CLI config. Tokens are automatically refreshed when they expire.

**Auth0 environment variables** (for custom identity providers or CI/CD):

| Variable | Purpose |
|---|---|
| `DAYTONA_AUTH0_DOMAIN` | Auth0 domain |
| `DAYTONA_AUTH0_CLIENT_ID` | Auth0 client ID |
| `DAYTONA_AUTH0_CLIENT_SECRET` | Auth0 client secret |
| `DAYTONA_AUTH0_CALLBACK_PORT` | Local callback port for OAuth redirect |
| `DAYTONA_AUTH0_AUDIENCE` | Auth0 audience |

### 3.5 Connection Pool Tuning

The Python SDK defaults to a connection pool of 250 simultaneous HTTP connections. For workloads with many concurrent long-lived operations (PTY sessions, exec sessions, code interpreter), set `connection_pool_maxsize=None` to remove the limit:

```python
config = DaytonaConfig(
    api_key="your-key",
    connection_pool_maxsize=None,  # unlimited connections
)
```

---

## 4. Core Usage

### 4.1 Sandbox Lifecycle

Sandboxes follow a defined state machine:

```
creating --> started <--> stopped --> archived --> destroyed
```

Additional transient states include: `pending_build`, `building_snapshot`, `pulling_snapshot`, `resizing`, `snapshotting`, `forking`, `restoring`, `starting`, `stopping`, `archiving`, `destroying`, `error`, `build_failed`, and `unknown`.

**Python lifecycle example:**

```python
from daytona import Daytona

daytona = Daytona()

# Create (state: creating -> started)
sandbox = daytona.create()
print(f"Sandbox {sandbox.id} is {sandbox.state}")

# Stop (state: started -> stopped)
sandbox.stop()

# Start again (state: stopped -> started)
sandbox.start()

# Get an existing sandbox by ID
same_sandbox = daytona.get(sandbox.id)

# Delete permanently (state: -> destroyed)
daytona.delete(sandbox)
```

**TypeScript lifecycle example:**

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()

const sandbox = await daytona.create()
console.log(`Sandbox ${sandbox.id} is ${sandbox.state}`)

await sandbox.stop()
await sandbox.start()

const existing = await daytona.get(sandbox.id)

await sandbox.delete()
```

### 4.2 Listing Sandboxes

**Python:**

```python
result = daytona.list()
print(f"Total sandboxes: {result.total}")
for sb in result.items:
    print(f"  {sb.id} - {sb.state}")
```

**CLI:**

```bash
# Default table output
daytona list

# JSON output
daytona list -f json

# YAML output
daytona list -f yaml
```

### 4.3 Creating Sandboxes from Images

Use `CreateSandboxFromImageParams` to specify a custom Docker image:

```python
from daytona import Daytona, CreateSandboxFromImageParams

daytona = Daytona()
sandbox = daytona.create(
    CreateSandboxFromImageParams(
        image="ubuntu:latest",
        language="python",
        env_vars={"MY_VAR": "hello"},
        auto_stop_interval=30,   # minutes; 0 = never
    )
)
```

### 4.4 Creating Sandboxes from Snapshots

Snapshots are pre-built environments that launch faster than building from an image:

```python
from daytona import Daytona, CreateSandboxFromSnapshotParams

daytona = Daytona()
sandbox = daytona.create(
    CreateSandboxFromSnapshotParams(
        snapshot="my-python-snapshot",
        language="python",
    )
)
```

### 4.5 Declarative Image Builder

The `Image` class provides a fluent, declarative API for building custom sandbox images without writing Dockerfiles manually.

**Factory methods:**

| Method | Description |
|---|---|
| `Image.base(image)` | Start from any Docker image |
| `Image.debian_slim(python_version)` | Debian slim with Python (3.9-3.13) |
| `Image.from_dockerfile(path)` | Build from an existing Dockerfile |

**Supported Python versions:** 3.9, 3.10, 3.11, 3.12, 3.13. If no version is specified, the local Python version is matched.

**Builder methods (chainable):**

| Method | Description |
|---|---|
| `.pip_install(*packages)` | Install pip packages |
| `.pip_install_from_requirements(path)` | Install from requirements.txt |
| `.pip_install_from_pyproject(path, optional_deps)` | Install from pyproject.toml |
| `.run_commands(*commands)` | Run shell commands |
| `.env(env_vars)` | Set environment variables |
| `.workdir(path)` | Set working directory |
| `.entrypoint(commands)` | Set container entrypoint |
| `.cmd(commands)` | Set default command |
| `.add_local_file(local, remote)` | Copy a local file into the image |
| `.add_local_dir(local, remote)` | Copy a local directory into the image |
| `.dockerfile_commands(commands)` | Add raw Dockerfile instructions |

**Example: Python data science environment:**

```python
from daytona import Daytona, CreateSandboxFromImageParams, Image

image = (
    Image.debian_slim("3.12")
    .pip_install("numpy", "pandas", "matplotlib", "scikit-learn")
    .env({"PYTHONDONTWRITEBYTECODE": "1"})
    .workdir("/home/daytona/project")
)

daytona = Daytona()
sandbox = daytona.create(
    CreateSandboxFromImageParams(image=image),
    on_snapshot_create_logs=print,  # stream build logs
)
```

**Example: Node.js + TypeScript environment:**

```python
from daytona import Daytona, CreateSandboxFromImageParams, Image

image = Image.base("ubuntu:22.04").run_commands(
    "apt-get update",
    "apt-get install -y --no-install-recommends curl ca-certificates",
    "curl -fsSL https://deb.nodesource.com/setup_20.x | bash -",
    "apt-get install -y nodejs",
    "npm install -g ts-node typescript",
)

daytona = Daytona()
sandbox = daytona.create(
    CreateSandboxFromImageParams(image=image, language="typescript"),
    timeout=200,
    on_snapshot_create_logs=print,
)
```

**TypeScript equivalent:**

```typescript
import { Daytona, Image } from '@daytona/sdk'

const daytona = new Daytona()
const sandbox = await daytona.create(
  {
    image: Image.base('ubuntu:22.04').runCommands(
      'apt-get update',
      'apt-get install -y --no-install-recommends python3 python3-pip',
    ),
    language: 'python',
  },
  { timeout: 200, onSnapshotCreateLogs: console.log },
)
```

### 4.6 Sandbox Parameters Reference

| Parameter | Type | Default | Description |
|---|---|---|---|
| `name` | string | auto-generated | Human-readable sandbox name |
| `language` | enum | `"python"` | `python`, `typescript`, or `javascript` |
| `os_user` | string | `"daytona"` | OS user inside the sandbox |
| `env_vars` | dict | `{}` | Environment variables |
| `labels` | dict | `{}` | Custom metadata labels |
| `public` | bool | `false` | Whether sandbox is publicly accessible |
| `auto_stop_interval` | int | `15` | Minutes of inactivity before auto-stop (0 = never) |
| `auto_archive_interval` | int | `10080` (7d) | Minutes stopped before auto-archive (0 = max interval) |
| `auto_delete_interval` | int | disabled | Minutes stopped before auto-delete (negative = disabled, 0 = immediate) |
| `volumes` | list | `[]` | Volume mounts to attach |
| `network_block_all` | bool | `false` | Block all outbound network access |
| `network_allow_list` | string | `""` | Comma-separated CIDR allowlist |
| `ephemeral` | bool | `false` | If true, sets `auto_delete_interval=0` |
| `image` | string/Image | default | Docker image or Image builder (from-image only) |
| `resources` | Resources | default | CPU/memory/disk (from-image only) |
| `snapshot` | string | none | Snapshot name (from-snapshot only) |

> [!WARNING]
> Setting `ephemeral=True` will automatically delete the sandbox when it stops. If you also set `auto_delete_interval`, it will be ignored and overridden to 0. The SDK emits a warning in this case.

### 4.7 Sandbox Classes

Sandboxes come in three resource classes:

| Class | Resources |
|---|---|
| **small** | Limited CPU, memory, and disk |
| **medium** | Moderate resources |
| **large** | Maximum resources |

Resource availability and exact specifications depend on your organization's plan and the target region.

### 4.8 Labels

Labels are key-value pairs for organizing and filtering sandboxes:

```python
# Set labels at creation
sandbox = daytona.create(
    CreateSandboxFromSnapshotParams(
        labels={"project": "data-pipeline", "env": "staging"}
    )
)

# Update labels on a running sandbox
sandbox.set_labels({"project": "data-pipeline", "env": "production"})
```

```typescript
await sandbox.setLabels({ public: 'true', environment: 'production' })
```

---

## 5. Common Tasks

### 5.1 Execute Shell Commands

```python
response = sandbox.process.exec("ls -la /home/daytona")
print(response.result)
print(f"Exit code: {response.exit_code}")
```

```typescript
const response = await sandbox.process.executeCommand('ls -la /home/daytona')
console.log(response.result)
console.log(`Exit code: ${response.exitCode}`)
```

### 5.2 Run Code with the Code Interpreter

The code interpreter executes Python code over WebSocket with streaming support:

```python
result = sandbox.code_interpreter.run_code("""
import math
for i in range(5):
    print(f"sqrt({i}) = {math.sqrt(i):.4f}")
""")
print(result.stdout)
if result.error:
    print(f"Error: {result.error.name}: {result.error.value}")
```

**With streaming callbacks (TypeScript):**

```typescript
const result = await sandbox.codeInterpreter.runCode(
  `
import time
for i in range(5):
    print(f"Step {i}")
    time.sleep(0.5)
`,
  {
    onStdout: (msg) => process.stdout.write(`STDOUT: ${msg.output}`),
    onStderr: (msg) => process.stderr.write(`STDERR: ${msg.output}`),
    onError: (err) => console.error(`ERROR: ${err.name}: ${err.value}`),
    timeout: 30,
  },
)
```

### 5.3 Stateful Code Interpreter Contexts

Variables persist across `run_code` calls within the same context. Create isolated contexts when you need separate state:

```python
# Default context - state persists
sandbox.code_interpreter.run_code("counter = 1")
result = sandbox.code_interpreter.run_code("counter += 1; print(counter)")
print(result.stdout)  # Output: 2

# Isolated context
ctx = sandbox.code_interpreter.create_context()
sandbox.code_interpreter.run_code("x = 42", context=ctx)
result = sandbox.code_interpreter.run_code("print(x)", context=ctx)
print(result.stdout)  # Output: 42

# Clean up
sandbox.code_interpreter.delete_context(ctx)
```

```typescript
const ctx = await sandbox.codeInterpreter.createContext()
await sandbox.codeInterpreter.runCode('x = 10', { context: ctx })
const result = await sandbox.codeInterpreter.runCode('print(x)', { context: ctx })
console.log(result.stdout) // Output: 10
await sandbox.codeInterpreter.deleteContext(ctx)
```

### 5.4 Run Code with Language Runtime (codeRun)

For non-Python languages, use `process.code_run` which executes via the sandbox runtime:

```typescript
// TypeScript code execution
const result = await sandbox.process.codeRun('console.log("Hello World from code!")')
console.log(result.result)

// Python code execution via process
const pyResult = await sandbox.process.codeRun('print("Hello from Python")')
console.log(pyResult.result)
```

The `code_run` method also returns chart artifacts when matplotlib plots are generated:

```python
response = sandbox.process.code_run("""
import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [1, 4, 9])
plt.title("Quadratic")
plt.show()
""")

if response.artifacts and response.artifacts.charts:
    for chart in response.artifacts.charts:
        print(f"Chart type: {chart.type}, title: {chart.title}")
        if chart.png:
            import base64
            img_bytes = base64.b64decode(chart.png)
            with open("chart.png", "wb") as f:
                f.write(img_bytes)
```

### 5.5 File System Operations

**Upload files:**

```python
from daytona import FileUpload

# Upload from bytes
sandbox.fs.upload_file(b"Hello, world!", "/home/daytona/hello.txt")

# Upload multiple files (from bytes and local paths)
sandbox.fs.upload_files([
    FileUpload(source=b"content here", destination="project/config.json"),
    FileUpload(source="/local/path/to/file.txt", destination="project/data.txt"),
])
```

**Download files:**

```python
from daytona import FileDownloadRequest

# Download to memory
content = sandbox.fs.download_file("project/config.json")
print(content.decode("utf-8"))

# Download multiple files (some to disk, some to memory)
results = sandbox.fs.download_files([
    FileDownloadRequest(source="project/config.json", destination="local-config.json"),
    FileDownloadRequest(source="project/data.txt"),  # to memory
])
for result in results:
    if result.error:
        print(f"Error: {result.error}")
    elif isinstance(result.result, str):
        print(f"Saved to {result.result}")
    elif result.result:
        print(f"Got {len(result.result)} bytes in memory")
```

**List, search, and manipulate files:**

```python
# List files
files = sandbox.fs.list_files("/home/daytona")

# Create a directory
sandbox.fs.create_folder("project-files", "755")

# Search for files by pattern
matches = sandbox.fs.search_files("project-files", "*.json")

# Find files containing specific text
matches = sandbox.fs.find_files("project-files", "var obj1 = new Base();")

# Replace text across files
sandbox.fs.replace_in_files(
    ["project/config.json"],
    '"debug": true',
    '"debug": false',
)
```

**TypeScript equivalents:**

```typescript
// Upload
await sandbox.fs.uploadFile(Buffer.from('Hello, World!'), '/home/daytona/hello.txt')

// Download
const content = await sandbox.fs.downloadFile('/home/daytona/hello.txt')
console.log(content.toString())

// Create folder
await sandbox.fs.createFolder('/home/daytona/new-dir', '755')

// List files
const files = await sandbox.fs.listFiles('/home/daytona')
```

### 5.6 Git Operations

```python
# Clone a repository
sandbox.git.clone(
    "https://github.com/example/repo",
    "my-project",
    "main",  # branch
)

# Pull latest changes
sandbox.git.pull("my-project")
```

### 5.7 Exec Sessions (Persistent Shell State)

Exec sessions maintain shell state (environment variables, working directory) across multiple commands:

```typescript
// Create a session
await sandbox.process.createSession('my-session')

// Execute commands in the session
const cmd1 = await sandbox.process.executeSessionCommand('my-session', {
  command: 'export FOO=BAR',
})

// Environment persists across commands
const cmd2 = await sandbox.process.executeSessionCommand('my-session', {
  command: 'echo $FOO',
})
console.log(cmd2.stdout) // Output: BAR

// Async execution with log streaming
const asyncCmd = await sandbox.process.executeSessionCommand('my-session', {
  command: 'for i in 1 2 3; do echo $i; sleep 1; done',
  runAsync: true,
})

// Stream logs
await sandbox.process.getSessionCommandLogs(
  'my-session',
  asyncCmd.cmdId,
  (stdout) => console.log('[STDOUT]:', stdout),
  (stderr) => console.log('[STDERR]:', stderr),
)

// Send input to a running command
await sandbox.process.sendSessionCommandInput('my-session', asyncCmd.cmdId, 'some input')

// Clean up
await sandbox.process.deleteSession('my-session')
```

### 5.8 PTY Sessions (Interactive Terminals)

PTY sessions provide full terminal emulation with resize support:

```python
from daytona import PtySize

# Create a PTY session
pty = sandbox.process.create_pty_session(
    id="my-terminal",
    pty_size=PtySize(cols=120, rows=30),
)

# Send commands
pty.send_input("echo 'Hello from PTY'\n")

# Resize the terminal
pty.resize(PtySize(cols=80, rows=25))

# Read output using iterator
for data in pty:
    text = data.decode("utf-8", errors="replace")
    print(text, end="")

# Or use wait() with a callback and timeout
import threading
thread = threading.Thread(target=pty.wait, args=(handle_data, 10))
thread.start()

# Send exit to close
pty.send_input("exit\n")

# Or kill forcibly
pty.kill()

print(f"Exit code: {pty.exit_code}")
```

### 5.9 Computer Use (GUI Automation)

Computer use provides VNC-based mouse, keyboard, and screen control for GUI automation:

**Mouse operations:**

```python
# Get current position
pos = sandbox.computer_use.mouse.get_position()
print(f"Mouse at: {pos.x}, {pos.y}")

# Move to coordinates
sandbox.computer_use.mouse.move(100, 200)

# Click (button: "left", "right", "middle"; count for double-click)
sandbox.computer_use.mouse.click(100, 200, button="left")

# Drag from one point to another
sandbox.computer_use.mouse.drag(100, 200, 300, 400)

# Scroll
sandbox.computer_use.mouse.scroll(0, -3)  # scroll up
```

**Keyboard operations:**

```python
# Type text
sandbox.computer_use.keyboard.type("Hello, World!")

# Press a key
sandbox.computer_use.keyboard.press("enter")

# Hotkey combinations
sandbox.computer_use.keyboard.hotkey("ctrl", "c")
```

**Screenshots:**

```python
from daytona import ScreenshotOptions, ScreenshotRegion

# Full screen screenshot
screenshot = sandbox.computer_use.screen.take_screenshot()

# Screenshot with options
screenshot = sandbox.computer_use.screen.take_screenshot(
    options=ScreenshotOptions(
        show_cursor=True,
        fmt="png",
        quality=80,
        scale=0.5,
    )
)

# Screenshot of a region
screenshot = sandbox.computer_use.screen.take_screenshot(
    region=ScreenshotRegion(x=0, y=0, width=800, height=600)
)
```

> [!CAUTION]
> Known issue ([#4417](https://github.com/daytonaio/daytona/issues/4417)): Named keys like `Escape` may produce `shift+escape` due to upstream robotgo behavior. If you encounter unexpected key behavior, use the key's lowercase name or test with simple keys first.

### 5.10 Language Server Protocol (LSP)

Start a language server for code intelligence:

```python
from daytona import LspCompletionPosition

# Start an LSP server
lsp = sandbox.create_lsp_server("typescript", "my-project")
lsp.start()

# Open a document
lsp.did_open("my-project/src/index.ts")

# Get document symbols
symbols = lsp.document_symbols("my-project/src/index.ts")
print("Symbols:", symbols)

# Get completions at a position
completions = lsp.completions(
    "my-project/src/index.ts",
    LspCompletionPosition(line=12, character=18),
)
print("Completions:", completions)

# Notify of document close
lsp.did_close("my-project/src/index.ts")
```

### 5.11 Chart Generation and Extraction

When executing matplotlib code via `process.code_run`, Daytona automatically extracts chart data:

```python
from daytona import (
    Daytona, CreateSandboxFromImageParams, Image,
    Chart, ChartType, LineChart, BarChart, PieChart,
    ScatterChart, BoxAndWhiskerChart, CompositeChart,
)

daytona = Daytona()
sandbox = daytona.create(
    CreateSandboxFromImageParams(
        image=Image.debian_slim("3.13").pip_install("matplotlib"),
    ),
    on_snapshot_create_logs=print,
)

code = """
import matplotlib.pyplot as plt
plt.bar(['A', 'B', 'C'], [10, 20, 15])
plt.title('Sales by Region')
plt.xlabel('Region')
plt.ylabel('Revenue ($M)')
plt.show()
"""

response = sandbox.process.code_run(code)
if response.artifacts and response.artifacts.charts:
    for chart in response.artifacts.charts:
        print(f"Type: {chart.type}, Title: {chart.title}")
        if isinstance(chart, BarChart):
            for elem in chart.elements:
                print(f"  {elem.label}: {elem.value}")

daytona.delete(sandbox)
```

Supported chart types:

| Type | Class | Data Elements |
|---|---|---|
| `line` | `LineChart` | `PointData` (label, points) |
| `scatter` | `ScatterChart` | `PointData` (label, points) |
| `bar` | `BarChart` | `BarData` (label, value, group) |
| `pie` | `PieChart` | `PieData` (label, angle, radius) |
| `box_and_whisker` | `BoxAndWhiskerChart` | `BoxAndWhiskerData` (label, min, Q1, median, Q3, max, outliers) |
| `composite_chart` | `CompositeChart` | Nested sub-charts |

### 5.12 Network Controls

Control outbound network access per sandbox:

```python
from daytona import CreateSandboxFromSnapshotParams

# Default: all network access allowed
sandbox = daytona.create()

# Block all outbound network access
sandbox = daytona.create(
    CreateSandboxFromSnapshotParams(network_block_all=True)
)

# Allow only specific CIDR ranges
sandbox = daytona.create(
    CreateSandboxFromSnapshotParams(
        network_allow_list="192.168.1.0/16,10.0.0.0/24"
    )
)
```

### 5.13 Volumes (Persistent Storage)

Volumes persist data across sandbox lifecycles. Multiple sandboxes can mount the same volume:

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()

// Create or get a volume (true = create if not exists)
const volume = await daytona.volume.get('my-volume', true)

// Mount to a sandbox
const sandbox1 = await daytona.create({
  language: 'typescript',
  volumes: [{ volumeId: volume.id, mountPath: '/home/daytona/data' }],
})

// Write data
await sandbox1.fs.uploadFile(Buffer.from('shared data'), '/home/daytona/data/shared.txt')

// Mount same volume to another sandbox
const sandbox2 = await daytona.create({
  language: 'typescript',
  volumes: [{ volumeId: volume.id, mountPath: '/home/daytona/files' }],
})

// Read the data written by sandbox1
const files = await sandbox2.fs.listFiles('/home/daytona/files')
console.log('Shared files:', files)
```

**Subpath mounting** isolates specific directories within a volume:

```typescript
const sandbox = await daytona.create({
  volumes: [{ volumeId: volume.id, mountPath: '/data', subpath: 'users/alice' }],
})
// Only sees files within volume-root/users/alice/
```

**CLI volume commands:**

```bash
daytona volume list
daytona volume list -f json
```

### 5.14 Snapshots

Snapshots capture the full state of a sandbox for fast reproduction:

```python
# List snapshots
page, limit = 1, 10
snapshots = daytona.snapshot.list(page=page, limit=limit)
for snap in snapshots.items:
    print(f"{snap.name} (state: {snap.state})")

# Create a sandbox from a snapshot
sandbox = daytona.create(
    CreateSandboxFromSnapshotParams(snapshot="my-snapshot")
)
```

**Go snapshot example:**

```go
ctx := context.Background()
page := 1
limit := 5
snapshots, err := client.Snapshot.List(ctx, &page, &limit)
if err != nil {
    log.Fatalf("Failed to list snapshots: %v", err)
}
log.Printf("Total snapshots: %d\n", snapshots.Total)
```

**CLI snapshot commands:**

```bash
daytona snapshot list
daytona snapshot list -f json
```

### 5.15 Organizations

Organizations group users, sandboxes, and resources. Switch between organizations in the CLI:

```bash
daytona organization list
daytona organization use
```

### 5.16 Auto-Stop, Auto-Archive, and Auto-Delete

Control sandbox lifecycle automation:

```python
sandbox = daytona.create(
    CreateSandboxFromSnapshotParams(
        auto_stop_interval=30,      # stop after 30 min idle
        auto_archive_interval=1440, # archive after 1 day stopped
        auto_delete_interval=4320,  # delete after 3 days stopped
    )
)
```

**Ephemeral sandboxes** delete immediately upon stopping:

```python
sandbox = daytona.create(
    CreateSandboxFromSnapshotParams(ephemeral=True)
)
# Sandbox is automatically deleted when it stops
```

### 5.17 Preview URLs

Get a public preview URL for a sandbox port:

```bash
daytona preview-url <sandbox-id>
```

### 5.18 SSH into a Sandbox

```bash
daytona ssh <sandbox-id>
```

### 5.19 Execute Commands via CLI

```bash
daytona exec <sandbox-id> -- echo "Hello from CLI"
```

### 5.20 Using the MCP Server

Daytona includes a Model Context Protocol (MCP) server for AI agent integration. The MCP server exposes sandbox tools (create, destroy, file operations, command execution, Git, preview URLs) via the MCP standard.

```bash
daytona mcp
```

The MCP server provides these tools:

| Tool | Description |
|---|---|
| `CreateSandbox` | Create a new sandbox |
| `DestroySandbox` | Delete a sandbox |
| `FileUpload` | Upload a file to a sandbox |
| `FileDownload` | Download a file from a sandbox |
| `FileInfo` | Get file metadata |
| `ListFiles` | List files in a directory |
| `MoveFile` | Move or rename a file |
| `DeleteFile` | Delete a file |
| `CreateFolder` | Create a directory |
| `ExecuteCommand` | Run a shell command |
| `PreviewLink` | Get a preview URL |
| `GitClone` | Clone a Git repository |

### 5.21 Output Formatting

The CLI supports multiple output formats:

```bash
# Default table format
daytona list

# JSON output
daytona list -f json

# YAML output
daytona list -f yaml
```

The `-f` flag works with `list`, `info`, and other read commands.

### 5.22 Region Selection

Target a specific region when creating sandboxes:

```python
config = DaytonaConfig(
    api_key="your-key",
    target="us",  # or "eu", etc.
)
daytona = Daytona(config)
```

Or via environment variable:

```bash
export DAYTONA_TARGET=eu
```

### 5.23 Pagination

List operations support pagination:

```python
# Python
result = daytona.list()  # uses defaults
print(f"Page items: {len(result.items)}, Total: {result.total}")
```

```go
// Go
page := 1
limit := 10
result, err := client.List(ctx, &page, &limit)
```

### 5.24 Async Python SDK

The Python SDK provides async variants for all operations:

```python
import asyncio
from daytona import Daytona

async def main():
    daytona = Daytona()
    sandbox = await daytona.create_async()

    result = await sandbox.code_interpreter.run_code_async(
        "print('async hello')"
    )
    print(result.stdout)

    await daytona.delete_async(sandbox)

asyncio.run(main())
```

### 5.25 Streaming Build Logs

Monitor sandbox image builds in real time:

```python
sandbox = daytona.create(
    CreateSandboxFromImageParams(
        image=Image.debian_slim("3.12").pip_install("tensorflow"),
    ),
    on_snapshot_create_logs=print,
)
```

```typescript
const sandbox = await daytona.create(
  { image: Image.debianSlim('3.12').pipInstall('tensorflow') },
  { onSnapshotCreateLogs: console.log },
)
```

### 5.26 Environment Variables in Sandboxes

Set environment variables at creation or pass them to code execution:

```python
# At creation
sandbox = daytona.create(
    CreateSandboxFromSnapshotParams(
        env_vars={"DATABASE_URL": "postgres://...", "API_KEY": "secret"}
    )
)

# At code execution time
result = sandbox.code_interpreter.run_code(
    "import os; print(os.environ['MY_VAR'])",
    envs={"MY_VAR": "runtime-value"},
)
```

---

## 6. Troubleshooting

### 6.1 Authentication Failures

**Error:** `DaytonaAuthenticationError` (HTTP 401)

**Cause:** Invalid, expired, or missing API key or JWT token.

**Solution:**
1. Verify your API key is correct: `echo $DAYTONA_API_KEY`
2. If using the CLI, re-authenticate: `daytona login`
3. If using JWT, ensure `organization_id` is also set
4. Check that the API URL matches your environment

**Prevention:** Store API keys in environment variables rather than hardcoding them. Use the CLI's profile system for persistent authentication.

### 6.2 Authorization Denied

**Error:** `DaytonaAuthorizationError` (HTTP 403)

**Cause:** Your account lacks permission for the requested operation, or the organization is suspended.

**Solution:** Verify your role within the organization. Contact your organization admin for elevated permissions.

**Prevention:** Use the organization management commands to verify your access level before performing admin operations.

### 6.3 Sandbox Not Found

**Error:** `DaytonaNotFoundError` (HTTP 404)

**Cause:** The sandbox ID is invalid, or the sandbox was already deleted/archived.

**Solution:**
1. List active sandboxes: `daytona list`
2. Check if the sandbox was auto-deleted or auto-archived
3. Verify the sandbox ID is correct

**Prevention:** Use `auto_delete_interval=-1` (disabled) for sandboxes you need to persist.

### 6.4 Sandbox Creation Timeout

**Error:** `DaytonaTimeoutError` during `daytona.create()`

**Cause:** Image build is taking longer than the timeout, or the region is experiencing high demand.

**Solution:**
1. Increase the timeout: `daytona.create(params, timeout=300)`
2. Use snapshots instead of building from image for faster starts
3. Pre-build complex images and create snapshots from them

**Prevention:** Use `Image.debian_slim()` or snapshots for fastest creation. Reserve custom `Image.base()` builds for when you need specific system packages.

### 6.5 Code Interpreter Timeout

**Error:** `DaytonaTimeoutError` during `code_interpreter.run_code()`

**Cause:** Code execution exceeded the configured timeout.

**Solution:**
1. Increase the timeout: `sandbox.code_interpreter.run_code(code, timeout=60)`
2. Break long-running code into smaller chunks
3. Use `process.exec()` for long-running shell operations instead

**Prevention:** Set appropriate timeouts based on expected execution time. The code interpreter is designed for interactive code snippets, not long-running batch jobs.

### 6.6 WebSocket Connection Failed

**Error:** `DaytonaConnectionError: Failed to execute code: ...`

**Cause:** Network connectivity issues between client and sandbox, or sandbox is not in `started` state.

**Solution:**
1. Verify sandbox state: `sandbox.state` should be `"started"`
2. Start the sandbox if stopped: `sandbox.start()`
3. Check your network connection and firewall rules

**Prevention:** Always check sandbox state before executing code operations.

### 6.7 Empty Code Execution

**Error:** `DaytonaValidationError: Code is required for execution`

**Cause:** Passing an empty string or whitespace-only string to `run_code()`.

**Solution:** Ensure the code string is non-empty and contains actual code.

### 6.8 Git Clone Fails on Small Sandboxes

**Issue:** [#4544](https://github.com/daytonaio/daytona/issues/4544) - The toolbox `git clone` uses pure-Go `go-git`, which can fail on sandboxes with limited memory.

**Cause:** The `go-git` library loads objects into memory, which can exceed the memory limits of small sandbox classes.

**Solution:**
1. Use a larger sandbox class
2. Clone via `sandbox.process.exec("git clone ...")` which uses the system `git` binary instead
3. Clone only the needed branch with `--single-branch --depth 1`

**Prevention:** For large repositories, prefer the system Git binary via exec over the SDK's built-in Git operations.

### 6.9 Docker-in-Docker Connection Failures

**Issue:** [#4461](https://github.com/daytonaio/daytona/issues/4461) - Sandboxes using Docker-in-Docker base images may fail to connect.

**Cause:** The Docker daemon inside the sandbox may not start properly depending on the base image configuration.

**Solution:** Use the official Daytona-supported sandbox images with Docker support. Check sandbox logs for Docker daemon startup errors.

### 6.10 Toolbox API Proxy 502 Errors

**Issue:** [#4545](https://github.com/daytonaio/daytona/issues/4545) - The toolbox API proxy returns bare `502` with empty body on upstream timeout.

**Cause:** Internal request to the sandbox daemon times out, and the proxy does not forward a useful error message.

**Solution:**
1. Retry the operation
2. Check if the sandbox is under heavy load
3. Increase operation timeouts on the client side

### 6.11 File Listing Path Mismatch

**Issue:** [#4542](https://github.com/daytonaio/daytona/issues/4542) - `listFiles` client calls `GET /files` but the daemon responds to `GET /files/`.

**Cause:** Trailing slash mismatch between the client SDK and the daemon API.

**Solution:** Ensure paths used in file operations include or exclude trailing slashes consistently. This is being tracked upstream.

### 6.12 TypeScript SDK getEnvVar on Cloudflare Workers

**Issue:** [#4484](https://github.com/daytonaio/daytona/issues/4484) - `getEnvVar()` does not read `process.env` on Cloudflare Workers.

**Cause:** Cloudflare Workers do not provide a `process.env` object in the same way Node.js does.

**Solution:** Pass configuration explicitly rather than relying on environment variable auto-detection:

```typescript
const daytona = new Daytona({
  apiKey: env.DAYTONA_API_KEY,  // Cloudflare Worker env binding
  apiUrl: env.DAYTONA_API_URL,
})
```

**Prevention:** Always pass explicit configuration when running in serverless environments.

### 6.13 Java SDK WebSocket Callbacks Not Fired

**Issue:** [#4558](https://github.com/daytonaio/daytona/issues/4558) - `getSessionCommandLogs` WebSocket callbacks are not triggered for plain-text log frames.

**Cause:** The Java SDK WebSocket handler only processes frames matching the expected demux format, missing plain-text frames.

**Solution:** Use polling-based log retrieval as a workaround until the issue is resolved upstream.

### 6.14 Computer Use Keyboard Named Keys

**Issue:** [#4417](https://github.com/daytonaio/daytona/issues/4417) - Named keys like `Escape` produce `shift+escape`.

**Cause:** Upstream `robotgo` library behavior applies shift modifier unexpectedly.

**Solution:** Use lowercase key names and test keyboard interactions carefully. For common shortcuts, use `hotkey()` which handles modifier keys explicitly.

### 6.15 Rate Limiting

**Error:** `DaytonaRateLimitError` (HTTP 429)

**Cause:** Too many API requests in a short time window.

**Solution:**
1. Implement exponential backoff retry logic
2. Batch operations where possible (e.g., `upload_files` instead of multiple `upload_file` calls)
3. Use `connection_pool_maxsize` to control concurrency

### 6.16 Resource Conflict

**Error:** `DaytonaConflictError` (HTTP 409)

**Cause:** Attempting to create a resource with a name that already exists.

**Solution:** Use a unique name, or retrieve the existing resource with `daytona.get()`.

### 6.17 Organization Suspended

**Error:** `Organization is suspended: <reason>`

**Cause:** Your organization has been suspended, possibly due to billing issues.

**Solution:** Contact Daytona support or check your billing status in the dashboard.

### 6.18 No Profiles Found (CLI)

**Error:** `no profiles found. Run 'daytona login' to authenticate`

**Cause:** CLI config file has no profiles, or was reset.

**Solution:** Run `daytona login` to create a new profile through browser-based authentication.

### 6.19 No Active Organization (CLI)

**Error:** `no active organization found. Run 'daytona organization use' to select an organization`

**Cause:** Multiple organizations are available but none is selected.

**Solution:** Run `daytona organization use` and select an organization.

### 6.20 Sandbox Auto-Stopped Unexpectedly

**Cause:** The `auto_stop_interval` (default 15 minutes) triggered because no sandbox events occurred.

**Solution:**
1. Set a longer `auto_stop_interval`
2. Set `auto_stop_interval=0` to disable auto-stop
3. Keep the sandbox active by running periodic operations

### 6.21 Sandbox Archived Unexpectedly

**Cause:** The `auto_archive_interval` (default 7 days) triggered after the sandbox remained stopped.

**Solution:**
1. Start the sandbox to unarchive it
2. Set a longer `auto_archive_interval` at creation time

### 6.22 Image Build Failures

**Error:** Sandbox state becomes `build_failed`

**Cause:** The Dockerfile generated by the Image builder or a custom Dockerfile has errors.

**Solution:**
1. Test the Dockerfile locally: `print(image.dockerfile())` to inspect it
2. Stream build logs: `on_snapshot_create_logs=print`
3. Check that all package names are correct and repositories are accessible

### 6.23 Connection Pool Exhausted

**Error:** Requests hanging or timing out under high concurrency.

**Cause:** The default connection pool of 250 is exhausted.

**Solution:** Set `connection_pool_maxsize=None` in `DaytonaConfig` for unlimited connections.

### 6.24 PTY Session Exit Code

**Issue:** PTY session shows unexpected exit code.

**Cause:** The command inside the PTY exited with an error, or the session was killed.

**Solution:** Check `pty_handle.exit_code` and `pty_handle.error` after the session ends for diagnostics.

### 6.25 Deprecated server_url Warning

**Warning:** `'server_url' is deprecated and will be removed in a future version. Use 'api_url' instead.`

**Cause:** Your code uses the deprecated `server_url` field in `DaytonaConfig`.

**Solution:** Replace `server_url` with `api_url`:

```python
# Before
config = DaytonaConfig(server_url="https://app.daytona.io/api")

# After
config = DaytonaConfig(api_url="https://app.daytona.io/api")
```

### 6.26 Invalid Python Version in Image Builder

**Error:** `DaytonaValidationError: Unsupported Python version`

**Cause:** The Python version passed to `Image.debian_slim()` is not in the supported list.

**Solution:** Use one of the supported series: `3.9`, `3.10`, `3.11`, `3.12`, `3.13`.

### 6.27 File Not Found in Image Builder

**Error:** `DaytonaNotFoundError: Local file ... does not exist`

**Cause:** A path passed to `add_local_file()`, `add_local_dir()`, `pip_install_from_requirements()`, or `from_dockerfile()` does not exist on the local machine.

**Solution:** Verify the file path exists and is accessible. Use absolute paths to avoid working-directory ambiguity.

> [!TIP]
> When debugging issues, always check `sandbox.state` first. Many errors stem from operating on a sandbox that is stopped, archived, or in a transient state. Use `sandbox.start()` to restore a stopped sandbox before performing operations.

---

## 7. FAQ

**How do I get an API key?**
Sign up at [app.daytona.io](https://app.daytona.io), navigate to your account settings, and generate an API key. Set it as the `DAYTONA_API_KEY` environment variable.

**What programming languages does the code interpreter support?**
The code interpreter (WebSocket-based `run_code` / `runCode`) executes **Python only**. For other languages, use `process.code_run` (which runs code through the sandbox's language runtime) or `process.exec` / `process.executeCommand` to run arbitrary shell commands.

**What is the difference between `code_interpreter.run_code` and `process.code_run`?**
`code_interpreter.run_code` uses a WebSocket-based Python interpreter with stateful contexts and real-time streaming callbacks. `process.code_run` executes code via the sandbox runtime and can handle multiple languages, but does not support persistent state between calls. `process.code_run` also returns chart artifacts from matplotlib plots.

**What is the difference between `process.exec` and exec sessions?**
`process.exec` (Python) / `process.executeCommand` (TypeScript) runs a single command in a fresh shell. Exec sessions (`createSession`, `executeSessionCommand`) maintain shell state (environment variables, working directory) across multiple commands.

**How fast do sandboxes start?**
From a snapshot: typically a few seconds. From a custom image (first build): depends on image complexity and package installation. Subsequent builds are cached.

**Can I use Docker inside a sandbox?**
Docker-in-Docker is possible but has known connectivity issues ([#4461](https://github.com/daytonaio/daytona/issues/4461)). Use official Daytona-supported Docker images for the best experience.

**How do volumes work?**
Volumes are persistent storage that survives sandbox deletion. Create a volume with `daytona.volume.get('name', true)`, then mount it to sandboxes via the `volumes` parameter. Multiple sandboxes can mount the same volume simultaneously.

**What happens when a sandbox is archived?**
An archived sandbox's compute resources are released but its filesystem state is preserved. Starting an archived sandbox restores it. Archives happen automatically based on `auto_archive_interval` (default 7 days after stopping).

**What is an ephemeral sandbox?**
A sandbox created with `ephemeral=True` is automatically deleted as soon as it stops. This is equivalent to setting `auto_delete_interval=0`. Useful for one-off tasks and CI/CD.

**How do I control network access?**
Use `network_block_all=True` to block all outbound traffic, or `network_allow_list="10.0.0.0/8,172.16.0.0/12"` to allow specific CIDR ranges. Default is full network access.

**What are sandbox labels?**
Labels are key-value pairs attached to sandboxes for metadata and filtering. Set them at creation or update them later with `sandbox.set_labels()`.

**What regions are available?**
Regions depend on your organization's configuration. Use the `target` parameter in `DaytonaConfig` or the `DAYTONA_TARGET` environment variable to select a region.

**What is the MCP server?**
The MCP (Model Context Protocol) server lets AI agents interact with Daytona sandboxes. Run `daytona mcp` to start it. It exposes tools for sandbox creation, file operations, command execution, and Git operations.

**Can I use Daytona with Cloudflare Workers?**
Yes, but pass configuration explicitly instead of relying on `process.env` auto-detection, which does not work in the Cloudflare Workers runtime ([#4484](https://github.com/daytonaio/daytona/issues/4484)).

**What chart types does the code interpreter extract?**
Line, scatter, bar, pie, box-and-whisker, and composite charts. Charts are extracted from matplotlib `plt.show()` calls via `process.code_run`.

**How do I resize a PTY session?**
Call `pty_handle.resize(PtySize(cols=80, rows=25))` at any time during an active PTY session.

**How do I send input to an async exec session command?**
Use `sandbox.process.sendSessionCommandInput(sessionId, commandId, 'your input')` to send stdin to a running async command.

**What is the default API URL?**
`https://app.daytona.io/api`. Override it with `api_url` in `DaytonaConfig` or the `DAYTONA_API_URL` environment variable.

**What is the `connection_pool_maxsize` setting?**
It limits the number of simultaneous HTTP connections the SDK maintains. Default is 250. Set to `None` for unlimited connections, which is recommended when running many concurrent long-lived operations.

**How do I open the Daytona documentation?**
Run `daytona docs` to open the official documentation at [daytona.io/docs](https://www.daytona.io/docs/) in your default browser.

**What are the CLI command aliases?**
The CLI supports shorthand aliases: `create`=`add`/`new`, `delete`=`remove`/`rm`, `list`=`ls`, `info`=`view`/`inspect`, `update`=`set`, `logs`=`log`, `forward`=`fwd`, `code`=`open`, `install`=`i`, `uninstall`=`u`.

**Where is the CLI config stored?**
In `$DAYTONA_CONFIG_DIR/config.json`, or `$XDG_CONFIG_HOME/daytona/config.json` (Linux/macOS), or `%APPDATA%/daytona/config.json` (Windows).

**How do I switch between CLI profiles?**
The config file supports multiple profiles. Set the active profile by updating `activeProfile` in the config, or set both `DAYTONA_API_URL` and `DAYTONA_API_KEY` environment variables to bypass profiles entirely.

**What is the `Image.debian_slim()` base?**
It creates a Debian Bookworm slim image with the specified Python version, pre-installs gcc, gfortran, and build-essential, upgrades pip, and sets the frontend to non-interactive. Supported Python series: 3.9, 3.10, 3.11, 3.12, 3.13.

**Can I build an image from my own Dockerfile?**
Yes. Use `Image.from_dockerfile("path/to/Dockerfile")`. The builder automatically extracts COPY sources from the Dockerfile and uploads them as build context.

**What happens if I set both `ephemeral` and `auto_delete_interval`?**
The SDK emits a warning and `ephemeral` wins: `auto_delete_interval` is forced to 0 (delete immediately on stop).

**How do I use subpath mounting with volumes?**
Pass a `subpath` parameter in the volume mount: `{ volumeId: vol.id, mountPath: '/data', subpath: 'users/alice' }`. The sandbox only sees files under that subpath.

**What error types does the SDK provide?**
The error hierarchy is: `DaytonaError` (base), `DaytonaNotFoundError` (404), `DaytonaAuthenticationError` (401), `DaytonaAuthorizationError` (403), `DaytonaConflictError` (409), `DaytonaRateLimitError` (429), `DaytonaValidationError` (400), `DaytonaConnectionError`, and `DaytonaTimeoutError`. All errors include `message`, `status_code`, `error_code`, and `headers` attributes.

**What LSP languages are supported?**
Python, TypeScript, and JavaScript (`LspLanguageId.PYTHON`, `LspLanguageId.TYPESCRIPT`, `LspLanguageId.JAVASCRIPT`). The appropriate language server must be installed in the sandbox image.

---

_Generated May 2026 from daytonaio/daytona at 4c6a681. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
