Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<img alt="Sandbox SDK with supported provider logos" src="./Background-with-text.png" width="820" />
</p>

Run the same TypeScript sandbox code on Local, E2B, Daytona, Vercel Sandbox, or Upstash Box.
Run the same TypeScript sandbox code on Local, E2B, Daytona, Vercel Sandbox, Upstash Box, or Ascii Box.

## Install

Expand All @@ -14,13 +14,14 @@ Node.js 22 or 24 is supported. Bun 1.3 or newer is also supported.

## Providers

| Provider | Runtime | Best for |
| --------------------------------------------------------------- | ----------------------- | -------------------------------------- |
| [Local](https://sandbox-sdk.app/docs/providers/local) | AgentOS VM | Development, CI, and self-hosting |
| [E2B](https://sandbox-sdk.app/docs/providers/e2b) | Hosted Linux sandbox | Coding agents and isolated jobs |
| [Daytona](https://sandbox-sdk.app/docs/providers/daytona) | Cloud workspace | Persistent projects and GPUs |
| [Vercel Sandbox](https://sandbox-sdk.app/docs/providers/vercel) | Hosted Linux sandbox | Vercel workloads and previews |
| [Upstash Box](https://sandbox-sdk.app/docs/providers/upstash) | Durable cloud container | Serverless agents and long-lived state |
| Provider | Runtime | Best for |
| --------------------------------------------------------------- | ------------------------- | ---------------------------------------- |
| [Local](https://sandbox-sdk.app/docs/providers/local) | AgentOS VM | Development, CI, and self-hosting |
| [E2B](https://sandbox-sdk.app/docs/providers/e2b) | Hosted Linux sandbox | Coding agents and isolated jobs |
| [Daytona](https://sandbox-sdk.app/docs/providers/daytona) | Cloud workspace | Persistent projects and GPUs |
| [Vercel Sandbox](https://sandbox-sdk.app/docs/providers/vercel) | Hosted Linux sandbox | Vercel workloads and previews |
| [Upstash Box](https://sandbox-sdk.app/docs/providers/upstash) | Durable cloud container | Serverless agents and long-lived state |
| [Ascii Box](https://sandbox-sdk.app/docs/providers/ascii) | Persistent cloud computer | Agents, previews, and durable workspaces |

Local is included. Cloud providers use their official SDKs and credentials.

Expand Down
15 changes: 8 additions & 7 deletions apps/fumadocs/content/docs/api/ports.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ const response = await preview.request?.("/health");

Authenticated adapters keep preview credentials inside `request()`. `toJSON()` never returns credential-bearing headers and redacts URL query values.

| Provider | Port behavior |
| -------------- | ------------------------------------------------------------------ |
| Local | Returns a private URL and bridges calls through `request()`. |
| E2B | Returns an E2B host and uses a native access token when required. |
| Daytona | Returns a public or token-authenticated preview URL. |
| Vercel Sandbox | Registers the port and returns a public `vercel.run` route. |
| Upstash Box | Returns a public URL or keeps its bearer token inside `request()`. |
| Provider | Port behavior |
| -------------- | ---------------------------------------------------------------------- |
| Local | Returns a private URL and bridges calls through `request()`. |
| E2B | Returns an E2B host and uses a native access token when required. |
| Daytona | Returns a public or token-authenticated preview URL. |
| Vercel Sandbox | Registers the port and returns a public `vercel.run` route. |
| Upstash Box | Returns a public URL or keeps its bearer token inside `request()`. |
| Ascii Box | Keeps `_token` and its same-origin cookie redirect inside `request()`. |

Compare provider preview behavior in [Providers](/docs/providers).
2 changes: 1 addition & 1 deletion apps/fumadocs/content/docs/api/processes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Each event reports `stream`, `data`, and an optional `timestamp`. Providers that

## Writing stdin

Check the capability before writing because Vercel does not expose normalized background stdin.
Check the capability before writing because Vercel and Ascii do not expose normalized background stdin.

```ts title="stdin.ts"
import { supports } from "@opencoredev/sandbox-sdk";
Expand Down
14 changes: 7 additions & 7 deletions apps/fumadocs/content/docs/api/sandboxes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ const sandbox = await createSandbox({

## Sandbox properties

| Property | Type | Description |
| -------------- | -------------------- | --------------------------------------------------- |
| `id` | `string` | Provider or adapter identifier for this sandbox. |
| `provider` | `ProviderName` | `local`, `e2b`, `daytona`, `vercel`, or `upstash`. |
| `cwd` | `string` | Normalized working directory. |
| `capabilities` | `CapabilityMap` | Supported operations and their modes. |
| `raw` | Provider-native type | Typed access to the underlying provider SDK object. |
| Property | Type | Description |
| -------------- | -------------------- | ----------------------------------------------------------- |
| `id` | `string` | Provider or adapter identifier for this sandbox. |
| `provider` | `ProviderName` | `local`, `e2b`, `daytona`, `vercel`, `upstash`, or `ascii`. |
| `cwd` | `string` | Normalized working directory. |
| `capabilities` | `CapabilityMap` | Supported operations and their modes. |
| `raw` | Provider-native type | Typed access to the underlying provider SDK object. |

## Stopping a sandbox

Expand Down
2 changes: 1 addition & 1 deletion apps/fumadocs/content/docs/api/snapshots.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ if (supports(sandbox, "snapshot.restore")) {
}
```

Only Local exposes normalized in-place restore. E2B and Vercel restore flows create new native sandboxes, so those operations remain on `sandbox.raw`. Daytona snapshot and fork behavior also remains provider-specific.
Only Local exposes normalized in-place restore. E2B and Vercel restore flows create new native sandboxes, so those operations remain on `sandbox.raw`. Daytona snapshot and fork behavior also remains provider-specific. Ascii captures a snapshot by archiving and resuming the Box; snapshot deletion and point-in-time restore remain on `sandbox.raw.api`.

## Read next

Expand Down
2 changes: 1 addition & 1 deletion apps/fumadocs/content/docs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Quickstart
description: Install Sandbox SDK, run a Local sandbox, and switch to a cloud provider.
---

Sandbox SDK uses one TypeScript API for Local, E2B, Daytona, Vercel Sandbox, and Upstash Box.
Sandbox SDK uses one TypeScript API for Local, E2B, Daytona, Vercel Sandbox, Upstash Box, and Ascii Box.

## Install

Expand Down
8 changes: 7 additions & 1 deletion apps/fumadocs/content/docs/integrations/eve.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Eve runs `bootstrap` once for a template identity. Each durable session starts f

## Choose a provider

<Tabs items={["Local", "E2B", "Daytona", "Vercel", "Upstash"]}>
<Tabs items={["Local", "E2B", "Daytona", "Vercel", "Upstash", "Ascii"]}>
<Tab value="Local">
```ts
import { local } from "@opencoredev/sandbox-sdk/local";
Expand Down Expand Up @@ -72,6 +72,12 @@ Eve runs `bootstrap` once for a template identity. Each durable session starts f
const backend = createEveSandboxBackend({ provider: upstash({ runtime: "node" }) });
```
</Tab>
<Tab value="Ascii">
```ts
import { ascii } from "@opencoredev/sandbox-sdk/ascii";
const backend = createEveSandboxBackend({ provider: ascii({ ttlSeconds: 3600 }) });
```
</Tab>
</Tabs>

The backend maps Eve seed files, filesystem methods, process streams, reconnect metadata, and shutdown. Network-policy changes throw an `unsupported` `SandboxError` when the selected provider cannot enforce them.
Expand Down
29 changes: 21 additions & 8 deletions apps/fumadocs/content/docs/integrations/mastra.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ bun add @opencoredev/sandbox-sdk @mastra/core

The Local provider is included. Install the native SDK only for the cloud provider you use.

| Provider | Additional package |
| -------------- | ------------------ |
| Local | None |
| E2B | `e2b` |
| Daytona | `@daytona/sdk` |
| Vercel Sandbox | `@vercel/sandbox` |
| Upstash Box | `@upstash/box` |
| Provider | Additional package |
| -------------- | ------------------- |
| Local | None |
| E2B | `e2b` |
| Daytona | `@daytona/sdk` |
| Vercel Sandbox | `@vercel/sandbox` |
| Upstash Box | `@upstash/box` |
| Ascii Box | `@asciidev/box-sdk` |

Configure the provider's credentials as described in its [provider guide](/docs/providers). The agent example below also expects `OPENAI_API_KEY` for its selected model.

Expand Down Expand Up @@ -76,7 +77,7 @@ The adapter normalizes Mastra's workspace contract once. Switching providers cha

Every supported provider uses the same `createMastraWorkspace()` factory.

<Tabs items={["Local", "E2B", "Daytona", "Vercel", "Upstash"]}>
<Tabs items={["Local", "E2B", "Daytona", "Vercel", "Upstash", "Ascii"]}>
<Tab value="Local">
```ts
import { createMastraWorkspace } from "@opencoredev/sandbox-sdk/mastra";
Expand Down Expand Up @@ -140,6 +141,18 @@ Every supported provider uses the same `createMastraWorkspace()` factory.
Set `UPSTASH_BOX_API_KEY` before starting the agent.

</Tab>
<Tab value="Ascii">
```ts
import { createMastraWorkspace } from "@opencoredev/sandbox-sdk/mastra";
import { ascii } from "@opencoredev/sandbox-sdk/ascii";

export const workspace = createMastraWorkspace({
provider: ascii({ ttlSeconds: 3600 }),
});
```
Set `BOX_API_KEY` before starting the agent.

</Tab>
</Tabs>

Provider capability differences still apply. Check the exact process, stdin, cancellation, port, and persistence modes in [Compatibility](/docs/reference/compatibility).
Expand Down
104 changes: 104 additions & 0 deletions apps/fumadocs/content/docs/providers/ascii.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
---
title: Ascii Box
description: Run Ascii cloud computers through the normalized SDK API.
icon: ascii
---

Ascii Box provides persistent cloud computers with files, commands, detached processes, protected previews, snapshots, desktop streaming, SSH, and native agent workflows.

## Installation

```bash title="Terminal"
bun add @opencoredev/sandbox-sdk @asciidev/box-sdk
```

## Authentication

Create an API key in the Box dashboard and set `BOX_API_KEY`, or pass `apiKey` to `ascii()`. Set `BOX_BASE_URL` only when targeting a non-production Box API.

## Run a command

```ts title="ascii.ts"
import { withSandbox } from "@opencoredev/sandbox-sdk";
import { ascii } from "@opencoredev/sandbox-sdk/ascii";

await withSandbox({ provider: ascii({ ttlSeconds: 600 }) }, async (sandbox) => {
const result = await sandbox.run("node --version");
console.log(result.stdout);
});
```

The Box command API preserves separate stdout and stderr streams. Foreground commands are limited to 60 seconds; use `sandbox.processes.start()` for longer work.

## Run an agent

Export one provider instance and pass it to [AI SDK](/docs/integrations/ai-sdk), [HarnessAgent](/docs/integrations/ai-sdk-harness), [Eve](/docs/integrations/eve), or [Mastra](/docs/integrations/mastra).

```ts title="agent-provider.ts"
import { ascii } from "@opencoredev/sandbox-sdk/ascii";

export const agentSandboxProvider = ascii({ ttlSeconds: 3600 });
```

Managed sessions archive the native Box when stopped and resume its persistent filesystem later. Destroying the session deletes the Box.

## Files and processes

Ascii's file and command endpoints use paths relative to the Box work directory. Sandbox SDK maps that directory to the sandbox's virtual working directory, `/workspace` by default.

```ts title="workspace.ts"
await sandbox.files.mkdir("output");
await sandbox.files.write("output/result.txt", "ready\n");

const process = await sandbox.processes.start("bun run dev");
for await (const event of process.output()) {
console.log(event.stream, event.data);
}
```

Background processes are detached inside the Box. Their stdout, stderr, and exit status are persisted under `.sandbox-sdk/processes` so callers can stream output, wait, inspect status, and send signals. Normalized stdin is not available.

## Ports

Box previews are protected by default. The adapter removes `_token` from the returned URL and retains it inside `preview.request()` so serialization does not leak the credential. On server runtimes, `request()` also completes Box's same-origin cookie redirect because native `fetch` does not provide a cookie jar.

```ts title="preview.ts"
const preview = await sandbox.ports.expose(3000);
const response = await preview.request?.("/health");
```

Pass `public: true` to `ascii()` only when the service is safe to expose without Box authentication.

## Snapshots and lifecycle

Ascii creates filesystem snapshots while archiving. `sandbox.snapshots.create()` archives the Box, waits for a new completed snapshot, then resumes the same Box. Snapshot deletion and point-in-time restoration are not exposed by Box v1 and remain unsupported on the normalized surface. Snapshot download and tree APIs remain typed on `sandbox.raw.api`.

`sandbox.stop()` deletes the Box because it is the normalized cleanup operation. If Box requires a recent safety snapshot before deletion, the adapter archives the Box, waits for the new snapshot, and retries deletion. Managed integration `stop()` calls archive instead, allowing the session to resume.

## Options

| Option | Type | Default | Behavior |
| ---------------- | ---------------- | ---------------------------- | ---------------------------------------------- |
| `apiKey` | `string` | `BOX_API_KEY` | Authenticates Box v1 requests. |
| `baseUrl` | `string` | `BOX_BASE_URL` or production | Selects the Box v1 API endpoint. |
| `ttlSeconds` | `number \| null` | Provider default | Configures automatic archival. |
| `noEnv` | `boolean` | `false` | Withholds account secrets and credentials. |
| `public` | `boolean` | `false` | Creates public rather than protected previews. |
| `readyTimeoutMs` | `number` | `300000` | Bounds provisioning and lifecycle waits. |
| `pollIntervalMs` | `number` | `1000` | Controls lifecycle and process polling. |
| `configuration` | `object` | `{}` | Adds official SDK fetch configuration. |

## Native API

```ts title="native.ts"
const box = await sandbox.raw.get();
const snapshots = await sandbox.raw.api.listBoxSnapshots({
boxId: sandbox.raw.id,
});
```

Prompting Codex or Claude Code, event streaming, desktop access, SSH keys, repository selection, forks, and snapshot downloads are provider-specific and remain available through the official `BoxApi` on `sandbox.raw.api`.

## Read next

See [Box's TypeScript SDK guide](https://docs.ascii.dev/box/sdks/typescript), compare exact modes in [Compatibility](/docs/reference/compatibility), or connect Ascii to [Mastra](/docs/integrations/mastra).
1 change: 1 addition & 0 deletions apps/fumadocs/content/docs/providers/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Every provider supports files, foreground commands, background processes, stream
| [Daytona](/docs/providers/daytona) | Persistent workspaces, GPUs | Linux workspace | Persistent | Public or authenticated | Native API |
| [Vercel Sandbox](/docs/providers/vercel) | Vercel workloads and previews | Linux sandbox | Optional | Public | Filesystem |
| [Upstash Box](/docs/providers/upstash) | Durable serverless boxes | Linux container | Persistent | Public or bearer token | Filesystem |
| [Ascii Box](/docs/providers/ascii) | Agents and durable workspaces | Cloud computer | Persistent | Protected or public | Archive filesystem |

Optional semantics differ. Check the generated [compatibility matrix](/docs/reference/compatibility) before depending on stdin, restore, resume, networking, GPUs, or a custom image.

Expand Down
2 changes: 1 addition & 1 deletion apps/fumadocs/content/docs/providers/meta.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"title": "Providers",
"icon": "providers",
"pages": ["index", "local", "e2b", "daytona", "vercel", "upstash"]
"pages": ["index", "local", "e2b", "daytona", "vercel", "upstash", "ascii"]
}
1 change: 1 addition & 0 deletions apps/fumadocs/content/docs/reference/compatibility.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ The matrix is generated from the same capability declarations exported by the ad
- Vercel and E2B snapshots create provider-native artifacts, but restore creates a new native sandbox and stays on `raw`.
- Daytona persistence, PTYs, networking, images, and GPUs are provider-native capabilities beyond the normalized core.
- Upstash Box provides durable filesystems, pause and resume, network policies, and public or bearer-token URLs; snapshot restore creates a new native Box.
- Ascii Box provides a persistent cloud computer, protected or public previews, detached cancellable processes, and archive/resume. Snapshot capture archives and resumes the Box; deletion and point-in-time restore remain provider-native.

## Read next

Expand Down
1 change: 1 addition & 0 deletions apps/fumadocs/content/docs/reference/package-exports.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { e2b } from "@opencoredev/sandbox-sdk/e2b";
import { daytona } from "@opencoredev/sandbox-sdk/daytona";
import { vercel } from "@opencoredev/sandbox-sdk/vercel";
import { upstash } from "@opencoredev/sandbox-sdk/upstash";
import { ascii } from "@opencoredev/sandbox-sdk/ascii";
```

Each adapter export includes its options type, native sandbox type, and capability declaration.
Expand Down
6 changes: 3 additions & 3 deletions apps/fumadocs/src/app/(home)/partners/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ export default function PartnersPage() {
<article className="prose mt-12 max-w-3xl">
<h2>What we maintain</h2>
<p>
OpenCore maintains five integrations: Local, E2B, Daytona, Vercel Sandbox and Upstash Box.
Local is powered by AgentOS under the hood. The unified API covers files, commands,
processes, ports, capabilities, errors, cleanup and typed native access.
OpenCore maintains six integrations: Local, E2B, Daytona, Vercel Sandbox, Upstash Box and
Ascii Box. Local is powered by AgentOS under the hood. The unified API covers files,
commands, processes, ports, capabilities, errors, cleanup and typed native access.
</p>

<h2>Continuous compatibility testing</h2>
Expand Down
1 change: 1 addition & 0 deletions apps/fumadocs/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const metadata: Metadata = {
"Daytona",
"Vercel Sandbox",
"Upstash Box",
"Ascii Box",
],
alternates: { canonical: "/" },
openGraph: {
Expand Down
3 changes: 3 additions & 0 deletions apps/fumadocs/src/components/docs-icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export function ProviderLogo({ id, ...props }: IconProps & { id: string }) {
return <VercelLogo {...props} />;
case "upstash":
return <UpstashLogo {...props} />;
case "ascii":
return <HugeiconsIcon icon={ServerStack01Icon} className={props.className} />;
default:
return <HugeiconsIcon icon={ServerStack01Icon} className={props.className} />;
}
Expand All @@ -42,6 +44,7 @@ export function resolveDocsIcon(icon: string | undefined): ReactNode {
case "daytona":
case "vercel":
case "upstash":
case "ascii":
return <ProviderLogo id={icon} />;
case "integrations":
return <HugeiconsIcon icon={PlugSocketIcon} />;
Expand Down
Loading