Choosing between traditional controls, rich console output, and Web-style components—with Native AOT in mind.
A deployment CLI that asks three questions has different needs from a terminal editor with panes, shortcuts, and drag interactions. Before choosing a framework, decide whether you need richer command-line output or a persistent interactive application.
This comparison focuses on programming models, input handling, component reuse, and deployment. It is based on official documentation and source code, not comparative performance benchmarks. AI assisted with drafting, translation, and condensation.
At a glance
| Framework | Development model | Input model | Suggested fit |
|---|---|---|---|
| Terminal.Gui | C# views, controls, layout, and commands | Integrated keyboard and mouse handling | Editors, file browsers, and multipane tools |
| Spectre.Console | Composable renderables and sequential prompts | Interactive prompts rather than a general-purpose event-driven control tree | Deployment tools, reports, and setup workflows |
| RazorConsole | Reusable Razor components and C# state | Component callbacks and Web-style keyboard/mouse events | Component-driven dashboards, forms, and interactive tools |
Terminal.Gui: a control-oriented application model
Terminal.Gui organizes an application around views, layout, focus, and commands. Developers compose controls such as lists, text editors, and dialogs, then connect them to application behavior.
Its keyboard system supports shortcuts and direct event handling. Its mouse system provides hit testing, event routing, coordinate conversion, and capture for interactions such as dragging.
I would shortlist it for applications with multiple independently interactive regions. The trade-off is learning its view lifecycle and input conventions. Check the major version when using examples: v1 and v2 APIs are not interchangeable.
Spectre.Console: polished output and guided workflows
Spectre.Console provides tables, trees, panels, progress displays, and interactive prompts. Its rendering model is a natural fit for tools that collect input, perform a task, and explain the result.
It also supports continuously updating output. However, a live dashboard is not automatically a complete UI framework: the Live Display documentation explicitly warns that it is not thread-safe and does not support combining it with prompts, progress displays, or status displays.
For a task-oriented CLI, I would start here. For a persistent interface with editable fields, selectable panes, and mouse interactions, evaluate a framework that supplies the surrounding interaction model.
RazorConsole: component-based TUI development with Web-style syntax
RazorConsole's distinguishing feature is component composition, not simply the ability to write tags. It brings Razor components, parameters, event callbacks, and lifecycle methods into terminal applications. State lives in ordinary C# fields and properties; component output updates as that state changes.
A reusable component can own its presentation and local behavior. For example, in a configured RazorConsole project:
@using RazorConsole.Components
<Panel Title="Build queue">
<Rows>
<p>Completed: @completed</p>
<TextButton Content="Complete next" OnClick="CompleteNext" />
</Rows>
</Panel>
@code {
private int completed;
private void CompleteNext() => completed++;
}
The same approach scales to task lists, detail panels, and command inputs: compose components rather than maintaining one large redraw routine.
This is conceptually similar to React Ink. Ink brings React components and state-driven rendering to terminal applications; RazorConsole follows a comparable development philosophy with Razor and C#. It is not an Ink port, and their APIs and rendering implementations differ.
RazorConsole also exposes Web-style events including @onclick, @onmousemove, and @onwheel, alongside keyboard handlers. Native hosts must enable mouse reporting.
Importantly, Web-style authoring does not mean browser rendering. RazorConsole renders terminal cells without requiring a Web server. Existing HTML/CSS and browser-dependent Blazor components cannot be assumed to work unchanged. Spectre.Console supplies part of its rendering foundation; RazorConsole adds the component and interaction layers.
Native AOT: compare packages, not just project names
Native AOT compiles an application ahead of time into native code, eliminating runtime JIT compilation and the need for a separately installed .NET runtime. Compatibility still depends on reflection, trimming, and the complete dependency graph.
| Package or framework | Verified AOT position |
|---|---|
| Terminal.Gui v2.5.0 | Declares IsAotCompatible=true and IsTrimmable=true; validate your application's dependencies and features. |
| Spectre.Console 0.57.2 | Declares AOT compatibility for its modern .NET targets. |
| Spectre.Console.Cli 0.55.0 | Explicitly declares AOT and trimming compatibility as false. Assess it separately from the rendering package. |
| RazorConsole official AOT guidance | Experimental support, with native Gallery builds available; routing, reflection, and third-party dependencies require care. |
These are version-specific findings, not blanket guarantees. Publish a representative prototype early and test the resulting executable on the intended platform. A successful build alone is insufficient, and this comparison establishes no startup-time or binary-size winner.
Which should you choose?
My starting recommendation is Spectre.Console for task-oriented CLIs, Terminal.Gui for control-heavy applications, and RazorConsole for teams that prefer reusable components and Razor/Blazor-style development.
With mouse, keyboard, and persistent UI requirements, I would prototype both Terminal.Gui and RazorConsole. Choose the model your team can maintain—and verify the actual terminal behavior and Native AOT artifact before committing.
Q&A
1. Is RazorConsole similar to React Ink?
Yes, at the programming-model level. Both make terminal interfaces composable and state-driven using concepts familiar from Web development. Ink uses React and JSX/TSX; RazorConsole uses Razor and C#. This does not imply compatible APIs, identical features, or equivalent performance. Ink documentation · RazorConsole documentation
2. Does RazorConsole support custom mouse and keyboard events?
Yes. It exposes keyboard handlers and mouse events for clicks, movement, hover, buttons, and scrolling. Down/move/up handlers can implement dragging. Native applications must set ConsoleLiveDisplayOptions.EnableMouseEvents = true; coordinates represent terminal cells rather than browser pixels. Mouse guide · Keyboard guide
3. Can I reuse existing Blazor components unchanged?
Not generally. Razor syntax and component concepts transfer, but browser-dependent components may rely on unsupported HTML, CSS, JavaScript, or DOM behavior. Reuse appropriate C# logic, then adapt the presentation to RazorConsole's terminal components and layout model. RazorConsole overview
4. Does using RazorConsole also mean using Spectre.Console?
Yes: Spectre.Console is part of its rendering foundation. RazorConsole adds component authoring, state, and interaction. They therefore operate at different layers rather than being entirely unrelated alternatives. Architecture and custom translators
5. Can Spectre.Console build an interactive application?
It supports interactive prompts and dynamic displays, so it is not limited to static output. However, those capabilities should not be confused with a general-purpose, simultaneously interactive control tree. Its documented Live Display restrictions matter when combining rendering and input. Live Display documentation
6. Does Native AOT guarantee a faster or smaller application?
No universal result follows from enabling it. Removing JIT changes startup behavior, but actual startup time, memory use, and distribution size depend on the workload and dependencies. Measure equivalent applications. Native AOT is also different from ordinary self-contained or single-file publishing. Native AOT overview · .NET deployment models
7. What should I test before selecting an AOT-compatible TUI framework?
Publish a realistic application, inspect trimming/AOT warnings, and run it without an installed .NET runtime on the target platform. Exercise navigation, input, routing, serialization, and required assets. Build for each intended operating system and architecture; one native executable does not run everywhere. Native AOT requirements
8. Are key-release events reliable in every terminal?
No. For example, Terminal.Gui documents that KeyUp requires driver-provided release information; its ANSI implementation relies on appropriate Kitty keyboard-protocol support. Do not design press-and-hold behavior around desktop-style key release without testing the exact terminal and driver combination. Terminal.Gui keyboard documentation
Version note: Package-specific AOT findings refer to the linked source versions; documentation was checked on September 29, 2026.
Top comments (0)