Choosing a .NET Console UI Library

The .NET ecosystem has several libraries for building console applications. Each solves a different problem. This guide helps you pick the right one.

Four Libraries, Four Jobs

Library What it is Think of it as...
Spectre.Console Rich console output & formatting A printer -- beautiful output, scrolls away
Terminal.Gui Forms-based TUI toolkit A dialog box -- single-screen forms and views
XenoAtom.Terminal.UI Reactive UI framework A WPF for the terminal -- reactive bindings, alpha blending
SharpConsoleUI Windowed console UI system A desktop -- overlapping windows with a compositor engine

They're complementary, not always competing. SharpConsoleUI can host Spectre.Console renderables inside its windows via SpectreRenderableControl.

Quick Decision Guide

I need to... Spectre.Console Terminal.Gui XenoAtom.Terminal.UI SharpConsoleUI
Pretty-print tables, trees, charts Best choice -- -- Via Spectre wrapper
Build a CLI tool with prompts Best choice -- Yes (inline mode) --
Build a single-screen forms app -- Best choice Best choice Works
Build a multi-window app with overlapping windows No v2 beta only No Best choice
Drag, resize, minimize, maximize windows No v2 beta only No Built-in
Embed a working terminal emulator No No No Built-in
Run independent async tasks per window No No No Built-in
Apply visual effects (blur, fade, gradients) No No Alpha blending only Built-in compositor
Use Spectre.Console markup in controls No (output only) No No (own markup) Yes, everywhere
Use it in production today on .NET 8+ Yes (v0.54) v1 stable, v2 in beta No (.NET 10 only) Yes (v2.4)

Detailed Comparison

Rendering Architecture

This is the most fundamental difference between the four libraries. It determines what kinds of visual effects and compositing are possible.

Spectre.Console Terminal.Gui v2 XenoAtom.Terminal.UI SharpConsoleUI
Buffer model No buffer (stream to stdout) Single shared buffer Single CellBuffer Per-window CharacterBuffer
Compositing N/A Painter's algorithm (back-to-front into shared buffer) Single buffer + diff True compositor (merge per-window buffers)
Compositor hooks No No No Yes (PreBufferPaint / PostBufferPaint)
Occlusion culling N/A No (hidden content still painted) Clip-skip only Yes (hidden regions skipped entirely)
Double buffering No Single back buffer Single buffer + diff Per-window double buffering
Dirty tracking No Cell-level Visual-level invalidation Region-level (3-level dirty tracking)
Flicker prevention Cursor repositioning (can flicker) ANSI driver diff Synchronized output (DEC 2026) Occlusion culling + diff-based flush
Frame management N/A Event-driven redraw Event-driven ~60 FPS with dirty-check skip
RGBA alpha blending No No Yes (sRGB-linear LUT) No

What this means in practice:

  • Spectre.Console writes formatted text to stdout. No screen buffer, no compositing, no concurrent updates.
  • Terminal.Gui paints all views into one shared buffer using a back-to-front painter's algorithm. If window A is fully behind window B, window A is still fully rendered.
  • XenoAtom.Terminal.UI uses a single cell buffer with reactive invalidation and frame-to-frame diffing. Has the most sophisticated color system with true RGBA alpha blending in linear color space. But no per-window buffers or compositor pipeline.
  • SharpConsoleUI gives each window its own character buffer, then composites them together. The PreBufferPaint hook fires before controls paint (for backgrounds, gradients, game rendering), controls render on top, then PostBufferPaint fires for effects (blur, fade, glow, transitions). This pipeline is unique -- no other .NET TUI framework exposes it.

Gradient Backgrounds

SharpConsoleUI supports multi-stop color gradients on windows that flow through the entire control hierarchy:

new WindowBuilder(system)
    .WithBackgroundGradient(
        ColorGradient.FromColors(Color.Navy, Color.DarkCyan, Color.Teal),
        GradientDirection.Vertical)
    .BuildAndShow();

