Skip to main content

Overview

The @mariozechner/pi-tui package is a minimal terminal UI framework designed for building flicker-free interactive CLI applications. It features differential rendering, synchronized output, and a component-based architecture.

Differential Rendering

Three-strategy rendering that only updates what changed

Synchronized Output

Uses CSI 2026 for atomic screen updates with zero flicker

Component-Based

Simple Component interface with render() method

Rich Components

Text, Input, Editor, Markdown, SelectList, Image, and more

Installation

Quick Start

Key Features

Differential Rendering

The TUI intelligently updates only what changed:
  1. First Render: Output all lines without clearing scrollback
  2. Width Changed: Clear screen and full re-render
  3. Normal Update: Move cursor to first changed line, clear to end, render changes
All updates wrapped in synchronized output (\x1b[?2026h\x1b[?2026l) for flicker-free rendering.

Component Interface

All components implement a simple interface:
Important: Each line returned by render() must not exceed the width parameter. Use truncateToWidth() or manual wrapping.

Built-in Components

Layout:
  • Container - Groups child components
  • Box - Container with padding and background
  • Spacer - Empty vertical spacing
Text:
  • Text - Multi-line text with word wrapping
  • TruncatedText - Single-line text with truncation
  • Markdown - Markdown rendering with syntax highlighting
Input:
  • Input - Single-line text input
  • Editor - Multi-line editor with autocomplete and paste handling
Selection:
  • SelectList - Interactive list with keyboard navigation
  • SettingsList - Settings panel with value cycling
Feedback:
  • Loader - Animated loading spinner
  • CancellableLoader - Loader with Escape key abort
  • Image - Inline images (Kitty/iTerm2 protocols)

Overlay System

Render components on top of existing content:
Anchor values: center, top-left, top-right, bottom-left, bottom-right, top-center, bottom-center, left-center, right-center

Keyboard Input

Use matchesKey() with the Key helper:
Key identifiers:
  • Basic: Key.enter, Key.escape, Key.tab, Key.space, Key.backspace, Key.delete
  • Arrows: Key.up, Key.down, Key.left, Key.right
  • Modifiers: Key.ctrl("c"), Key.shift("tab"), Key.alt("left"), Key.ctrlShift("p")

IME Support (CJK Input)

Components with text cursors should implement Focusable for IME support:
The TUI positions the hardware cursor at CURSOR_MARKER location for CJK IME candidate windows.

Autocomplete

Combine slash commands and file path completion:
Features:
  • Type / for slash commands
  • Press Tab for file paths
  • Supports ~/, ./, ../, and @ prefix

Component Examples

Text with Background

Multi-line Editor

Key Bindings:
  • Enter - Submit (if not disabled)
  • Shift+Enter, Ctrl+Enter, Alt+Enter - New line
  • Tab - Autocomplete
  • Ctrl+K - Delete to end of line
  • Ctrl+W - Delete word backwards

Markdown Rendering

Interactive List

Inline Images

Supported terminals: Kitty, Ghostty, WezTerm, iTerm2. Falls back to text placeholder on unsupported terminals.

Loading Spinner

Creating Custom Components

Basic Component

Component with Caching

Utilities

Text Width and Truncation

ANSI Code Handling

Both visibleWidth() and truncateToWidth() correctly handle ANSI escape codes:

Terminal Abstraction

The TUI works with any object implementing the Terminal interface:
Implementations:
  • ProcessTerminal - Uses process.stdin/stdout
  • VirtualTerminal - For testing (uses @xterm/headless)

Example: Chat Interface

See test/chat-simple.ts in the package for a complete example with:
  • Markdown messages with custom backgrounds
  • Loading spinner during responses
  • Editor with autocomplete and slash commands
  • Spacers between messages
Run it:

Debug Logging

Capture raw ANSI output for debugging: