inline terminal rendering · .NET 10
dcli
Styled output flows into the terminal's real scrollback, while a small interactive region — input line, status bar, dropdowns, dialogs — stays pinned at the bottom. It's the rendering model behind Claude-Code-style CLIs.
Inline, not full-screen
No alternate screen. Your program's output and the user's history stay in native scrollback, exactly where a CLI user expects them.
Commit horizon
Only a bounded window near the bottom is re-rendered; everything above is frozen, write-once, and owned by the terminal.
Fixed region
A pinned bottom stack — input editor and status bar, with a dialog slot above and an autocomplete dropdown below.
Single-writer loop
One actor thread owns all UI state and stdout. You post fire-and-forget commands in; events flow out on a channel.
Awaitable dialogs
SelectAsync / MultiSelectAsync / ChoiceAsync / InputAsync and wizards read like ordinary async calls.
Testable without a TTY
A companion Dcli.Testing package provides a HeadlessTerminal harness for frame-snapshot tests.
Install
dotnet add package dcli --prerelease
The current line is a release candidate (
0.2.0-rc.x); drop--prereleaseonce a stable version ships.
Quick start
using Dcli;
// StartAsync enters raw mode and starts the render loop. `await using`
// guarantees the terminal is restored on every exit path.
await using Terminal terminal = await Terminal.StartAsync(new TerminalOptions());
terminal.Status.SetRows(Line.FromText("Type a message and press Enter. Ctrl+C to quit."));
terminal.Scrollback.Append("Welcome to the echo demo.");
await foreach (TerminalEvent evt in terminal.Events.ReadAllAsync())
{
switch (evt)
{
case InputSubmitted(var text):
terminal.Scrollback.Append(new LineBuilder().Dim("> ").Text(text).Build());
terminal.Input.Clear();
break;
}
}
The mental model in 30 seconds
| Concept | What it means |
|---|---|
| Inline rendering | No alternate screen. Output scrolls into the terminal’s native history. |
| Commit horizon | Only a bounded window near the bottom is re-rendered; everything above is frozen. |
| Fixed region | The pinned bottom stack: input editor + status bar, dialog slot, dropdown. |
| Single-writer loop | One actor thread owns all UI state and stdout. |
| Mechanics vs. semantics | dcli renders and routes keys. You own protocols and what “submit” means. |
- Target framework:
net10.0· License: MPL-2.0 - Platforms: Linux, macOS, Windows (modern VT terminals)
Full guides — concepts, styled text, dialogs, events, testing, architecture, API reference — are in the repository docs.