Controls with transparent backgrounds blend naturally with the gradient behind them. Controls with explicit backgrounds punch through. Gradients support four directions (horizontal, vertical, diagonal down, diagonal up) and can be defined with named presets ("warm", "cool", "spectrum") or arrow notation ("red→yellow→green").

Gradient text is also supported in markup: [gradient=spectrum]Rainbow Text[/]

Neither Terminal.Gui nor XenoAtom.Terminal.UI offer window-level gradients that propagate through nested containers and controls.

Input & Interactivity

Spectre.Console Terminal.Gui v2 XenoAtom.Terminal.UI SharpConsoleUI
Keyboard Blocking ReadKey only Full event-driven Full event-driven + routed Full event-driven
Mouse None Click, drag, wheel Click, drag, wheel, hover Click, drag, wheel, double-click, hover
Focus system None (one prompt at a time) Tab-based focus chain Tab-based + routed focus Window + control focus with Alt+1-9 cycling
Modal dialogs Sequential prompts Dialog-based Dialog + Backdrop True modal stack with input blocking
Concurrent interactive controls No Yes Yes Yes, across multiple windows

Controls

Control type Spectre.Console Terminal.Gui v2 XenoAtom.Terminal.UI SharpConsoleUI
Button -- Yes Yes Yes
Text input Prompt (blocking) TextField, TextView TextBox, TextArea PromptControl, MultilineEditControl
List / selection SelectionPrompt (blocking) ListView ListBox, SelectionList ListControl (live, searchable)
Tree view Tree (static output) TreeView<T> TreeView TreeControl
Data grid / table Table (static output) TableView DataGridControl TableControl (virtual, sort, filter, edit)
Tabs -- TabView TabControl TabControl
Menu bar -- MenuBar MenuBar + CommandPalette MenuControl with portals
Dropdown -- ComboBox Select<T> DropdownControl with smart positioning
Checkbox -- CheckBox CheckBox, Switch CheckboxControl
Progress bar ProgressBar (excellent) ProgressBar ProgressBar + task groups ProgressBarControl
Canvas / drawing Canvas (basic) LineCanvas Canvas CanvasControl (30+ primitives)
Terminal emulator -- -- -- TerminalControl (PTY)
Sparklines -- -- Sparkline SparklineControl (4 render modes)
Bar graphs BarChart (static) -- BarChart, LineChart, Breakdown BarGraphControl (live, gradient)
FIGlet text FigletText -- TextFiglet (25 fonts) FigleControl (with wrapping)
Log viewer -- -- LogControl LogViewerControl
Splitter -- TileView HSplitter, VSplitter SplitterControl
Image rendering -- -- -- ImageControl
Toolbar -- -- CommandBar ToolbarControl
Date picker -- DatePicker, DateEditor -- --
Slider -- LinearRange Slider --
Hex viewer -- HexView -- --
Graph view -- GraphView LineChart, BreakdownChart --
Color picker -- ColorPicker (RGB/HSL) ColorPicker --
Radio button -- OptionSelector RadioButtonList --
Accordion -- -- Accordion, Collapsible --
Markdown -- -- MarkdownControl (Markdig) --
Wizard / stepper -- Wizard -- --
Toast notifications -- -- ToastService NotificationSystem

Honest take: Terminal.Gui has the most mature and widest control library -- battle-tested over years, with specialized widgets like DatePicker, ColorPicker, Slider, HexView, and Wizard. XenoAtom.Terminal.UI ships the most controls overall (100+) but is only 2 months old. SharpConsoleUI has fewer controls, but its unique strengths are interactive/live controls (TerminalControl, SparklineControl, BarGraphControl, CanvasControl with 30+ drawing primitives) and the window management + compositor layer.

Window Management

This is SharpConsoleUI's primary differentiator.

