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

# Use interactive terminals

> Open and control interactive terminal sessions in a Devbox.

Use `terminal.open()` for programs that require a pseudo-terminal or interactive input. Read terminal output, write input, resize the terminal, and wait for it to exit.

<Info>
  Opening a terminal starts a stopped Devbox automatically. Unlike Namespace [Sessions](/docs/devbox/sessions), an SDK terminal is tied to its connection and does not persist for later reattachment.
</Info>

## `terminal.open()`

Open an interactive shell in the Devbox and control it through a `TerminalSession`.

### Example

Open a terminal, print its output, run a command, and wait for it to exit:

```typescript {2-4,6-7,9} theme={null}
const devbox = await client.devboxes.get("sdk-example");
const terminal = await devbox.terminal.open({
  columns: 120,
  rows: 40,
});
terminal.onData((data) => process.stdout.write(data));
terminal.write("pwd\n");
terminal.write("exit\n");
const { exitCode, signal } = await terminal.wait();
```

### API reference

```typescript theme={null}
terminal.open(options?: TerminalOpenOptions): Promise<TerminalSession>
```

#### Arguments and options

<ResponseField name="options" type="TerminalOpenOptions">
  Options used to open the terminal.

  <Expandable title="properties" defaultOpen>
    <ResponseField name="columns" type="number" default="80">
      The initial terminal width in columns.
    </ResponseField>

    <ResponseField name="rows" type="number" default="24">
      The initial terminal height in rows.
    </ResponseField>

    <ResponseField name="term" type="string" default="xterm-256color">
      The terminal type reported to the remote shell.
    </ResponseField>

    <ResponseField name="env" type="Record<string, string>">
      Environment variables requested for the terminal session.
    </ResponseField>

    <ResponseField name="signal" type="AbortSignal">
      Cancels terminal setup. If aborted after the terminal opens, the SDK closes the terminal.
    </ResponseField>

    <ResponseField name="timeoutMs" type="number">
      The timeout budget for activation, connection, and terminal setup. It does not limit the lifetime of an open terminal.
    </ResponseField>
  </Expandable>
</ResponseField>

#### Return value

`terminal.open()` resolves with a `TerminalSession`.

```typescript theme={null}
interface TerminalSession {
  write(data: string | Uint8Array): void;
  resize(columns: number, rows: number): void;
  close(): void;
  onData(listener: (data: Uint8Array) => void): () => void;
  onExit(listener: (exitCode: number | null, signal: string | null) => void): () => void;
  onError(listener: (error: Error) => void): () => void;
  wait(): Promise<{ exitCode: number | null; signal: string | null }>;
}
```

The methods on `TerminalSession` are documented below.

### More examples

#### Forward local input

Forward local terminal input to a remote shell and keep it open until the user types `exit`.

```typescript {2,4-5,8-10,13,17-21} theme={null}
const devbox = await client.devboxes.get("my-devbox");
const terminal = await devbox.terminal.open();

const forwardInput = (data: Buffer) => terminal.write(data);
const unsubscribe = terminal.onData((data) => process.stdout.write(data));

try {
  process.stdin.setRawMode(true);
  process.stdin.resume();
  process.stdin.on("data", forwardInput);

  // Wait until the remote shell ends, such as after the user types "exit".
  const result = await terminal.wait();

  process.exitCode = result.exitCode ?? 1;
} finally {
  process.stdin.off("data", forwardInput);
  process.stdin.pause();
  process.stdin.setRawMode(false);
  unsubscribe();
  terminal.close();
}
```

***

## `terminal.write()`

Send text or bytes to the terminal's standard input. Strings are written as provided, so include `\n` when submitting a command.

### Example

```typescript theme={null}
terminal.write("npm test\n");
```

### API reference

```typescript theme={null}
write(data: string | Uint8Array): void
```

#### Arguments and options

<ResponseField name="data" type="string | Uint8Array" required>
  Text or bytes to send to the terminal.
