Skip to main content

Terminal

The Terminal interface provides low-level access to terminal operations including rendering, cursor control, and screen management.

Terminal Interface

Minimal terminal interface for TUI with input handling and screen control.
interface Terminal {
  // Lifecycle
  start(onInput: (data: string) => void, onResize: () => void): void;
  stop(): void;
  drainInput(maxMs?: number, idleMs?: number): Promise<void>;

  // Output
  write(data: string): void;

  // Dimensions
  get columns(): number;
  get rows(): number;

  // Keyboard protocol
  get kittyProtocolActive(): boolean;

  // Cursor control
  moveBy(lines: number): void;
  hideCursor(): void;
  showCursor(): void;

  // Clear operations
  clearLine(): void;
  clearFromCursor(): void;
  clearScreen(): void;

  // Title
  setTitle(title: string): void;
}

ProcessTerminal Class

Real terminal implementation using process.stdin/process.stdout.
class ProcessTerminal implements Terminal

Constructor

Creates a new ProcessTerminal instance.
const terminal = new ProcessTerminal();

Methods

start()

Starts the terminal with input and resize handlers.
onInput
(data: string) => void
required
Callback invoked when input data is received
onResize
() => void
required
Callback invoked when terminal is resized
terminal.start(
  (data) => console.log('Input:', data),
  () => console.log('Resized to', terminal.columns, 'x', terminal.rows)
);

stop()

Stops the terminal and restores previous state.
terminal.stop();

drainInput()

Drains stdin before exiting to prevent Kitty key release events from leaking to the parent shell over slow SSH connections.
maxMs
number
default:"1000"
Maximum time to drain in milliseconds
idleMs
number
default:"50"
Exit early if no input arrives within this time in milliseconds
await terminal.drainInput(1000, 50);

write()

Writes output to the terminal.
data
string
required
Data to write to terminal
terminal.write('\x1b[32mGreen text\x1b[0m\n');

moveBy()

Moves cursor up or down by N lines relative to current position.
lines
number
required
Number of lines to move. Positive moves down, negative moves up.
terminal.moveBy(-3);  // Move up 3 lines
terminal.moveBy(5);   // Move down 5 lines

hideCursor() / showCursor()

Controls cursor visibility.
terminal.hideCursor();
// ... render content ...
terminal.showCursor();

clearLine()

Clears the current line.
terminal.clearLine();

clearFromCursor()

Clears from cursor to end of screen.
terminal.clearFromCursor();

clearScreen()

Clears entire screen and moves cursor to (0,0).
terminal.clearScreen();

setTitle()

Sets terminal window title.
title
string
required
Window title text
terminal.setTitle('My Application');

Properties

columns

Current terminal width in columns.
const width = terminal.columns; // e.g., 80

rows

Current terminal height in rows.
const height = terminal.rows; // e.g., 24

kittyProtocolActive

Whether Kitty keyboard protocol is active.
if (terminal.kittyProtocolActive) {
  // Enhanced keyboard protocol available
}

Features

Kitty Keyboard Protocol

The terminal automatically queries and enables the Kitty keyboard protocol when available, providing:
  • Disambiguated escape codes
  • Key press/repeat/release events
  • Alternate keys (shifted key, base layout key)
  • Support for non-Latin keyboard layouts

Bracketed Paste Mode

Bracketed paste mode is automatically enabled, wrapping pastes in \x1b[200~\x1b[201~ sequences.

Windows VT Input Support

On Windows, automatically enables ENABLE_VIRTUAL_TERMINAL_INPUT so the terminal sends VT sequences for modified keys (e.g., \x1b[Z for Shift+Tab).

Example Usage

import { ProcessTerminal } from '@pi-ai/tui';

const terminal = new ProcessTerminal();

terminal.start(
  (data) => {
    // Handle input
    if (data === '\x03') { // Ctrl+C
      terminal.stop();
      process.exit(0);
    }
    terminal.write(`You typed: ${data}\r\n`);
  },
  () => {
    // Handle resize
    terminal.write(`Resized to ${terminal.columns}x${terminal.rows}\r\n`);
  }
);

terminal.setTitle('My Terminal App');
terminal.write('Welcome! Press Ctrl+C to exit.\r\n');

Environment Variables

PI_TUI_WRITE_LOG
string
Path to log all terminal writes (for debugging)
PI_TUI_WRITE_LOG=/tmp/tui-writes.log node app.js

Build docs developers (and LLMs) love