Feature Spectre.Console Terminal.Gui v2 XenoAtom.Terminal.UI SharpConsoleUI
Multiple overlapping windows -- Beta Popups only (WindowLayer) Yes
Window Z-order management -- Basic Z-stack for overlays Multi-pass (Normal/Active/AlwaysOnTop)
Drag to move -- Beta Popup drag only Yes
Drag to resize (8 directions) -- Beta No Yes, configurable per-direction
Minimize / Maximize -- -- No Yes
Close button -- -- No Yes
Window state events -- -- No Yes (StateChanged, Closing with cancel)
Independent async window threads -- -- No Yes
Modal window stack -- Basic Dialog + Backdrop Yes, with input blocking
Always-on-top windows -- -- No Yes
Per-window compositor hooks -- -- No Yes (PreBufferPaint, PostBufferPaint)
Window templates -- -- No Yes (DialogTemplate, ToolWindowTemplate)
Taskbar -- -- No Yes (Alt+1-9 switching)

XenoAtom.Terminal.UI has a WindowLayer that supports z-ordered overlays with bring-to-front and click-to-focus, plus Popup and Dialog controls. But there is no full window manager with title bars, minimize/maximize/close chrome, or arbitrary resizing.

Rich Text Markup Everywhere

SharpConsoleUI uses a Spectre-compatible markup syntax ([red bold]text[/]) that works on virtually every control -- not just in output rendering:

// Checkbox with colored label
var checkbox = Controls.Checkbox()
    .WithLabel("[red]C[/]heck[yellow]B[/]ox")
    .Build();

// List with rich items
var list = Controls.List()
    .WithItems("[green]Online[/] Server 1", "[red]Offline[/] Server 2")
    .Build();

// Button with styled text
var button = Controls.Button()
    .WithText("[bold]Save[/] changes")
    .Build();
Control Markup in text/labels
Buttons, Checkboxes Yes
List items, Tree nodes Yes
Tab headers, Dropdowns Yes
Prompts, Panels, Rules Yes
Bar graph labels Yes
MarkupControl Yes (entire content)
Status bars Yes

How this compares:

  • Spectre.Console has excellent markup -- but only for static output that scrolls away. You can't use it in live, interactive controls.
  • Terminal.Gui has no markup system. Styling requires working with ColorScheme objects and attribute-based formatting. v2 adds VisualRole semantic styling, but no inline markup syntax.
  • XenoAtom.Terminal.UI has its own markup and Brush system (including gradient brushes for text), but it's a separate syntax incompatible with Spectre.Console. No IRenderable bridge.
  • SharpConsoleUI parses Spectre-compatible markup directly into cells (no ANSI roundtrip) and supports any Spectre IRenderable (Tables, Charts, BarCharts) as a control via SpectreRenderableControl. This extends Spectre.Console rather than replacing it.

Layout System

Spectre.Console Terminal.Gui v2 XenoAtom.Terminal.UI SharpConsoleUI
Approach Measure/Render Pos/Dim with arithmetic Flexbox + Grid + Dock DOM pipeline (Measure/Arrange/Paint)
Containers Layout (grid cells) View nesting VStack, HStack, WrapStack, Grid, DockLayout, ZStack, Splitter, ScrollViewer HorizontalGrid, ColumnContainer, ScrollablePanel
Reactive layout No Computed Pos/Dim [Bindable] source-generated with dependency tracking MVVM binding with auto-invalidation
Flexibility Low High (Pos/Dim arithmetic) Very high (WPF/Avalonia-level) Moderate

XenoAtom.Terminal.UI has the most sophisticated layout system with a proper FlexAllocator (grow/shrink/min/max like CSS Flexbox), full Grid with row/column definitions, and DockLayout. Terminal.Gui's Pos/Dim system with arithmetic composition is also very powerful. SharpConsoleUI's layout is simpler -- it prioritizes the compositor pipeline over layout complexity.

Developer Experience

