> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sailresearch.com/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript SDK

> The Sail TypeScript SDK for sailboxes, for Node and Bun agent harnesses

Sail ships a TypeScript SDK for sailboxes (`@sailresearch/sdk` on npm), built
for TS agent harnesses on **Node 22+** and **Bun**. It shares one engine with
the Python and [Rust](/rust-sdk) SDKs, so behavior matches across
languages. This page covers install and TypeScript-specific notes.

## Install

<CodeGroup>
  ```bash npm theme={null}
  npm install @sailresearch/sdk
  ```

  ```bash pnpm theme={null}
  pnpm add @sailresearch/sdk
  ```

  ```bash bun theme={null}
  bun add @sailresearch/sdk
  ```
</CodeGroup>

Prebuilt native binaries are published per platform (Linux, macOS, Windows) and
selected automatically at install time.

## Configure

Set `SAIL_API_KEY` in the environment; the SDK also
reads `~/.sail`. The object-model statics use this configuration by default, or
construct a `Client` explicitly with `Client.fromConfig({ apiKey })`.

## Quickstart

```ts theme={null}
import { App, Sailbox } from "@sailresearch/sdk";

// Look up (or create) the app your sandboxes belong to.
const app = await App.find("example-app", { mintIfMissing: true });

// Boot a sandbox (defaults to a Debian base image).
const sb = await Sailbox.create({ app, name: "worker-1" });

// Run a command and stream its output.
const proc = await sb.exec("echo hello && ls /");
for await (const chunk of proc.stdout) process.stdout.write(chunk);
const result = await proc.wait();
console.log("exit code:", result.exitCode);

// Move files.
await sb.write("/tmp/note.txt", "hi from the harness\n");
const contents = await sb.read("/tmp/note.txt");

// Expose a port and wait until it is routable.
await sb.expose(8080, "http");
const listener = await sb.waitForListener(8080);
if (listener.endpoint?.kind === "http") {
  console.log("reachable at:", listener.endpoint.url);
}

// Lifecycle: pause / sleep / resume / checkpoint / terminate.
await sb.terminate();
```

## Custom images

Use the fluent `Image` builder and pass it to `Sailbox.create`. Local files and
directories are hashed and uploaded for you when the sailbox is created.

```ts theme={null}
import { App, Image, Sailbox } from "@sailresearch/sdk";

const app = await App.find("example-app", { mintIfMissing: true });

const image = Image.debian("arm64")
  .aptInstall("git")
  .pipInstall("numpy")
  .addLocalDir("./app", "/app", { ignore: ["node_modules/", ".git/"] })
  .runCommand("pip install -e /app");

const sb = await Sailbox.create({ app, name: "worker", image });
```

## Surface

<Note>
  Voyages (agent tracing) and inference calls are currently Python-only; the
  TypeScript SDK covers the full sailbox surface. See the [Voyages
  reference](/voyages-sdk).
</Note>

* `Sailbox`: `create` / `get` / `list` / `listPage` / `fromCheckpoint`, and
  per-instance `exec`, `shell`, `read` / `write` / `writeStream` /
  `readStream`, `expose` / `unexpose` / `listeners` / `listener` /
  `waitForListener`, `ingressAuthHeaders`, `enableSsh`, and `terminate` /
  `pause` / `sleep` / `resume` / `checkpoint` / `upgrade`.
* `App`: `find` / `list`.
* `Volume`: `find` / `list`, and per-instance `delete`.
* `Image`: `debian` / `devbox`, `aptInstall` / `pipInstall` / `runCommand` / `env`,
  `addLocalFile` / `addLocalDir`, `build`, `toSpec` (`Sailbox.create` builds it
  for you).
* `Client`: the lower-level surface with the same operations.

## Errors

Everything the SDK throws extends `SailError`, so one
`catch (e) { if (e instanceof SailError) }` handles all of it; subclasses like
`NotFoundError` and `SailboxExecutionError` let you match specific failures. See
[Errors](/sailbox-sdk-errors) for the full hierarchy.

## API reference

For the complete listing of every class, method, parameter, and type, see the
[TypeScript SDK reference](/reference/typescript-sdk).
