Library / SDK
tui-cs/TerminalGuiDesigner avatar
tui-cs/TerminalGuiDesigner

TerminalGuiDesigner gives Terminal.Gui a drag and drop visual designer

Forms Designer for Terminal.Gui (aka gui.cs)

577 stars37 forksC#MIT

At a glance

What is it?
TerminalGuiDesigner is a cross platform designer for Terminal.Gui applications that works the way the WinForms designer does, producing a Designer.cs file that is regenerated on every save. Its most interesting engineering is the dependency handling, since the designer tracks which views hold RelativeTo dependencies on others and refuses to delete a view that others depend on.
Who is it for?
Adopt TerminalGuiDesigner if you build Terminal.Gui applications and want to lay out dialogs visually rather than by hand, since it produces the same Designer.cs pattern WinForms developers already know. Skip it if your views are simple enough to write in a few lines, since the designer has overhead, and if you rely on custom View subclasses, because supporting user defined View types is still an unchecked item on the feature list.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A WinForms designer for a text UI toolkit

TerminalGuiDesigner is a cross platform designer for Terminal.Gui applications, and the comparison the README draws is the one that explains the whole project.

Built with CodeDom and Roslyn, it lets you create complicated views with drag and drop just like the WinForms designer you know and love, or hate.

That parenthetical is doing some work, and it is worth being clear about what the resemblance means. It is not that Terminal.Gui is WinForms, it is that the workflow is the one WinForms developers already have in their hands. You create a dialog, drop controls onto it, set properties in a property grid, save, and get a Designer.cs file that the application instantiates.

The CodeDom and Roslyn part is the mechanism, and it is a deliberate choice over generating code from a template. CodeDom is the .NET component for reading and writing source code as a document model rather than as text, and Roslyn gives the actual parsing and analysis. So the designer emits real C# that the compiler sees, not string templates it hopes will still compile.

The output convention is the WinForms one. You get MyDialog.cs for your own code and MyDialog.Designer.cs for the generated part, and the documentation warns you to avoid making any changes to the Designer file as it will be rewritten when saving.

The project is C#, MIT licensed, with the default branch v2 and the last push on 2026-09-03. The README refers to the project as being in alpha and links a feature list for progress, and the badges point at a NuGet package, a build workflow and a code coverage report.

Two versions ship side by side. Version 1 targets Terminal.Gui version 1 and version 2 targets Terminal.Gui version 2, which is currently pre-alpha, and the instruction is to ensure you match the Terminal.Gui library version you reference to the designer version.

Installing and the one line that matters

The install is a dotnet tool installation, which means it lives in your tool manifest rather than in your project.

For version 1:

code
dotnet tool install --global TerminalGuiDesigner

And to update to the latest version:

code
dotnet tool update --global TerminalGuiDesigner

For version 2, which targets Terminal.Gui version 2 that is currently pre-alpha, you install version 2 of the designer with the prerelease flag:

code
dotnet tool install --global TerminalGuiDesigner --prerelease

And then the instruction that prevents the most common mistake: ensure that you match the Terminal.Gui library version you reference to the designer version.

That is a real constraint, and it is the kind of thing that produces a confusing failure if you ignore it. A designer that generates code for one major version of the library, run against a project referencing another, would produce output that does not match the APIs in use.

The removal command is the mirror of the install:

code
dotnet tool uninstall --global TerminalGuiDesigner

Since it is a global tool, uninstalling it does not touch your project at all, which is one of the advantages of the dotnet tool approach over shipping a designer inside the project.

Building from source is the other route, and it needs the dotnet 8.0 SDK:

code
cd src
dotnet run

The repository layout is conventional for a .NET project with a src/ directory, and the CI badge points at a build workflow.

The usage loop, and the file that gets rewritten

The usage section walks through the whole cycle, and it is short enough to follow end to end.

You install the dotnet SDK and create a new console application with references to Terminal.Gui, then install the designer and create a new dialog:

code
dotnet new console -n hello
cd hello
dotnet add package Terminal.Gui
dotnet tool install --global TerminalGuiDesigner
TerminalGuiDesigner MyDialog.cs

Then you enter a namespace, add a Button to the view, save with Ctrl+S, and exit the designer with Ctrl+Q.

The generated dialog is instantiated in Program.cs:

csharp
using Terminal.Gui;

Application.Init();

Application.Run(new YourNamespace.MyDialog());

Application.Shutdown();

And the key instruction comes next. You can add new code to MyDialog.cs but should avoid making any changes to MyDialog.Designer.cs, as this will be rewritten when saving.

So the split is the WinForms split. The Designer file is generated and owned by the tool. Your file is yours, and the designer even tells you where to put your logic, with an example of adding an event handler after InitializeComponent:

csharp
button1.Accepting += ()=>MessageBox.Query("Hello","Hello World","Ok");

The Accepting event is the Terminal.Gui equivalent of a click handler, and wiring it to MessageBox.Query means clicking the button in the running program shows a message box.

You can re-open the designer at any time by running it from the command line with the file you want to edit or create:

code
TerminalGuiDesigner MyDialog.cs

That is the part that makes it a designer rather than a wizard. The tool is a file argument, not a one-time setup step, so the loop is design, save, write code, run, adjust, re-open.

There is a troubleshooting note for the case where the colours are wrong, and the flag is --usc. The explanation is that the designer is built to be robust with top level catch blocks, but if it can still be crashed you may find your console blocking input, and the fix is to type reset and enter in the console.

The feature list is honest about what is missing

The feature list doubles as a roadmap, and features in italics are experimental and require passing the -e flag when starting the application. That is a useful convention, because it distinguishes what is shipped from what is hidden behind a flag.