</ResponseField>

`write()` throws an `Error` if the terminal is already closed.

***

## `terminal.resize()`

Change the dimensions of the remote pseudo-terminal.

### Example

```typescript theme={null}
terminal.resize(160, 50);
```

### API reference

```typescript theme={null}
resize(columns: number, rows: number): void
```

#### Arguments and options

<ResponseField name="columns" type="number" required>
  The new terminal width in columns.
</ResponseField>

<ResponseField name="rows" type="number" required>
  The new terminal height in rows.
</ResponseField>

`resize()` throws an `Error` if the terminal is already closed.

***

## `terminal.close()`

Close the terminal locally. Calling `close()` more than once has no effect.

### Example

```typescript theme={null}
terminal.close();
```

### API reference

```typescript theme={null}
close(): void
```

#### Arguments and options

This method has no arguments or options.

Closing the terminal causes pending `wait()` calls to resolve when the underlying channel closes. A locally closed terminal reports a `null` exit code and signal.

***

## `terminal.onData()`

Subscribe to terminal output. Standard output and standard error are delivered through the same listener.

### Example

```typescript theme={null}
terminal.onData((data) => process.stdout.write(data));
```

### API reference

```typescript theme={null}
onData(listener: (data: Uint8Array) => void): () => void
```

#### Arguments and options

<ResponseField name="listener" type="(data: Uint8Array) => void" required>
  Called with each output chunk.
</ResponseField>

#### Return value

Returns a function that removes the listener.

### More examples

#### Stop listening for output

```typescript {1,5} theme={null}
const unsubscribe = terminal.onData((data) => process.stdout.write(data));
// Use the terminal while the listener receives output.

// Unsubscribe when done.
unsubscribe();
```

***

## `terminal.onExit()`

Subscribe to the terminal's exit event.

### Example

```typescript {1-4} theme={null}
const unsubscribe = terminal.onExit((code, signal) => {
  console.log({
    code,
    signal,
  });
});
```

### API reference

```typescript theme={null}
onExit(listener: (exitCode: number | null, signal: string | null) => void): () => void
```

#### Arguments and options

<ResponseField name="listener" type="(exitCode: number | null, signal: string | null) => void" required>
  Called when the terminal closes. Either value may be `null` when the remote side does not report it.
</ResponseField>

#### Return value

Returns a function that removes the listener.

***

## `terminal.onError()`

Subscribe to terminal transport errors.

### Example

```typescript theme={null}
const unsubscribe = terminal.onError((error) => console.error(error));
```

### API reference

```typescript theme={null}
onError(listener: (error: Error) => void): () => void
```

#### Arguments and options

<ResponseField name="listener" type="(error: Error) => void" required>
  Called when the terminal transport reports an error.
</ResponseField>

#### Return value

Returns a function that removes the listener.

***

## `terminal.wait()`

Wait for the terminal to close. Calling `wait()` after exit resolves immediately with the recorded result.

### Example

```typescript theme={null}
const { exitCode, signal } = await terminal.wait();
```

### API reference

```typescript theme={null}
wait(): Promise<{ exitCode: number | null; signal: string | null }>
```

#### Arguments and options

This method has no arguments or options.

#### Return value

<ResponseField name="exitCode" type="number | null" required>
  The remote shell's exit code, or `null` when no exit code is available.
</ResponseField>

<ResponseField name="signal" type="string | null" required>
  The signal that ended the remote shell, or `null` when no signal is available.
</ResponseField>

## Related documentation

<Columns cols={2}>
  <Card title="Run commands" icon="terminal" href="/docs/reference/typescript-sdk/commands">
    Run structured commands and shell scripts without an interactive terminal.
  </Card>

  <Card title="Handle errors and timeouts" icon="triangle-alert" href="/docs/reference/typescript-sdk/errors">
    Cancel operations and handle SDK failures.
  </Card>
</Columns>
