Exploring PixelPrompt: Dart’s Declarative Terminal UI Framework

PixelPrompt is a Dart-based terminal UI (TUI) framework that brings Flutter‑style declarative UI, component hierarchy, layout engines, and efficient ANSI‑based rendering to the console, using character cells, double buffering, and diff rendering to create interactive, styled terminal applications.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Exploring PixelPrompt: Dart’s Declarative Terminal UI Framework

Today we introduce a special Dart open‑source library PixelPrompt, a Dart terminal UI (TUI) framework that follows a Flutter‑like reactive UI implementation and uses Dart to create a declarative TUI.

ezgif-6a50f0eac4a051
ezgif-6a50f0eac4a051

PixelPrompt has no direct relationship with Flutter; it is a pure Dart implementation whose UI runs in the terminal, not as an app UI. It is similar to the UI shown by tools like Claude Code or Gemini CLI.

PixelPrompt brings Dart’s declarative UI style to the terminal, allowing developers to use layout, state components, and keyboard/mouse events to build interactive, styled terminal applications.

Because it is a terminal UI framework, PixelPrompt does not render based on pixels but on character cells (BufferCell), which distinguishes it from typical application UI implementations.

Inside PixelPrompt, the UI is composed of “components” similar to Flutter’s widgets. The project defines an abstract class Component as the base for all UI elements, with two core component types: BuildableComponent: analogous to Flutter’s StatelessWidget, used to build static, stateless UI parts via a build method that returns child components. StatefulComponent: analogous to Flutter’s StatefulWidget, used for dynamic UI parts that maintain internal state. It creates a ComponentState object via createState and triggers UI redraws with setState.

This feels very Flutter‑like.

The rendering mechanism uses a class called CanvasBuffer, which maintains a two‑dimensional grid ( List<List<BufferCell>>) in memory, representing every character position on the terminal screen.

Each BufferCell stores the character, foreground color, background color, and style (bold, italic, etc.).

When a component needs to render, it calls its render method, drawing its content into a specified region of the CanvasBuffer.

The RenderManager efficiently compares the current CanvasBuffer with the previous frame and outputs only the changed cells using ANSI escape sequences, updating the screen, moving the cursor, and changing colors.

The key to TUI programs running on macOS, Linux, and Windows terminals is a universal standard: ANSI escape codes.

In the TUI world, ANSI escape sequences act as a “common language” for the terminal, allowing commands such as moving the cursor, changing text colors, applying styles, and clearing parts of the screen.

Move cursor to any screen position.

Change subsequent text’s foreground/background colors.

Change text style (bold, underline, etc.).

Clear part or all of the screen.

Thus, in TUI rendering, render = turn UI into ANSI . Most ANSI codes follow a common format:

Escape character: usually written as \x1B in PixelPrompt code.

Control Sequence Introducer (CSI): the escape character followed by [.

Parameters: one or more numbers separated by ; between CSI and the final character.

Terminator: a letter that defines the command type.

Examples in PixelPrompt code:

Move cursor : format \x1B[<row>;<col>H. For example \x1B[10;20H moves the cursor to row 10, column 20.

Set graphic style : format \x1B[<params>m. Used to change colors and styles. Examples:

Foreground red: \x1B[31m.

Background green: \x1B[42m.

Bold: \x1B[1m.

24‑bit true color foreground: \x1B[38;2;<r>;<g>;<b>m (e.g., \x1B[38;2;255;100;50m).

Reset all: \x1B[0m.

Example in PowerShell:

Write-Host "$([char]27)[2J$([char]27)[5;10H$([char]27)[93mThis is a complex"

This command clears the screen ( [2J), moves the cursor to row 5 column 10 ( [5;10H), and sets bright yellow text ( [93m).

Removing [2J results in no screen clear, only cursor movement and text output.

For layout support, PixelPrompt defines a LayoutEngine that calculates and positions all components on the terminal screen. It provides Flutter‑like Row and Column components, using a childGap to compute sizes.

The layout process is recursive, starting from the root App component, measuring each component ( measure ) and assigning a rectangular area ( Rect ) for rendering.

Measurement

The engine calls the root component’s measure method with a maximum size ( maxSize) to estimate required space, then recursively computes positions via _layoutRecursiveCompute, assigning a Rect to every child.

Output

After the recursive compute finishes, it returns a List<PositionedComponentInstance>. Each instance pairs a component with its final Rect. The rendering system iterates this list, calling each component’s render method with the CanvasBuffer and its Rect.

The CanvasBuffer holds two 2‑D lists ( List<List<BufferCell>>) implementing double buffering: _screenBuffer: the current frame to be drawn; all draw operations update this buffer. _previousFrame: the previous frame already displayed on the terminal.

The render() method performs diff rendering, comparing each cell in _screenBuffer with the corresponding cell in _previousFrame. Only changed cells generate ANSI commands, producing a minimal update string that is written to the terminal via stdout.write(), achieving high performance and flicker‑free refresh.

ANSI Final Rendering

After all components have drawn into the CanvasBuffer, the main program calls canvasBuffer.render(). This method traverses _screenBuffer, compares each cell with _previousFrame, generates the necessary ANSI sequences for differences, concatenates them, and outputs the result to the terminal.

The overall process is illustrated in the diagram below:

PixelPrompt brings Dart into a niche domain of terminal UI, filling a gap in Dart’s desktop capabilities. Although many projects may not need it, it offers an interesting experiment.

Currently PixelPrompt is still experimental; its API is unstable, and features such as menus, tables, multiline text fields, scroll views, and visual debuggers are still under development.

DARTLayout EngineANSIterminal UIPixelPromptTUI
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.