What is done covers most of what a designer needs. You can design classes, with Window, Dialog, View and Top level all checked. You can configure root properties such as Window.Width and Title, and subview properties including Name, X and Y, Width and Height, Text and Color Schemes. You can edit multiple views' properties at once, for example selecting three views and setting all Width to 10. Mouse input covers dragging to move, dragging into and out of a subview, and dragging to resize. There is undo and redo, direct editing of text by typing, and easy menu bar designing with create, move, submenu, separators by typing three dashes, shortcuts and field names. Status bar designing is done too, and view dependency management is done, along with multi select, multi delete, multi keyboard move, multi mouse drag move, multi set property, and multi copy and paste.

The dependency management section is the one that shows real thought, and it has three parts. It prevents deleting views where other views hold RelativeTo dependencies. It writes out dependent views to InitializeComponent before dependers, so the initialisation order is correct. And it orders multi delete operations to delete dependers before dependants, which is the mirror image of the previous point.

That last set is what makes the designer safe with a layout. A view positioned relative to another view, in Terminal.Gui terms with RelativeTo, is a dependency edge, and getting the order wrong produces a layout that does not build. Handling it in the tool means you cannot produce that breakage by accident.

Now the unchecked items, which are a fair picture of the remaining work. Create Events such as MyButton_OnClick is not done, so event wiring is manual. Cut is not implemented. To OS clipboard is not done, so you cannot copy a view from one Designer file to another. Move views to subviews with the keyboard is not done, only with the mouse. Reading and presenting xmldoc comments when editing properties is not done. Visual Studio and Visual Studio Code plugins are not done, so there is no right click to open a Designer file in the designer console.

And then the corner cases, which are the interesting group. Allowing the design of abstract classes, of generic classes such as MyDialog with a type parameter, and of classes that inherit from another are all not done, with a note that inherited views should be locked to prevent editing. Locking views to prevent accidental dragging is also not done. Support for user defined View types is not done.

So the designer handles the flat, concrete case well and the inheritance and generics case not at all.

Keybindings are configurable and the menu editor has its own language

The keybindings section is short and it shows a designer that takes the terminal seriously.

You can change keybindings by copying a Keys.yaml file into your current directory. That is a data-driven approach rather than a compiled-in table, so a user who wants different keys can copy a file and edit it, without the tool needing a rebuild.

The menu bar editing controls are then a table, and they read like a description of a text-mode UI rather than a desktop one. Shift Up and Down move the selected menu item up or down. Shift Right moves the selected menu item to a submenu of the one above. Shift Left moves the selected submenu item up a level. Del removes the selected menu item. Enter adds a new menu item. Typing edits the title of the selected item. Ctrl+T sets a shortcut, and Ctrl+R sets the menu field name.

Two of those are unusual. Shift Right moving an item into the submenu of the item above is a specific rearrangement operation that a desktop menu editor does not have, because in a terminal you rearrange with the cursor rather than with a mouse. And typing to edit a title is the same trick the feature list mentions for direct text editing elsewhere in the designer.

New root level menus are added by right clicking the MenuBar and selecting Add Menu. A menu separator is created by typing three dashes. That last one is a nice piece of interface design, since a separator in a menu is a structural element rather than a labelled one, and typing a marker is faster than finding a menu command.

The final section of the feature list is still cut off in the documentation available here, and it enumerates the supported view types. The ones that are checked include Button, Checkbox, ComboBox, DateField, FrameView, GraphView, HexView, Label, Line, ListView and MenuBar, and MenuBar has one unchecked sub-item, Copy and Paste preserving menu entries.

So the designer covers the full set of Terminal.Gui input controls, which is the sign of a tool that has been used rather than sketched.

Editorial conclusion

Adopt TerminalGuiDesigner if you build Terminal.Gui applications and want to lay out dialogs visually rather than by hand, since it produces the same Designer.cs pattern WinForms developers already know. Skip it if your views are simple enough to write in a few lines, since the designer has overhead, and if you rely on custom View subclasses, because supporting user defined View types is still an unchecked item on the feature list. Verify first which Terminal.Gui version you target, since the designer version must match the library version, and whether you use the V1 or the prerelease V2 line, since the two are installed with different flags.

Frequently asked questions

How do I install TerminalGuiDesigner and which version should I pick?

Install it as a global dotnet tool with `dotnet tool install --global TerminalGuiDesigner`, and for the version targeting Terminal.Gui 2, which is currently pre-alpha, add the `--prerelease` flag. You should match the Terminal.Gui library version you reference to the designer version. Update with `dotnet tool update --global TerminalGuiDesigner` and remove with `dotnet tool uninstall --global TerminalGuiDesigner`.

What does the TerminalGuiDesigner generate and what should I not edit?

You create a class file such as MyDialog.cs and the designer writes a companion MyDialog.Designer.cs, in the same pattern as WinForms. You can add your own code to MyDialog.cs, for example an Accepting handler after InitializeComponent, but should avoid changing MyDialog.Designer.cs because it is rewritten each time you save.

What can TerminalGuiDesigner not do yet?

Event creation such as a generated MyButton_OnClick handler is not implemented, nor is cut, copy to the OS clipboard, moving views into subviews with the keyboard, reading xmldoc comments when editing properties, Visual Studio and Visual Studio Code plugins, and locking views against accidental dragging. The corner cases are also open: designing abstract classes, generic classes such as MyDialog with a type parameter, classes that inherit from another, and user defined View types.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. tui-cs/TerminalGuiDesigner on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/tui-cs-terminalguidesigner.svg)](https://hysenlabs.com/projects/tui-cs-terminalguidesigner)

Was this useful?