Spectre.Console Terminal.Gui v2 XenoAtom.Terminal.UI SharpConsoleUI
API style Fluent builders Property assignment Property assignment + reactive bindings Fluent builders
Data binding None Manual / events Reactive [Bindable] with auto-invalidation MVVM with Bind/BindTwoWay
Async support Limited (Progress) Event-driven Dispatcher-based Full async/await, per-window threads
Plugin architecture No No No Yes (themes, controls, windows, services)
Theming No built-in theming JSON-based Scheme + VisualRole Theme + 73 per-control style files Theme registry with runtime switching
Markup syntax [red bold]text[/] No markup Own markup + Brush/Gradient [red bold]text[/] (Spectre-compatible)
Testing support Spectre.Console.Testing Input injection (v2) Screenshot/snapshot testing HeadlessConsoleDriver
Logging N/A Microsoft.Extensions.Logging N/A Built-in LogService (file-based, never console)

Project Health (March 2026)

Spectre.Console Terminal.Gui XenoAtom.Terminal.UI SharpConsoleUI
Stars ~11,260 ~10,830 ~140 114
NuGet downloads ~9.9M ~1.6M New 6,504
Contributors ~115 199 1 1
Latest stable 0.54.0 (pre-1.0) 1.19.0 (v1 only) 1.4.0 2.4.40
v2 / latest 0.54.0 v2 beta.1 (March 2026) 1.4.0 2.4.40
.NET version .NET Standard 2.0+ .NET 10 (v2 beta) .NET 10 only .NET 8.0+
License MIT MIT BSD-2-Clause MIT
Repo age ~5 years ~7 years ~2 months ~1 year

Honest take: Terminal.Gui and Spectre.Console have large communities and years of battle-testing. XenoAtom.Terminal.UI is brand new (January 2026) but built by Alexandre Mutel, a highly respected .NET developer (Markdig, SharpDX, Scriban, former .NET Foundation TSG member). SharpConsoleUI is solo-maintained. If you need maximum community support, StackOverflow answers, and long-term maintenance guarantees, the larger libraries are safer bets. SharpConsoleUI and XenoAtom compensate with rapid iteration and features the others don't offer.

When NOT to Use SharpConsoleUI

Be honest about the right tool:

  • Just need pretty CLI output? Use Spectre.Console. It's purpose-built for that and does it better than anything else in .NET.
  • Building a simple single-screen form? Terminal.Gui has the widest mature control library. XenoAtom.Terminal.UI has the most modern architecture with reactive bindings, but requires .NET 10.
  • Need maximum community and ecosystem? The bigger libraries have more users, more contributors, more blog posts, and more StackOverflow answers.
  • Targeting .NET 6 or older? SharpConsoleUI requires .NET 8+. Spectre.Console and Terminal.Gui v1 support .NET Standard 2.0. XenoAtom requires .NET 10.
  • Need DatePicker, Slider, ColorPicker, or HexView? Terminal.Gui has these built-in. XenoAtom has Slider and ColorPicker. SharpConsoleUI doesn't (yet).
  • Need source-generated reactive bindings? XenoAtom's [Bindable] source-generated property system with automatic dependency tracking is more sophisticated than SharpConsoleUI's lambda-based MVVM bindings.

When SharpConsoleUI Shines

SharpConsoleUI is the right choice when you need:

  • Multi-window desktop-style apps -- overlapping windows with drag, resize, minimize, maximize, taskbar. No other .NET library does this in a stable release.
  • Visual effects and compositing -- gradient backgrounds, blur, fade transitions, custom buffer effects via PreBufferPaint/PostBufferPaint. The compositor pipeline is unique in the .NET TUI space.
  • Dashboard / monitoring tools -- independent async window threads mean each panel updates on its own schedule without blocking the UI.
  • IDE-like tools -- LazyDotIDE is a working .NET IDE built entirely on SharpConsoleUI, proving the framework handles complex, multi-window applications.
  • Embedded terminal + UI -- TerminalControl gives you a real PTY-backed terminal emulator inside a window, alongside your UI controls. Unique in the .NET ecosystem.
  • MVVM data binding -- Bind() and BindTwoWay() with lambda expressions, type converters, and standard INotifyPropertyChanged ViewModels. All controls support property change notification out of the box.
  • Spectre.Console integration -- use [red bold]markup[/] in every control, and embed any IRenderable (Tables, Charts, BarCharts) as a windowed control. Extends Spectre.Console rather than replacing it.
  • Live data visualization -- SparklineControl and BarGraphControl update in real-time with configurable styles.
  • Plugin-based architectures -- extend the framework with custom themes, controls, windows, and services.

Code Comparison

Creating a selectable list

Spectre.Console (blocking -- halts your program until user selects):

var choice = AnsiConsole.Prompt(
    new SelectionPrompt<string>()
        .Title("Pick a language:")
        .AddChoices("C#", "F#", "VB.NET"));
// Nothing else can happen on screen while this runs

Terminal.Gui (single-screen):

var list = new ListView(new[] { "C#", "F#", "VB.NET" })
{
    X = 0, Y = 0,
    Width = Dim.Fill(),
    Height = Dim.Fill()
};
win.Add(list);

SharpConsoleUI (inside a managed window, alongside other windows):

var list = Controls.List()
    .WithItems("C#", "F#", "VB.NET")
    .OnSelected((window, args) => { /* handle selection */ })
    .Build();
window.AddControl(list);
// Other windows continue updating independently

Creating a live-updating dashboard

Spectre.Console -- possible with Live, but only one live region, no windowing:

await AnsiConsole.Live(table).StartAsync(async ctx =>
{
    while (true)
    {
        UpdateTable(table);
        ctx.Refresh();
        await Task.Delay(1000);
    }
});
// Nothing else can be on screen

SharpConsoleUI -- multiple independent windows, each with its own update loop:

var cpuWindow = new WindowBuilder(system)
    .WithTitle("CPU Monitor")
    .WithSize(40, 12)
    .WithAsyncWindowThread(async (window, token) =>
    {
        while (!token.IsCancellationRequested)
        {
            sparkline.AddValue(GetCpuUsage());
            await Task.Delay(500, token);
        }
    })
    .Build();

var logWindow = new WindowBuilder(system)
    .WithTitle("Live Logs")
    .WithSize(60, 20)
    .WithAsyncWindowThread(async (window, token) =>
    {
        await foreach (var entry in logStream.ReadAllAsync(token))
            logViewer.AddEntry(entry);
    })
    .Build();

// Both windows run simultaneously, user can drag/resize/switch between them

Compatibility with Spectre.Console

SharpConsoleUI doesn't replace Spectre.Console -- it can host it. Use SpectreRenderableControl to embed any Spectre.Console renderable inside a SharpConsoleUI window:

var table = new Table()
    .AddColumn("Name")
    .AddColumn("Status")
    .AddRow("Server 1", "[green]Online[/]")
    .AddRow("Server 2", "[red]Offline[/]");

window.AddControl(new SpectreRenderableControl(table));
// Spectre's beautiful table, inside a draggable, resizable window

This gives you Spectre's polished formatting with SharpConsoleUI's window management -- the best of both worlds.


Rendering Architecture Deep Dive

TUI frameworks differ most fundamentally in how they turn a tree of controls into pixels on screen. This section explains where SharpConsoleUI sits and why the differences matter.

How TUI Frameworks Render

Approach Description Used by
String output View() returns a string; framework diffs strings BubbleTea (Go)
Immediate-mode Redraw entire UI into a single buffer each frame Ratatui (Rust)
Retained-mode, shared buffer Widget tree paints into one buffer with dirty tracking Textual (Python), Terminal.Gui (.NET)
Retained-mode, per-window buffers Each window has its own buffer; a compositor merges them SharpConsoleUI (.NET)

Most TUI frameworks use a single shared buffer. SharpConsoleUI gives each window its own CharacterBuffer, then composites them together -- a pattern borrowed from desktop window managers (DWM, Quartz, Wayland compositors), adapted for character cells.

The Compositor Pipeline

