# Sandbox
URL: /docs/core/api-reference/sandbox

The main client — sandbox(), resume(), restoreSnapshot(), connect(), and sandboxes management.



```ts
import { Sandbox } from "@alineo-labs/sandbox";
```

## Constructor [#constructor]

```ts
new Sandbox(options: SandboxClientOptions)
```

### SandboxClientOptions [#sandboxclientoptions]

| Option             | Type               | Required | Description                                                                                                                                            |
| ------------------ | ------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `baseUrl`          | `string`           | Yes      | OpenSandbox server URL, e.g. `"http://localhost:8080"`                                                                                                 |
| `apiKey`           | `string`           | No       | OpenSandbox API key. Empty string for local dev with no auth.                                                                                          |
| `adapter`          | `IStorageAdapter`  | Yes      | Storage adapter for the run ledger                                                                                                                     |
| `maxConcurrency`   | `number`           | No       | Max simultaneous active sandboxes. Omit for no limit.                                                                                                  |
| `useServerProxy`   | `boolean`          | No       | Route execd and proxy traffic through the server. Required when the server runs in Docker via `alineo init`. Defaults to `false`.                      |
| `credentialBroker` | `CredentialBroker` | No       | Backend for `sb.credentials.*`. Defaults to `OpenSandboxCredentialBroker` (`@alineo-labs/vault`) — see [Credentials](/docs/core/concepts/credentials). |

```ts
const client = new Sandbox({
  baseUrl: process.env.OPEN_SANDBOX_URL ?? "http://localhost:8080",
  apiKey: process.env.OPEN_SANDBOX_API_KEY ?? "",
  adapter: new SQLiteAdapter("./ledger.db"),
  maxConcurrency: 10,
});
```

## Methods [#methods]

### sandbox() [#sandbox]

```ts
await client.sandbox(opts: SandboxOptions): Promise<SandboxHandle>
```

Creates a container, waits until it reaches `Running` state, and returns a live `SandboxHandle` object. Writes a `sandbox.created` event to the ledger.

If `maxConcurrency` is set, awaits a slot before creating the container. The slot is released when `sb.close()` is called.

See [Sandboxes](/docs/core/concepts/sandboxes) for `SandboxOptions` reference.

```ts
const sb = await client.sandbox({
  image: "ubuntu:22.04",
  resources: { cpu: "500m", memory: "512Mi" },
  name: "my-run",
});
try {
  await sb.exec("echo hello").pipe(process.stdout);
} finally {
  await sb.close();
}
```

### resume() [#resume]

```ts
await client.resume(
  sandboxId: string,
  opts?: { tag?: string; resolveCredential?: CredentialResolver },
): Promise<SandboxHandle>
```

Restores a sandbox session from its last checkpoint (or the checkpoint matching `opts.tag`, if given):

1. Reads the ledger to find the last `sandbox.checkpoint_created` event (or the last one matching `opts.tag`)
2. Creates a new container from the snapshot
3. Populates a replay cache from execs that completed before the checkpoint
4. Re-registers any credentials the sandbox had bound (see [Credentials](/docs/core/concepts/credentials)) — `opts.resolveCredential` supplies values that can't be re-derived automatically
5. Returns a `SandboxHandle` — pre-checkpoint execs return cached results; later execs run live

Throws `SandboxClientError` (404) if the session is not found or has no matching checkpoint. Throws `SandboxError` if a bound credential can't be resolved.

```ts
const sbResume = await client.resume(originalSandboxId);
try {
  await sbResume.exec("pip install -q requests").pipe(process.stdout); // replayed
  await sbResume.exec("python3 script.py").pipe(process.stdout); // live
} finally {
  await sbResume.close();
}

// Resume from a specific named checkpoint instead of the most recent one:
const sbTagged = await client.resume(originalSandboxId, { tag: "after-apt" });
```

### restoreSnapshot() [#restoresnapshot]

```ts
await client.restoreSnapshot(
  snapshotId: string,
  name: string,
  resources: { cpu: string; memory: string; gpu?: string },
): Promise<SandboxHandle>
```

Creates a fresh sandbox from a snapshot ID **without** exec replay — unlike `resume()`, the new sandbox starts with a clean exec history; nothing from the ledger is replayed. Use this when you want to restore a checkpointed environment and run new commands from scratch, rather than continue exactly where the checkpoint left off.

This is also what `sb.fork()` uses under the hood — see [Forking sandboxes](/docs/core/concepts/forking) for the relationship between `checkpoint()`, `fork()`, `resume()`, and `restoreSnapshot()`.

```ts
const snapshotId = await sb.checkpoint();
await sb.close();

// Later — restore and run fresh commands:
const sb2 = await client.restoreSnapshot(snapshotId, "my-sandbox", {
  cpu: "500m",
  memory: "256Mi",
});
await sb2.exec("npm test");
await sb2.close();
```

### connect() [#connect]

```ts
await client.connect(
  sandboxId: string,
  name: string,
  opts?: { resources?: { cpu: string; memory: string; gpu?: string } },
): Promise<SandboxHandle>
```

