# Get Started

Sandbox0 is a long-running agent sandbox with a durable writable RootFS. As agents install dependencies, edit code, and accumulate data, incremental checkpoints and on-demand resume avoid copying the entire growing filesystem during pause/resume. Sandbox0 Cloud uses `https://api.sandbox0.ai` for sandboxes, templates, and credentials.

## What is Sandbox0?

Sandbox0 gives long-running AI agents an isolated workspace that enables you to:

- **Run code securely** in isolated environments with full process control
- **Run for as long as needed** with `ttl=0` and `hard_ttl=0`, or set your own pause and deletion policies
- **Persist sandbox files** across pause/resume with rootfs checkpoints tied to the sandbox identity
- **Keep growing workspaces reusable** with incremental block-COW checkpoints and demand reads on resume
- **Version and fan out durable state** with rootfs snapshots, restore, and forks
- **Control network access** with fine-grained policies
- **Scale efficiently** with one resource-neutral warm-carrier pool and
  claim-time CPU/memory leases

### Control Plane vs Data Plane

Sandbox0 follows a control plane / data plane architecture:

| Layer | Components | Purpose |
|-------|------------|---------|
| **Control Plane** | regional-gateway, scheduler | Multi-cluster routing, tenant management, request forwarding |
| **Data Plane** | cluster-gateway, manager, dedicated Nomad nodes, ctld HA pair | Sandbox lifecycle, process execution, file operations, storage, resource leases, and network enforcement |

Each provider/region (e.g., `aws-us-east-1`) has an independent data plane and control plane deployment with dedicated PostgreSQL and S3 storage.

`manager` and regional PostgreSQL own lifecycle, capacity, and RootFS metadata.
On each dedicated Nomad node, the active process in the `ctld` HA pair owns
RootFS attachment, dynamic lease cgroups, and the network policy runtime; the
standby takes over those responsibilities after promotion.

---

## Quickstart

Get your first sandbox running in minutes.

### Prerequisites

- A Sandbox0 account
- `s0` CLI installed

### Install s0 CLI (Required)

macOS and Linux:

```bash
curl -fsSL https://raw.githubusercontent.com/sandbox0-ai/s0/main/scripts/install.sh | bash
```

Windows PowerShell:

```powershell
irm https://raw.githubusercontent.com/sandbox0-ai/s0/main/scripts/install.ps1 | iex
```

Or with Go:

```bash
go install github.com/sandbox0-ai/s0/cmd/s0@latest
```

Manual release archives are available from <DocLink href="https://github.com/sandbox0-ai/s0/releases/latest" newTab>GitHub Releases</DocLink>. See the <DocLink href="https://github.com/sandbox0-ai/s0#installation" newTab>s0 README</DocLink> for platform-specific manual install steps.

### Install SDK

<Tabs
  tabs={[
    {
      label: "Go",
      language: "go",
      code: `go get github.com/sandbox0-ai/sdk-go`
    },
    {
      label: "Python",
      language: "python",
      code: `pip install sandbox0`
    },
    {
      label: "TypeScript",
      language: "bash",
      code: `npm install sandbox0`
    }
  ]}
/>

### Authenticate

For Sandbox0 Cloud, sign in with `s0 auth login`. That is enough for interactive CLI usage.

If you want to use the SDKs or raw HTTP API, create a team-scoped API key and export it as `SANDBOX0_TOKEN`:

```bash
# Login with your account (stores session in ~/.s0/config.yaml)
s0 auth login

# If the server did not auto-select a team yet:
# s0 team list
# s0 team create --name my-team --home-region <region-id>
# s0 team use <team-id>

# Create a 30-day API key for SDK and automation usage.
export SANDBOX0_TOKEN="$(s0 apikey create --name sdk-quickstart --role developer --expires-in 30d --raw)"
export SANDBOX0_BASE_URL="https://api.sandbox0.ai"
```

<Callout variant="info">
If you only use the local `s0` CLI interactively, you can stop after `s0 auth login`. API keys are the standard way to authenticate SDK and HTTP requests.
</Callout>

<Tabs
  tabs={[
    {
      label: "Go",
      language: "go",
      code: `import sandbox0 "github.com/sandbox0-ai/sdk-go"
import "os"

client, err := sandbox0.NewClient(
    sandbox0.WithToken(os.Getenv("SANDBOX0_TOKEN")),
    sandbox0.WithBaseURL(os.Getenv("SANDBOX0_BASE_URL")),
)`
    },
    {
      label: "Python",
      language: "python",
      code: `from sandbox0 import Client
import os

client = Client(
    token=os.environ["SANDBOX0_TOKEN"],
    base_url=os.environ.get("SANDBOX0_BASE_URL", "https://api.sandbox0.ai"),
)`
    },
    {
      label: "TypeScript",
      language: "typescript",
      code: `import { Client } from 'sandbox0';

const client = new Client({
    token: process.env.SANDBOX0_TOKEN!,
    baseUrl: process.env.SANDBOX0_BASE_URL || 'https://api.sandbox0.ai',
});`
    }
  ]}
/>

### Claim Your First Sandbox

Create a sandbox from the `default` template:

<Tabs
  tabs={[
    {
      label: "Go",
      language: "go",
      code: `package main

import (
    "context"
    "fmt"
    "log"
    "os"

    sandbox0 "github.com/sandbox0-ai/sdk-go"
)

func main() {
    client, err := sandbox0.NewClient(
        sandbox0.WithToken(os.Getenv("SANDBOX0_TOKEN")),
        sandbox0.WithBaseURL(os.Getenv("SANDBOX0_BASE_URL")),
    )
    if err != nil {
        log.Fatal(err)
    }

    ctx := context.Background()

    // Claim a sandbox from the "default" template
    sandbox, err := client.ClaimSandbox(ctx, "default",
        sandbox0.WithSandboxTTL(300),      // Auto-pause after 5 minutes (default: 5m)
        sandbox0.WithSandboxHardTTL(3600), // Delete sandbox state after 1 hour (optional, 0 disables)
    )
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Sandbox ID: %s\\n", sandbox.ID)
    fmt.Printf("Status: %s\\n", sandbox.Status)

    // Clean up when done
    defer client.DeleteSandbox(ctx, sandbox.ID)
}`
    },
    {
      label: "Python",
      language: "python",
      code: `from sandbox0 import Client
from sandbox0.apispec.models.sandbox_config import SandboxConfig
import os

client = Client(
    token=os.environ["SANDBOX0_TOKEN"],
    base_url=os.environ.get("SANDBOX0_BASE_URL", "https://api.sandbox0.ai"),
)

# Claim a sandbox from the "default" template
with client.sandboxes.open("default", config=SandboxConfig(
    ttl=300,       # Auto-pause after 5 minutes (default: 5m)
    hard_ttl=3600, # Delete sandbox state after 1 hour (optional, 0 disables)
)) as sandbox:
    print(f"Sandbox ID: {sandbox.id}")
    print(f"Status: {sandbox.status}")`
    },
    {
      label: "TypeScript",
      language: "typescript",
      code: `// Run with: bun run main.ts
// Or: npx tsx main.ts (requires @types/node)
import { Client } from 'sandbox0';

const client = new Client({
    token: process.env.SANDBOX0_TOKEN!,
    baseUrl: process.env.SANDBOX0_BASE_URL || 'https://api.sandbox0.ai',
});

// Claim a sandbox from the "default" template
const sandbox = await client.sandboxes.claim('default', {
    ttl: 300,       // Auto-pause after 5 minutes (default: 5m)
    hardTtl: 3600,  // Delete sandbox state after 1 hour (optional, 0 disables)
});
console.log('Sandbox ID:', sandbox.id);
console.log('Status:', sandbox.status);

// Clean up when done
await client.sandboxes.delete(sandbox.id);`
    },
    {
      label: "CLI",
      language: "bash",
      code: `# Claim a sandbox
s0 sandbox create --template default --ttl 300 --hard-ttl 3600

# Output:
# Sandbox ID: sb_abc123
# Status: running

# Clean up when done
s0 sandbox delete sb_abc123`
    }
  ]}
/>

### Run Your First Command

Execute code in your sandbox using `Run` (REPL-style, stateful) or `Cmd` (one-shot command):