Per-Window Buffers    Compositor           Console Driver
┌──────────┐
│ Window A │──┐
└──────────┘  │   ┌──────────────────┐   ┌─────────────────┐
┌──────────┐  ├──▶│ Visible Regions  │──▶│ Diff-based flush│──▶ stdout
│ Window B │──┤   │ (skip occluded)  │   │ (changed cells) │
└──────────┘  │   └──────────────────┘   └─────────────────┘
┌──────────┐  │
│ Overlay  │──┘
└──────────┘

The visible regions calculator uses rectangle subtraction to determine which pixels of each window are actually visible on screen. Occluded regions are skipped entirely rather than painted and overwritten.

Each window's render also supports compositor hooks: PreBufferPaint fires before controls (for gradients, custom backgrounds), then controls paint, then PostBufferPaint fires (for effects like blur or fade).

Frame-Coupled Animations

The animation system runs inside the main render loop, not on separate timers:

  1. Poll input
  2. Advance animations (AnimationManager.Update(deltaTime))
  3. Layout pass (Measure → Arrange → Paint)
  4. Composite and flush

Delta time is capped at 33ms to prevent animations from completing instantly after idle periods. This is what enables smooth transitions in controls like NavigationView -- the animation and layout run in the same frame tick.

DOM Layout

SharpConsoleUI uses a three-pass DOM layout (Measure → Arrange → Paint) similar to WPF and Avalonia. Each control reports its desired size, receives its final bounds from its parent, then paints into its window buffer. This is what allows the responsive NavigationView to detect its actual width and switch display modes.


Cross-Ecosystem Comparison

Different languages have their own established TUI frameworks. Here's how the major ones compare architecturally.

Feature Comparison

SharpConsoleUI Textual Ratatui BubbleTea Terminal.Gui
Language C# Python Rust Go C#
Architecture Compositor Retained + segment compositor Immediate-mode Elm (TEA) Retained, shared buffer
Overlapping windows Yes Screens (modal stack) No No v2 beta
Window management Drag, resize, minimize, maximize No No No v2 beta
Built-in animations Frame-coupled tweens CSS-like transitions Via tachyonfx crate No No
Overlay/portal system Yes (auto-positioning, auto-dismiss) Screen stack Manual Manual No
Responsive controls Yes (NavigationView) CSS-like media queries No No No
Per-window buffers Yes No No No No
Compositor hooks PreBufferPaint / PostBufferPaint No No No No
DOM layout pipeline Measure / Arrange / Paint CSS Box Model Constraint-based String concat Pos/Dim arithmetic
Async per-window Yes Async workers Manual Goroutines No
Desktop packaging schost textual-web (browser) No No No
Embedded terminal PTY-backed No No No No
Mouse Full Full Via backend Via backend Full
24-bit color Yes Yes Yes Via Lip Gloss Yes

How They Differ

Ratatui is a lightweight Rust library where you own the event loop and redraw the entire UI each frame. Clean and fast, but no retained state or compositing -- you manage everything yourself.

BubbleTea uses the Elm architecture in Go -- your View() returns a string, the framework diffs it. Elegant for single-screen apps. The string-based model doesn't support pixel-level compositing.

Textual has its own segment-based compositor that merges overlapping widget output. It uses a spatial grid for fast hit-testing and supports CSS-like animations and styling. The most feature-rich Python TUI framework.

Terminal.Gui is the most mature .NET TUI library with the widest control set. v2 (beta) adds overlapping window support. Uses a shared buffer with painter's algorithm rendering.

SharpConsoleUI takes the compositor approach further with per-window buffers, occlusion culling via rectangle subtraction, and compositor hooks for visual effects. The animation system and DOM layout pipeline enable features like the responsive NavigationView with animated mode transitions.

Each framework makes different tradeoffs. The compositor approach adds complexity but enables desktop-class features (window management, visual effects, animated responsive controls) that are difficult to achieve with a shared buffer or string-based model.


Last updated: March 2026