MiniTui

Terminal UIs for .NET: immediate mode, fast, and dependency-free.

Describe the screen every frame, and MiniTui draws only what changed. Widgets, layout, screens and focus, the mouse and the clipboard, themes, and a test harness, on Windows, Linux and macOS.

dotnet add package MiniTui

Widgets

Lists, tables, trees, tabs, text fields and editors, gauges, sparklines, line and bar charts, and a braille canvas. Each is a builder that draws into a buffer.

Widgets

Screens and focus

Grow from one render callback to a stack of screens built from components, with focus scopes, dialogs, menus, a command palette and scoped key bindings.

Screens and components

Layout

Constraints solved with exact integer arithmetic, so regions never overlap or drop a cell, and split panes you drag with the mouse.

Layout

Async without blocking

HTTP calls and slow work run off the UI thread, and their results come back on it. Loadable<T> shows loading, errors and retries.

Async data and HTTP

The terminal, done right

Raw input with the kitty keyboard protocol, bracketed paste, mouse and hover, OSC 52 clipboard, light and dark detection, and a terminal that's restored on exit, crashes and Ctrl+Z.

The terminal

Testable

ComponentHarness runs a screen without a terminal: press keys, click, and assert on the cells it drew.

Testing

A whole app in a screenful

A render callback and a key map. The status bar shows the key hints, q quits, and the terminal is restored however the app ends.

Getting started

using MiniTui;

var count = 0;
var app = App.Create();
var keys = new KeyMap()
    .Add("k,up", "+1", () => count++)
    .Add("j,down", "-1", () => count--)
    .Add("q", "Quit", app.Quit);

app.OnKey(keys.Handle)
    .Render((buf, screen) =>
    {
        var inner = Widget.Block().Title(" Counter ").Draw(buf, new Rect(2, 1, 30, 5));
        buf.SetString(inner.X + 1, inner.Y + 1, $"Count: {count}", Style.Default.Bold());
        Widget.StatusBar().Left(keys.Hints(screen.Width)).Draw(buf, screen);
    })
    .Run();