<Tabs
  tabs={[
    {
      label: "Go",
      language: "go",
      code: `// Run a REPL-style snippet (stateful; env/vars preserved between calls)
runResult, err := sandbox.Run(ctx, "python", "x = 2")
if err != nil {
    log.Fatal(err)
}
fmt.Print(runResult.OutputRaw)

runResult, err = sandbox.Run(ctx, "python", "print(x)")
if err != nil {
    log.Fatal(err)
}
fmt.Print(runResult.OutputRaw)

// Run a one-shot command (stateless)
cmdResult, err := sandbox.Cmd(ctx, "/bin/sh -c 'echo Hello, Sandbox0!'")
if err != nil {
    log.Fatal(err)
}
fmt.Print(cmdResult.OutputRaw)`
    },
    {
      label: "Python",
      language: "python",
      code: `# Run a REPL-style snippet (stateful; env/vars preserved between calls)
run_result = sandbox.run("python", "x = 2")
print(run_result.output_raw, end="")

run_result = sandbox.run("python", "print(x)")
print(run_result.output_raw, end="")

# Run a one-shot command (stateless)
cmd_result = sandbox.cmd("/bin/sh -c 'echo Hello, Sandbox0!'")
print(cmd_result.output_raw, end="")`
    },
    {
      label: "TypeScript",
      language: "typescript",
      code: `// Run a REPL-style snippet (stateful; env/vars preserved between calls)
const runResult = await sandbox.run('python', 'x = 2');
process.stdout.write(runResult.outputRaw);

const runResult2 = await sandbox.run('python', 'print(x)');
process.stdout.write(runResult2.outputRaw);

// Run a one-shot command (stateless)
const cmdResult = await sandbox.cmd("/bin/sh -c 'echo Hello, Sandbox0!'");
process.stdout.write(cmdResult.outputRaw);`
    },
    {
      label: "CLI",
      language: "bash",
      code: `# Execute a command in the sandbox
s0 sandbox exec sb_abc123 -- echo "Hello, Sandbox0!"

# Output:
# Hello, Sandbox0!`
    }
  ]}
/>

Need live command output instead of a final buffered result?

- Go: `sandbox.CmdStream(...)`
- Python: `sandbox.cmd_stream(...)`
- TypeScript: `sandbox.cmdStream(...)`
- CLI: `s0 sandbox exec --stream -- ...`

### Basic File Operations

Read and write files in your sandbox:

<Tabs
  tabs={[
    {
      label: "Go",
      language: "go",
      code: `// Write a file
_, err = sandbox.WriteFile(ctx, "/tmp/hello.txt", []byte("Hello from Sandbox0!"))
if err != nil {
    log.Fatal(err)
}

// Read the file back
content, err := sandbox.ReadFile(ctx, "/tmp/hello.txt")
if err != nil {
    log.Fatal(err)
}
fmt.Printf("File content: %s\\n", string(content))`
    },
    {
      label: "Python",
      language: "python",
      code: `# Write a file
sandbox.write_file("/tmp/hello.txt", b"Hello from Sandbox0!")

# Read the file back
content = sandbox.read_file("/tmp/hello.txt")
print(f"File content: {content.decode()}")`
    },
    {
      label: "TypeScript",
      language: "typescript",
      code: `// Write a file
await sandbox.writeFile('/tmp/hello.txt', 'Hello from Sandbox0!');

// Read the file back
const content = await sandbox.readFile('/tmp/hello.txt');
console.log('File content:', Buffer.from(content).toString());`
    },
    {
      label: "CLI",
      language: "bash",
      code: `# Write a file
s0 sandbox files write /tmp/hello.txt --data "Hello from Sandbox0!" -s sb_abc123

# Read a file
s0 sandbox files cat /tmp/hello.txt -s sb_abc123

# Output:
# Hello from Sandbox0!`
    }
  ]}
/>

---

## Next Steps

<CardGroup>
  <Card title="Concepts" href="/docs/sandbox/get-started/concepts" cta="Continue">
    Understand the runtime, storage, networking, and control-plane concepts before implementation.
  </Card>

  <Card title="Overview" href="/docs/sandbox" cta="Continue">
    Learn the sandbox lifecycle and the runtime APIs available to each isolated environment.
  </Card>
</CardGroup>
