Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/badlogic/pi-mono/llms.txt

Use this file to discover all available pages before exploring further.

The TUI library includes a comprehensive set of built-in components for building interactive terminal applications.

Text Components

Text

Displays multi-line text with word wrapping:
const text = new Text(
  "Hello World",
  1,  // paddingX
  1,  // paddingY
  (text) => chalk.bgGray(text)  // optional background
);
text.setText("Updated text");

TruncatedText

Single-line text that truncates to fit:
const truncated = new TruncatedText(
  "Very long line that will be truncated...",
  0,  // paddingX
  0   // paddingY
);

Markdown

Renders markdown with syntax highlighting:
const md = new Markdown(
  "# Hello\n\nSome **bold** text",
  1,  // paddingX
  1,  // paddingY
  theme,
  defaultStyle
);

Input Components

Input

Single-line text input:
const input = new Input();
input.onSubmit = (value) => console.log(value);
input.setValue("initial");
Key Bindings:
  • Enter - Submit
  • Ctrl+A / Ctrl+E - Line start/end
  • Ctrl+W / Alt+Backspace - Delete word
  • Ctrl+Left / Ctrl+Right - Word navigation

Editor

Multi-line editor with autocomplete:
const editor = new Editor(tui, theme, options);
editor.onSubmit = (text) => console.log(text);
editor.onChange = (text) => console.log("Changed:", text);
editor.setAutocompleteProvider(provider);
Features:
  • Multi-line editing with word wrap
  • Slash command autocomplete
  • File path autocomplete (Tab)
  • Large paste handling
Key Bindings:
  • Enter - Submit
  • Shift+Enter / Alt+Enter - New line
  • Tab - Autocomplete
  • Ctrl+] - Jump to character

Selection Components

SelectList

Interactive selection list:
const list = new SelectList(
  [
    { value: "opt1", label: "Option 1", description: "First" },
    { value: "opt2", label: "Option 2", description: "Second" },
  ],
  5,  // maxVisible
  theme
);

list.onSelect = (item) => console.log("Selected:", item);
list.onCancel = () => console.log("Cancelled");
list.setFilter("opt");
Controls:
  • Arrow keys - Navigate
  • Enter - Select
  • Escape - Cancel

SettingsList

Settings panel with value cycling:
const settings = new SettingsList(
  [
    { id: "theme", label: "Theme", currentValue: "dark", values: ["dark", "light"] },
    { id: "model", label: "Model", currentValue: "gpt-4", submenu: modelSelector },
  ],
  10,  // maxVisible
  theme,
  (id, newValue) => console.log(`${id} changed to ${newValue}`),
  () => console.log("Cancelled")
);
Controls:
  • Arrow keys - Navigate
  • Enter/Space - Cycle value or open submenu
  • Escape - Cancel

Visual Components

Loader

Animated loading spinner:
const loader = new Loader(
  tui,
  (s) => chalk.cyan(s),
  (s) => chalk.gray(s),
  "Loading..."
);
loader.start();
loader.setMessage("Still loading...");
loader.stop();

CancellableLoader

Loader with abort signal:
const loader = new CancellableLoader(
  tui,
  (s) => chalk.cyan(s),
  (s) => chalk.gray(s),
  "Working..."
);
loader.onAbort = () => done(null);
doAsyncWork(loader.signal).then(done);

Image

Inline images (Kitty/iTerm2):
const image = new Image(
  base64Data,
  "image/png",
  theme,
  { maxWidthCells: 80, maxHeightCells: 24 }
);

Layout Components

Container

Groups child components:
const container = new Container();
container.addChild(component);
container.removeChild(component);

Box

Container with padding and background:
const box = new Box(
  1,  // paddingX
  1,  // paddingY
  (text) => chalk.bgGray(text)
);
box.addChild(new Text("Content"));

Spacer

Empty lines for spacing:
const spacer = new Spacer(2);  // 2 empty lines

Autocomplete

CombinedAutocompleteProvider

Slash commands and file paths:
import { CombinedAutocompleteProvider } from "@mariozechner/pi-tui";

const provider = new CombinedAutocompleteProvider(
  [
    { name: "help", description: "Show help" },
    { name: "clear", description: "Clear screen" },
  ],
  process.cwd()
);

editor.setAutocompleteProvider(provider);

Key Detection

Use matchesKey() for keyboard input:
import { matchesKey, Key } from "@mariozechner/pi-tui";

if (matchesKey(data, Key.ctrl("c"))) {
  process.exit(0);
} else if (matchesKey(data, Key.enter)) {
  submit();
} else if (matchesKey(data, Key.escape)) {
  cancel();
}

Utilities

import { visibleWidth, truncateToWidth, wrapTextWithAnsi } from "@mariozechner/pi-tui";

// Get visible width (ignoring ANSI codes)
const width = visibleWidth("\x1b[31mHello\x1b[0m");  // 5

// Truncate to width with ellipsis
const truncated = truncateToWidth("Hello World", 8);  // "Hello..."

// Wrap text preserving ANSI codes
const lines = wrapTextWithAnsi("Long text...", 20);

Next Steps

TUI Overview

Learn TUI concepts

API Reference

Complete component API

Build docs developers (and LLMs) love