Attaches to an already-`Running` sandbox by ID, no snapshot or ledger replay involved — the container must already be running (throws `SandboxClientError` (409) otherwise). Use this to reconnect to a live sandbox created outside the current process, e.g. from a saved `sandboxId`.

`opts.resources` is only needed if you intend to call `.fork()` on the returned `SandboxHandle` afterwards — the control API doesn't echo back a running sandbox's own resource limits, so there's no way to discover them here; without it, `.fork()` is unavailable on the returned object.

```ts
// In a new process, reconnect to a sandbox started earlier:
const sb = await client.connect(savedSandboxId, "my-sandbox");
const { stdout } = await sb.exec("cat /results.txt");
await sb.close();
```

### sandboxes [#sandboxes]

```ts
client.sandboxes: {
  list(opts?: ListSandboxOptions): Promise<SandboxDetails[]>
  listByName(name: string, opts?: ListSandboxOptions): Promise<SandboxDetails[]>
  get(name: string, sandboxId: string): Promise<SandboxDetails | null>
  delete(name: string, sandboxId: string): Promise<void>
}
```

Access to the ledger's session history.

```ts
// List all sessions, newest first
const all = await client.sandboxes.list();

// Filter
const running = await client.sandboxes.list({ status: SandboxStatus.Running, limit: 20 });

// By name
const named = await client.sandboxes.listByName("my-ci-job");

// Single session
const session = await client.sandboxes.get("my-job", sandboxId);

// Delete
await client.sandboxes.delete("my-job", sandboxId);
```

### ListSandboxOptions [#listsandboxoptions]

| Option   | Type            | Description                                                  |
| -------- | --------------- | ------------------------------------------------------------ |
| `status` | `SandboxStatus` | Filter by status: `"running"` or `"completed"`               |
| `limit`  | `number`        | Max results to return                                        |
| `before` | `number`        | Return only sessions started before this Unix timestamp (ms) |

## SandboxHandle class [#sandboxhandle-class]

See [SandboxHandle](#sandboxhandle-class) below for the object returned by `sandbox()` and `resume()`.

### SandboxHandle methods [#sandboxhandle-methods]

| Method                            | Returns                               | Description                                           |
| --------------------------------- | ------------------------------------- | ----------------------------------------------------- |
| `sb.exec(cmd, opts?)`             | `ExecHandle`                          | Run a shell command                                   |
| `sb.execCode(code, opts?)`        | `ExecHandle`                          | Run code via the interpreter                          |
| `sb.proxy(port)`                  | `Promise<{ url, headers }>`           | Get a proxied URL for an in-sandbox port              |
| `sb.metrics()`                    | `Promise<{ cpu, memory, timestamp }>` | Current CPU and memory usage                          |
| `sb.writeFile(path, content)`     | `Promise<void>`                       | Write a UTF-8 file into the container                 |
| `sb.readFile(path)`               | `Promise<string>`                     | Read a file from the container as a string            |
| `sb.moveFile(from, to)`           | `Promise<void>`                       | Move or rename a file                                 |
| `sb.deleteFile(path)`             | `Promise<void>`                       | Delete a file                                         |
| `sb.createDirectory(path)`        | `Promise<void>`                       | Create a directory (and parents)                      |
| `sb.deleteDirectory(path)`        | `Promise<void>`                       | Delete a directory                                    |
| `sb.getFileInfo(path)`            | `Promise<FileInfo>`                   | File metadata: size, type, mode, timestamps           |
| `sb.replaceInFiles(replacements)` | `Promise<void>`                       | In-place substring replacement across files           |
| `sb.transfer(path, target)`       | `Promise<void>`                       | Copy a file to another `SandboxHandle` instance       |
| `sb.searchFiles(pattern, path?)`  | `Promise<string[]>`                   | Search for files matching a glob                      |
| `sb.listDirectory(path, opts?)`   | `Promise<FileInfo[]>`                 | List directory entries with metadata                  |
| `sb.checkpoint(name?)`            | `Promise<string>`                     | Snapshot the container state, returns the snapshot ID |
| `sb.listCheckpoints()`            | `Promise<CheckpointInfo[]>`           | All checkpoints for this sandbox                      |
| `sb.fork(tag?, runId?, opts?)`    | `Promise<SandboxHandle>`              | Snapshot and return an independent copy               |
| `sb.close()`                      | `Promise<void>`                       | Delete the container and release resources            |

### sb.credentials [#sbcredentials]

```ts
sb.credentials: {
  set(name: string, value: string, binding: CredentialBinding, source?: CredentialSource): Promise<void>
  patch(name: string, changes: Partial<{ value: string; binding: CredentialBinding }>): Promise<void>
  remove(name: string): Promise<void>
  listBindings(): Promise<Array<{ name: string; binding: CredentialBinding }>>
}
```

Register, update, remove, and list credentials injected into this sandbox's outbound requests — requires the sandbox to have been created with `credentialProxy: true`. See [Credentials](/docs/core/concepts/credentials).

### SandboxHandle properties [#sandboxhandle-properties]

| Property       | Type     | Description                          |
| -------------- | -------- | ------------------------------------ |
| `sb.sandboxId` | `string` | OpenSandbox container ID             |
| `sb.name`      | `string` | User-provided name or auto-generated |
