← All libraries

CandyVt

🍬 CandyVt

In-memory virtual terminal emulator

port of x/vt vt500-parser cell-grid snapshot-tests no-pty

Feed an ANSI byte stream in, query a cell grid + cursor + mode state out — without ever spawning a real terminal. Built on a Paul-Williams VT500 state machine that mirrors charmbracelet/x/ansi/parser.

Install

composer require sugarcraft/candy-vt

Quickstart

use SugarCraft\Vt\Terminal\Terminal;

$term = Terminal::create(cols: 80, rows: 24);
$term->feed("\x1b[1;31mHello\x1b[0m world");

$screen = $term->screen();
$screen->cell(0, 0)->grapheme;       // 'H'
$screen->cell(0, 0)->sgr->bold;      // true
$screen->cell(0, 0)->foreground();   // 16-color red

$term->feed("\x1b]2;Demo\x07");
$term->windowTitle();                 // 'Demo'

$term->feed("\x1b[?1049h");
$term->mode()->altScreen;             // true

What's in the box

VT500 parser15-state Paul-Williams state machine. Direct port of charmbracelet/x/ansi/parser. Handles partial input across feed() calls.
Full SGR16-color, bright, 256-color, and truecolor for fg + bg; bold / italic / underline / strikethrough / blink / reverse / dim / hidden toggles.
Cursor + erase + scrollCUU/CUD/CUF/CUB/CUP/CHA/VPA, DECSC/DECRC, EL/ED/ECH/DCH/ICH, SU/SD, IND/RI/NEL.
DEC modes1049 alt screen + cursor save, 25 cursor visibility, 1000/1002/1003/1006 mouse, 2004 bracketed paste, 2026 sync.
OSC dispatch0/1/2 window title, 4 palette set, 8 hyperlinks (per-cell attribution), 52 clipboard write/read events.
Width-awareCJK + most emoji take 2 cells with a continuation marker. Delegates to candy-core's Util\Width for grapheme width.

Use it for

Source & demos

Try the quickstart →

API

ClassMethodDescription
Terminalcreate(cols, rows)Create a virtual terminal
Terminalfeed(bytes)Feed ANSI bytes to terminal
Terminalscreen()Get current cell grid
Terminalcursor()Get cursor position
Terminalmode()Get terminal mode state
TerminalwindowTitle()Get window title from OSC
Screencell(col, row)Get cell at position
Cellgrapheme, sgr, foreground(), background()Cell content and style

Demos.

VHS-recorded GIFs of every example shipped with the library. Regenerated automatically on every push that touches the source.

Feed and screenshot

Feed and screenshot

An ANSI byte stream feeds into a Terminal; the cell grid prints back as a screenshot, with window title, cursor position, and hyperlink span.