Skip to main content
Use sandbox.pty for full interactive terminal sessions. PTY (pseudo-terminal) mode is useful for interactive shells, REPLs, and commands that require terminal features.

Creating a PTY Session

from moru import Sandbox

sandbox = Sandbox.create()

# Create a PTY session
handle = sandbox.pty.create(
    cols=80,
    rows=24,
    on_data=lambda data: print(data.decode(), end="")
)

# Send commands
handle.send_input("echo 'Hello from PTY'\n")
handle.send_input("ls -la\n")

# Wait a bit for output
import time
time.sleep(1)

# Kill the session
handle.kill()
sandbox.kill()

PTY Options

OptionTypeDescription
colsnumberTerminal width in columns
rowsnumberTerminal height in rows
on_data / onDatafunctionCallback for terminal output (bytes)
userstringUser to run as
envsobjectEnvironment variables
cwdstringWorking directory
timeout / timeoutMsnumberSession timeout

Starting with a Command

Start a PTY with a specific command instead of a shell:
# Start Python REPL in PTY
handle = sandbox.pty.start(
    "python3",
    cols=80,
    rows=24,
    on_data=lambda data: print(data.decode(), end="")
)

# Interact with Python
handle.send_input("print('Hello')\n")
handle.send_input("2 + 2\n")

Terminal Resize

Resize the terminal during a session:
handle = sandbox.pty.create(cols=80, rows=24, on_data=print)

# Later, resize the terminal
handle.resize(120, 40)  # New size: 120 columns x 40 rows

Interactive Shell Example

import sys
import tty
import termios

sandbox = Sandbox.create()

def on_output(data):
    sys.stdout.buffer.write(data)
    sys.stdout.flush()

handle = sandbox.pty.create(
    cols=80,
    rows=24,
    on_data=on_output
)

# Set terminal to raw mode
old_settings = termios.tcgetattr(sys.stdin)
try:
    tty.setraw(sys.stdin.fileno())

    # Read input and send to PTY
    while True:
        char = sys.stdin.read(1)
        if char == '\x03':  # Ctrl+C
            break
        handle.send_input(char)
finally:
    termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)
    handle.kill()
    sandbox.kill()

Vim/Editor Example

sandbox = Sandbox.create()

# Install vim if needed
sandbox.commands.run("apt-get update && apt-get install -y vim", user="root")

# Create a file to edit
sandbox.files.write("/home/user/test.py", "print('Hello')")

# Open vim in PTY
handle = sandbox.pty.start(
    "vim /home/user/test.py",
    cols=120,
    rows=40,
    on_data=lambda data: print(data.decode(), end="")
)

# Send vim commands
handle.send_input("i")  # Insert mode
handle.send_input("# Modified by PTY\n")
handle.send_input("\x1b")  # Escape
handle.send_input(":wq\n")  # Save and quit

handle.wait()

Environment Variables

handle = sandbox.pty.create(
    cols=80,
    rows=24,
    envs={
        "TERM": "xterm-256color",
        "EDITOR": "vim",
        "PS1": "moru> "
    },
    on_data=lambda data: print(data.decode(), end="")
)

When to Use PTY vs Regular Commands

Use PTY WhenUse Regular Commands When
Interactive shells (bash, zsh)Simple command execution
REPLs (python, node)Scripts and automation
Text editors (vim, nano)Background processes
Commands with progress barsGetting command output
Terminal UI applicationsStreaming logs

Next Steps