# Introduction

ComputeSDK is the open, multi-provider harness that powers ComputeSDK Benchmarks and a TypeScript sandbox SDK for secure code execution across multiple cloud providers with one unified API.

## ComputeSDK: the benchmark harness for sandboxes

ComputeSDK is the open, multi-provider harness behind [ComputeSDK Benchmarks](https://www.computesdk.com/benchmarks). It exposes one provider-agnostic sandbox API so benchmarks can run the same workload on every provider and produce fair, reproducible results. The same API is also available as a TypeScript SDK for building AI agents, code execution platforms, developer tools, testing systems, and any product that needs safe cloud sandboxes.

Because every provider returns the same sandbox interface, your application code stays the same even when you switch providers.

## How the sandbox API works

ComputeSDK is built around provider packages. Each provider ships as its own package under the `@computesdk/` scope. Install only the providers you need.

**Sandboxes** — Isolated compute environments for running code safely\
**Providers** — Cloud platforms that host those sandboxes

When you install a package like `@computesdk/e2b`, you get a factory function for that provider. Every provider returns the same sandbox interface, so you can swap infrastructure without rewriting core logic.

## Supported cloud sandbox providers

| Package                        | Provider     |
| ------------------------------ | ------------ |
| `@computesdk/archil`           | Archil       |
| `@computesdk/beam`             | Beam         |
| `@computesdk/blaxel`           | Blaxel       |
| `@computesdk/cloud-run`        | Cloud Run    |
| `@computesdk/cloudflare`       | Cloudflare   |
| `@computesdk/codesandbox`      | CodeSandbox  |
| `@computesdk/createos-sandbox` | CreateOS     |
| `@computesdk/daytona`          | Daytona      |
| `@computesdk/declaw`           | Declaw       |
| `@computesdk/e2b`              | E2B          |
| `@computesdk/hopx`             | HopX         |
| `@computesdk/isorun`           | Isorun       |
| `@computesdk/lightning`        | Lightning    |
| `@computesdk/modal`            | Modal        |
| `@computesdk/northflank`       | Northflank   |
| `@computesdk/opencomputer`     | OpenComputer |
| `@computesdk/run-cloud`        | Run Cloud    |
| `@computesdk/runloop`          | Runloop      |
| `@computesdk/sandbox0`         | Sandbox0     |
| `@computesdk/superserve`       | Superserve   |
| `@computesdk/tensorlake`       | Tensorlake   |
| `@computesdk/upstash`          | Upstash      |
| `@computesdk/vercel`           | Vercel       |

## Why teams use ComputeSDK

**Provider-agnostic sandbox API** — Switch providers with minimal code changes\
**Open benchmark harness** — Powers [ComputeSDK Benchmarks](https://www.computesdk.com/benchmarks) with the same API on every provider\
**Secure code execution** — Run untrusted code in isolated sandboxes\
**Lean installs** — Add only the cloud sandbox providers you need\
**TypeScript-native SDK** — Get a clean developer experience with strong typing\
**Production-ready** — Build reliable AI and developer workflows on one interface

### Common use cases

* **Benchmarking infrastructure providers** — Compare sandbox, storage, browser, and AI gateway providers with one consistent harness
* **AI agent infrastructure** — Let agents run code, commands, and file operations safely
* **Code execution platforms** — Execute user-submitted code in isolated sandboxes
* **Browser IDEs and education tools** — Provide interactive coding environments
* **Data workflows** — Run scripts with filesystem access in disposable environments
* **Testing and CI systems** — Create clean sandboxes for repeatable execution

## Core features

**Open benchmark harness** — Run the same workload on every provider and publish reproducible benchmarks ([ComputeSDK Benchmarks](https://www.computesdk.com/benchmarks))\
**Multi-provider support** — Use E2B, Modal, Vercel, and other providers through one SDK\
**Sandbox lifecycle management** — Create, reconnect, list, and destroy sandboxes\
**Filesystem operations** — Read, write, remove, and organize files\
**Shell command execution** — Run commands directly inside each sandbox\
**Type-safe APIs** — Use full TypeScript support with clear errors

## Quick example

Install a provider package:

```bash
npm install @computesdk/e2b
```

Set your provider credentials:

```bash
export E2B_API_KEY=your_e2b_api_key
```

Create a sandbox and run a command:

```typescript
import { e2b } from '@computesdk/e2b';

// Create a compute instance for E2B
const compute = e2b({ apiKey: process.env.E2B_API_KEY });

// Create a sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello World!"');
console.log(result.stdout); // "Hello World!"

// Clean up
await sandbox.destroy();
```

This pattern gives you a secure code execution sandbox with a single provider package. The same API shape works across supported providers.

### Use multiple providers

You can use multiple providers in the same project. Install the packages you need and create separate compute instances:

```bash
npm install @computesdk/e2b @computesdk/modal
```

```typescript
import { e2b } from '@computesdk/e2b';
import { modal } from '@computesdk/modal';

// Create compute instances for each provider
const e2bCompute = e2b({ apiKey: process.env.E2B_API_KEY });
const modalCompute = modal({
  tokenId: process.env.MODAL_TOKEN_ID,
  tokenSecret: process.env.MODAL_TOKEN_SECRET,
});

// Use one provider for lightweight tasks
const lightSandbox = await e2bCompute.sandbox.create();
await lightSandbox.runCommand('echo "Quick task"');
await lightSandbox.destroy();

// Use another provider for GPU-intensive workloads
const gpuSandbox = await modalCompute.sandbox.create();
await gpuSandbox.runCommand('python -c "import torch; print(torch.cuda.is_available())"');
await gpuSandbox.destroy();
```

The sandbox API stays consistent across providers. That makes it easier to route workloads by cost, region, latency, or hardware needs.

### Configure multi-provider routing in one SDK

If you'd rather configure several providers together — for resilience, routing, or load balancing — install the `computesdk` core package alongside the providers you want:

```bash
npm install computesdk @computesdk/e2b @computesdk/modal
```

Register multiple providers with `compute.setConfig` and choose a strategy:

```typescript
import { compute } from 'computesdk';
import { e2b } from '@computesdk/e2b';
import { modal } from '@computesdk/modal';

compute.setConfig({
  providers: [
    e2b({ apiKey: process.env.E2B_API_KEY }),
    modal({
      tokenId: process.env.MODAL_TOKEN_ID,
      tokenSecret: process.env.MODAL_TOKEN_SECRET,
    }),
  ],
  providerStrategy: 'priority', // 'priority' (default) or 'round-robin'
  fallbackOnError: true,        // try the next provider if one fails
});

// Uses the configured strategy
const sandbox = await compute.sandbox.create();

// Override per call to target a specific provider by name
const gpuSandbox = await compute.sandbox.create({ provider: 'modal' });
```

**Strategies**

* `priority` — always try providers in order; combine with `fallbackOnError: true` to cascade on failure
* `round-robin` — distribute new sandboxes evenly across providers

Operations like `destroy` and snapshots automatically route to the provider that owns each sandbox, so you don't need to track affinity yourself.

## Next steps

Start with [Installation](/getting-started/installation) to set up a provider. Then follow [Quick Start](/getting-started/quick-start) to launch your first sandbox.


# Installation

## Install a Provider Package

Install the provider package for the platform you want to use:

```bash
# Pick one (or more) providers
npm install @computesdk/archil
npm install @computesdk/blaxel
npm install @computesdk/cloudflare
npm install @computesdk/codesandbox
npm install @computesdk/daytona
npm install @computesdk/declaw
npm install @computesdk/e2b
npm install @computesdk/hopx
npm install @computesdk/modal
npm install @computesdk/namespace
npm install @computesdk/runloop
npm install @computesdk/tensorlake
npm install @computesdk/upstash
npm install @computesdk/vercel
```

You only need to install the providers your project uses.

## Provider Credentials

Each provider requires its own API credentials. Add them to a `.env` file in the root of your project or export them in your shell:

### Archil

```bash
ARCHIL_API_KEY=your_archil_api_key
ARCHIL_REGION=aws-us-east-1
ARCHIL_DISK_ID=your_archil_disk_id
```

### Blaxel

```bash
BL_API_KEY=your_blaxel_api_key
BL_WORKSPACE=your_blaxel_workspace
```

### Cloudflare

```bash
CLOUDFLARE_API_TOKEN=your_cloudflare_api_token
CLOUDFLARE_ACCOUNT_ID=your_cloudflare_account_id
```

### CodeSandbox

```bash
CSB_API_KEY=your_codesandbox_api_key
```

### Daytona

```bash
DAYTONA_API_KEY=your_daytona_api_key
```

### Declaw

```bash
DECLAW_API_KEY=your_declaw_api_key
```

### E2B

```bash
E2B_API_KEY=your_e2b_api_key
```

### HopX

```bash
HOPX_API_KEY=your_hopx_api_key
```

### Modal

```bash
MODAL_TOKEN_ID=your_modal_token_id
MODAL_TOKEN_SECRET=your_modal_token_secret
```

### Namespace

```bash
NSC_TOKEN=your_namespace_nsc_token
```

### Runloop

```bash
RUNLOOP_API_KEY=your_runloop_api_key
```

### Tensorlake

```bash
TENSORLAKE_API_KEY=your_tensorlake_api_key
```

### Upstash

```bash
UPSTASH_BOX_API_KEY=your_upstash_box_api_key
```

### Vercel

```bash
VERCEL_TOKEN=your_vercel_token
VERCEL_TEAM_ID=your_team_id
VERCEL_PROJECT_ID=your_project_id
```

Refer to each provider's documentation page for the full list of supported environment variables and configuration options.

## Verify Your Setup

After installing a provider and setting credentials, verify everything works:

```typescript
import { e2b } from '@computesdk/e2b';

const compute = e2b({ apiKey: process.env.E2B_API_KEY });
const sandbox = await compute.sandbox.create();

const result = await sandbox.runCommand('echo "Hello from ComputeSDK!"');
console.log(result.stdout); // "Hello from ComputeSDK!"

await sandbox.destroy();
```

Replace the import and configuration with whichever provider you installed.


# Quick Start

Welcome to ComputeSDK! This guide will get you up and running with the open, multi-provider harness behind [ComputeSDK Benchmarks](https://www.computesdk.com/benchmarks): a unified TypeScript interface for secure, isolated code execution across cloud providers.

## Installation

Install the provider package for the platform you want to use. This guide uses E2B as an example, but the sandbox API is the same across all providers.

```bash
npm install @computesdk/e2b
```

Then add your provider credentials to a `.env` file:

```bash
E2B_API_KEY=your_e2b_api_key
```

## Basic Usage

A **sandbox** is an isolated compute environment where you can safely execute code. Each sandbox runs on your chosen cloud provider (E2B, Modal, Vercel, etc.) with a unified interface. The `create()` method provisions a new sandbox, `runCommand()` executes shell commands and returns the result, and `destroy()` tears down the sandbox to free resources.

```typescript
import { e2b } from '@computesdk/e2b';

// Create a compute instance for your provider
const compute = e2b({ apiKey: process.env.E2B_API_KEY });

// Create a sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello World!"');
console.log(result.stdout); // "Hello World!"

// Clean up
await sandbox.destroy();
```

## Filesystem Operations

Each sandbox has its own isolated filesystem. You can read, write, and manage files using absolute paths (starting with `/`). Files persist for the sandbox lifetime and are destroyed when you call `destroy()`.

```typescript
// Write file
await sandbox.filesystem.writeFile('/tmp/hello.py', 'print("Hello")');

// Read file
const content = await sandbox.filesystem.readFile('/tmp/hello.py');

// Create directory
await sandbox.filesystem.mkdir('/tmp/mydir');

// List directory
const files = await sandbox.filesystem.readdir('/tmp');

// Check if exists
const exists = await sandbox.filesystem.exists('/tmp/hello.py');

// Remove file/directory
await sandbox.filesystem.remove('/tmp/hello.py');
```

## Shell Commands

Use `runCommand()` for shell operations, package installation, or system commands. It provides full shell access with detailed execution results including stdout, stderr, exit codes, and execution time.

```typescript
// Run shell command
const result = await sandbox.runCommand('ls -la');
console.log(result.stdout);

// With different working directory
const result2 = await sandbox.runCommand('pwd', { cwd: '/tmp' });
```

## Error Handling

ComputeSDK methods throw exceptions for API/network failures. For command execution errors, check the `exitCode` in the result rather than relying on exceptions. Exit code `0` indicates success, non-zero indicates failure.

```typescript
try {
  const sandbox = await compute.sandbox.create();
  const result = await sandbox.runCommand('some-command');
} catch (error) {
  console.error('Failed:', error.message);
}
```

## Essential Patterns

### Resource Cleanup (Critical for Production)

Always destroy sandboxes when done to avoid resource leaks and unnecessary costs. Sandboxes consume resources until explicitly destroyed or they timeout.

```typescript
// ✅ Recommended: Use try-finally
let sandbox;
try {
  sandbox = await compute.sandbox.create();
  await sandbox.runCommand('echo "Hello"');
} finally {
  await sandbox?.destroy();
}
```

### Error Handling with Exit Codes

Commands return exit codes following Unix conventions: `0` means success, non-zero indicates failure. Always check `exitCode` rather than catching exceptions for command failures.

```typescript
const result = await sandbox.runCommand('npm test');
if (result.exitCode !== 0) {
  console.error('Tests failed:', result.stderr);
} else {
  console.log('Tests passed!', result.stdout);
}
```

## Understanding Results

### Command Execution Results

When you call `runCommand()`, you receive:

* `stdout`: Standard output (normal program output)
* `stderr`: Standard error (error messages and warnings)
* `exitCode`: `0` for success, non-zero for failures
* `durationMs`: Execution time in milliseconds

```typescript
const result = await sandbox.runCommand('npm install');
console.log(result.stdout);      // Installation logs
console.log(result.stderr);      // Warnings or errors
console.log(result.exitCode);    // 0
console.log(result.durationMs);  // 2341
```


# Providers


# AWS Bedrock AgentCore

Install and use the AWS Bedrock AgentCore provider for ComputeSDK with AWS credentials, regional config, and session-based sandboxes.

[AWS Bedrock AgentCore Code Interpreter](https://docs.aws.amazon.com/bedrock-agentcore/) provider for [ComputeSDK](/) — secure, fully-managed, session-based sandboxes for running code and shell commands, with no infrastructure to provision.

A ComputeSDK sandbox maps onto an AgentCore Code Interpreter session. See [compute.sandbox](/reference/compute.sandbox) for lifecycle methods and [Sandbox (interface)](/reference/sandbox) for command, filesystem, and URL behavior.

## Installation & Setup

```bash
npm install @computesdk/agentcore
```

There is no API key. The provider uses the standard [AWS credential provider chain](https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html) — the same resolution as the AWS CLI — so environment variables, SSO sessions, named profiles, and instance roles all work, including temporary credentials.

A region is required, via `region` in config or `AWS_REGION` / `AWS_DEFAULT_REGION`.

### IAM permissions

```
bedrock-agentcore:StartCodeInterpreterSession
bedrock-agentcore:InvokeCodeInterpreter
bedrock-agentcore:StopCodeInterpreterSession
bedrock-agentcore:GetCodeInterpreterSession
bedrock-agentcore:ListCodeInterpreterSessions
```

## Usage

```typescript
import { agentcore } from '@computesdk/agentcore';

const compute = agentcore({ region: 'us-west-2' });

// Create sandbox (an AgentCore Code Interpreter session)
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from AgentCore!"');
console.log(result.stdout); // "Hello from AgentCore!"

// Run code via the available runtimes (e.g. Python)
const code = await sandbox.runCommand('python3 -c "print(2 + 2)"');
console.log(code.stdout); // "4"

// Work with files (files persist for the life of the session)
await sandbox.filesystem.writeFile('/tmp/hello.py', 'print("Hello World")');
const content = await sandbox.filesystem.readFile('/tmp/hello.py');

// Clean up
await sandbox.destroy();
```

### Named profile

```typescript
agentcore({ region: 'us-west-2', profile: 'my-profile' });
```

### Explicit / temporary credentials

```typescript
agentcore({
  region: 'us-west-2',
  credentials: {
    accessKeyId: '...',
    secretAccessKey: '...',
    sessionToken: '...', // temporary credentials supported
  },
});
```

### Configuration Options

```typescript
interface AgentCoreConfig {
  /** AWS region. Falls back to AWS_REGION / AWS_DEFAULT_REGION */
  region?: string;
  /** Code interpreter to use. Defaults to the managed `aws.codeinterpreter.v1` */
  codeInterpreterIdentifier?: string;
  /** Named AWS profile to use for credentials */
  profile?: string;
  /** Explicit credentials. Omit to use the default AWS credential chain */
  credentials?: AwsCredentialIdentity | AwsCredentialIdentityProvider;
  /** Session timeout in seconds (max 28800 / 8h). Default 900. Overridden by per-create `timeout` (ms) */
  sessionTimeoutSeconds?: number;
}
```

## Limitations

* **No preview URLs / ports.** AgentCore Code Interpreter has no inbound network endpoint, so `getUrl()` throws.
* **No interactive PTY.** Commands are request/response.
* **Sessions expire.** A session auto-terminates after its idle timeout; create a new sandbox afterward.
* **Filesystem persists, shell environment does not.** Files survive across `runCommand` calls, but each command runs in a fresh shell — `cd`, `export`, and shell variables do not carry over. Chain them in one command or use the `cwd`/`env` options.
* **Background commands don't outlive the call.** `{ background: true }` returns immediately, but AgentCore terminates the process tree when the invocation ends, so the job is killed rather than left running.

## Related topics

Compare this provider with other options on [Providers](/providers).

* Use [Quick Start](/getting-started/quick-start) for the shared sandbox model and cleanup patterns.
* Use [compute.sandbox](/reference/compute.sandbox) for `create()`, timeout, reconnect, and destroy flows.
* Use [Sandbox (interface)](/reference/sandbox) for `runCommand()`, `filesystem`, and `getUrl()` details.


# Agentuity

Use Agentuity with ComputeSDK to create sandboxes, authenticate with an SDK key, and configure runtime, region, and timeout settings.

Agentuity provider for ComputeSDK

## Installation & Setup

```bash
npm install @computesdk/agentuity
```

Add your Agentuity credentials to a `.env` file:

```bash
AGENTUITY_SDK_KEY=your_agentuity_sdk_key
```

## Usage

```typescript
import { agentuity } from '@computesdk/agentuity';

const compute = agentuity({
  apiKey: process.env.AGENTUITY_SDK_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Agentuity!"');
console.log(result.stdout); // "Hello from Agentuity!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface AgentuityConfig {
  /** Agentuity SDK key - if not provided, will use AGENTUITY_SDK_KEY env var */
  apiKey?: string;
  /** Region for API endpoints ('local', 'usc', or a full custom base URL). Default: 'usc' */
  region?: string;
  /** Override the sandbox base URL entirely */
  baseURL?: string;
  /** Default runtime, e.g. 'bun:1', 'python:3.14', 'node:22' */
  runtime?: string;
  /** Idle timeout passed to the sandbox (e.g. '5m', '1h') */
  idleTimeout?: string;
  /** Execution timeout passed to the sandbox (e.g. '30m', '2h') */
  executionTimeout?: string;
}
```


# Archil

Use Archil with ComputeSDK to run commands against an existing disk with API key auth, region config, and exec-only container sessions.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/archil/>" %}

Archil provider for ComputeSDK

## Installation & Setup

```bash
npm install @computesdk/archil
```

Add your Archil credentials to a `.env` file:

```bash
ARCHIL_API_KEY=your_archil_api_key
ARCHIL_REGION=aws-us-east-1
ARCHIL_DISK_ID=your_archil_disk_id
```

## Usage

Archil is exec-only — `create()` resolves a handle to an existing Archil disk id. Each command runs in an Archil-managed container with that disk attached.

```typescript
import { archil } from '@computesdk/archil';

const compute = archil({
  apiKey: process.env.ARCHIL_API_KEY,
  region: process.env.ARCHIL_REGION,
});

// Attach to an existing Archil disk by id
const diskId = process.env.ARCHIL_DISK_ID;
if (!diskId) throw new Error('ARCHIL_DISK_ID is not set');

const sandbox = await compute.sandbox.create({ diskId });

// Run a shell command against the mounted disk
const result = await sandbox.runCommand('echo hello > /mnt/note && cat /mnt/note');
console.log(result.stdout); // "hello"

// destroy() is a no-op — disk lifecycle is managed by Archil
await sandbox.destroy();
```

### Configuration Options

```typescript
interface ArchilConfig {
  /** Archil API key - if not provided, will use ARCHIL_API_KEY env var */
  apiKey?: string;
  /** Archil region (e.g. "aws-us-east-1") - if not provided, will use ARCHIL_REGION env var */
  region?: string;
  /** Override the control-plane base URL (useful for testing) */
  baseUrl?: string;
}
```

### Supported Operations

| Method       | Supported | Notes                                                              |
| ------------ | --------- | ------------------------------------------------------------------ |
| `create`     | ✅         | Resolves an existing disk from top-level `diskId`.                 |
| `getById`    | ✅         | Requires the disk id.                                              |
| `list`       | ✅         | Lists all disks visible to the API key.                            |
| `destroy`    | no-op     | Disk lifecycle is managed by Archil.                               |
| `runCommand` | ✅         | Calls Archil's HTTP `exec` endpoint and waits for completion.      |
| `getInfo`    | ✅         |                                                                    |
| `getUrl`     | ❌         | Each exec runs in a fresh ephemeral container — no port to expose. |
| `filesystem` | ✅         | Implemented via shell commands (`cat`, `find`, `mkdir`, etc.).     |

### Limitations

* Each `exec` call provisions a fresh container — no persistent state between calls beyond what is written to the disk.
* Responses are truncated to \~5 MB by the Archil control plane.
* `getUrl` is not supported — each exec runs in a fresh ephemeral container, so there is no long-lived process to expose a port on.
* Filesystem operations are implemented as shell commands, so each call costs one HTTP round trip.


# Beam

Use Beam with ComputeSDK to create sandboxes with token and workspace authentication, then run commands with configurable gateway and timeout settings.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/beam/>" %}

Beam provider for ComputeSDK

## Installation & Setup

```bash
npm install @computesdk/beam
```

Add your Beam credentials to a `.env` file:

```bash
BEAM_TOKEN=your_beam_token
BEAM_WORKSPACE_ID=your_beam_workspace_id
```

## Usage

```typescript
import { beam } from '@computesdk/beam';

const compute = beam({
  token: process.env.BEAM_TOKEN,
  workspaceId: process.env.BEAM_WORKSPACE_ID,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Beam!"');
console.log(result.stdout); // "Hello from Beam!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface BeamConfig {
  /** Beam API token - if not provided, will use BEAM_TOKEN env var */
  token?: string;
  /** Beam workspace ID - if not provided, will use BEAM_WORKSPACE_ID env var */
  workspaceId?: string;
  /** Gateway URL for custom/staging environments */
  gatewayUrl?: string;
  /** Request timeout in milliseconds */
  timeout?: number;
}
```


# Blaxel

Use Blaxel with ComputeSDK to create sandboxes with API key and workspace authentication, and configure image, region, memory, and exposed ports.

Blaxel provider for ComputeSDK

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/blaxel/>" %}

## Installation & Setup

```bash
npm install @computesdk/blaxel
```

Add your Blaxel credentials to a `.env` file:

```bash
BL_API_KEY=your_blaxel_api_key
BL_WORKSPACE=your_blaxel_workspace
```

## Usage

```typescript
import { blaxel } from '@computesdk/blaxel';

const compute = blaxel({
  apiKey: process.env.BL_API_KEY,
  workspace: process.env.BL_WORKSPACE,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Blaxel!"');
console.log(result.stdout); // "Hello from Blaxel!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface BlaxelConfig {
  /** Blaxel API key - if not provided, will use BL_API_KEY env var */
  apiKey?: string;
  /** Blaxel workspace ID - if not provided, will use BL_WORKSPACE env var */
  workspace?: string;
  /** Default image for sandboxes */
  image?: string;
  /** Default region for sandbox deployment */
  region?: string;
  /** Default memory allocation in MB */
  memory?: number;
  /** Default ports to expose on the sandbox */
  ports?: number[];
}
```

### Default Images

The provider automatically selects images based on the runtime specified at creation time:

* **Python:** `blaxel/py-app:latest`
* **Node.js:** `blaxel/ts-app:latest`
* **Default:** `blaxel/base-image:latest`


# Cloud Run

Use the Google Cloud Run provider for ComputeSDK to run sandboxed commands in remote or direct mode, with ephemeral or stateful sandboxes, gateway auth, and sandbox CLI configuration.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/cloud-run/>" %}

Use the Google Cloud Run sandbox provider for ComputeSDK to run isolated commands and filesystem operations inside Cloud Run. Choose remote mode for a deployed gateway, or direct mode for in-container sandbox CLI control.

## Install and set up the Cloud Run provider

```bash
npm install @computesdk/cloud-run
```

The Google Cloud Run provider works in two modes:

* **Remote mode** — connect to a deployed Cloud Run gateway service. Set both `CLOUD_RUN_SANDBOX_URL` and `CLOUD_RUN_SANDBOX_SECRET`:

```bash
CLOUD_RUN_SANDBOX_URL=https://your-gateway-xyz.run.app
CLOUD_RUN_SANDBOX_SECRET=your_shared_secret
# Optional: Google-signed identity token for IAM-authenticated services
CLOUD_RUN_AUTH_TOKEN=your_identity_token
```

* **Direct mode** — run your app inside a Cloud Run service deployed with `gcloud beta run deploy --sandbox-launcher`, and the provider drives the in-container `sandbox` CLI (default `/usr/local/gcp/bin/sandbox`). Override the binary with `CLOUD_RUN_SANDBOX_BINARY`.

Remote mode is selected automatically when both `sandboxUrl` and `sandboxSecret` are set; otherwise the provider runs in direct mode.

Cloud Run supports two execution modes for sandbox sessions:

* **Ephemeral mode** (default) — `create()` creates a local logical handle only, `runCommand()` uses `sandbox do`, and `destroy()` removes local bookkeeping only.
* **Stateful mode** — set `executionMode: 'stateful'` to have `create()` call `sandbox run <id> --detach`, `runCommand()` call `sandbox exec <id>`, and `destroy()` call `sandbox delete <id>`.

| SDK method     | Ephemeral mode (default)             | Stateful mode                               |
| -------------- | ------------------------------------ | ------------------------------------------- |
| `create()`     | Local logical handle only            | `sandbox run <id> --detach`                 |
| `runCommand()` | `sandbox do -- /bin/sh -c <command>` | `sandbox exec <id> -- /bin/sh -c <command>` |
| `destroy()`    | Local bookkeeping only               | `sandbox delete <id>`                       |
| `filesystem`   | Per-operation `sandbox do`           | Per-operation `sandbox exec <id>`           |

## Use the Cloud Run provider

```typescript
import { cloudRun } from '@computesdk/cloud-run';

const compute = cloudRun({
  sandboxUrl: process.env.CLOUD_RUN_SANDBOX_URL,
  sandboxSecret: process.env.CLOUD_RUN_SANDBOX_SECRET,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Cloud Run!"');
console.log(result.stdout); // "Hello from Cloud Run!"

// Clean up
await sandbox.destroy();
```

### Cloud Run configuration options

```typescript
interface CloudRunConfig {
  /** URL of the deployed Cloud Run gateway service for remote mode. */
  sandboxUrl?: string;
  /** Shared bearer token for the deployed Cloud Run gateway service. */
  sandboxSecret?: string;
  /** Optional Google-signed identity token for Cloud Run services that require IAM auth. */
  gatewayAuthToken?: string;
  /** Execution mode. Ephemeral uses `sandbox do`; stateful uses `sandbox run`, `exec`, and `delete`. Defaults to ephemeral. */
  executionMode?: 'ephemeral' | 'stateful';
  /** Path to the Cloud Run sandbox binary. Defaults to CLOUD_RUN_SANDBOX_BINARY or /usr/local/gcp/bin/sandbox. */
  sandboxBinary?: string;
  /** Sandbox CLI mode. Cloud Run's CLI defaults this to local. */
  mode?: 'local' | 'container';
  /** Allow network egress from sandboxed commands. GCP service account access remains blocked by Cloud Run. */
  allowEgress?: boolean;
  /** Root filesystem to expose to sandboxes. Defaults to /. */
  rootfs?: string;
  /** Working directory for sandboxed commands or newly-created stateful sessions. */
  workdir?: string;
  /** Container template name for Cloud Run multi-container services. */
  template?: string;
  /** Writable persistent host path shared across executions. */
  persistDir?: string;
  /** Writable overlay directory. Caller is responsible for cleanup. */
  overlayDir?: string;
  /** Allow mounted filesystems to be writable. */
  write?: boolean;
  /** Bind mounts to attach to the sandbox. */
  mounts?: CloudRunMount[];
  /** Environment variables applied to sandboxed commands or newly-created stateful sessions. */
  env?: Record<string, string>;
  /** Extra args passed before the sandbox subcommand, e.g. global debug flags. */
  globalArgs?: string[];
  /** Extra args passed to `sandbox do` and `sandbox run`. */
  runArgs?: string[];
  /** Extra args passed to `sandbox exec` in stateful mode. */
  execArgs?: string[];
}

interface CloudRunMount {
  type?: 'bind';
  src: string;
  dst: string;
}
```

### Supported ComputeSDK operations

| Method       | Supported | Notes                                                                                                |
| ------------ | --------- | ---------------------------------------------------------------------------------------------------- |
| `create`     | ✅         | Ephemeral mode creates a logical handle; stateful mode starts a detached sandbox with `sandbox run`. |
| `getById`    | ✅         | Remote mode checks the gateway `/v1/sandbox/info` endpoint.                                          |
| `list`       | ✅         | Returns sandboxes tracked in-process.                                                                |
| `destroy`    | ✅         | Ephemeral mode drops the handle; stateful mode deletes the detached sandbox.                         |
| `runCommand` | ✅         | Uses `sandbox do` in ephemeral mode and `sandbox exec` in stateful mode.                             |
| `getInfo`    | ✅         |                                                                                                      |
| `getUrl`     | ❌         | Throws — Cloud Run Sandboxes do not expose per-sandbox ports through the sandbox CLI.                |
| `filesystem` | ✅         | Uses `sandbox do` in ephemeral mode and `sandbox exec` in stateful mode.                             |

### Cloud Run notes and limitations

* Default command timeout is 300,000 ms (5 minutes).
* Direct mode requires the service to be deployed with `gcloud beta run deploy --sandbox-launcher`, or the sandbox binary check will fail.
* `getUrl` is not supported and throws for the requested port.


# Cloudflare

Install, configure, and use the Cloudflare provider for ComputeSDK to run sandboxes on Cloudflare's edge network.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/cloudflare/>" %}

Cloudflare provider for ComputeSDK - Execute code in secure, isolated sandboxes on Cloudflare's edge network.

## Installation

```bash
npm install @computesdk/cloudflare
```

## Setup

To use the Cloudflare provider in remote mode, you connect to Cloudflare's official Sandbox bridge Worker. This only needs to be deployed once.

You can print these setup instructions at any time by running:

```bash
npx @computesdk/cloudflare
```

> **Note:** This command only prints instructions — it does not deploy anything and does not require Docker.

### Step 1: Deploy the official bridge Worker

Deploy Cloudflare's official Sandbox bridge Worker by following the guide at [developers.cloudflare.com/sandbox/bridge](https://developers.cloudflare.com/sandbox/bridge/).

### Step 2: Set the bridge Worker's API key secret

From your bridge Worker project, set the `SANDBOX_API_KEY` secret:

```bash
npx wrangler secret put SANDBOX_API_KEY
```

### Step 3: Configure your app

Add the bridge URL and the same API key to your `.env` file:

```bash
CLOUDFLARE_SANDBOX_URL=https://<your-bridge-subdomain>.workers.dev
CLOUDFLARE_SANDBOX_API_KEY=<same value as SANDBOX_API_KEY>
```

These are the only env vars needed at runtime.

> **Warm pool:** Warm pool support is configured on the bridge Worker. Set `WARM_POOL_TARGET` to a positive value (for example `WARM_POOL_TARGET=10`) to keep sandboxes warm.

## Usage

```typescript
import { cloudflare } from '@computesdk/cloudflare';

const compute = cloudflare({
  sandboxUrl: process.env.CLOUDFLARE_SANDBOX_URL,
  sandboxApiKey: process.env.CLOUDFLARE_SANDBOX_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Cloudflare!"');
console.log(result.stdout); // "Hello from Cloudflare!"

// Clean up
await sandbox.destroy();
```

### Run Commands

```typescript
const result = await sandbox.runCommand('ls -la /app');
console.log(result.stdout);
```

### Filesystem

```typescript
await sandbox.filesystem.writeFile('/app/config.json', JSON.stringify({ key: 'value' }));
const content = await sandbox.filesystem.readFile('/app/config.json');

await sandbox.filesystem.mkdir('/app/data');
const files = await sandbox.filesystem.readdir('/app');
const exists = await sandbox.filesystem.exists('/app/config.json');
await sandbox.filesystem.remove('/app/temp.txt');
```

### Port Forwarding

```typescript
const url = await sandbox.getUrl({ port: 3000 });
console.log(`Service available at: ${url}`);
```

### Environment Variables

Pass environment variables at the provider level:

```typescript
const compute = cloudflare({
  sandboxUrl: process.env.CLOUDFLARE_SANDBOX_URL,
  sandboxApiKey: process.env.CLOUDFLARE_SANDBOX_API_KEY,
  envVars: {
    API_KEY: 'your-api-key',
    DATABASE_URL: 'postgresql://localhost:5432/mydb',
  },
});
```

Or per-sandbox at creation time:

```typescript
const sandbox = await compute.sandbox.create({
  envs: { NODE_ENV: 'production' },
});
```

### Configuration Options

```typescript
interface CloudflareConfig {
  /** URL of the deployed bridge Worker (remote mode) */
  sandboxUrl?: string;
  /** API key for authenticating with the bridge Worker */
  sandboxApiKey?: string;
  /** @deprecated Use sandboxApiKey instead. */
  sandboxSecret?: string;
  /** Durable Object binding (direct mode only - see below) */
  sandboxBinding?: any;
  /** Warm pool configuration (direct mode only) */
  warmPool?: {
    binding: any;
    target?: number;
    refreshInterval?: number;
    poolName?: string;
  };
  /** Execution timeout in milliseconds */
  timeout?: number;
  /** Default runtime environment */
  runtime?: string;
  /** Environment variables to pass to sandbox */
  envVars?: Record<string, string>;
  /** Options forwarded to the underlying @cloudflare/sandbox SDK (direct mode) */
  sandboxOptions?: {
    sleepAfter?: string | number;
    keepAlive?: boolean;
  };
}
```

## Limitations

* Resource limits apply based on your Cloudflare plan
* Some system calls may be restricted in the container environment
* Listing all sandboxes is not supported — use `getById` to reconnect to a specific sandbox


# CodeSandbox

Install and use the CodeSandbox provider for ComputeSDK to create sandboxes and run commands in CodeSandbox environments.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/codesandbox/>" %}

CodeSandbox provider for ComputeSDK - Execute code in CodeSandbox development environments.

## Installation & Setup

```bash
npm install @computesdk/codesandbox
```

Add your CodeSandbox credentials to a `.env` file:

```bash
CSB_API_KEY=your_codesandbox_api_key
```

## Usage

```typescript
import { codesandbox } from '@computesdk/codesandbox';

const compute = codesandbox({
  apiKey: process.env.CSB_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from CodeSandbox!"');
console.log(result.stdout); // "Hello from CodeSandbox!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface CodesandboxConfig {
  /** CodeSandbox API key - if not provided, will fallback to CSB_API_KEY environment variable */
  apiKey?: string;
  /** Template to use for new sandboxes */
  templateId?: string;
  /** Default runtime environment, e.g. 'node', 'python' */
  runtime?: string;
  /** Execution timeout in milliseconds */
  timeout?: number;
}
```


# Collimate

Install and use the Collimate provider for ComputeSDK, including the required template ID for creating and running sandboxes.

Collimate provider for ComputeSDK.

## Installation & Setup

```bash
npm install @computesdk/collimate
```

Add your Collimate credentials to a `.env` file:

```bash
COLLIMATE_API_KEY=your_collimate_api_key
```

Get your key at <https://collimate.ai>.

## Usage

Collimate sandboxes are created from a template, so a `templateId` is required — pass it in the provider config or in the `create()` options.

```typescript
import { collimate } from '@computesdk/collimate';

const compute = collimate({
  apiKey: process.env.COLLIMATE_API_KEY,
  templateId: 'python',
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Collimate!"');
console.log(result.stdout); // "Hello from Collimate!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface CollimateConfig {
  /** Collimate API server URL. Default: "https://api.collimate.ai" */
  serverUrl?: string;
  /** API key. Falls back to COLLIMATE_API_KEY env var. */
  apiKey?: string;
  /** Default template ID for sandbox creation. */
  templateId?: string;
  /** Default execution timeout in seconds. Default: 900 */
  timeout?: number;
}
```

### Supported Operations

| Method       | Supported | Notes                                                                                             |
| ------------ | --------- | ------------------------------------------------------------------------------------------------- |
| `create`     | ✅         | Requires a `templateId` from config or create options.                                            |
| `getById`    | ✅         | Returns `null` when the session no longer exists.                                                 |
| `list`       | ✅         | Lists sessions visible to the API key.                                                            |
| `destroy`    | ✅         | Deletes the session.                                                                              |
| `runCommand` | ✅         | Executes via the Collimate exec API (`bash -lc`).                                                 |
| `getInfo`    | ✅         |                                                                                                   |
| `getUrl`     | ❌         | Throws — sandboxes are accessed through the exec API, not a per-port public URL.                  |
| `filesystem` | ✅         | Implemented against the exec API (`writeFile` uploads file specs; reads/dirs use shell commands). |

### Notes

* `timeout` is expressed in **seconds** (default 900) and is converted to milliseconds internally.
* `getUrl` is not supported and throws for the requested port.


# CreateOS

CreateOS provider for ComputeSDK — NodeOps VM sandboxes with pause/resume/fork snapshots. A thin adapter over the official @nodeops-createos/sandbox package.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/createos/>" %}

CreateOS provider for ComputeSDK — NodeOps VM sandboxes with pause/resume/fork snapshots. A thin adapter over the official `@nodeops-createos/sandbox` package.

## Installation & Setup

```bash
npm install @computesdk/createos-sandbox
```

Add your CreateOS credentials to a `.env` file:

```bash
CREATEOS_SANDBOX_API_KEY=your_createos_api_key
# Optional: override the control-plane base URL (defaults to https://api.sb.createos.sh)
CREATEOS_SANDBOX_BASE_URL=https://api.sb.createos.sh
```

## Usage

```typescript
import { createosSandbox } from '@computesdk/createos-sandbox';

const compute = createosSandbox({
  apiKey: process.env.CREATEOS_SANDBOX_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from CreateOS!"');
console.log(result.stdout); // "Hello from CreateOS!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface CreateosConfig {
  /** createos-sandbox API key. Falls back to the CREATEOS_SANDBOX_API_KEY env var. */
  apiKey?: string;
  /** Control-plane base URL. Falls back to the CREATEOS_SANDBOX_BASE_URL env var, then the production control plane. */
  baseUrl?: string;
  /** Default shape when create options pin neither `shape` nor cpus/memoryMb. */
  shape?: string;
  /** Default rootfs catalog name or template id. Empty = host default. */
  rootfs?: string;
  /** Reported `getInfo().timeout` in ms. Informational only. */
  timeout?: number;
}
```

### Supported Operations

| Method       | Supported | Notes                                                                                                                                           |
| ------------ | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `create`     | ✅         | Sizes the VM from a fixed shape catalog; maps `cpus`/`memoryMb` onto the nearest shape. A `snapshotId` forks a paused sandbox into a fresh one. |
| `getById`    | ✅         | Returns `null` on a genuine 404; other errors propagate.                                                                                        |
| `list`       | ✅         | Lists up to 100 sandboxes.                                                                                                                      |
| `destroy`    | ✅         | Idempotent — a 404 is treated as already gone.                                                                                                  |
| `runCommand` | ✅         | Runs via `sh -c`; per-command `cwd`/`env`/`background` are synthesised into an inline script.                                                   |
| `getInfo`    | ✅         | Refreshes the handle from the control plane.                                                                                                    |
| `getUrl`     | ✅         | Returns a preview URL via `sandbox.previewUrl(port)` (defaults to `https`).                                                                     |
| `filesystem` | ✅         | `readFile`/`writeFile` use the native file upload/download API; other ops use shell commands.                                                   |
| `snapshot`   | ✅         | See notes below.                                                                                                                                |

### Snapshots

CreateOS has no decoupled snapshot object — **pausing IS the snapshot**, and the paused sandbox id is the snapshot id:

* `snapshot.create` pauses the sandbox (the source VM stops) and returns the sandbox id as the snapshot id.
* `snapshot.list` returns all paused sandboxes.
* `snapshot.delete` destroys the paused sandbox.
* `create({ snapshotId })` forks the paused bundle into a fresh running sandbox.

### Notes

* Requires Node.js >= 22.
* `getInstance()` returns the bare native `@nodeops-createos/sandbox` handle, exposing the full stateful API (pause / resume / fork / disks / networks / bandwidth) that ComputeSDK's core surface does not model.
* `timeout` is informational only — it is reported by `getInfo()` but does not enforce an execution limit.


# Daytona

Install and use the Daytona provider for ComputeSDK to create sandboxes and run commands in Daytona development workspaces.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/daytona/>" %}

Daytona provider for ComputeSDK - Execute code in Daytona development workspaces.

## Installation & Setup

```bash
npm install @computesdk/daytona
```

Add your Daytona credentials to a `.env` file:

```bash
DAYTONA_API_KEY=your_daytona_api_key
```

## Usage

```typescript
import { daytona } from '@computesdk/daytona';

const compute = daytona({
  apiKey: process.env.DAYTONA_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Daytona!"');
console.log(result.stdout); // "Hello from Daytona!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface DaytonaConfig {
  /** Daytona API key - if not provided, will use DAYTONA_API_KEY env var */
  apiKey?: string;
  /** Default runtime environment (e.g. 'node', 'python') */
  runtime?: string;
  /** Execution timeout in milliseconds */
  timeout?: number;
}
```


# Declaw

Declaw runs Firecracker microVMs with a built-in security stack: PII scanning, prompt-injection defense, TLS-intercepting egress proxy, and per-sandbox network policies.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/declaw/>" %}

Declaw provider for ComputeSDK

Declaw runs Firecracker microVMs with a built-in security stack: PII scanning, prompt-injection defense, TLS-intercepting egress proxy, and per-sandbox network policies.

## Installation & Setup

```bash
npm install @computesdk/declaw
```

Add your Declaw credentials to a `.env` file:

```bash
DECLAW_API_KEY=your_declaw_api_key
```

API keys must start with `dcl_`.

## Usage

```typescript
import { declaw } from '@computesdk/declaw';

const compute = declaw({
  apiKey: process.env.DECLAW_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('node -v');
console.log(result.stdout); // v20.x.x

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface DeclawConfig {
  /** Declaw API key - if not provided, will use DECLAW_API_KEY env var */
  apiKey?: string;
  /** API domain - if not provided, will use DECLAW_DOMAIN env var */
  domain?: string;
  /** Default create-time timeout in milliseconds (default: 300000) */
  timeout?: number;
}
```

When `domain` is not set (and `DECLAW_DOMAIN` is not set), the provider passes `undefined` to the underlying `@declaw/sdk`. The effective default of `api.declaw.ai` is applied by `@declaw/sdk`, not by this provider.

## Templates

`templateId` maps to a Declaw template alias. Defaults to `node` (Ubuntu 22.04 + Node.js 20).

**Built-in templates:**

* `base`
* `node` (default)
* `python`
* `code-interpreter`
* `ai-agent`
* `mcp-server`
* `web-dev`
* `devops`

```typescript
const sandbox = await compute.sandbox.create({
  templateId: 'python',
});
```

Custom templates can be built through the Declaw CLI — see the [Declaw docs](https://docs.declaw.ai/).


# Docker

Docker provider for ComputeSDK — local containerized sandboxes (Python or Node.js) for development and testing.

Docker provider for ComputeSDK — local containerized sandboxes (Python or Node.js) for development and testing.

## Installation & Setup

```bash
npm install @computesdk/docker
```

This provider is **local** — it talks to a Docker Engine/daemon rather than a hosted API, so there are no credentials to configure. Docker must be installed and running on the host. By default the provider connects over the standard socket, falling back to `DOCKER_HOST` or `/var/run/docker.sock`.

## Usage

```typescript
import { docker } from '@computesdk/docker';

const compute = docker({
  runtime: 'python',
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Docker!"');
console.log(result.stdout); // "Hello from Docker!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface DockerConfig {
  /** Connection to the Docker daemon (exactly what dockerode accepts). Defaults to socket / DOCKER_HOST. */
  connection?: DockerConnection;
  /** Default image runtime identifier, e.g. 'python' or 'node'. Defaults to 'python'. */
  runtime?: string;
  /** Reported timeout in ms. Defaults to 300000 (5 minutes). */
  timeout?: number;
  /** Default image & pull policy for sandboxes. Defaults to python:3.11-slim / ifNotPresent. */
  image: DockerImage;
  /** Declarative container defaults (workdir, env, ports, resources, etc.). */
  container?: ContainerDefaults;
  /** Raw dockerode container create options merged last. */
  createOptions?: ContainerCreateOptions;
  /** Raw dockerode container start options. */
  startOptions?: ContainerStartOptions;
  /** When the provider should clean up containers it created ('always' | 'onSuccess' | 'never'). */
  cleanup?: CleanupPolicy;
  /** Stream container logs. Defaults to false. */
  streamLogs?: boolean;
}

interface DockerImage {
  /** Image reference, e.g. 'python:3.11-slim'. */
  name: string;
  /** Pull strategy: 'always' | 'ifNotPresent' | 'never'. Defaults to 'ifNotPresent'. */
  pullPolicy?: PullPolicy;
  /** Auth for pulling private images (Engine API AuthConfig shape). */
  auth?: RegistryAuth;
}
```

The provider ships sensible defaults (`defaultDockerConfig`) that are merged with your config, so `docker()` with no arguments works out of the box using `python:3.11-slim` with a `/workspace` working directory and a 512 MB memory limit.

### Supported Operations

| Method       | Supported | Notes                                                                                                                                                |
| ------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `create`     | ✅         | Only `'python'` or `'node'` runtimes are supported; any other value throws. Pulls the image (per `pullPolicy`) and starts a keep-alive container.    |
| `getById`    | ✅         | Resolves a container by id; returns `null` if it does not exist.                                                                                     |
| `list`       | ✅         | Lists containers labeled `com.computesdk.sandbox`.                                                                                                   |
| `destroy`    | ✅         | Stops and force-removes the container.                                                                                                               |
| `runCommand` | ✅         | Executes via `docker exec` (`/bin/sh -c`).                                                                                                           |
| `getInfo`    | ✅         |                                                                                                                                                      |
| `getUrl`     | ✅         | Builds a URL from the container's published port bindings, or falls back to the container IP. Requires the port to be exposed via `container.ports`. |
| `filesystem` | ✅         | Implemented via shell commands inside the container.                                                                                                 |

### Notes

* Runtime is limited to `'python'` (default `python:3.11-slim`) or `'node'` (default `node:20-alpine`). Passing any other runtime throws.
* Containers are launched with a keep-alive command so they stay running for exec, filesystem, and background use.
* `getUrl` reads published port bindings; set `container.ports` in the config to expose a port on the host.


# E2B

Set up the E2B provider for ComputeSDK, configure your API key, and create sandboxes to run commands.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/e2b/>" %}

E2B provider for ComputeSDK

## Installation & Setup

```bash
npm install @computesdk/e2b
```

Add your E2B credentials to a `.env` file:

```bash
E2B_API_KEY=your_e2b_api_key
```

> **Note:** E2B API keys must start with `e2b_`. The provider throws an error if the key is in any other format.

## Usage

```typescript
import { e2b } from '@computesdk/e2b';

const compute = e2b({
  apiKey: process.env.E2B_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from E2B!"');
console.log(result.stdout); // "Hello from E2B!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface E2BConfig {
  /** E2B API key - if not provided, will use E2B_API_KEY env var */
  apiKey?: string;
  /** Execution timeout in milliseconds */
  timeout?: number;
}
```


# Freestyle

Set up the Freestyle provider for ComputeSDK, configure your API key, and create sandboxes to run commands.

Freestyle provider for ComputeSDK

## Installation & Setup

```bash
npm install @computesdk/freestyle
```

Add your Freestyle credentials to a `.env` file:

```bash
FREESTYLE_API_KEY=your_freestyle_api_key
```

## Usage

```typescript
import { freestyle } from '@computesdk/freestyle';

const compute = freestyle({
  apiKey: process.env.FREESTYLE_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Freestyle!"');
console.log(result.stdout); // "Hello from Freestyle!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface FreestyleConfig {
  /** Freestyle API key - if not provided, will use FREESTYLE_API_KEY env var */
  apiKey?: string;
  /** Default runtime hint (e.g. 'node', 'python'). Default: 'node' */
  runtime?: string;
  /** Timeout in milliseconds for shell commands (runCommand). Default: 30000 */
  timeout?: number;
}
```


# HopX

Set up the HopX provider for ComputeSDK, configure your API key, and create sandboxes to run commands.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/hopx/>" %}

HopX provider for ComputeSDK

## Installation & Setup

```bash
npm install @computesdk/hopx
```

Add your HopX credentials to a `.env` file:

```bash
HOPX_API_KEY=your_hopx_api_key
```

## Usage

```typescript
import { hopx } from '@computesdk/hopx';

const compute = hopx({
  apiKey: process.env.HOPX_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from HopX!"');
console.log(result.stdout); // "Hello from HopX!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface HopxConfig {
  /** HopX API key - if not provided, will use HOPX_API_KEY env var */
  apiKey?: string;
  /** Execution timeout in milliseconds */
  timeout?: number;
  /** Template name for sandbox creation (e.g. 'code-interpreter') */
  template?: string;
  /** Base API URL for custom/staging environments */
  baseURL?: string;
}
```


# Isorun

Isorun provider for ComputeSDK — isolated Linux VM sandboxes for running untrusted and AI-generated code, billed by the second.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/isorun/>" %}

Isorun provider for ComputeSDK — isolated Linux VM sandboxes for running untrusted and AI-generated code, billed by the second.

## Installation & Setup

```bash
npm install @computesdk/isorun
```

Add your Isorun credentials to a `.env` file:

```bash
ISORUN_API_KEY=your_isorun_api_key
```

## Usage

```typescript
import { isorun } from '@computesdk/isorun';

const compute = isorun({
  apiKey: process.env.ISORUN_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Isorun!"');
console.log(result.stdout); // "Hello from Isorun!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface IsorunConfig {
  /** API key. Falls back to `ISORUN_API_KEY` env var. The runner endpoint is derived from the key. */
  apiKey?: string;
}
```

### Supported Operations

| Method       | Supported | Notes                                                                                                                                                      |
| ------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `create`     | ✅         | Defaults to the `node` runtime (`node:22`); pass `runtime: 'python'` for `python:3.12-slim`. Accepts `image`, `vcpus`, `memMiB`, `diskMiB`, and `timeout`. |
| `getById`    | ✅         |                                                                                                                                                            |
| `list`       | ✅         |                                                                                                                                                            |
| `destroy`    | ✅         |                                                                                                                                                            |
| `runCommand` | ✅         | Supports `env`, `cwd`, and `background` options.                                                                                                           |
| `getInfo`    | ✅         |                                                                                                                                                            |
| `getUrl`     | ✅         | Returns the sandbox URL for a given port; honors a custom `protocol`.                                                                                      |
| `filesystem` | ✅         | `readFile` / `writeFile` are native; `mkdir`, `readdir`, `exists`, `remove` run via shell commands.                                                        |
| `snapshot`   | ✅         | `compute.snapshot.create` / `list` / `delete`.                                                                                                             |

### Notes

* The default command/sandbox timeout is 300000 ms (5 minutes).
* The `isorun` SDK exposes extra capabilities without ComputeSDK slots — `fork(n)`, `hibernate()` / `resume()`, and `setTimeout(seconds)`. Reach the raw instance via `compute.sandbox.getInstance(sandbox)`.


# Just Bash

just-bash provider for ComputeSDK — local sandboxed bash execution with a virtual filesystem. No external services, containers, or authentication required.

just-bash provider for ComputeSDK — local sandboxed bash execution with a virtual filesystem. No external services, containers, or authentication required.

## Installation & Setup

```bash
npm install @computesdk/just-bash
```

No environment variables or credentials are required. just-bash runs entirely locally, interpreting commands in TypeScript against an in-memory virtual filesystem.

## Usage

```typescript
import { justBash } from '@computesdk/just-bash';

const compute = justBash({});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from just-bash!"');
console.log(result.stdout); // "Hello from just-bash!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface JustBashConfig {
  /** Enable Python support via pyodide (disabled by default) */
  python?: boolean;
  /** Initial files to populate in the virtual filesystem */
  files?: BashOptions['files'];
  /** Initial environment variables */
  env?: Record<string, string>;
  /** Working directory (defaults to /home/user) */
  cwd?: string;
  /** Custom filesystem implementation (InMemoryFs by default; also OverlayFs, ReadWriteFs, MountableFs) */
  fs?: BashOptions['fs'];
  /** Custom commands created with defineCommand() */
  customCommands?: BashOptions['customCommands'];
  /** Network configuration for curl (disabled by default) */
  network?: BashOptions['network'];
}
```

### Supported Operations

| Method       | Supported | Notes                                                                       |
| ------------ | --------- | --------------------------------------------------------------------------- |
| `create`     | ✅         | Creates an in-process sandbox; `runtime: 'python'` also enables Python.     |
| `getById`    | ✅         | Looks up sandboxes tracked in the current process.                          |
| `list`       | ✅         |                                                                             |
| `destroy`    | ✅         | Removes the sandbox from the in-process registry.                           |
| `runCommand` | ✅         | Supports `env` and `cwd`. 60+ built-in commands (jq, awk, sed, grep, etc.). |
| `getInfo`    | ✅         |                                                                             |
| `getUrl`     | ❌         | Throws — just-bash is a local sandbox with no network capabilities.         |
| `filesystem` | ✅         | `readFile`, `writeFile`, `mkdir`, `readdir`, `exists`, `remove`.            |

### Notes

* **Local, no network** — no API keys, containers, or external services. Ideal for tests, CI, AI-agent tooling, and offline use.
* **In-memory by default** — files do not persist across process restarts unless you supply an `OverlayFs`, `ReadWriteFs`, or `MountableFs` backend via `fs`.
* **Not real processes** — commands are interpreted in TypeScript, not executed as OS processes; there is no real Node.js runtime.
* **Python via pyodide** — requires `python: true` and runs a WebAssembly-based interpreter.


# Kubernetes

Kubernetes provider for ComputeSDK — run each sandbox as a Pod in your cluster and execute commands via pods/exec.

Kubernetes provider for ComputeSDK — run each sandbox as a Pod in your cluster and execute commands via `pods/exec`.

## Installation

```bash
npm install @computesdk/k8s
```

## Setup

The provider uses your current kubeconfig context by default. It calls `loadFromDefault()` from `@kubernetes/client-node`, which reads `$KUBECONFIG` if set, otherwise `~/.kube/config`. Override with `kubeConfigPath` or `context` in the provider config if you need to target a specific cluster.

The identity used by your kubeconfig needs the following RBAC in the target namespace:

| Resource    | Verbs                             |
| ----------- | --------------------------------- |
| `pods`      | `create`, `get`, `list`, `delete` |
| `pods/exec` | `create`                          |
| `services`  | `delete`                          |

`services: delete` is required because `destroy` opportunistically cleans up a Service named `<pod-name>-svc` (in case one was created out-of-band to back `getUrl`). The provider never creates Services itself.

Local clusters (kind, k3d, minikube, Docker Desktop) grant cluster-admin by default and need no extra setup.

## Usage

```typescript
import { k8s } from '@computesdk/k8s';

const compute = k8s({
  namespace: 'default',
  runtime: 'node',
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from k8s!"');
console.log(result.stdout); // "Hello from k8s!"

// Clean up
await sandbox.destroy();
```

Sandbox IDs are namespace-prefixed: `<namespace>/<podName>` (e.g. `default/computesdk-sbx-abc12345`). `create()`, `getById()`, and `list()` all return this form, so values round-trip without normalization. `getById()` and `destroy()` also accept a bare Pod name for convenience — bare IDs are resolved against the provider's configured `namespace`.

### Pod Layout

Each sandbox is a single Pod with one container:

* **Pod name**: `<podNamePrefix>-<up to 8 random base36 chars>` (default prefix `computesdk-sbx`).
* **Container name**: `sandbox` — use this with `kubectl exec` (e.g. `kubectl exec -it -c sandbox <pod> -- /bin/sh`).
* **Labels**: `computesdk.io/managed=true`, `computesdk.io/runtime=<node|python>`, `computesdk.io/sandbox-id=<pod-name>`.
* **Annotations**: any `metadata` you pass to `create()` is stored as `computesdk.io/meta-<key>`. Non-string values are JSON-stringified.
* **Restart policy**: `Never`. Pods are one-shot; recreate the sandbox if the container dies.

`compute.sandbox.list()` returns Pods in the configured `namespace` that match `computesdk.io/managed=true`. Sandboxes in other namespaces are not returned.

### Run Commands

```typescript
const result = await sandbox.runCommand('ls -la /');
console.log(result.stdout);

// Pipes, redirects, cwd, env, background
await sandbox.runCommand('node app.js', {
  cwd: '/app',
  env: { NODE_ENV: 'production' },
});

await sandbox.runCommand('python server.py', { background: true });
```

Background commands are launched with `nohup` and their combined stdout/stderr is redirected to `/tmp/computesdk-bg.log` inside the Pod. Tail it with another `runCommand('cat /tmp/computesdk-bg.log')` if you need the output.

### Environment Variables

Pass environment variables to the Pod at creation time:

```typescript
const sandbox = await compute.sandbox.create({
  envs: {
    API_KEY: 'your-api-key',
    DATABASE_URL: 'postgresql://localhost:5432/mydb',
  },
});
```

These are set on the Pod's container spec and available to every command in the sandbox.

### Port Forwarding

`getUrl` is template-based in this MVP — set `urlTemplate` to construct routable URLs through your own ingress, gateway, or DNS pattern. The provider substitutes these placeholders:

| Placeholder   | Value                                       |
| ------------- | ------------------------------------------- |
| `{protocol}`  | From the `protocol` option (default `http`) |
| `{service}`   | `<pod-name>-svc`                            |
| `{namespace}` | Pod namespace                               |
| `{port}`      | From the `port` option                      |

```typescript
const compute = k8s({
  urlTemplate: '{protocol}://{service}.{namespace}.svc.cluster.local:{port}',
});

const sandbox = await compute.sandbox.create();
const url = await sandbox.getUrl({ port: 3000 });
// http://computesdk-sbx-abc123-svc.default.svc.cluster.local:3000
```

If `urlTemplate` is not set, `getUrl` returns a placeholder URL ending in `.invalid` so misconfiguration is obvious.

### Configuration Options

```typescript
interface K8sConfig {
  /** Path to kubeconfig file - if not set, uses $KUBECONFIG or ~/.kube/config */
  kubeConfigPath?: string;
  /** Raw kubeconfig YAML/JSON string - takes precedence over path-based loading */
  kubeConfigRaw?: string;
  /** Kubeconfig context to use - defaults to the current-context */
  context?: string;
  /** Target namespace for created Pods - defaults to "default" */
  namespace?: string;
  /** Container image - defaults to node:20-alpine or python:3.11-slim based on runtime */
  image?: string;
  /** Runtime - defaults to "node" */
  runtime?: 'node' | 'python';
  /** Time to wait for Pod to reach Running state, in ms - defaults to 120000 */
  timeout?: number;
  /** Prefix for generated Pod names - defaults to "computesdk-sbx" */
  podNamePrefix?: string;
  /** URL template for getUrl - see Port Forwarding section */
  urlTemplate?: string;
}
```

Kubeconfig loading precedence:

1. `kubeConfigRaw`
2. `KUBECONFIG_B64` (base64-encoded kubeconfig)
3. `kubeConfigPath`
4. default kubeconfig resolution

## Limitations

* Filesystem methods are not implemented in this MVP — use `runCommand` with `cat`, `tee`, etc. to read and write files.
* The provider never creates Kubernetes Services. `getUrl` is purely template-based — set `urlTemplate` to match your existing routing setup (ingress, gateway, or DNS).
* Pod resource requests and limits are fixed (250m / 256Mi requests, 1 CPU / 1Gi limits). Set `image` if you need a different runtime; CPU/memory are not yet configurable.
* Pods use `restartPolicy: Never`. If the container exits, the sandbox is gone — create a new one.
* `compute.sandbox.list()` only scans the namespace configured on the provider; it does not enumerate across namespaces.


# Leap0

Leap0 provider for ComputeSDK - enterprise-grade cloud sandboxes for AI agents with full filesystem, git, process, and desktop support.

[Leap0](https://leap0.dev) provider for ComputeSDK - enterprise-grade cloud sandboxes for AI agents with full filesystem, git, process, and desktop support.

## Installation & Setup

```bash
npm install @computesdk/leap0
```

Add your Leap0 API key to a `.env` file:

```bash
LEAP0_API_KEY=your_leap0_api_key
```

Get your API key at [app.leap0.dev](https://app.leap0.dev/login).

## Usage

```typescript
import { leap0 } from '@computesdk/leap0';

const compute = leap0({
  apiKey: process.env.LEAP0_API_KEY,
  template: 'system/debian:bookworm',
});

// Create sandbox (uses the default template from config)
const sandbox = await compute.sandbox.create();

// Or override the template at create time via templateId
const sandbox2 = await compute.sandbox.create({
  templateId: 'system/code-interpreter:v0.1.0',
});

// Run a command
const result = await sandbox.runCommand('echo "Hello from Leap0!"');
console.log(result.stdout); // "Hello from Leap0!"

// Work with files
await sandbox.filesystem.writeFile('/tmp/hello.py', 'print("Hello World")');
const content = await sandbox.filesystem.readFile('/tmp/hello.py');

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface Leap0Config {
  /** Leap0 API key - if not provided, will use LEAP0_API_KEY env var */
  apiKey?: string;
  /** Base URL for the Leap0 API (default: https://api.leap0.dev) */
  baseUrl?: string;
  /** Sandbox domain for URL generation (default: sandbox.leap0.dev) */
  sandboxDomain?: string;
  /** Client timeout in seconds */
  timeout?: number;
  /** Default template name to use when creating sandboxes (e.g. 'system/debian:bookworm') */
  template?: string;
}
```


# Lelantos

Lelantos provider for ComputeSDK — execute code in secure, EU-native Firecracker microVM sandboxes.

Lelantos provider for ComputeSDK — execute code in secure, EU-native [Firecracker](https://firecracker-microvm.github.io/) microVM sandboxes. Lelantos is an E2B-API-compatible platform running on Hetzner bare-metal in the EU, so this provider wraps the same `e2b` npm SDK pointed at the Lelantos control plane.

## Installation & Setup

```bash
npm install @computesdk/lelantos
```

Add your Lelantos credentials to a `.env` file:

```bash
LELANTOS_API_KEY=lel_your_api_key_here
# Optional — override the control-plane + sandbox domain (defaults to lelantos.ai)
LELANTOS_DOMAIN=lelantos.ai
# Optional — explicit control-plane URL (overrides the domain-derived URL)
LELANTOS_API_URL=https://api.lelantos.ai
```

Lelantos issues `lel_…` keys. The provider accepts both the `lel_…` and `e2b_…` forms of a Lelantos key, and resolves credentials with the fallback order `config` → `LELANTOS_*` → `E2B_*` so it is a drop-in for E2B-shaped configs.

## Usage

```typescript
import { lelantos } from '@computesdk/lelantos';

const compute = lelantos({
  apiKey: process.env.LELANTOS_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Lelantos!"');
console.log(result.stdout); // "Hello from Lelantos!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface LelantosConfig {
  /**
   * Lelantos API key. Accepts the `lel_…` form OR the `e2b_…` form of a
   * lelantos key (a native `lel_<hex>` key is transparently presented to the
   * e2b SDK as its `e2b_<hex>` alias). If not provided, falls back to the
   * `LELANTOS_API_KEY` environment variable, then `E2B_API_KEY`.
   */
  apiKey?: string;
  /**
   * Lelantos control-plane + sandbox domain, e.g. `'lelantos.ai'`. The e2b SDK
   * derives the control-plane URL as `https://api.${domain}` and the sandbox
   * preview host as `{port}-{sandboxId}.${domain}`. If not provided, falls back
   * to the `LELANTOS_DOMAIN` then `E2B_DOMAIN` environment variable, then
   * defaults to `'lelantos.ai'`.
   */
  domain?: string;
  /**
   * Explicit control-plane URL override (e.g. a non-`api.` host or a port).
   * Takes precedence over `domain`-derived URLs for control-plane calls. Falls
   * back to `LELANTOS_API_URL` then `E2B_API_URL`.
   */
  apiUrl?: string;
  /** Execution timeout in milliseconds (defaults to 300000). */
  timeout?: number;
}
```

### Supported Operations

| Method       | Supported | Notes                                                                                                                                    |
| ------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `create`     | ✅         | Boot from a `templateId` / `snapshotId` when supplied.                                                                                   |
| `getById`    | ✅         | Reconnects to a running sandbox by id.                                                                                                   |
| `list`       | ✅         |                                                                                                                                          |
| `destroy`    | ✅         |                                                                                                                                          |
| `runCommand` | ✅         | Supports `env`, `cwd`, `background`. Real non-zero exit codes are returned, not thrown. Transient infra errors are retried with backoff. |
| `getInfo`    | ✅         |                                                                                                                                          |
| `getUrl`     | ✅         | Returns `https://{port}-{sandboxId}.{domain}` for the given port.                                                                        |
| `filesystem` | ✅         | `readFile`, `writeFile`, `mkdir`, `readdir`, `exists`, `remove` (native e2b files).                                                      |
| `snapshot`   | ✅         | `compute.snapshot.create` snapshots a running sandbox; `list` / `delete` map to templates.                                               |
| `template`   | partial   | `list` / `delete` supported; `create` throws — build via the E2B template protocol / CLI or `snapshot.create()`.                         |

### Notes

* Because the wire protocol is E2B-compatible, `domain` / `apiUrl` are threaded into **every** SDK call (create, connect, list, kill, snapshot, template) so lifecycle operations stay on Lelantos rather than falling back to `api.e2b.app`.
* Sandboxes run in the EU (single-region today).
* Point at a self-hosted or staging slot by setting `domain` (and optionally `apiUrl`).


# Lightning

Lightning AI provider for ComputeSDK — create and manage Lightning AI cloud sandboxes: run shell commands, read/write files, and manage the sandbox lifecycle.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/lightning/>" %}

Lightning AI provider for ComputeSDK — create and manage [Lightning AI](https://lightning.ai/) cloud sandboxes: run shell commands, read/write files, and manage the sandbox lifecycle.

## Installation & Setup

```bash
npm install @computesdk/lightning
```

> The underlying `@lightningai/sdk` is published ESM-only and requires **Node.js 22+**. This package loads it via dynamic `import()`, so it works from both ESM and CommonJS projects.

Add your Lightning AI credentials to a `.env` file:

```bash
LIGHTNING_API_KEY=your_api_key_here
# Optional: override the Lightning Cloud base URL
LIGHTNING_CLOUD_URL=https://lightning.ai
```

`LIGHTNING_SANDBOX_API_KEY` is also accepted and takes precedence over `LIGHTNING_API_KEY`, matching the SDK.

## Usage

```typescript
import { lightning } from '@computesdk/lightning';

const compute = lightning({
  apiKey: process.env.LIGHTNING_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Lightning!"');
console.log(result.stdout); // "Hello from Lightning!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface LightningConfig {
  /** Lightning AI API key - falls back to LIGHTNING_SANDBOX_API_KEY, then LIGHTNING_API_KEY env vars. */
  apiKey?: string;
  /** Lightning Cloud base URL - falls back to LIGHTNING_CLOUD_URL, then production. */
  baseUrl?: string;
  /** Instance type for new sandboxes (e.g. "cpu-1", "cpu-2", ... "cpu-16"). Defaults to "cpu-1". */
  instanceType?: string;
  /** Curated runtime image for new sandboxes (e.g. "node24", "python313"). */
  runtime?: string;
  /** Whether new sandboxes persist filesystem state across stops via auto-snapshots. */
  persistent?: boolean;
  /** Request spot capacity for new sandboxes. */
  spot?: boolean;
  /** Ports to expose on new sandboxes when none are supplied per-create. */
  ports?: number[];
  /** Maximum sandbox lifetime in milliseconds before auto-stop. */
  timeout?: number;
}
```

### Supported Operations

| Method       | Supported | Notes                                                                                                               |
| ------------ | --------- | ------------------------------------------------------------------------------------------------------------------- |
| `create`     | ✅         | Honors `instanceType`, `runtime`, `ports`, `spot`, `persistent`, `timeout`; boot from a `snapshotId`.               |
| `getById`    | ✅         | Reconnects by id.                                                                                                   |
| `list`       | ✅         |                                                                                                                     |
| `destroy`    | ✅         |                                                                                                                     |
| `runCommand` | ✅         | Supports `cwd`, `env`, `background`. Combined stdout/stderr surfaced on `stdout` (`stderr` left empty).             |
| `getInfo`    | ✅         |                                                                                                                     |
| `getUrl`     | ✅         | Returns the public HTTPS URL for a port; the port must be declared via `ports` at create time, otherwise it throws. |
| `filesystem` | ✅         | `readFile`, `writeFile`, `mkdir`, `readdir`, `exists`, `remove`.                                                    |
| `snapshot`   | ✅         | `compute.snapshot.create` / `list` / `delete`, and restore via `snapshotId` on create.                              |

### Notes

* **Node.js 22+** is required by the underlying `@lightningai/sdk`.
* **Combined output** — stdout and stderr are returned as a single combined stream on `result.stdout`.
* **Snapshots** — Lightning snapshots are unnamed, so `CreateSnapshotOptions.name` / `metadata` are accepted for parity but not persisted. `/tmp` and other platform defaults are excluded from snapshots — persist data under `$HOME` to survive a restore.
* **Credentials & concurrency** — the SDK stores auth in process-global state, so the provider serializes the brief credential switch between provider instances using *different* API keys. Same-key operations run fully concurrently.
* Drop down to the native SDK sandbox via `sandbox.getInstance()`.


# Modal

Set up the Modal provider for ComputeSDK, configure your credentials, and create sandboxes to run commands with optional GPU support.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/modal/>" %}

Modal provider for ComputeSDK - Execute code with GPU support for machine learning workloads.

## Installation & Setup

```bash
npm install @computesdk/modal
```

Add your Modal credentials to a `.env` file:

```bash
MODAL_TOKEN_ID=your_modal_token_id
MODAL_TOKEN_SECRET=your_modal_token_secret
```

## Usage

```typescript
import { modal } from '@computesdk/modal';

const compute = modal({
  tokenId: process.env.MODAL_TOKEN_ID,
  tokenSecret: process.env.MODAL_TOKEN_SECRET,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Modal!"');
console.log(result.stdout); // "Hello from Modal!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface ModalConfig {
  /** Modal token ID - if not provided, will use MODAL_TOKEN_ID env var */
  tokenId?: string;
  /** Modal token secret - if not provided, will use MODAL_TOKEN_SECRET env var */
  tokenSecret?: string;
  /** Execution timeout in milliseconds */
  timeout?: number;
  /** Modal environment (sandbox or main) */
  environment?: string;
  /** Ports to expose (unencrypted by default) */
  ports?: number[];
  /** Port for the daemon SSE channel (defaults to 38989); set false to disable */
  daemonSsePort?: number | false;
  /** Modal app name (default: 'computesdk-modal') */
  appName?: string;
  /** Use Modal's experimental scalable sandboxes API */
  scalableSandboxes?: boolean;
}
```

Ports are exposed with unencrypted tunnels by default for maximum compatibility.


# Mosaic

Mosaic provider for ComputeSDK - Firecracker-based sandbox environments with command execution.

Mosaic provides Firecracker-based sandbox environments with command execution, a workspace filesystem, preview URLs, snapshots, and environments built from container images.

## Installation and setup

```bash
npm install computesdk @computesdk/mosaic
```

Set the API endpoint and bearer token:

```bash
export MOSAIC_API_URL=https://your-mosaic-api.example.com
export MOSAIC_API_TOKEN=your_mosaic_token
```

## Usage

```typescript
import { compute } from 'computesdk';
import { mosaic } from '@computesdk/mosaic';

compute.setConfig({
  provider: mosaic({
    baseUrl: process.env.MOSAIC_API_URL,
    apiKey: process.env.MOSAIC_API_TOKEN,
  }),
});

const sandbox = await compute.sandbox.create({
  templateId: 'node-20',
  memoryMb: 4096,
  vcpus: 2,
});

const result = await sandbox.runCommand('node --version');
console.log(result.stdout);

await sandbox.destroy();
```

## Configuration options

The provider accepts `baseUrl`, `apiKey`, `template`, `memoryMb`, `vcpu`, `requestTimeoutMs`, `networkEnabled`, and `previewExpiresInSeconds`. If `baseUrl` or `apiKey` is omitted, the provider reads `MOSAIC_API_URL` or `MOSAIC_API_TOKEN`. Sandboxes have outbound network access unless `networkEnabled` is set to `false`.

## Templates, snapshots, and images

`node-20` and `python-3.11` are Mosaic's stock templates. Anything else — a `templateId` that is not stock, a `snapshotId`, or an `image` — is one of your own environments, addressed by id or by the name you gave it.

```typescript
const provider = mosaic({});

// Build an environment from any linux/amd64 registry image. Minutes, once.
await provider.template.create({ name: 'my-env', image: 'python:3.12-slim' });

// Sandboxes from it restore in about a second, like any other template.
const sandbox = await compute.sandbox.create({ templateId: 'my-env' });

// Or checkpoint a sandbox you have already set up.
await provider.snapshot.create(sandbox.sandboxId, { name: 'my-toolchain' });
await compute.sandbox.create({ snapshotId: 'my-toolchain' });
```

`template.create` also takes `retentionSeconds` and `registryUsername`/`registryPassword` for a private image. Registry credentials are used for that single pull and are never stored.

## Supported operations

`create`, `getById`, `list`, `destroy`, `runCommand`, `getInfo`, `getUrl`, the filesystem helpers, and the snapshot and template managers are all supported.

`background: true` starts a durable process rather than a backgrounded shell job, so a dev server outlives the request that started it; the returned `stdout` is the process id. Filesystem calls inside `/workspace` use Mosaic's binary-safe files API and paths outside it fall back to the shell. Images must be `linux/amd64` and contain `/bin/sh`, so distroless and scratch images are refused.


# Namespace

Namespace provider for ComputeSDK - Deploy and manage containerized sandboxes on Namespace's cloud infrastructure.

Namespace provider for ComputeSDK - Deploy and manage containerized sandboxes on Namespace's cloud infrastructure.

## Installation & Setup

```bash
npm install @computesdk/namespace
```

Add your Namespace credentials to a `.env` file:

```bash
NSC_TOKEN=your_namespace_nsc_token
```

## Usage

```typescript
import { namespace } from '@computesdk/namespace';

const compute = namespace({
  token: process.env.NSC_TOKEN,
});

// Create a new sandbox
const sandbox = await compute.sandbox.create();
console.log(`Sandbox created: ${sandbox.sandboxId}`);

// Get sandbox info
const info = await sandbox.getInfo();
console.log(`Sandbox status: ${info.status}`);

// Clean up when done
await sandbox.destroy();
```

### Customizing Instance Resources

You can customize the compute resources allocated to your sandboxes:

```typescript
const compute = namespace({
  token: process.env.NSC_TOKEN,
  virtualCpu: 4,
  memoryMegabytes: 8192,
});

const sandbox = await compute.sandbox.create();
```

### Configuration Reference

| Option                | Environment Variable | Required | Description                                                                 |
| --------------------- | -------------------- | -------- | --------------------------------------------------------------------------- |
| `token`               | `NSC_TOKEN`          | Yes\*    | Your Namespace API token                                                    |
| `tokenFile`           | `NSC_TOKEN_FILE`     | Yes\*    | Path to a JSON token file (e.g. from `nsc login`) containing `bearer_token` |
| `virtualCpu`          | -                    | No       | Number of virtual CPU cores (default: 2)                                    |
| `memoryMegabytes`     | -                    | No       | Memory allocation in MB (default: 4096)                                     |
| `machineArch`         | -                    | No       | Machine architecture (default: 'amd64')                                     |
| `os`                  | -                    | No       | Operating system (default: 'linux')                                         |
| `documentedPurpose`   | -                    | No       | Documented purpose for the instance                                         |
| `destroyReason`       | -                    | No       | Reason recorded when destroying instances (default: 'ComputeSDK cleanup')   |
| `targetContainerName` | -                    | No       | Target container name for command execution (default: 'main-container')     |

\* Provide either `token` (or `NSC_TOKEN`) or `tokenFile` (or `NSC_TOKEN_FILE`).

```typescript
interface NamespaceConfig {
  /** Namespace API token - if not provided, uses NSC_TOKEN env var */
  token?: string;
  /** Path to a JSON token file (e.g. from `nsc login`) containing bearer_token - falls back to NSC_TOKEN_FILE */
  tokenFile?: string;
  /** Virtual CPU cores for the instance (default: 2) */
  virtualCpu?: number;
  /** Memory in megabytes for the instance (default: 4096) */
  memoryMegabytes?: number;
  /** Machine architecture (default: 'amd64') */
  machineArch?: string;
  /** Operating system (default: 'linux') */
  os?: string;
  /** Documented purpose for the instance */
  documentedPurpose?: string;
  /** Reason for destroying instances (default: 'ComputeSDK cleanup') */
  destroyReason?: string;
  /** Target container name for command execution (default: 'main-container') */
  targetContainerName?: string;
}
```

## Next Steps

* Learn about [sandbox lifecycle management](https://github.com/computesdk/computesdk/tree/main/docs/reference/compute.sandbox)
* Explore [Sandbox methods](https://github.com/computesdk/computesdk/tree/main/docs/reference/sandbox/README.md)
* View the [@computesdk/namespace package](https://github.com/computesdk/computesdk/blob/main/packages/namespace/README.md)


# NeevCloud

NeevCloud provider for ComputeSDK - run commands and manage files in secure cloud sandboxes with preview URLs.

[NeevCloud](https://neevcloud.com) provider for ComputeSDK - run commands and manage files in secure cloud sandboxes.

## Installation & Setup

```bash
npm install @computesdk/neevcloud
```

Add your NeevCloud credentials to a `.env` file:

```bash
NEEV_API_KEY=your_neev_api_key
NEEV_ORG_ID=your_neev_org_id
NEEV_PROJECT_ID=your_neev_project_id
```

## Usage

```typescript
import { neevcloud } from '@computesdk/neevcloud';

const compute = neevcloud({
  apiKey: process.env.NEEV_API_KEY,
  orgId: process.env.NEEV_ORG_ID,
  projectId: process.env.NEEV_PROJECT_ID,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from NeevCloud!"');
console.log(result.stdout); // "Hello from NeevCloud!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface NeevCloudConfig {
  /** NeevCloud API key - if not provided, will use NEEV_API_KEY env var */
  apiKey?: string;
  /** Org the sandboxes belong to - if not provided, will use NEEV_ORG_ID env var */
  orgId?: string;
  /** Project the sandboxes belong to - if not provided, will use NEEV_PROJECT_ID env var */
  projectId?: string;
  /** Request timeout in milliseconds */
  timeout?: number;
}
```

### Preview URLs

Expose any port over a public HTTPS URL:

```typescript
await sandbox.runCommand('python3 -m http.server 3000', { background: true });
const url = await sandbox.getUrl({ port: 3000 });
```

### Boot Source

Start from a catalogue template, a raw OCI image, or the platform default (`templateId` and `image` are mutually exclusive):

```typescript
await compute.sandbox.create({ templateId: 'sb-ubuntu-24-04-minimal' });
await compute.sandbox.create({ image: 'docker.io/library/python:3.12' });
```


# Northflank

Set up the Northflank provider for ComputeSDK, pass your project credentials, and create deployment-backed sandboxes to run commands and expose ports.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/northflank/>" %}

Northflank provider for ComputeSDK — each sandbox is a deployment service in your Northflank project. Commands run in the container via Northflank's exec API; ports are exposed through the service's public DNS.

## Installation & Setup

```bash
npm install @computesdk/northflank
```

Add your Northflank credentials to a `.env` file:

```bash
NORTHFLANK_TOKEN=your_api_token
NORTHFLANK_PROJECT_ID=your_project_id
```

Create the token under **Team settings → API → Tokens → Create API token**, then create (or pick) a Northflank project for your sandboxes.

## Usage

```typescript
import { northflank } from '@computesdk/northflank';

const compute = northflank({
  token: process.env.NORTHFLANK_TOKEN!,
  projectId: process.env.NORTHFLANK_PROJECT_ID!,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Northflank!"');
console.log(result.stdout); // "Hello from Northflank!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface NorthflankConfig {
  /** Northflank API token (required) */
  token: string;
  /** Northflank project ID that services are created in (required) */
  projectId: string;
  /** Northflank team ID (optional) */
  teamId?: string;
  /** Override the API base URL - defaults to "https://api.northflank.com" */
  host?: string;
  /** Prefix for generated service names - defaults to "computesdk-" */
  servicePrefix?: string;
  /** Container image - defaults to the image for the selected runtime (node:20-slim / python:3.11-slim) */
  image?: string;
  /** Runtime label - defaults to "node" */
  runtime?: string;
  /** Northflank deployment plan - defaults to "nf-compute-50" */
  deploymentPlan?: string;
  /** Ports to expose on create - a number or a { name, internalPort, public?, protocol? } object */
  ports?: (number | { name: string; internalPort: number; public?: boolean; protocol?: 'HTTP' | 'HTTP/2' | 'TCP' | 'UDP' })[];
  /** Time to wait for the container to become exec-ready, in ms - defaults to 120000 */
  timeout?: number;
  /** Deploy from a Northflank build service instead of an external image */
  internalDeployment?: {
    /** Build service ID inside the same Northflank project */
    id: string;
    /** Branch to deploy from - defaults to "main" */
    branch?: string;
    /** Build SHA to deploy - defaults to "latest" */
    buildSHA?: string;
  };
}
```

### Supported Operations

| Method       | Supported | Notes                                                                                                                    |
| ------------ | --------- | ------------------------------------------------------------------------------------------------------------------------ |
| `create`     | ✅         | Creates a Northflank deployment service kept alive by a long-running command.                                            |
| `getById`    | ✅         | Only returns services whose name starts with `servicePrefix` (ComputeSDK-managed).                                       |
| `list`       | ✅         | Lists ComputeSDK-managed services in the project (paginated).                                                            |
| `destroy`    | ✅         | Deletes the service; a no-op if it no longer exists.                                                                     |
| `runCommand` | ✅         | Runs via Northflank's exec API. The first exec retries until the pod is ready.                                           |
| `getInfo`    | ✅         |                                                                                                                          |
| `getUrl`     | ✅         | Exposes the port publicly and returns its Northflank DNS. Only HTTP / HTTP/2 ports can get a public URL; TCP/UDP throws. |
| `filesystem` | ✅         | `readFile`/`writeFile` use Northflank's file-copy API; other ops run as shell commands.                                  |

### Notes

* `token` and `projectId` are required — the provider does not read them from the environment automatically, so pass `process.env.NORTHFLANK_TOKEN` / `process.env.NORTHFLANK_PROJECT_ID` yourself.
* Background commands (`runCommand(cmd, { background: true })`) are launched with `nohup` and redirected to `/tmp/computesdk-bg.log`.


# OpenComputer

OpenComputer provides persistent cloud VMs with command execution, filesystem access, preview URLs, and checkpoints.

## Installation

```bash
npm install computesdk @computesdk/opencomputer
```

## Environment Variables

```bash
export OPENCOMPUTER_API_KEY=your_api_key_here
# Optional
export OPENCOMPUTER_API_URL=https://app.opencomputer.dev
```

## Usage

```typescript
import { compute } from 'computesdk';
import { opencomputer } from '@computesdk/opencomputer';

compute.setConfig({
  provider: opencomputer({ apiKey: process.env.OPENCOMPUTER_API_KEY }),
});

const sandbox = await compute.sandbox.create({ templateId: 'base' });

const result = await sandbox.runCommand('node --version');
console.log(result.stdout);

await sandbox.destroy();
```

## Options

```typescript
opencomputer({
  apiKey: process.env.OPENCOMPUTER_API_KEY,
  apiUrl: process.env.OPENCOMPUTER_API_URL,
  template: 'base',
  timeout: 300_000,
  memoryMB: 4096,
  cpuCount: 2,
  diskMB: 20480,
  burst: true,
});
```

Per-create options such as `templateId`, `timeout`, `envs`, `metadata`, `memory`, `memoryMB`, `cpuCount`, `diskMB`, `secretStore`, `burst`, `previewAuth`, and `webhooks` are forwarded to OpenComputer where supported.

## Snapshots

ComputeSDK snapshots map to OpenComputer checkpoints:

```typescript
const snapshot = await compute.snapshot.create(sandbox.sandboxId, {
  name: 'configured',
});

const clone = await compute.sandbox.create({ snapshotId: snapshot.id });

await compute.snapshot.delete(snapshot.id);
```

Snapshot IDs returned by this provider are formatted as `sandboxId:checkpointId` because OpenComputer deletes checkpoints under their source sandbox. Raw OpenComputer checkpoint IDs are also accepted when creating a sandbox from a checkpoint.

Snapshots default to OpenComputer `disk_only` checkpoints with `promoteToFull: true`. Override with `metadata: { kind: 'full' }` or `metadata: { promoteToFull: false }` when needed.


# Quilt

Quilt provider for ComputeSDK — tenant-scoped Linux sandboxes with exec, published HTTP/WebSocket services, shell-backed filesystem operations, and snapshots.

Quilt provider for ComputeSDK — tenant-scoped Linux sandboxes with exec, published HTTP/WebSocket services, shell-backed filesystem operations, and snapshots.

## Installation & Setup

```bash
npm install @computesdk/quilt
```

Add your Quilt configuration to a `.env` file. A base URL plus one credential (`apiKey` or `accessToken`) is required:

```bash
QUILT_BASE_URL=https://backend.example.com
QUILT_API_KEY=your_api_key
# or, instead of an API key:
QUILT_ACCESS_TOKEN=your_access_token
# required for snapshot operations:
QUILT_TENANT_ID=your_tenant_id
```

## Usage

```typescript
import { quilt } from '@computesdk/quilt';

const compute = quilt({
  baseUrl: process.env.QUILT_BASE_URL,
  apiKey: process.env.QUILT_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Quilt!"');
console.log(result.stdout); // "Hello from Quilt!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface QuiltConfig {
  /** Quilt backend base URL - falls back to QUILT_BASE_URL / QUILT_API_BASE_URL. Required. */
  baseUrl?: string;
  /** Quilt API key (sent as X-Api-Key) - falls back to QUILT_API_KEY. Provide this or accessToken. */
  apiKey?: string;
  /** Quilt access token (sent as a Bearer token) - falls back to QUILT_ACCESS_TOKEN. Provide this or apiKey. */
  accessToken?: string;
  /** Tenant ID - falls back to QUILT_TENANT_ID. Required for snapshot operations. */
  tenantId?: string;
  /** Container image - falls back to QUILT_IMAGE, then defaults to "prod" */
  image?: string;
  /** Operation timeout in ms - falls back to QUILT_TIMEOUT_MS, then defaults to 300000 */
  timeout?: number;
  /** Auth mode for published services - falls back to QUILT_PUBLISHED_SERVICE_AUTH_MODE, defaults to "service_token" */
  publishedServiceAuthMode?: 'service_token' | 'public';
  /** TTL in seconds for published services - falls back to QUILT_PUBLISHED_SERVICE_TTL_SECS */
  publishedServiceTtlSecs?: number;
  /** Poll interval for async operations in ms - falls back to QUILT_POLL_INTERVAL_MS, defaults to 1000 */
  pollIntervalMs?: number;
}
```

### Supported Operations

| Method                                | Supported | Notes                                                                                      |
| ------------------------------------- | --------- | ------------------------------------------------------------------------------------------ |
| `create`                              | ✅         | Creates a container; pass `snapshotId` in create options to clone from a snapshot instead. |
| `getById`                             | ✅         | Returns `null` for a missing container.                                                    |
| `list`                                | ✅         | Lists tenant containers (paginated).                                                       |
| `destroy`                             | ✅         | Deletes the container; a no-op if it no longer exists.                                     |
| `runCommand`                          | ✅         | Synchronous exec via Quilt's `/exec` API. A timed-out command reports exit code `124`.     |
| `getInfo`                             | ✅         |                                                                                            |
| `getUrl`                              | ✅         | Creates (or reuses) a published service. Supports `http`/`https` and `ws`/`wss` protocols. |
| `filesystem`                          | ✅         | Implemented over exec (`base64`, `ls -la`, `mkdir -p`, `rm -rf`, etc.).                    |
| `snapshot.create` / `list` / `delete` | ✅         | Requires `tenantId`. Snapshots are created crash-consistent with volumes excluded.         |

### Notes

* A base URL and at least one credential (`apiKey` or `accessToken`) are required; the provider throws a descriptive error if either is missing.
* Snapshot operations (and cloning via `create({ snapshotId })`) require `tenantId`, sent as the `X-Tenant-Id` header.


# Railway

Railway provider for ComputeSDK — run commands in Railway Sandboxes, ephemeral compute environments backed by the Railway platform.

Railway provider for ComputeSDK — run commands in [Railway Sandboxes](https://docs.railway.com/sandboxes), ephemeral compute environments backed by the Railway platform.

## Installation & Setup

```bash
npm install @computesdk/railway
```

> **Requires Node.js >= 22** — the underlying `railway` SDK depends on Node 22 APIs (e.g. global `WebSocket`).

Add your Railway credentials to a `.env` file:

```bash
RAILWAY_API_TOKEN=your_token
RAILWAY_ENVIRONMENT_ID=your_environment_id
```

Create the token at [railway.com/account/tokens](https://railway.com/account/tokens); find the environment ID under your Railway project's environment settings.

## Usage

```typescript
import { railway } from '@computesdk/railway';

const compute = railway({
  token: process.env.RAILWAY_API_TOKEN,
  environmentId: process.env.RAILWAY_ENVIRONMENT_ID,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Railway!"');
console.log(result.stdout); // "Hello from Railway!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface RailwayConfig {
  /** Railway API token - falls back to the RAILWAY_API_TOKEN environment variable */
  token?: string;
  /** Railway environment ID - falls back to the RAILWAY_ENVIRONMENT_ID environment variable */
  environmentId?: string;
}
```

### Supported Operations

| Method       | Supported | Notes                                                                                                                                 |
| ------------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `create`     | ✅         | Creates a Railway sandbox. Honors `envs`, `idleTimeoutMinutes`, and `networkIsolation` create options.                                |
| `getById`    | ✅         | Returns `null` when the sandbox is not found.                                                                                         |
| `list`       | ✅         | Connects to each listed sandbox; unreachable ones are dropped.                                                                        |
| `destroy`    | ✅         | Best-effort; ignores already-destroyed / unreachable sandboxes.                                                                       |
| `runCommand` | ✅         | Runs via Railway's `sandbox.exec`. A signal-terminated command reports exit code `-1`.                                                |
| `getInfo`    | ✅         |                                                                                                                                       |
| `getUrl`     | ❌         | Throws — Railway sandboxes cannot expose ports / public URLs. Use sandbox-to-sandbox networking within a Railway environment instead. |
| `filesystem` | ✅         | Implemented over the shell (`base64`, `ls -la`, `mkdir -p`, `rm -rf`, etc.).                                                          |

### Notes

* Railway has no dedicated filesystem or port-exposure API, so `getUrl` throws and filesystem operations are shell-backed.


# Run Cloud

Run Cloud provider for ComputeSDK - fast Firecracker microVM sandboxes with configurable resources, filesystem access, and snapshots.

[Run Cloud](https://run.cloud) provides fast Firecracker microVM sandboxes for AI agents, CI, and untrusted code execution.

## Installation & Setup

```bash
npm install computesdk @computesdk/run-cloud
```

Create an API key in the [Run Cloud dashboard](https://run.cloud), then export it:

```bash
export RUN_CLOUD_API_KEY=rc_live_your_key
```

`RUN_CLOUD_API_TOKEN` is supported as an alias. `RUN_CLOUD_API_URL` optionally targets a custom Run Cloud deployment.

## Usage

```typescript
import { compute } from 'computesdk';
import { runCloud } from '@computesdk/run-cloud';

compute.setConfig({
  provider: runCloud({
    apiKey: process.env.RUN_CLOUD_API_KEY,
    cpu: 2,
    memory: 4096,
    disk: 40,
  }),
});

const sandbox = await compute.sandbox.create({
  templateId: 'runcloud/agent-base',
  name: 'agent-task',
});

const result = await sandbox.runCommand('node --version');
console.log(result.stdout);

await sandbox.filesystem.writeFile('/tmp/result.txt', result.stdout);

const snapshot = await compute.snapshot.create(sandbox.sandboxId, {
  name: 'after-setup',
});

await sandbox.destroy();

const restored = await compute.sandbox.create({
  snapshotId: snapshot.id,
});
```

## Configuration Options

```typescript
interface RunCloudConfig {
  apiKey?: string;
  apiUrl?: string;
  fetch?: typeof fetch;
  image?: string;
  cpu?: number;
  memory?: number;
  disk?: number;
  idlePauseSeconds?: number;
  timeout?: number;
  region?: string;
  orgId?: string;
  commandTimeout?: number;
  tunnelTtlSeconds?: number;
}
```

`cpu` accepts fractional vCPUs, `memory` uses MiB, and `disk` uses GiB. `timeout` and `commandTimeout` use milliseconds; `idlePauseSeconds` and `tunnelTtlSeconds` use seconds.

Fresh creates accept per-create `templateId` or `image`, `cpu`, `memory`, `disk`, `idlePauseSeconds`, `timeoutSeconds`, `region`, `name`, `orgId`, and `idempotencyKey` overrides. Snapshot restores accept `cpu`, `memory`, `disk`, `timeoutSeconds`, `region`, and `name` overrides; options the restore API cannot apply are rejected instead of being silently ignored.

Sandbox-level environment variables are not yet persisted by Run Cloud. Pass command-scoped variables through `runCommand`:

```typescript
await sandbox.runCommand('echo "$MODEL"', {
  env: { MODEL: 'gpt-5' },
});
```

## Supported Operations

| Method       | Supported | Notes                                                                   |
| ------------ | --------- | ----------------------------------------------------------------------- |
| `create`     | ✅         | Fresh image boot or snapshot restore with resource overrides.           |
| `getById`    | ✅         | Returns `null` for missing sandboxes.                                   |
| `list`       | ✅         | Lists running sandboxes.                                                |
| `destroy`    | ✅         | Idempotent when already deleted.                                        |
| `runCommand` | ✅         | Supports cwd, env, timeout, streaming callbacks, and background mode.   |
| `getInfo`    | ✅         | Refreshes lifecycle and resource metadata.                              |
| `getUrl`     | ✅         | Opens an expiring capability URL without making the sandbox persistent. |
| Filesystem   | ✅         | Read, write, mkdir, list, exists, and remove.                           |
| Snapshots    | ✅         | Create, list, delete, and restore.                                      |

Use `sandbox.getInstance()` to access the official Run Cloud client and native sandbox record.

Tunnel hostnames are random bearer capabilities. Do not write them to public logs. They expire automatically and are removed when the tunnel or sandbox is deleted.


# Runloop

Set up the Runloop provider for ComputeSDK, configure your API key, and create sandboxes to run commands.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/runloop/>" %}

Runloop provider for ComputeSDK

## Installation & Setup

```bash
npm install @computesdk/runloop
```

Add your Runloop credentials to a `.env` file:

```bash
RUNLOOP_API_KEY=your_runloop_api_key
```

## Usage

```typescript
import { runloop } from '@computesdk/runloop';

const compute = runloop({
  apiKey: process.env.RUNLOOP_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Runloop!"');
console.log(result.stdout); // "Hello from Runloop!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface RunloopConfig {
  /** Runloop API key - if not provided, will use RUNLOOP_API_KEY env var */
  apiKey?: string;
  /** Execution timeout in milliseconds */
  timeout?: number;
}
```


# Sail

Sail provider for ComputeSDK - isolated Firecracker microVM sandboxes with fast startup, command execution, and native filesystem access.

[Sail](https://sailresearch.com) provides maximally-efficient Firecracker microVM sandboxes for running agent and developer workloads. They can live forever and bill only for active CPU, memory, and disk usage.

## Installation & Setup

```bash
npm install computesdk @computesdk/sail
```

Node.js 22 or newer is required. Create an API key at [app.sailresearch.com](https://app.sailresearch.com), then export it:

```bash
export SAIL_API_KEY=your_sail_api_key
```

## Usage

```typescript
import { sail } from '@computesdk/sail';

const compute = sail({ app: 'my-app' });

const sandbox = await compute.sandbox.create();
const result = await sandbox.runCommand('node --version');
console.log(result.stdout);

await sandbox.filesystem.writeFile('/tmp/result.txt', result.stdout);
console.log(await sandbox.filesystem.readFile('/tmp/result.txt'));

await sandbox.destroy();
```

## Configuration Options

```typescript
interface SailConfig {
  apiKey?: string;
  app?: string;
  image?: ImageSpec | Image;
}
```

`apiKey` falls back to `SAIL_API_KEY`. `app` falls back to `SAIL_APP`, then `computesdk`, and is created on first use when missing. `image` defaults to Sail's ARM64 Devbox builtin, which includes Node.js and Bun. Pass a different image when the workload needs another runtime or architecture.

Create accepts Sailbox `size` values `s`, `m`, and `l`, optional `memoryGib`, a name, and an `AbortSignal`. It defaults to `s`; explicit size choices override that default. Unsupported universal options are rejected rather than silently ignored.

## Supported Operations

| Method       | Supported | Notes                                                       |
| ------------ | --------- | ----------------------------------------------------------- |
| `create`     | Yes       | Defaults to an ARM64 Devbox on `S`.                         |
| `getById`    | Yes       | Returns `null` for missing or terminated Sailboxes.         |
| `list`       | Yes       | Lists live and actionable Sailboxes for the configured app. |
| `destroy`    | Yes       | Terminates the Sailbox.                                     |
| `runCommand` | Yes       | Supports cwd, environment, timeout, and background mode.    |
| `getInfo`    | Yes       | Maps current Sail lifecycle state to ComputeSDK.            |
| `getUrl`     | Yes       | Supports public HTTP/HTTPS and TCP listeners.               |
| `filesystem` | Yes       | Native read, write, mkdir, list, exists, and remove.        |
| Templates    | No        | Configure a Sail `Image` on the provider.                   |
| Snapshots    | No        | Use the native Sail SDK for checkpoints.                    |

`getUrl` preserves existing listener policy and rejects protocol conflicts instead of replacing a listener's allowlist.

Use `sandbox.getInstance()` for Sail-specific checkpoint, sleep, resume, SSH, listener allowlist, and credential-injection APIs.


# Sandbox0

Sandbox0 provider for ComputeSDK - fast persistent sandboxes with command execution and native filesystem access.

Sandbox0 provides fast persistent cloud sandboxes with shell command execution and native filesystem operations.

## Installation & Setup

```bash
npm install computesdk @computesdk/sandbox0
```

Set a Sandbox0 team API key:

```bash
export SANDBOX0_TOKEN=your_sandbox0_token
```

`SANDBOX0_BASE_URL` is optional and defaults to `https://api.sandbox0.ai`. For automated team workloads, set it to the team's home-region endpoint so requests go directly to the regional gateway.

An interactive access token can also be used by setting both `SANDBOX0_TOKEN` and `SANDBOX0_TEAM_ID`.

## Usage

```typescript
import { compute } from 'computesdk';
import { sandbox0 } from '@computesdk/sandbox0';

compute.setConfig({
  provider: sandbox0({
    token: process.env.SANDBOX0_TOKEN,
    hardTtl: 600,
  }),
});

const sandbox = await compute.sandbox.create({
  templateId: 'coding-agent',
  memory: 256,
});

const result = await sandbox.runCommand('node --version');
console.log(result.stdout);

await sandbox.filesystem.writeFile('/tmp/result.txt', result.stdout);
console.log(await sandbox.filesystem.readFile('/tmp/result.txt'));

await sandbox.destroy();
```

## Configuration Options

```typescript
interface Sandbox0Config {
  token?: string;
  teamId?: string;
  baseUrl?: string;
  templateId?: string;
  ttl?: number;
  hardTtl?: number;
  memory?: number | string;
  envs?: Record<string, string>;
  commandTimeout?: number;
}
```

Numeric memory values are interpreted as MiB. `ttl` and `hardTtl` use seconds; `commandTimeout` uses milliseconds. When `templateId` is omitted, the provider uses `SANDBOX0_TEMPLATE` and then falls back to `coding-agent`.

Per-create `templateId`, `snapshotId`, `memory`, `envs`, `ttl`, `hardTtl`, and `autoResume` options override provider defaults where applicable.

## Supported Operations

| Method       | Supported | Notes                                                                                                                                                          |
| ------------ | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `create`     | ✅         | Claims a Sandbox0 sandbox from a template; supports snapshot restore and memory overrides.                                                                     |
| `getById`    | ✅         | Returns `null` for a missing sandbox.                                                                                                                          |
| `list`       | ✅         | Paginates through sandboxes visible to the team token.                                                                                                         |
| `destroy`    | ✅         | Idempotent, with bounded retry for throttling and server failures.                                                                                             |
| `runCommand` | ✅         | Uses `sh -lc`; foreground calls follow an asynchronous Context through WebSocket with API polling fallback. Supports `cwd`, env, timeout, and background mode. |
| `getInfo`    | ✅         | Uses lifecycle metadata already returned by Sandbox0 without adding a post-create request.                                                                     |
| `getUrl`     | ✅         | Returns the URL of an existing public Sandbox0 service for the requested port.                                                                                 |
| `filesystem` | ✅         | Native read, write, mkdir, list, stat, and delete operations.                                                                                                  |

For automated workloads, set `hardTtl` as a safety net in addition to calling `destroy`.

Foreground commands use the requested timeout as both a local deadline and the Sandbox0 Context TTL. If the WebSocket disconnects before a terminal event, the provider continues through the Context API. A timeout also triggers a best-effort Context deletion.

Use `sandbox.getInstance()` for Sandbox0-specific pause/resume, services, snapshots, volumes, and observability APIs.


# Secure Exec

Secure execution provider for ComputeSDK — a local, isolated sandbox using secure-exec's V8 isolates, with an in-memory filesystem. No remote service or credentials required.

Secure execution provider for ComputeSDK — a local, isolated sandbox using [secure-exec](https://www.npmjs.com/package/secure-exec)'s V8 isolates, with an in-memory filesystem. No remote service or credentials required.

## Installation & Setup

```bash
npm install @computesdk/secure-exec
```

There are no credentials to configure — sandboxes run locally in a V8 isolate.

> **Platform requirement:** the underlying V8 runtime binary (`secure-exec-v8`) is currently only available for **linux-x64**. `create()` throws on other platforms.

## Usage

```typescript
import { secureExec } from '@computesdk/secure-exec';

const compute = secureExec({
  memoryLimitMb: 128,
  cpuTimeLimitMs: 30_000,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Secure-Exec!"');
console.log(result.stdout); // "Hello from Secure-Exec!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface SecureExecConfig {
  /** Memory cap for the V8 isolate in MB. Default: 128 */
  memoryLimitMb?: number;
  /** CPU time budget per exec call in ms. Default: 30_000 */
  cpuTimeLimitMs?: number;
  /** Allowlist of commands sandboxed code can spawn. Default: all allowed */
  allowedCommands?: string[];
}
```

### Supported Operations

| Method       | Supported | Notes                                                                              |
| ------------ | --------- | ---------------------------------------------------------------------------------- |
| `create`     | ✅         | Spins up a local V8 isolate with an in-memory filesystem rooted at `/workspace`.   |
| `getById`    | ❌         | Always returns `null` — sandboxes are in-process and not addressable across calls. |
| `list`       | ❌         | Always returns an empty array.                                                     |
| `destroy`    | no-op     | Nothing to tear down remotely.                                                     |
| `runCommand` | ✅         | Executes shell commands inside the isolate via `spawnSync`.                        |
| `getInfo`    | ✅         | Reports `metadata: { local: true }`.                                               |
| `getUrl`     | ❌         | Throws — `getUrl is not supported by secure-exec provider.`                        |
| `filesystem` | ✅         | Backed by secure-exec's in-memory filesystem (not shell-based).                    |

### Notes

* This provider is **local-only**: sandboxes live in the current Node process, so `getById` and `list` do not return anything and `destroy` is a no-op.
* Commands sandboxed code may spawn can be restricted with `allowedCommands`; by default all commands are allowed.


# Sprites

Set up the Sprites provider for ComputeSDK, configure your token, and create cloud sandboxes to run commands and expose apps.

Sprites provider for ComputeSDK - cloud sandboxes powered by Sprites

## Installation & Setup

```bash
npm install @computesdk/sprites
```

Add your Sprites credentials to a `.env` file:

```bash
SPRITES_TOKEN=your_sprites_token
```

## Usage

```typescript
import { sprites } from '@computesdk/sprites';

const compute = sprites({
  apiKey: process.env.SPRITES_TOKEN,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Sprites!"');
console.log(result.stdout); // "Hello from Sprites!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface SpritesConfig {
  /** Sprites API token - if not provided, will fallback to SPRITES_TOKEN environment variable */
  apiKey?: string;
  /** Base URL for the Sprites API - defaults to https://api.sprites.dev/v1 */
  baseUrl?: string;
  /** Execution timeout in milliseconds */
  timeout?: number;
}
```

### Supported Operations

| Method       | Supported | Notes                                                                   |
| ------------ | --------- | ----------------------------------------------------------------------- |
| `create`     | ✅         | Provisions a new Sprite via `POST /sprites`.                            |
| `getById`    | ✅         | Looks up a Sprite by name.                                              |
| `list`       | ✅         | Lists all Sprites for the token.                                        |
| `destroy`    | ✅         | Deletes the Sprite.                                                     |
| `runCommand` | ✅         | Executes commands over the `bash` exec endpoint; supports `cwd`/`env`.  |
| `getInfo`    | ✅         |                                                                         |
| `getUrl`     | ✅         | Returns the Sprite's public URL (Sprites are created with public auth). |
| `filesystem` | ✅         | Native `read`, `write`, `mkdir`, `readdir`, `exists`, `remove`.         |


# Superserve

Superserve provides sandbox infrastructure to run code in isolated cloud environments powered by Firecracker MicroVMs.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/superserve/>" %}

Superserve provides sandbox infrastructure to run code in isolated cloud environments powered by Firecracker MicroVMs.

## Installation & Setup

```bash
npm install @computesdk/superserve
```

Add your Superserve credentials to a `.env` file:

```bash
SUPERSERVE_API_KEY=your_api_key
```

## Usage

```typescript
import { superserve } from '@computesdk/superserve';

const compute = superserve({
  apiKey: process.env.SUPERSERVE_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Superserve!"');
console.log(result.stdout); // "Hello from Superserve!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface SuperserveConfig {
  /** Superserve API key. Falls back to `SUPERSERVE_API_KEY` env var. */
  apiKey?: string;
  /** API base URL. Falls back to `SUPERSERVE_BASE_URL` env var, then `https://api.superserve.ai`. */
  baseUrl?: string;
  /** Default sandbox idle timeout in milliseconds. */
  timeout?: number;
}
```

### Supported Operations

| Method       | Supported | Notes                                                                                                                                  |
| ------------ | --------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `create`     | ✅         | Boots a Firecracker microVM; accepts `templateId` to boot from a template.                                                             |
| `getById`    | ✅         | Connects to a sandbox by id (issues `POST /activate`, auto-resumes paused).                                                            |
| `list`       | ✅         | Read-only — returns `SandboxInfo` stubs without opening a session.                                                                     |
| `destroy`    | ✅         | Kills the sandbox by id.                                                                                                               |
| `runCommand` | ✅         | Supports `cwd`, `env`, `timeout`, and `background`.                                                                                    |
| `getInfo`    | ✅         | `paused` maps to `stopped`, `failed` to `error`, otherwise `running`.                                                                  |
| `filesystem` | ✅         | `readFile`/`writeFile` use the data plane; `mkdir`/`readdir`/`exists`/`remove` are shell fallbacks.                                    |
| `getUrl`     | ❌         | Throws — arbitrary port forwarding is not supported. Run a reverse-proxy inside the sandbox.                                           |
| `snapshot`   | ❌         | Throws — Superserve has no standalone snapshot resource. Use templates, or SDK `pause()` / `resume()` for in-place state preservation. |

### Notes

* Templates are supported for listing and deletion. `template.create` throws — creating a template requires a build spec (`from` + `steps`), so use `@superserve/sdk` `Template.create()` directly.
* Authentication failures (HTTP 401, missing key, SDK `AuthenticationError`) are normalized into a single user-facing message.


# Tenki

Tenki Cloud provider for ComputeSDK - microVM sandboxes with native filesystem, preview URLs, snapshots, and SSH.

Tenki Cloud provider for ComputeSDK - microVM sandboxes with native filesystem, preview URLs, snapshots, and SSH.

## Installation & Setup

```bash
npm install @computesdk/tenki
```

Requires Node.js 20 or later (the Tenki SDK's gRPC transport depends on it).

Add your Tenki credentials to a `.env` file:

```bash
TENKI_API_KEY=tk_your_api_key
```

## Usage

```typescript
import { tenki } from '@computesdk/tenki';

const compute = tenki({
  apiKey: process.env.TENKI_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Tenki!"');
console.log(result.stdout); // "Hello from Tenki!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface TenkiConfig {
  /** Tenki API key (tk_...). Falls back to TENKI_API_KEY / TENKI_AUTH_TOKEN env vars. */
  apiKey?: string;
  /** API base URL. Falls back to TENKI_API_URL, then https://api.tenki.cloud. */
  baseUrl?: string;
  /** Workspace to create sandboxes in. Falls back to TENKI_WORKSPACE_ID; workspace API keys infer it server-side. */
  workspaceId?: string;
  /** @deprecated Tenki no longer scopes sandboxes by project. */
  projectId?: string;
  /** Default runCommand timeout in milliseconds. */
  timeout?: number;
  /** Default sandbox resources applied at create() time. */
  cpuCores?: number;
  memoryMb?: number;
  diskSizeGb?: number;
}
```

### Supported Operations

| Method       | Supported | Notes                                                                                                                                     |
| ------------ | --------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `create`     | ✅         | Boots a microVM in the resolved workspace/project; accepts per-call `cpuCores`/`memoryMb`/`diskSizeGb` overrides.                         |
| `getById`    | ✅         | Resolves a session by id; returns null for unknown/invalid ids.                                                                           |
| `list`       | ✅         | Lists sessions for the API key.                                                                                                           |
| `destroy`    | ✅         | Closes the session (no-op if already gone).                                                                                               |
| `runCommand` | ✅         | Wrapped in `sh -lc` so pipes, globs, and env expansion work; supports `cwd`, `env`, `timeout`, `background`, and stdout/stderr streaming. |
| `getInfo`    | ✅         |                                                                                                                                           |
| `getUrl`     | ✅         | Exposes a port and returns its public preview URL (e.g. `https://<slug>.sb.tenki.sh`).                                                    |
| `filesystem` | ✅         | Native data-plane file API (`readFile`, `writeFile`, `mkdir`, `readdir`, `remove`); `exists` uses `test -e` for consistency.              |

### Notes

* Workspace API keys infer their workspace server-side. Set `workspaceId`, or `TENKI_WORKSPACE_ID`, only when using trusted service credentials that require explicit scope.
* Background commands (`{ background: true }`) detach stdio automatically; a bare `&` would hold the exec output stream open.
* Snapshots and pause/resume exist in the underlying `@tenkicloud/sandbox` SDK but are not yet wired to the provider's snapshot methods. For advanced features (SSH, volumes, tunnels, git, snapshots), use `sandbox.getInstance()` to reach the SDK `Session` directly.


# Tensorlake

Tensorlake provider for ComputeSDK - Stateful MicroVM sandboxes for agentic applications and LLM-generated code execution.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/tensorlake/>" %}

Tensorlake provider for ComputeSDK - Stateful MicroVM sandboxes for agentic applications and LLM-generated code execution.

## Installation & Setup

```bash
npm install @computesdk/tensorlake
```

Add your Tensorlake credentials to a `.env` file:

```bash
TENSORLAKE_API_KEY=your_tensorlake_api_key
```

## Usage

```typescript
import { tensorlake } from '@computesdk/tensorlake';

const compute = tensorlake({
  apiKey: process.env.TENSORLAKE_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Tensorlake!"');
console.log(result.stdout); // "Hello from Tensorlake!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface TensorlakeConfig {
  /** Tensorlake API key - if not provided, will use TENSORLAKE_API_KEY env var */
  apiKey?: string;
  /** Override for the management API base URL */
  apiUrl?: string;
  /** Override for the sandbox proxy URL */
  proxyUrl?: string;
  /** Default container image for new sandboxes (default: ubuntu-minimal) */
  image?: string;
  /** Execution timeout in milliseconds */
  timeout?: number;
}
```

### Sandbox Images

Tensorlake supports custom container images. The default is `ubuntu-minimal`:

```typescript
const sandbox = await compute.sandbox.create({ image: 'ubuntu-minimal' });
```

### Snapshots

Tensorlake supports snapshotting sandboxes for fast restores:

```typescript
// Create a snapshot from a running sandbox
const snapshot = await compute.snapshot.create(sandboxId);

// Restore from a snapshot
const sandbox = await compute.sandbox.create({ snapshotId: snapshot.id });
```


# Upstash

Set up the Upstash provider for ComputeSDK, configure your API key, and create default or ephemeral boxes to run commands.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/upstash/>" %}

Upstash provider for ComputeSDK

## Installation & Setup

```bash
npm install @computesdk/upstash
```

Add your Upstash credentials to a `.env` file:

```bash
UPSTASH_BOX_API_KEY=your_upstash_box_api_key
```

## Usage

```typescript
import { upstash } from '@computesdk/upstash';

const compute = upstash({
  apiKey: process.env.UPSTASH_BOX_API_KEY,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Upstash!"');
console.log(result.stdout); // "Hello from Upstash!"

// Clean up
await sandbox.destroy();
```

## Box Types

Upstash supports two box variants:

* **Default Box** — Full sandbox with filesystem, shell, snapshots, and preview URLs. Best for persistent or long-running work.
* **Ephemeral Box** *(optional)* — Lightweight, instant-ready box with code execution and filesystem only. No preview URLs. Best for short-lived, one-off tasks.

For more details, see the [Upstash Box documentation](https://upstash.com/docs/box/overall/quickstart).

```typescript
// Default box
const sandbox = await compute.sandbox.create();

// Ephemeral box
const sandbox = await compute.sandbox.create({ ephemeral: true });
```

### Configuration Options

```typescript
interface UpstashConfig {
  /** Upstash Box API key - if not provided, will use UPSTASH_BOX_API_KEY env var */
  apiKey?: string;
  /** Default runtime environment (e.g. 'node', 'python') */
  runtime?: string;
  /** Execution timeout in milliseconds (default: 600000) */
  timeout?: number;
}
```


# Vercel

Set up the Vercel provider for ComputeSDK, configure project credentials or OIDC auth, and create sandboxes to run commands.

{% embed url="<https://www.computesdk.com/benchmarks/sandboxes/vercel/>" %}

Vercel provider for ComputeSDK - Execute code in globally distributed serverless environments.

## Installation & Setup

```bash
npm install @computesdk/vercel
```

Add your Vercel credentials to a `.env` file:

```bash
VERCEL_TOKEN=your_vercel_token
VERCEL_TEAM_ID=your_vercel_team_id
VERCEL_PROJECT_ID=your_vercel_project_id
```

## Usage

```typescript
import { vercel } from '@computesdk/vercel';

const compute = vercel({
  token: process.env.VERCEL_TOKEN,
  teamId: process.env.VERCEL_TEAM_ID,
  projectId: process.env.VERCEL_PROJECT_ID,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Vercel!"');
console.log(result.stdout); // "Hello from Vercel!"

// Clean up
await sandbox.destroy();
```

### Configuration Options

```typescript
interface VercelConfig {
  /** Vercel token - if not provided, will use env vars */
  token?: string;
  /** Team ID for team accounts */
  teamId?: string;
  /** Project ID */
  projectId?: string;
  /** Execution timeout in milliseconds */
  timeout?: number;
  /** Ports to expose on the sandbox */
  ports?: number[];
  /** Port for the daemon SSE channel (defaults to 38989); set false to disable */
  daemonSsePort?: number | false;
}
```

### Authentication

When no credentials are provided in config (no `token`, `teamId`, or `projectId`), the provider falls back to OIDC authentication using the `VERCEL_OIDC_TOKEN` environment variable. Run `vercel env pull` to populate `VERCEL_OIDC_TOKEN` in your `.env` file. This is an alternative to the token-based authentication shown above.


# Sandbox (interface)

## Overview

Methods available for interacting with a compute sandbox.

\ <br>

***

## `runCommand(command, options?)`

Execute shell commands in the sandbox with full control over execution environment.

**Parameters:**

* `command` (string, required): The shell command to execute as a single string
* `options` (RunCommandOptions, optional): Execution options
  * `cwd` (string, optional): Working directory for command execution
  * `env` (Record\<string, string>, optional): Environment variables to set
  * `timeout` (number, optional): Command timeout in milliseconds
  * `background` (boolean, optional): Run command in background without waiting for completion
  * `onStdout` ((data: string) => void, optional): Callback invoked with stdout chunks as the command runs
  * `onStderr` ((data: string) => void, optional): Callback invoked with stderr chunks as the command runs

**Returns:** `Promise<CommandResult>` - Command execution result with output streams, exit code, and duration

**CommandResult interface:**

* `stdout` (string): Standard output from the command
* `stderr` (string): Standard error output from the command
* `exitCode` (number): Exit code (0 for success, non-zero for errors)
* `durationMs` (number): Command execution duration in milliseconds

**Examples:**

```typescript
// Simple command execution
const result = await sandbox.runCommand('ls -la');
console.log(result.stdout);      // Directory listing
console.log(result.exitCode);    // 0
console.log(result.durationMs);  // 45

// Command with working directory
const result = await sandbox.runCommand('npm install', {
  cwd: '/app'
});
console.log(result.stdout);

// Command with environment variables
const result = await sandbox.runCommand('node server.js', {
  env: { 
    NODE_ENV: 'production',
    PORT: '3000'
  }
});

// Background command execution
const result = await sandbox.runCommand('npm run dev', {
  background: true
});
// Command runs in background, result returns immediately

// Combined options
const result = await sandbox.runCommand('python script.py', {
  cwd: '/app/scripts',
  env: { DEBUG: 'true' },
  timeout: 30000
});

// Stream output as it arrives
const result = await sandbox.runCommand('npm install', {
  onStdout: (chunk) => process.stdout.write(chunk),
  onStderr: (chunk) => process.stderr.write(chunk),
});
// Callbacks fire incrementally during execution;
// the resolved `result` still contains the full stdout/stderr.

// Error handling with exit codes
const result = await sandbox.runCommand('grep pattern file.txt');
if (result.exitCode !== 0) {
  console.error('Command failed:', result.stderr);
} else {
  console.log('Match found:', result.stdout);
}

// Multi-command execution (use shell operators)
const result = await sandbox.runCommand('cd /app && npm install && npm test');

// Command with shell pipes and redirects
const result = await sandbox.runCommand('cat data.txt | grep "error" | wc -l');
```

**Notes:**

* Commands are executed as a single string, not as separate command + arguments arrays
* Use shell operators (`&&`, `||`, `|`, etc.) within the command string for complex operations
* Non-zero exit codes indicate command failure but do not throw errors - check `exitCode` in the result
* Background commands return immediately with `exitCode: 0` without waiting for completion
* The command runs in a shell context, so all shell features (pipes, redirects, etc.) are available
* Passing `onStdout` / `onStderr` enables incremental streaming of command output. The returned `CommandResult` still contains the complete `stdout` and `stderr` once the command finishes
* Streaming callbacks cannot be combined with `background: true` — doing so throws
* Available on all sandbox instances regardless of provider

### Streaming output with `onStdout` / `onStderr`

By default `runCommand` buffers all output and only resolves once the command finishes. Pass `onStdout` and/or `onStderr` to receive output **incrementally** as the command runs — useful for long-running commands (installs, builds, dev servers) where you want to surface progress instead of waiting for completion.

Both are optional callbacks with the signature `(data: string) => void`. Each fires once per output chunk delivered as the command streams, in order, while the command executes.

```typescript
// Forward live output to the local console
const result = await sandbox.runCommand('npm install', {
  onStdout: (chunk) => process.stdout.write(chunk),
  onStderr: (chunk) => process.stderr.write(chunk),
});

// The resolved result still contains the COMPLETE output
console.log(result.exitCode);          // 0
console.log(result.stdout.length);     // full stdout, same as without callbacks
```

Accumulate streamed chunks yourself, e.g. to push progress to a UI:

```typescript
const lines: string[] = [];
await sandbox.runCommand('python train.py', {
  onStdout: (chunk) => {
    lines.push(chunk);
    sendToClient(chunk);   // stream to a websocket, log drain, etc.
  },
});
```

**Behavior:**

* **The callbacks are additive, not a replacement.** The returned `CommandResult` still contains the full `stdout` and `stderr` once the command finishes, regardless of whether you passed callbacks.
* **Chunk boundaries are not guaranteed.** A chunk may contain a partial line, multiple lines, or a mix — do not assume one callback invocation equals one line. Buffer and split on `\n` yourself if you need line-by-line handling.
* **Incremental delivery depends on the sandbox environment.** Streaming is handled by a built-in in-sandbox daemon, not by each provider — the command always runs and the full output is always returned in the result. But if the environment can't stream live chunks, the callbacks fall back to firing once when the command completes, carrying the full output, rather than incrementally.
* **Cannot be combined with `background: true`.** Passing streaming callbacks together with `background: true` throws, since a backgrounded command returns immediately and has no output to stream.

\ <br>

***

## `getInfo()`

Get information about the sandbox including status, provider, and metadata.

**Parameters:** None

**Returns:** `Promise<SandboxInfo>` - Sandbox information including status and configuration

**SandboxInfo interface:**

* `id` (string): Unique identifier for the sandbox
* `provider` (string): Provider hosting the sandbox (e.g., 'e2b', 'modal', 'docker')
* `status` (string): Current sandbox status ('running' | 'stopped' | 'error')
* `createdAt` (Date): Timestamp when the sandbox was created
* `timeout` (number): Execution timeout in milliseconds
* `metadata` (Record\<string, any>, optional): Additional provider-specific metadata

**Examples:**

```typescript
// Basic usage - inspect sandbox info
const info = await sandbox.getInfo();
console.log(info.id);         // "sb_abc123..."
console.log(info.provider);   // "e2b"
console.log(info.status);     // "running"

// Check sandbox status
const info = await sandbox.getInfo();
if (info.status === 'running') {
  console.log('Sandbox is active');
  await sandbox.runCommand('echo "Hello"');
} else {
  console.log('Sandbox is not available');
}

// Access provider info
const info = await sandbox.getInfo();
console.log(`Running on ${info.provider}`);
console.log(`Created: ${info.createdAt.toISOString()}`);
console.log(`Timeout: ${info.timeout}ms`);

// Full info inspection for debugging
const info = await sandbox.getInfo();
console.log('Sandbox Information:');
console.log(`  ID: ${info.id}`);
console.log(`  Provider: ${info.provider}`);
console.log(`  Status: ${info.status}`);
console.log(`  Created: ${info.createdAt}`);
console.log(`  Timeout: ${info.timeout}ms`);
if (info.metadata) {
  console.log(`  Metadata:`, info.metadata);
}
```

**Notes:**

* Returns information about the sandbox's current state and configuration
* May return locally cached information depending on provider implementation
* The `metadata` field contains any custom metadata set during sandbox creation
* Available on all sandbox instances regardless of provider

\ <br>

***

## `getUrl(options)`

Get a publicly accessible URL for accessing services running on a specific port in the sandbox.

**Parameters:**

* `options` (object, required): URL configuration options
  * `port` (number, required): Port number where the service is running in the sandbox
  * `protocol` (string, optional): Protocol to use ('http' | 'https'). Defaults to 'https'

**Returns:** `Promise<string>` - Publicly accessible URL for the specified port

**Examples:**

```typescript
// Access web server on port 3000
const url = await sandbox.getUrl({ port: 3000 });
console.log(url);  // "https://sandbox-123-3000.preview.computesdk.com"

// Use URL to make HTTP request
const url = await sandbox.getUrl({ port: 8080 });
const response = await fetch(url);
console.log(await response.text());

// Specify HTTP protocol
const url = await sandbox.getUrl({ 
  port: 5000, 
  protocol: 'http' 
});
console.log(url);  // "http://sandbox-123-5000.preview.computesdk.com"

// Multiple services on different ports
const apiUrl = await sandbox.getUrl({ port: 3000 });
const wsUrl = await sandbox.getUrl({ port: 8080 });
console.log('API:', apiUrl);
console.log('WebSocket:', wsUrl);

// Start server and get URL
await sandbox.runCommand('npm start', { background: true });
await new Promise(resolve => setTimeout(resolve, 2000)); // Wait for server
const url = await sandbox.getUrl({ port: 3000 });
console.log(`Server running at: ${url}`);

// Error case - accessing URL before service is ready
const url = await sandbox.getUrl({ port: 3000 });
try {
  const response = await fetch(url);
  console.log('Server is ready:', response.status);
} catch (error) {
  console.error('Service not running on port 3000 yet');
  // Wait and retry, or start the service first
}
```

**Notes:**

* Returns a publicly accessible URL that routes to the specified port in your sandbox
* Whether a network call is needed depends on the provider — some construct the URL synchronously from the sandbox host (e.g. E2B), while others resolve it via an API call (e.g. Modal tunnels, Daytona preview links). Always `await` the result
* The service must be running on the specified port for the URL to be accessible

\ <br>

***

## `sandbox.filesystem`

ComputeSDK provides filesystem operations for managing files and directories within sandboxes. All filesystem operations are accessed through the `sandbox.filesystem` object.

### `filesystem.readFile(path)`

Read the contents of a file from the sandbox filesystem.

**Parameters:**

* `path` (string, required): Absolute path to the file to read within the sandbox

**Returns:** `Promise<string>` - File contents as UTF-8 encoded string

**Examples:**

```typescript
// Basic file reading
const content = await sandbox.filesystem.readFile('/app/config.txt');
console.log(content);  // "port=3000\nhost=localhost"

// Read a JSON file
const jsonContent = await sandbox.filesystem.readFile('/app/package.json');
const packageData = JSON.parse(jsonContent);
console.log(packageData.name);     // "my-app"
console.log(packageData.version);  // "1.0.0"

// Read configuration files
const envContent = await sandbox.filesystem.readFile('/app/.env');
console.log(envContent);  // "API_KEY=secret\nDEBUG=true"

// Error handling for non-existent files
try {
  const content = await sandbox.filesystem.readFile('/nonexistent.txt');
} catch (error) {
  console.error('Failed to read file:', error.message);
  // "Failed to read file: File not found: /nonexistent.txt"
}

// Check existence before reading
const filePath = '/app/optional-config.json';
if (await sandbox.filesystem.exists(filePath)) {
  const content = await sandbox.filesystem.readFile(filePath);
  console.log('Config loaded:', content);
} else {
  console.log('Config file not found, using defaults');
}

// Read after writing
await sandbox.filesystem.writeFile('/app/output.txt', 'Hello, World!');
const content = await sandbox.filesystem.readFile('/app/output.txt');
console.log(content);  // "Hello, World!"

// Read code files
const scriptContent = await sandbox.filesystem.readFile('/app/server.js');
console.log(scriptContent);  // "const express = require('express');\n..."

// Read markdown files
const readme = await sandbox.filesystem.readFile('/app/README.md');
console.log(readme);  // "# My Project\n\nDescription..."
```

**Notes:**

* Always returns UTF-8 encoded strings
* Throws an error if the file does not exist
* Requires absolute paths (paths should start with `/`)
* No encoding options available - always returns UTF-8

\ <br>

***

### `filesystem.writeFile(path, content)`

Write content to a file in the sandbox filesystem, creating the file if it doesn't exist.

**Parameters:**

* `path` (string, required): Absolute path where the file should be written
* `content` (string, required): Content to write to the file as UTF-8 text

**Returns:** `Promise<void>` - Resolves when the file is successfully written

**Examples:**

```typescript
// Basic file writing
await sandbox.filesystem.writeFile('/app/config.txt', 'port=3000\nhost=localhost');
console.log('File written successfully');

// Write JSON data
const data = { name: 'my-app', version: '1.0.0' };
await sandbox.filesystem.writeFile('/app/package.json', JSON.stringify(data, null, 2));

// Write configuration files
const envContent = 'API_KEY=secret\nDEBUG=true\nPORT=3000';
await sandbox.filesystem.writeFile('/app/.env', envContent);

// Overwrite existing files
await sandbox.filesystem.writeFile('/app/log.txt', 'First entry');
await sandbox.filesystem.writeFile('/app/log.txt', 'Second entry');
const content = await sandbox.filesystem.readFile('/app/log.txt');
console.log(content);  // "Second entry" (first entry was overwritten)

// Error handling
try {
  await sandbox.filesystem.writeFile('/app/data.json', JSON.stringify({ key: 'value' }));
  console.log('File created successfully');
} catch (error) {
  console.error('Failed to write file:', error.message);
}

// Write multiline content with template literals
const script = `#!/bin/bash
echo "Starting application..."
npm install
npm start
`;
await sandbox.filesystem.writeFile('/app/start.sh', script);

// Write then read to verify
const newContent = 'Hello, World!';
await sandbox.filesystem.writeFile('/app/greeting.txt', newContent);
const readBack = await sandbox.filesystem.readFile('/app/greeting.txt');
console.log(readBack === newContent);  // true
```

**Notes:**

* Always writes UTF-8 encoded text
* Creates the file if it doesn't exist
* Overwrites existing files completely (previous content is lost)
* Requires absolute paths (paths should start with `/`)
* No encoding options available - always UTF-8

\ <br>

***

### `filesystem.mkdir(path)`

Create a directory in the sandbox filesystem, automatically creating parent directories as needed.

**Parameters:**

* `path` (string, required): Absolute path of the directory to create

**Returns:** `Promise<void>` - Resolves when the directory is successfully created

**Examples:**

```typescript
// Basic directory creation
await sandbox.filesystem.mkdir('/app/data');
console.log('Directory created');

// Multiple directories for project structure
await sandbox.filesystem.mkdir('/app/src');
await sandbox.filesystem.mkdir('/app/tests');
await sandbox.filesystem.mkdir('/app/dist');

// Directory already exists - succeeds silently
await sandbox.filesystem.mkdir('/app/data');
await sandbox.filesystem.mkdir('/app/data'); // No error thrown
console.log('Both calls succeeded');

// Error handling
try {
  await sandbox.filesystem.mkdir('/app/project/data');
  console.log('Directory created successfully');
} catch (error) {
  console.error('Failed to create directory:', error.message);
}
```

**Notes:**

* Automatically creates parent directories as needed
* Does not throw an error if the directory already exists
* Requires absolute paths (paths should start with `/`)
* Throws errors only on actual failures (permissions, invalid paths, disk space issues)

\ <br>

***

### `filesystem.readdir(path)`

List the contents of a directory in the sandbox filesystem.

**Parameters:**

* `path` (string, required): Absolute path to the directory to list

**Returns:** `Promise<FileEntry[]>` - Array of entries in the directory

**FileEntry interface:**

* `name` (string): Name of the file or directory
* `type` ('file' | 'directory'): Type of the entry
* `size` (number, optional): Size in bytes (for files)
* `modified` (Date, optional): Last modification timestamp

**Examples:**

```typescript
// Basic directory listing
const entries = await sandbox.filesystem.readdir('/app');
console.log(entries);
// [
//   { name: 'config.json', type: 'file', size: 245 },
//   { name: 'src', type: 'directory' },
//   { name: 'package.json', type: 'file', size: 512 }
// ]

// List and display all entries
const entries = await sandbox.filesystem.readdir('/app');
entries.forEach(entry => {
  console.log(`${entry.type === 'directory' ? '📁' : '📄'} ${entry.name}`);
});
// 📄 config.json
// 📁 src
// 📄 package.json


// Find specific files by extension
const entries = await sandbox.filesystem.readdir('/app/src');
const jsFiles = entries.filter(e => 
  e.type === 'file' && e.name.endsWith('.js')
);
console.log('JavaScript files:', jsFiles.map(f => f.name));

// Count files and directories
const entries = await sandbox.filesystem.readdir('/app');
const fileCount = entries.filter(e => e.type === 'file').length;
const dirCount = entries.filter(e => e.type === 'directory').length;
console.log(`Found ${fileCount} files and ${dirCount} directories`);

// Check if directory is empty
const entries = await sandbox.filesystem.readdir('/app/temp');
if (entries.length === 0) {
  console.log('Directory is empty');
} else {
  console.log(`Directory contains ${entries.length} items`);
}

// Error handling for non-existent directories
try {
  const entries = await sandbox.filesystem.readdir('/nonexistent');
  console.log(entries);
} catch (error) {
  console.error('Failed to read directory:', error.message);
  // "Failed to read directory: Directory not found: /nonexistent"
}

// Check existence before reading
const dirPath = '/app/optional-data';
if (await sandbox.filesystem.exists(dirPath)) {
  const entries = await sandbox.filesystem.readdir(dirPath);
  console.log(`Found ${entries.length} entries in ${dirPath}`);
} else {
  console.log('Directory does not exist');
}
```

**Notes:**

* Returns an array of FileEntry objects with file/directory metadata
* Requires absolute paths (paths should start with `/`)
* Only lists direct children - does not recursively list subdirectories
* Throws an error if the directory does not exist
* The `size` and `modified` fields may not be available on all providers
* Empty directories return an empty array (not an error)

\ <br>

***

### `filesystem.exists(path)`

Check if a file or directory exists at the specified path in the sandbox filesystem.

**Parameters:**

* `path` (string, required): Absolute path to the file or directory to check

**Returns:** `Promise<boolean>` - Returns `true` if the path exists (file or directory), `false` otherwise

**Examples:**

```typescript
// Basic file existence check
const exists = await sandbox.filesystem.exists('/app/config.json');
console.log(exists);  // true

// Basic directory existence check
const dirExists = await sandbox.filesystem.exists('/app/src');
console.log(dirExists);  // true

// Check for non-existent path (returns false, doesn't throw error)
const missing = await sandbox.filesystem.exists('/app/nonexistent.txt');
console.log(missing);  // false

// Check before reading to avoid errors
const configPath = '/app/config.json';
if (await sandbox.filesystem.exists(configPath)) {
  const content = await sandbox.filesystem.readFile(configPath);
  console.log('Config loaded:', content);
} else {
  console.log('Config file not found, using defaults');
}

// Check before writing to avoid overwriting
const outputPath = '/app/output.txt';
if (await sandbox.filesystem.exists(outputPath)) {
  console.log('File already exists, skipping write');
} else {
  await sandbox.filesystem.writeFile(outputPath, 'New content');
  console.log('File created');
}

// Verify file creation
await sandbox.filesystem.writeFile('/app/data.json', '{}');
const created = await sandbox.filesystem.exists('/app/data.json');
console.log('File created successfully:', created);  // true

// Verify file deletion
await sandbox.filesystem.writeFile('/app/temp.txt', 'temporary');
await sandbox.filesystem.remove('/app/temp.txt');
const stillExists = await sandbox.filesystem.exists('/app/temp.txt');
console.log('File still exists:', stillExists);  // false

// Verify directory creation
await sandbox.filesystem.mkdir('/app/logs');
const dirCreated = await sandbox.filesystem.exists('/app/logs');
console.log('Directory created:', dirCreated);  // true


// Check multiple files at once
const requiredFiles = ['/app/package.json', '/app/src/index.js', '/app/README.md'];
const checks = await Promise.all(
  requiredFiles.map(path => sandbox.filesystem.exists(path))
);
const allExist = checks.every(exists => exists);
console.log('All required files present:', allExist);
```

**Notes:**

* Returns a boolean value - never throws errors (unlike `readFile` or `readdir`)
* Works for both files and directories - no distinction in the return value
* Requires absolute paths (paths should start with `/`)
* Returns `false` for non-existent paths, not an error
* Cannot distinguish between a file and directory from the return value alone
* Useful for defensive programming to prevent errors before operations

\ <br>

***

### `filesystem.remove(path)`

Remove a file or directory from the sandbox filesystem. For directories, this recursively removes all contents.

**Parameters:**

* `path` (string, required): Absolute path to the file or directory to remove

**Returns:** `Promise<void>` - Resolves when the file or directory is successfully removed

**Examples:**

```typescript
// Basic file removal
await sandbox.filesystem.writeFile('/app/temp.txt', 'temporary data');
await sandbox.filesystem.remove('/app/temp.txt');
console.log('File removed');

// Basic directory removal (recursive)
await sandbox.filesystem.mkdir('/app/old-data');
await sandbox.filesystem.writeFile('/app/old-data/file1.txt', 'data');
await sandbox.filesystem.writeFile('/app/old-data/file2.txt', 'data');
await sandbox.filesystem.remove('/app/old-data');
console.log('Directory and all contents removed');

// Remove file and verify deletion
await sandbox.filesystem.writeFile('/app/output.txt', 'content');
await sandbox.filesystem.remove('/app/output.txt');
const exists = await sandbox.filesystem.exists('/app/output.txt');
console.log('File still exists:', exists);  // false

// Remove directory with nested contents
await sandbox.filesystem.mkdir('/app/cache/images/thumbnails');
await sandbox.filesystem.writeFile('/app/cache/data.json', '{}');
await sandbox.filesystem.writeFile('/app/cache/images/photo.jpg', 'image data');
await sandbox.filesystem.remove('/app/cache');
console.log('Entire cache directory tree removed');

// Error handling for non-existent paths
try {
  await sandbox.filesystem.remove('/app/nonexistent.txt');
} catch (error) {
  console.error('Failed to remove:', error.message);
  // "Failed to remove: File not found: /app/nonexistent.txt"
}

// Safe removal with existence check
const filePath = '/app/optional-cache.json';
if (await sandbox.filesystem.exists(filePath)) {
  await sandbox.filesystem.remove(filePath);
  console.log('Cache file removed');
} else {
  console.log('No cache file to remove');
}
```

**Notes:**

* Works for both files and directories - no distinction needed
* **Recursive deletion for directories** - removes all contents and subdirectories (like `rm -rf`)
* Requires absolute paths (paths should start with `/`)
* Throws an error if the path does not exist
* **Deletion is permanent** - no recycle bin, trash, or undo capability
* **Use with caution** - destructive operation that cannot be reversed
* For directories, all nested files and subdirectories are removed automatically
* No confirmation prompt - removal happens immediately


# compute

## Overview

`compute` is ComputeSDK's unified entrypoint for managing sandboxes across one or more providers. There are two import styles you can use:

1. **Direct provider mode** — import a provider package (e.g. `@computesdk/e2b`) and use the returned instance as your compute object. Best for single-provider apps.
2. **Core `compute` from `computesdk`** — import `compute` from the `computesdk` package and configure it with one or more provider instances. Best when you want resilient routing, round-robin load balancing, or a single module-level entrypoint that multiple files share.

Both modes expose the same shape: `compute.sandbox.*` for sandbox lifecycle and operations, and `compute.snapshot.*` for snapshot management (when supported by the provider).

Every provider package depends on `computesdk`, so it is always installed alongside them — the choice between the two modes is purely about what you import.

## Installation

Install the provider packages you need. `computesdk` is pulled in automatically as a dependency of every provider package, so you don't need to list it separately (though listing it explicitly is harmless and makes the intent clear when you use the `compute` import).

```bash
# Single provider — computesdk is installed transitively
npm install @computesdk/e2b

# Multiple providers
npm install @computesdk/e2b @computesdk/modal

# Explicit (equivalent to the above, just makes the dependency visible)
npm install computesdk @computesdk/e2b @computesdk/modal
```

## Provider Credentials

Each provider reads its own environment variables. See the [installation guide](/getting-started/installation) for the full list or the individual provider reference pages under `/docs/providers`.

```bash
# Example: E2B
E2B_API_KEY=your_e2b_api_key

# Example: Modal
MODAL_TOKEN_ID=your_modal_token_id
MODAL_TOKEN_SECRET=your_modal_token_secret
```

***

## Direct Provider Mode

Call the provider factory with credentials and use the returned object as your `compute` instance. This is the fastest path for a single-provider app.

```typescript
import { e2b } from '@computesdk/e2b';

const compute = e2b({ apiKey: process.env.E2B_API_KEY });

const sandbox = await compute.sandbox.create();
const result = await sandbox.runCommand('echo "Hello!"');
console.log(result.stdout);
await sandbox.destroy();
```

**Notes:**

* Every provider factory (`e2b`, `modal`, `vercel`, `daytona`, etc.) returns an object with the same shape.
* Swapping providers is usually a one-line change: replace the import and factory call.
* No core `computesdk` import is required in this mode.

<br>

***

## Core `compute` Mode

Import `compute` from `computesdk` and register one or more providers. The same `compute` singleton is used throughout your app.

### Single Provider

```typescript
import { compute } from 'computesdk';
import { e2b } from '@computesdk/e2b';

compute.setConfig({
  provider: e2b({ apiKey: process.env.E2B_API_KEY }),
});

const sandbox = await compute.sandbox.create();
await sandbox.runCommand('echo "Hello!"');
await sandbox.destroy();
```

### Multi-Provider

Pass a `providers` array to configure several providers under the same `compute` entrypoint:

```typescript
import { compute } from 'computesdk';
import { e2b } from '@computesdk/e2b';
import { modal } from '@computesdk/modal';

compute.setConfig({
  providers: [
    e2b({ apiKey: process.env.E2B_API_KEY }),
    modal({
      tokenId: process.env.MODAL_TOKEN_ID,
      tokenSecret: process.env.MODAL_TOKEN_SECRET,
    }),
  ],
  providerStrategy: 'priority', // 'priority' (default) or 'round-robin'
  fallbackOnError: true,        // default: true
});

// Uses the configured strategy
const sandbox = await compute.sandbox.create();

// Override for one call
const gpuSandbox = await compute.sandbox.create({ provider: 'modal' });
```

### Callable Form

You can also call `compute(config)` to get a new, isolated instance without touching the singleton — useful for request-scoped configuration, testing, or running multiple independent configurations side by side.

```typescript
import { compute } from 'computesdk';
import { vercel } from '@computesdk/vercel';

const scoped = compute({
  provider: vercel({
    token: process.env.VERCEL_TOKEN,
    teamId: process.env.VERCEL_TEAM_ID,
    projectId: process.env.VERCEL_PROJECT_ID,
  }),
});

const sandbox = await scoped.sandbox.create();
```

<br>

***

## `compute.setConfig(config)`

Configure the module-level `compute` singleton.

**Parameters:**

* `config` (ExplicitComputeConfig, required):
  * `provider` (DirectProvider, optional) — single primary provider
  * `providers` (DirectProvider\[], optional) — ordered list of providers
  * `providerStrategy` (`'priority' | 'round-robin'`, optional) — default `'priority'`
  * `fallbackOnError` (boolean, optional) — default `true`

At least one of `provider` or `providers` must be supplied. When both are provided, `provider` is treated as the first provider, and duplicates (by `.name`) are removed from `providers`.

**Returns:** `void`

**Examples:**

```typescript
import { compute } from 'computesdk';
import { e2b } from '@computesdk/e2b';
import { modal } from '@computesdk/modal';

// Single provider
compute.setConfig({
  provider: e2b({ apiKey: process.env.E2B_API_KEY }),
});

// Multi-provider with priority routing + failover
compute.setConfig({
  providers: [
    e2b({ apiKey: process.env.E2B_API_KEY }),
    modal({
      tokenId: process.env.MODAL_TOKEN_ID,
      tokenSecret: process.env.MODAL_TOKEN_SECRET,
    }),
  ],
  providerStrategy: 'priority',
  fallbackOnError: true,
});

// Multi-provider with round-robin load balancing
compute.setConfig({
  providers: [
    e2b({ apiKey: process.env.E2B_API_KEY }),
    modal({
      tokenId: process.env.MODAL_TOKEN_ID,
      tokenSecret: process.env.MODAL_TOKEN_SECRET,
    }),
  ],
  providerStrategy: 'round-robin',
});

// Primary + fallback pool
compute.setConfig({
  provider: e2b({ apiKey: process.env.E2B_API_KEY }),       // primary
  providers: [                                               // fallbacks
    modal({
      tokenId: process.env.MODAL_TOKEN_ID,
      tokenSecret: process.env.MODAL_TOKEN_SECRET,
    }),
  ],
});
```

**Notes:**

* Re-calling `setConfig` replaces the prior configuration and resets internal routing state (round-robin cursor, sandbox-to-provider affinity cache).
* Providers are deduplicated by their `name` property, so the same provider registered twice is only called once.

<br>

***

## Provider Selection Strategies

When more than one provider is configured, ComputeSDK picks which one to use per call based on `providerStrategy`.

### `priority` (default)

Providers are tried in the order you passed them. The first successful one handles the call. If `fallbackOnError` is `true`, failures cascade to the next provider.

```typescript
compute.setConfig({
  providers: [e2b({...}), modal({...})],
  providerStrategy: 'priority',
  fallbackOnError: true,
});

// Tries e2b first; falls back to modal only if e2b throws
await compute.sandbox.create();
```

Use when you have a preferred provider and want the others purely as a safety net.

### `round-robin`

New sandboxes rotate through providers in order. Good for distributing load evenly across providers with similar capability profiles.

```typescript
compute.setConfig({
  providers: [e2b({...}), modal({...})],
  providerStrategy: 'round-robin',
});

await compute.sandbox.create(); // e2b
await compute.sandbox.create(); // modal
await compute.sandbox.create(); // e2b
```

Failover via `fallbackOnError` still applies: if the round-robin pick fails, the next provider is tried.

<br>

***

## `fallbackOnError`

Controls whether `create` tries the next provider after a failure.

* `true` (default) — on failure, move to the next candidate and keep going until one succeeds or all fail
* `false` — the first failure throws immediately

```typescript
compute.setConfig({
  providers: [e2b({...}), modal({...})],
  fallbackOnError: false,
});

// If e2b throws, the error propagates — modal is never tried
await compute.sandbox.create();
```

**Notes:**

* When a caller specifies `{ provider: 'modal' }` explicitly, `fallbackOnError` is ignored for that call — the target provider is the only one tried.
* Failover only applies to `create`. Operations on an existing sandbox (`destroy`, snapshot work) use provider affinity instead — see below.

<br>

***

## Per-Call Provider Override

Most `compute.sandbox.*` methods accept an optional `provider` field to target a specific provider by name, bypassing the strategy:

```typescript
// Force this sandbox onto Modal, regardless of strategy
const gpuSandbox = await compute.sandbox.create({ provider: 'modal' });

// Target a specific provider for a snapshot
const snap = await compute.snapshot.create(sandboxId, { provider: 'e2b' });
```

The override must match a configured provider's `.name` exactly. If not, a descriptive error is thrown listing the configured providers.

<br>

***

## Provider Affinity

For sandboxes created through `compute`, the owning provider is tracked internally. Operations that act on an existing sandbox prefer the owning provider first:

* `compute.sandbox.destroy(sandboxId)`
* `compute.sandbox.getById(sandboxId)`
* `compute.snapshot.create(sandboxId, options)`
* `compute.snapshot.delete(snapshotId)`

Affinity is **preferred, not exclusive**: if the owning provider fails, ComputeSDK falls through to the other configured providers.

**Caveats:**

* Affinity is kept in an in-memory map that is reset every time `setConfig` is called.
* Sandbox IDs minted outside the current `compute` instance (e.g., from a different process, or fetched via raw SDK) have no recorded affinity — every configured provider is probed.
* This means, in long-running processes, the happy path is one call to the owning provider; in fresh processes with only a stored ID, expect a probe across providers.

<br>

***

## `compute.sandbox.*`

The full sandbox API is documented in [compute.sandbox](https://github.com/computesdk/computesdk/tree/main/docs/reference/computesandbox/README.md). Summary of available methods:

| Method               | Purpose                                                                    |
| -------------------- | -------------------------------------------------------------------------- |
| `create(options?)`   | Provision a new sandbox                                                    |
| `getById(sandboxId)` | Reconnect to an existing sandbox                                           |
| `list()`             | List active sandboxes (aggregated across providers in multi-provider mode) |
| `destroy(sandboxId)` | Tear down a sandbox                                                        |

All of these accept a `provider` override where applicable. See [Sandbox](https://github.com/computesdk/computesdk/tree/main/docs/reference/sandbox/README.md) for the instance methods (`runCommand`, `filesystem.*`).

<br>

***

## `compute.snapshot.*`

Available when at least one configured provider supports snapshots.

| Method                        | Purpose                                              |
| ----------------------------- | ---------------------------------------------------- |
| `create(sandboxId, options?)` | Capture a snapshot of a running sandbox              |
| `list()`                      | List snapshots across providers that support listing |
| `delete(snapshotId)`          | Delete a snapshot                                    |

```typescript
const sandbox = await compute.sandbox.create();
const snap = await compute.snapshot.create(sandbox.sandboxId, {
  name: 'post-setup',
  metadata: { owner: 'team-backend' },
});

const snapshots = await compute.snapshot.list();
await compute.snapshot.delete(snap.id);
```

**Notes:**

* `create` routes to the sandbox's owning provider first; otherwise tries any snapshot-capable provider.
* `delete` tracks the owning provider of each snapshot so deletes land on the right platform.
* If no configured provider supports snapshots, calls throw a descriptive error.

<br>

***

## Error Handling

ComputeSDK surfaces descriptive, aggregated errors when all candidates fail:

```typescript
try {
  const sandbox = await compute.sandbox.create();
} catch (error) {
  // Example message:
  // Failed to create sandbox across 2 provider(s).
  //   - e2b: rate limited
  //   - modal: authentication failed
  console.error(error.message);
}
```

Common error cases:

* **No provider configured** — Call `compute.setConfig({ provider: ... })` or `compute.setConfig({ providers: [...] })` before any sandbox call.
* **`provider: 'foo'` override with no matching provider** — The error lists the configured provider names.
* **All providers failed** — The message includes one line per provider with its failure reason.

<br>

***

## End-to-End Example

```typescript
import { compute } from 'computesdk';
import { e2b } from '@computesdk/e2b';
import { modal } from '@computesdk/modal';

compute.setConfig({
  providers: [
    e2b({ apiKey: process.env.E2B_API_KEY }),
    modal({
      tokenId: process.env.MODAL_TOKEN_ID,
      tokenSecret: process.env.MODAL_TOKEN_SECRET,
    }),
  ],
  providerStrategy: 'priority',
  fallbackOnError: true,
});

async function runUserCode(userId: string, code: string) {
  const sandbox = await compute.sandbox.create({
    timeout: 5 * 60 * 1000,
    metadata: { userId },
    envs: { USER_ID: userId },
  });

  try {
    await sandbox.filesystem.writeFile('/tmp/main.py', code);
    const result = await sandbox.runCommand('python /tmp/main.py');
    return {
      stdout: result.stdout,
      stderr: result.stderr,
      exitCode: result.exitCode,
      provider: sandbox.provider,
    };
  } finally {
    await sandbox.destroy();
  }
}
```

<br>

***

## Related

* [compute.sandbox](https://github.com/computesdk/computesdk/tree/main/docs/reference/computesandbox/README.md) — sandbox lifecycle methods
* [Sandbox](https://github.com/computesdk/computesdk/tree/main/docs/reference/sandbox/README.md) — sandbox instance methods (code, commands, filesystem, terminal)
* [Introduction](https://github.com/computesdk/computesdk/tree/main/docs/getting-started/introduction/README.md) — high-level overview
* [Installation](https://github.com/computesdk/computesdk/tree/main/docs/getting-started/installation/README.md) — provider setup and credentials
* [Quick Start](https://github.com/computesdk/computesdk/tree/main/docs/getting-started/quick-start/README.md) — minimal end-to-end walkthrough


# compute.sandbox

## Overview

Core methods for creating, destroying, listing, and retrieving sandbox instances.

***

## `create(options?)`

Create a new compute sandbox instance.

**Parameters:**

* `options` (CreateSandboxOptions, optional): Configuration options for sandbox creation
  * `timeout` (number, optional): Sandbox execution timeout in milliseconds
  * `templateId` (string, optional): Provider-agnostic template or image identifier to boot from
  * `snapshotId` (string, optional): Snapshot ID to restore from; each provider maps this to its native concept (E2B template, Daytona snapshot, Modal image, etc.)
  * `metadata` (Record\<string, any>, optional): Custom metadata to attach to the sandbox
  * `envs` (Record\<string, string>, optional): Environment variables to set in the sandbox
  * `signal` (AbortSignal, optional): Cancels sandbox creation and cleans up an orphaned sandbox if the signal aborts
  * `name`, `namespace`, `directory` (string, optional): Provider-specific naming/placement hints
  * Additional provider-specific properties are passed through (e.g. `domain` for E2B)

**Returns:** `Promise<Sandbox>` - New sandbox instance ready for code execution and commands

**Sandbox instance properties:**

* `sandboxId` (string): Unique identifier for the sandbox
* `provider` (string): Provider hosting the sandbox (e.g., 'e2b', 'modal', 'vercel')
* `filesystem` (SandboxFileSystem): File system operations interface
* Core methods: `runCommand()`, `getInfo()`, `getUrl()`, `destroy()`
* See [Sandbox API Reference](/reference/sandbox) for complete interface documentation

**CreateSandboxOptions interface:**

```typescript
{
  timeout?: number;                // Execution timeout in milliseconds
  templateId?: string;             // Provider template/image identifier
  snapshotId?: string;             // Snapshot to restore from
  metadata?: Record<string, any>;  // Custom metadata
  envs?: Record<string, string>;   // Environment variables
  signal?: AbortSignal;            // Cancel creation / clean up orphaned sandbox
  name?: string;                   // Provider-specific name
  namespace?: string;              // Provider-specific namespace
  directory?: string;              // Provider-specific working directory
  [key: string]: any;              // Provider-specific properties
}
```

**Examples:**

```typescript
import { e2b } from '@computesdk/e2b';

const compute = e2b({ apiKey: process.env.E2B_API_KEY });

// Basic sandbox creation
const sandbox = await compute.sandbox.create();
console.log(sandbox.sandboxId);  // "sb_abc123..."
console.log(sandbox.provider);   // "e2b"

// With timeout (30 minutes)
const sandbox = await compute.sandbox.create({
  timeout: 30 * 60 * 1000
});

// With environment variables
const sandbox = await compute.sandbox.create({
  envs: {
    API_KEY: 'your-api-key',
    NODE_ENV: 'production',
    DATABASE_URL: 'postgresql://...'
  }
});

// With provider template/image
const sandbox = await compute.sandbox.create({
  templateId: 'your-template-id'
});

// With custom metadata
const sandbox = await compute.sandbox.create({
  metadata: {
    userId: 'user-123',
    projectId: 'proj-456',
    environment: 'staging'
  }
});

// With multiple options combined
const sandbox = await compute.sandbox.create({
  timeout: 60 * 60 * 1000,  // 1 hour
  templateId: 'your-template-id',
  envs: {
    NODE_ENV: 'production',
    DEBUG: 'true'
  },
  metadata: {
    owner: 'team-backend',
    purpose: 'integration-tests'
  }
});

// Error handling - missing credentials
try {
  const sandbox = await compute.sandbox.create();
} catch (error) {
  console.error('Failed to create sandbox:', error.message);
}
```

**Notes:**

* Configure your provider by importing and initializing a provider package (e.g., `@computesdk/e2b`) with your credentials
* Each call creates a new sandbox instance with a unique `sandboxId`
* The `timeout` option sets maximum sandbox lifetime; sandboxes auto-terminate after this period
* The `templateId` parameter is provider-specific (refers to templates, images, or runtime environments)
* Environment variables set via `envs` are available to all commands and code executed in the sandbox
* Throws an error if the provider is missing required credentials (e.g., API key)

\ <br>

***

## `destroy(sandboxId)`

Destroy a sandbox and clean up all associated resources.

**Parameters:**

* `sandboxId` (string, required): Unique identifier of the sandbox to destroy

**Returns:** `Promise<void>` - Resolves when sandbox is successfully destroyed

> **⚠️ CAUTION:** Destroying a sandbox is a permanent operation. All data, files, and running processes in the sandbox will be irreversibly deleted.

**Examples:**

```typescript
import { e2b } from '@computesdk/e2b';

const compute = e2b({ apiKey: process.env.E2B_API_KEY });

// Basic cleanup after use
const sandbox = await compute.sandbox.create();
// ... use sandbox ...
await sandbox.destroy();

// Alternative: destroy by ID
await compute.sandbox.destroy(sandbox.sandboxId);

// Batch cleanup - destroy multiple sandboxes
const sandboxIds = ['sb_123...', 'sb_456...', 'sb_789...'];
await Promise.all(sandboxIds.map(id => compute.sandbox.destroy(id)));

// With error handling
try {
  await sandbox.destroy();
  console.log('Sandbox destroyed successfully');
} catch (error) {
  console.error('Failed to destroy sandbox:', error.message);
}

// Best practice: ensure cleanup with finally block
let sandbox;
try {
  sandbox = await compute.sandbox.create();
  await sandbox.runCommand('echo "Hello"');
} finally {
  if (sandbox) {
    await sandbox.destroy();
  }
}
```

**Notes:**

* You can call `sandbox.destroy()` directly on the sandbox instance, or `compute.sandbox.destroy(sandboxId)` with the ID
* Destroying a sandbox terminates all running processes and releases all allocated resources
* This operation is idempotent - calling destroy on an already-destroyed sandbox succeeds without error
* Best practice: Use `finally` blocks or cleanup handlers to ensure sandboxes are destroyed even if errors occur
* All sandbox data and files are permanently lost after destruction

\ <br>

***

## `getById(sandboxId)`

Retrieve an existing sandbox instance by its unique identifier.

**Parameters:**

* `sandboxId` (string, required): Unique identifier of the sandbox to retrieve

**Returns:** `Promise<Sandbox | null>` - Sandbox instance if found, or `null` if the sandbox doesn't exist

**Sandbox instance properties:**

* `sandboxId` (string): Unique identifier for the sandbox
* `provider` (string): Provider hosting the sandbox
* `filesystem` (SandboxFileSystem): File system operations interface
* Core methods: `runCommand()`, `getInfo()`, `getUrl()`, `destroy()`
* See [Sandbox API Reference](/reference/sandbox) for complete interface documentation

**Examples:**

```typescript
import { e2b } from '@computesdk/e2b';

const compute = e2b({ apiKey: process.env.E2B_API_KEY });

// Reconnect to existing sandbox by ID
const sandboxId = 'sb_abc123...';
const sandbox = await compute.sandbox.getById(sandboxId);

if (sandbox) {
  const result = await sandbox.runCommand('echo "Reconnected!"');
  console.log(result.stdout);  // "Reconnected!"
}

// Store ID and reconnect later
// Step 1: Create and store ID
const newSandbox = await compute.sandbox.create();
const storedId = newSandbox.sandboxId;
// Store storedId in database, config file, etc.

// Step 2: Later, retrieve using stored ID
const retrievedSandbox = await compute.sandbox.getById(storedId);
if (retrievedSandbox) {
  await retrievedSandbox.runCommand('npm install');
}

// Check if sandbox exists before using
const sandbox = await compute.sandbox.getById(sandboxId);

if (sandbox === null) {
  console.log('Sandbox not found - creating new one');
  const newSandbox = await compute.sandbox.create();
} else {
  console.log('Sandbox found - using existing one');
  await sandbox.runCommand('echo "Still active!"');
}

// Graceful handling of missing sandbox
const sandboxId = 'sb_might_not_exist...';
const sandbox = await compute.sandbox.getById(sandboxId);

if (sandbox) {
  // Sandbox exists - use it
  await sandbox.runCommand('npm test');
  console.log('Tests completed on existing sandbox');
} else {
  // Sandbox not found - handle accordingly
  console.log('Sandbox no longer exists');
}
```

**Notes:**

* Returns `null` for non-existent or destroyed sandboxes (does not throw errors)
* Retrieved sandboxes have full functionality identical to newly created sandboxes
* Useful for reconnecting to long-lived sandboxes or implementing persistent sandbox patterns
* Sandbox IDs can be stored and used to reconnect later across application restarts

\ <br>

***

## `list()`

Retrieve a list of your active sandboxes from your provider.

```typescript
import { e2b } from '@computesdk/e2b';

const compute = e2b({ apiKey: process.env.E2B_API_KEY });

const sandboxes = await compute.sandbox.list();

for (const sandbox of sandboxes) {
  console.log(sandbox.sandboxId);
}
```

**Notes:**

* Returns all active sandboxes for the configured provider
* Provider support for listing sandboxes varies — check your provider's documentation for details

\ <br>

***


# LLM Documentation Files

AI-optimized documentation files for ComputeSDK, the open benchmark harness for cloud infrastructure.

ComputeSDK is the open, multi-provider benchmark harness behind [ComputeSDK Benchmarks](https://www.computesdk.com/benchmarks). These AI-optimized documentation files are designed for training large language models (LLMs) and AI assistants. They contain our complete documentation in a format that's easy for AI systems to understand and use.

### Available Files

#### [llms-small.txt](https://github.com/computesdk/computesdk/tree/main/llms-small.txt)

A minimal version containing essential information about ComputeSDK and ComputeSDK Benchmarks, perfect for quick AI context.

#### [llms-full.txt](https://github.com/computesdk/computesdk/tree/main/llms-full.txt)

The complete documentation — including the benchmark harness overview, API references, and provider information. This comprehensive file contains everything an AI needs to help users with ComputeSDK and its benchmarks.


