Skip to content

Latest commit

 

History

History
342 lines (255 loc) · 9.22 KB

File metadata and controls

342 lines (255 loc) · 9.22 KB
title Interactive terminal (PTY)
sidebarTitle Interactive terminal

The PTY (pseudo-terminal) module allows you to create interactive terminal sessions in the sandbox with real-time, bidirectional communication.

Unlike commands.run() which executes a command and returns output after completion, PTY provides:

  • Real-time streaming - Output is streamed as it happens via callbacks
  • Bidirectional input - Send input while the terminal is running
  • Interactive shell - Full terminal support with ANSI colors and escape sequences
  • Session persistence - Disconnect and reconnect to running sessions

Create a PTY session

Use sandbox.pty.create() to start an interactive bash shell.

```js JavaScript & TypeScript import { Sandbox } from '@e2b/code-interpreter'

const sandbox = await Sandbox.create()

const terminal = await sandbox.pty.create({ cols: 80, // Terminal width in characters rows: 24, // Terminal height in characters onData: (data) => { // Called whenever terminal outputs data process.stdout.write(data) }, envs: { MY_VAR: 'hello' }, // Optional environment variables cwd: '/home/user', // Optional working directory user: 'root', // Optional user to run as })

// terminal.pid contains the process ID console.log('Terminal PID:', terminal.pid)


```python Python
from e2b_code_interpreter import Sandbox

sandbox = Sandbox()

terminal = sandbox.pty.create(
    cols=80,              # Terminal width in characters
    rows=24,              # Terminal height in characters
    on_data=lambda data: print(data.decode(), end=''),  # end='' prevents print from adding extra newline
    envs={'MY_VAR': 'hello'},  # Optional environment variables
    cwd='/home/user',          # Optional working directory
    user='root',               # Optional user to run as
)

# terminal.pid contains the process ID
print('Terminal PID:', terminal.pid)
The PTY runs an interactive bash shell with `TERM=xterm-256color`, which supports ANSI colors and escape sequences.

Timeout

PTY sessions have a configurable timeout that controls the session duration. The default is 60 seconds. For interactive or long-running sessions, set timeoutMs: 0 (JavaScript) or timeout=0 (Python) to keep the session open indefinitely.

```js JavaScript & TypeScript import { Sandbox } from '@e2b/code-interpreter'

const sandbox = await Sandbox.create()

const terminal = await sandbox.pty.create({ cols: 80, rows: 24, onData: (data) => process.stdout.write(data), timeoutMs: 0, // Keep the session open indefinitely })


```python Python
from e2b_code_interpreter import Sandbox

sandbox = Sandbox()

# end='' prevents print() from adding an extra newline
# (PTY output already contains newlines)
terminal = sandbox.pty.create(
    cols=80,
    rows=24,
    on_data=lambda data: print(data.decode(), end=''),
    timeout=0,  # Keep the session open indefinitely
)

Send input to PTY

Use sendInput() in JavaScript or send_stdin() in Python to send data to the terminal. These methods return a Promise (JavaScript) or complete synchronously (Python) - the actual output will be delivered to your onData callback.

```js JavaScript & TypeScript import { Sandbox } from '@e2b/code-interpreter'

const sandbox = await Sandbox.create()

const terminal = await sandbox.pty.create({ cols: 80, rows: 24, onData: (data) => process.stdout.write(data), })

// Send a command (don't forget the newline!) await sandbox.pty.sendInput( terminal.pid, new TextEncoder().encode('echo "Hello from PTY"\n') )


```python Python
from e2b_code_interpreter import Sandbox

sandbox = Sandbox()

terminal = sandbox.pty.create(
    cols=80,
    rows=24,
    on_data=lambda data: print(data.decode(), end=''),  # end='' prevents extra newline
)

# Send a command as bytes (b'...' is Python's byte string syntax)
# Don't forget the newline!
sandbox.pty.send_stdin(terminal.pid, b'echo "Hello from PTY"\n')

Resize the terminal

When the user's terminal window changes size, notify the PTY with resize(). The cols and rows parameters are measured in characters, not pixels.

```js JavaScript & TypeScript import { Sandbox } from '@e2b/code-interpreter'

const sandbox = await Sandbox.create()

const terminal = await sandbox.pty.create({ cols: 80, rows: 24, onData: (data) => process.stdout.write(data), })

// Resize to new dimensions (in characters) await sandbox.pty.resize(terminal.pid, { cols: 120, rows: 40, })


```python Python
from e2b_code_interpreter import Sandbox

sandbox = Sandbox()

terminal = sandbox.pty.create(
    cols=80,
    rows=24,
    on_data=lambda data: print(data.decode(), end=''),  # end='' prevents extra newline
)

# Resize to new dimensions (in characters)
sandbox.pty.resize(terminal.pid, cols=120, rows=40)

Disconnect and reconnect

You can disconnect from a PTY session while keeping it running, then reconnect later with a new data handler. This is useful for:

  • Resuming terminal sessions after network interruptions
  • Sharing terminal access between multiple clients
  • Implementing terminal session persistence
```js JavaScript & TypeScript import { Sandbox } from '@e2b/code-interpreter'

const sandbox = await Sandbox.create()

// Create a PTY session const terminal = await sandbox.pty.create({ cols: 80, rows: 24, onData: (data) => console.log('Handler 1:', new TextDecoder().decode(data)), })

const pid = terminal.pid

// Send a command await sandbox.pty.sendInput(pid, new TextEncoder().encode('echo hello\n'))

// Disconnect - PTY keeps running in the background await terminal.disconnect()

// Later: reconnect with a new data handler const reconnected = await sandbox.pty.connect(pid, { onData: (data) => console.log('Handler 2:', new TextDecoder().decode(data)), })

// Continue using the session await sandbox.pty.sendInput(pid, new TextEncoder().encode('echo world\n'))

// Wait for the terminal to exit await reconnected.wait()


```python Python
import time
from e2b_code_interpreter import Sandbox

sandbox = Sandbox()

# Create a PTY session
terminal = sandbox.pty.create(
    cols=80,
    rows=24,
    on_data=lambda data: print('Handler 1:', data.decode()),
)

pid = terminal.pid

# Send a command
sandbox.pty.send_stdin(pid, b'echo hello\n')
time.sleep(0.5)

# Disconnect - PTY keeps running in the background
terminal.disconnect()

# Later: reconnect with a new data handler
reconnected = sandbox.pty.connect(
    pid,
    on_data=lambda data: print('Handler 2:', data.decode()),
)

# Continue using the session
sandbox.pty.send_stdin(pid, b'echo world\n')

# Wait for the terminal to exit
reconnected.wait()

Kill the PTY

Terminate the PTY session with kill().

```js JavaScript & TypeScript import { Sandbox } from '@e2b/code-interpreter'

const sandbox = await Sandbox.create()

const terminal = await sandbox.pty.create({ cols: 80, rows: 24, onData: (data) => process.stdout.write(data), })

// Kill the PTY const killed = await sandbox.pty.kill(terminal.pid) console.log('Killed:', killed) // true if successful

// Or use the handle method // await terminal.kill()


```python Python
from e2b_code_interpreter import Sandbox

sandbox = Sandbox()

terminal = sandbox.pty.create(
    cols=80,
    rows=24,
    on_data=lambda data: print(data.decode(), end=''),  # end='' prevents extra newline
)

# Kill the PTY
killed = sandbox.pty.kill(terminal.pid)
print('Killed:', killed)  # True if successful

# Or use the handle method
# terminal.kill()

Wait for PTY to exit

Use wait() to wait for the terminal session to end (e.g., when the user types exit).

```js JavaScript & TypeScript import { Sandbox } from '@e2b/code-interpreter'

const sandbox = await Sandbox.create()

const terminal = await sandbox.pty.create({ cols: 80, rows: 24, onData: (data) => process.stdout.write(data), })

// Send exit command await sandbox.pty.sendInput(terminal.pid, new TextEncoder().encode('exit\n'))

// Wait for the terminal to exit const result = await terminal.wait() console.log('Exit code:', result.exitCode)


```python Python
from e2b_code_interpreter import Sandbox

sandbox = Sandbox()

terminal = sandbox.pty.create(
    cols=80,
    rows=24,
    on_data=lambda data: print(data.decode(), end=''),  # end='' prevents extra newline
)

# Send exit command
sandbox.pty.send_stdin(terminal.pid, b'exit\n')

# Wait for the terminal to exit
result = terminal.wait()
print('Exit code:', result.exit_code)

Interactive terminal (SSH-like)

Building a fully interactive terminal (like SSH) requires handling raw mode, stdin forwarding, and terminal resize events. For a production implementation, see the E2B CLI source code which uses the same sandbox.pty API documented above.