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

# PTY

> TypeScript SDK reference for sandbox.pty — create and drive interactive pseudo-terminals inside the sandbox.

The TypeScript SDK exposes PTY support through `sandbox.pty`. The module
has three callables you'll use directly: `pty.create()` to start a new
session, `pty.connect()` to reattach to an existing one, and the
low-level `pty.sendStdin / resize / kill` trio when you already hold
a `pid`.

For conceptual background see the
[PTY feature overview](/features/pty).

## `sandbox.pty.create(opts?)` → `Promise<PtyHandle>`

Create a new PTY session. The sandbox spawns an interactive `bash -l`
login shell with `TERM=xterm-256color` pre-set.

```typescript theme={null}
const handle = await sandbox.pty.create({
  size: { cols: 120, rows: 30 },
  user: "user",
  cwd: "/workspace",
  envs: { FOO: "bar" },
  timeout: 3600,            // seconds; 0 = indefinite
  onData: (bytes) => process.stdout.write(bytes),
});
```

### `PtyCreateOpts`

| Field            | Type                         | Default                  | Description                                                                               |
| ---------------- | ---------------------------- | ------------------------ | ----------------------------------------------------------------------------------------- |
| `size`           | `PtySize`                    | `{ cols: 80, rows: 24 }` | Initial terminal size.                                                                    |
| `user`           | `string`                     | `"user"`                 | User the shell runs as.                                                                   |
| `cwd`            | `string`                     | `undefined`              | Starting working directory.                                                               |
| `envs`           | `Record<string, string>`     | `undefined`              | Environment variables merged into the shell env. `TERM` defaults to `xterm-256color`.     |
| `timeout`        | `number`                     | `3600`                   | PTY session TTL in seconds. `0` keeps the session alive until the sandbox itself expires. |
| `onData`         | `(data: Uint8Array) => void` | `undefined`              | If provided, the handle auto-opens the output stream and invokes this for each chunk.     |
| `requestTimeout` | `number`                     | `undefined`              | Per-request timeout in milliseconds for the create POST.                                  |

## `sandbox.pty.connect(pid, opts?)` → `PtyHandle`

Reattach to a PTY session that's already running. Returns a fresh
`PtyHandle` that streams live output from the moment it connects.
Multiple clients can be attached to the same pid concurrently.

```typescript theme={null}
const handle = sandbox.pty.connect(pid, {
  onData: (bytes) => term.write(bytes),  // e.g. forward to xterm.js
});
```

### `PtyConnectOpts`

| Field    | Type                         | Description                                                                                                 |
| -------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `onData` | `(data: Uint8Array) => void` | Optional callback invoked with every output chunk. Omit to drive the stream manually via `handle.stream()`. |

## `PtyHandle`

Returned by both `create()` and `connect()`.

### Properties

* `handle.pid: number` — remote process id.

### Methods

#### `handle.sendInput(data: Uint8Array | string, requestTimeout?: number): Promise<void>`

Forward input to the shell. Strings are UTF-8 encoded.

```typescript theme={null}
await handle.sendInput("echo hello\n");
await handle.sendInput(new Uint8Array([0x03]));  // Ctrl-C
```

#### `handle.resize(size: PtySize, requestTimeout?: number): Promise<void>`

Change the remote terminal dimensions. Fires `SIGWINCH` inside the
sandbox so ncurses apps redraw.

#### `handle.disconnect(): void`

Stop consuming output **without killing the remote process**. A later
`sandbox.pty.connect(pid)` reattaches cleanly.

#### `handle.kill(requestTimeout?: number): Promise<boolean>`

Terminate the remote shell. Returns `true` if the session existed at
the time of the call.

#### `handle.wait(): Promise<PtyResult>`

Resolves when the remote shell exits.

#### `handle.stream(): AsyncGenerator<Uint8Array>`

Async iterator over raw output chunks — for when you want to drive the
stream manually instead of via `onData`:

```typescript theme={null}
for await (const chunk of handle.stream()) {
  term.write(chunk);
}
```

Don't mix `onData` and `stream()` on the same handle; they consume the
same underlying connection.

## `PtyResult`

```typescript theme={null}
interface PtyResult {
  exitCode: number;   // -1 if the stream dropped without a clean exit frame
}
```

## Low-level API (by pid)

When you don't hold a `PtyHandle`, use the module-level methods:

```typescript theme={null}
await sandbox.pty.sendStdin(pid, data);     // Uint8Array | string
await sandbox.pty.resize(pid, { cols, rows });
await sandbox.pty.kill(pid);                // → boolean
```

## Example: wire a sandbox PTY into xterm.js

```typescript theme={null}
import { Terminal } from "@xterm/xterm";
import { FitAddon } from "@xterm/addon-fit";
import { Sandbox } from "@declaw/sdk";

const term = new Terminal({ cursorBlink: true });
const fit = new FitAddon();
term.loadAddon(fit);
term.open(document.getElementById("terminal")!);
fit.fit();

const sbx = await Sandbox.create();
const handle = await sbx.pty.create({
  size: { cols: term.cols, rows: term.rows },
  onData: (bytes) => term.write(bytes),
});

// keystrokes → sandbox PTY
term.onData((d) => handle.sendInput(d));

// pane resize → TIOCSWINSZ
new ResizeObserver(() => {
  fit.fit();
  void handle.resize({ cols: term.cols, rows: term.rows });
}).observe(document.getElementById("terminal")!);
```

That's the full wiring for a browser terminal talking to a sandbox PTY —
every keystroke round-trips through `sendInput`, every output byte
comes back via `onData`, every pane resize fires `TIOCSWINSZ` inside
the sandbox.
