dotnet-terminal-gui
Building full TUI apps. Terminal.Gui v2: views, layout (Pos/Dim), menus, dialogs, bindings, themes.
What this skill does
# dotnet-terminal-gui
Terminal.Gui v2 for building full terminal user interfaces with windows, menus, dialogs, views, layout, event handling, color themes, and mouse support. Cross-platform across Windows, macOS, and Linux terminals.
**Version assumptions:** .NET 8.0+ baseline. Terminal.Gui 2.0.0-alpha (v2 Alpha is the active development line for new projects -- API is stable with comprehensive features; breaking changes possible before Beta but core architecture is solid). v1.x (1.19.0) is in maintenance mode with no new features.
**Scope boundary:** This skill owns full TUI application development with Terminal.Gui -- application lifecycle, layout, views, menus, dialogs, event handling, themes. Rich console output (tables, progress bars, prompts, markup) is owned by [skill:dotnet-spectre-console]. CLI command-line parsing is owned by [skill:dotnet-system-commandline]. CLI application architecture and distribution are owned by [skill:dotnet-cli-architecture] and [skill:dotnet-cli-distribution].
Cross-references: [skill:dotnet-spectre-console] for rich console output alternative, [skill:dotnet-csharp-async-patterns] for async TUI patterns, [skill:dotnet-native-aot] for AOT compilation considerations, [skill:dotnet-system-commandline] for CLI parsing, [skill:dotnet-csharp-dependency-injection] for DI in TUI apps, [skill:dotnet-accessibility] for TUI accessibility limitations and screen reader considerations.
---
## Package Reference
```xml
<ItemGroup>
<!-- v2 Alpha -- recommended for new projects -->
<PackageReference Include="Terminal.Gui" Version="2.0.0-alpha.*" />
</ItemGroup>
```
Terminal.Gui v2 targets .NET 8+ and .NET Standard 2.0/2.1. For v1 maintenance projects, use `Version="1.19.*"`.
---
## Application Lifecycle
Terminal.Gui v2 uses an instance-based model with `IApplication` and `IDisposable` for proper resource cleanup. This replaces v1's static `Application.Init()` / `Application.Run()` / `Application.Shutdown()` pattern.
### Basic Application
```csharp
using Terminal.Gui;
// Create and initialize the application (instance-based in v2)
using IApplication app = Application.Create().Init();
var window = new Window
{
Title = "My TUI App",
Width = Dim.Fill(),
Height = Dim.Fill()
};
var label = new Label
{
Text = "Hello, Terminal.Gui!",
X = Pos.Center(),
Y = Pos.Center()
};
window.Add(label);
app.Run(window);
```
### Application with Typed Result
```csharp
using IApplication app = Application.Create().Init();
// Run a dialog and get a typed result
app.Run<MyInputDialog>();
string? result = app.GetResult<string>();
```
### Lifecycle Events
```csharp
// IsRunningChanging -- cancellable, fires before state change
// IsRunningChanged -- non-cancellable, fires after state change
window.IsRunningChanged += (sender, args) =>
{
if (!args.NewValue)
{
// Window is closing -- clean up resources
}
};
```
---
## Layout System
Terminal.Gui v2 unifies layout into a single model (v1's Absolute/Computed distinction is removed). Position is controlled by `Pos` (X, Y) and size by `Dim` (Width, Height), both relative to the SuperView's content area.
### Pos Types (Positioning)
```csharp
// Absolute -- fixed coordinate
view.X = 5; // Pos.Absolute(5)
// Percent -- percentage of parent
view.X = Pos.Percent(25); // 25% from left
// Center -- centered in parent
view.X = Pos.Center();
// AnchorEnd -- anchored from right/bottom edge
view.X = Pos.AnchorEnd(10); // 10 from right edge
// Relative to another view
view.X = Pos.Right(otherView) + 1; // 1 right of otherView
view.Y = Pos.Bottom(otherView) + 1; // 1 below otherView
view.X = Pos.Left(otherView); // aligned left with otherView
view.Y = Pos.Top(otherView); // aligned top with otherView
// Align -- align groups of views
view.X = Pos.Align(Alignment.End); // right-align (e.g., dialog buttons)
// Func -- custom function
view.X = Pos.Func(() => CalculateX());
// Arithmetic
view.X = Pos.Center() - 10;
view.Y = Pos.Bottom(label) + 2;
```
### Dim Types (Sizing)
```csharp
// Absolute -- fixed size
view.Width = 40; // Dim.Absolute(40)
// Percent -- percentage of parent
view.Width = Dim.Percent(50); // 50% of parent width
// Fill -- fill remaining space
view.Width = Dim.Fill(); // fill to right edge
view.Width = Dim.Fill(2); // fill minus 2 (margin)
// Auto -- size based on content (replaces v1's AutoSize)
view.Width = Dim.Auto();
view.Width = Dim.Auto(minimumContentDim: 20);
// Relative to another view
view.Width = Dim.Width(otherView);
view.Height = Dim.Height(otherView);
// Func -- custom function
view.Width = Dim.Func(() => CalculateWidth());
// Arithmetic
view.Width = Dim.Fill() - 10;
view.Height = Dim.Height(label) + 2;
```
### Frame vs. Viewport
- **Frame** -- outermost rectangle: location and size relative to SuperView
- **Viewport** -- visible portion of content area: acts as a scrollable portal into the view's content
```csharp
// Set content size larger than viewport to enable scrolling
view.SetContentSize(new Size(200, 100));
// Viewport automatically provides scroll behavior
```
---
## Core Views
### Container Views
```csharp
// Window -- top-level container with title bar and border
var window = new Window
{
Title = "Main Window",
Width = Dim.Fill(),
Height = Dim.Fill()
};
// FrameView -- bordered container without title bar behavior
var frame = new FrameView
{
Title = "Settings",
X = 1, Y = 1,
Width = Dim.Fill(1),
Height = 10
};
window.Add(frame);
```
### Text and Input Views
```csharp
// Label -- static text display
var label = new Label
{
Text = "Username:",
X = 1, Y = 1
};
// TextField -- single-line text input
var textField = new TextField
{
X = Pos.Right(label) + 1,
Y = Pos.Top(label),
Width = 30,
Text = ""
};
// TextView -- multi-line text editor
var textView = new TextView
{
X = 1, Y = 3,
Width = Dim.Fill(1),
Height = Dim.Fill(1),
Text = "Multi-line\nediting area"
};
```
### Button
```csharp
var button = new Button
{
Text = "OK",
X = Pos.Center(),
Y = Pos.Bottom(textField) + 1
};
// Accept event (v2 replaces v1's Clicked)
button.Accepting += (sender, args) =>
{
MessageBox.Query(button.App!, "Info", $"You entered: {textField.Text}", "OK");
args.Handled = true; // prevent event bubbling
};
```
### ListView and TableView
```csharp
// ListView -- scrollable list
var items = new List<string> { "Item 1", "Item 2", "Item 3" };
var listView = new ListView
{
X = 1, Y = 1,
Width = Dim.Fill(1),
Height = Dim.Fill(1),
Source = new ListWrapper<string>(new ObservableCollection<string>(items))
};
listView.SelectedItemChanged += (sender, args) =>
{
// args.Value is the selected item index
};
```
### CheckBox and RadioGroup
```csharp
var checkbox = new CheckBox
{
Text = "Enable notifications",
X = 1, Y = 1
};
checkbox.CheckedStateChanging += (sender, args) =>
{
// args.NewValue is the new CheckState
};
var radioGroup = new RadioGroup
{
X = 1, Y = 3,
RadioLabels = ["Option A", "Option B", "Option C"]
};
radioGroup.SelectedItemChanged += (sender, args) =>
{
// args.SelectedItem is the selected index
};
```
### Additional v2 Views
```csharp
// DatePicker -- calendar-based date input
var datePicker = new DatePicker
{
X = 1, Y = 1,
Date = DateTime.Today
};
// NumericUpDown -- numeric spinner
var spinner = new NumericUpDown<int>
{
X = 1, Y = 3,
Value = 42
};
// ColorPicker -- TrueColor selection
var colorPicker = new ColorPicker
{
X = 1, Y = 5,
SelectedColor = new Color(0, 120, 215)
};
```
---
## Menus and Status Bar
### MenuBar
In v2, `MenuBar` takes a `MenuBarItem[]` constructor parameter. `MenuItem` supports both positional constructors and object initializer syntax.
```csharp
var menuBar = new MenuBar([
new MenuBarItem("_Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.