Configuration Deep Dive
Terminal.Gui loads themes, glyphs, key bindings, and view defaults from JSON using Microsoft.Extensions.Configuration via TuiConfigurationBuilder.
The legacy ConfigurationManager type was removed in 2.5.0. To convert a pre-2.5.0 config.json, see Migrating ConfigurationManager to TuiConfigurationBuilder. For the other 2.5.0 API breaks, see 2.5.0 Breaking Changes.
Quick start
Library defaults are applied when Terminal.Gui.dll loads. To overlay runtime JSON or switch themes:
TuiConfigurationBuilder builder = new ("MyApp");
builder.RuntimeConfig = """{ "Theme": "Dark" }""";
builder.ApplyToStaticFacades ();
builder.ThemeManager.SwitchTheme ("Dark");
Views read static facades such as Button.DefaultShadow (backed by ButtonSettings.Current).
Sources and precedence
TuiConfigurationBuilder.Build loads sources lowest-to-highest:
- Hard-coded Settings POCO
initdefaults - Library embedded
Terminal.Gui.Resources.config.json - App embedded
config.json ~/.tui/config.jsonand./.tui/config.json~/.tui/{appName}.config.jsonand./.tui/{appName}.config.jsonTUI_CONFIGenvironment variable (inline JSON)TuiConfigurationBuilder.RuntimeConfig
Later sources override earlier ones property-by-property.
./.tui/ paths resolve against the process's current directory (never the app's install directory).
A bad source never crashes the app. A malformed source (invalid JSON, an unreadable file, an invalid scheme value) is skipped; the error is collected in TuiJsonErrors and logged at shutdown. A legacy-shaped source (dotted keys or array Themes/Schemes) is skipped with a WARN log — convert it with Tools/MigrateConfig.
JSON shape
Settings are nested objects, not dotted keys. The JSON Schema is docfx/schemas/tui-config-schema.json, hosted at https://tui-cs.github.io/Terminal.Gui/schemas/tui-config-schema.json after docs publish.
{
"Theme": "Dark",
"Application": {
"IsMouseDisabled": false
},
"Button": {
"DefaultShadow": "Opaque"
},
"Glyphs": {
"CheckStateChecked": "☑"
},
"Themes": {
"Dark": {
"Button": { "DefaultShadow": "None" },
"Glyphs": { "LeftBracket": "[", "RightBracket": "]" }
}
}
}
Themes is a dictionary of theme name → overlay. Each overlay uses the same nested section names as the root (Button, Glyphs, Dialog, …). Properties omitted from an overlay keep the root value.
A pre-MEC file with "Button.DefaultShadow": "None" or "Themes": [ { "Dark": { } } ] is not applied; a warning is logged. Convert it with Tools/MigrateConfig.
Settings POCOs
| Kind | Types | Storage |
|---|---|---|
| Theme-scoped | ButtonSettings, DialogSettings, GlyphSettings, MenuSettings, … |
Immutable record with Current swapped atomically |
| Process-wide | ApplicationSettings, DriverSettings, KeySettings, ThemeSettings, … |
Mutable Defaults instance |
Theme overlays apply only to theme-scoped POCOs. The selected theme name is ThemeSettings.Defaults.Theme (JSON scalar "Theme").
Key bindings overlay hard-coded defaults from nested JSON:
{
"Application": {
"DefaultKeyBindings": {
"Quit": { "All": ["Esc", "Ctrl+Q"] }
}
},
"View": {
"ViewKeyBindings": {
"TextField": {
"CutToEndOfLine": { "All": ["Ctrl+K"] }
}
}
}
}
Unmentioned commands keep their compile-time bindings. See Keyboard.
To change a theme-scoped default in code:
ButtonSettings.Current = ButtonSettings.Current with { DefaultShadow = ShadowStyles.None };
Themes and schemes
- IThemeManager (
TuiConfigurationBuilder.ThemeManager) lists theme names and callsSwitchTheme. - ThemeChanges.
ThemeChangedis the process-wide observer for theme switches. - Schemes live inside each theme's
Schemesdictionary and are applied through <xref:Terminal.Gui.Drawing.SchemeManager>.
builder.ThemeManager.ThemeChanged += (_, args) =>
{
// args.Value is the new theme name
};
ThemeChanges.ThemeChanged += (_, _) => view.SetNeedsDraw ();
App settings
To bind an application-specific POCO:
public class MyAppSettings
{
public string Title { get; set; } = "My App";
public static MyAppSettings Defaults { get; set; } = new ();
}
TuiConfigurationBuilder builder = new ("MyApp");
builder.BindAppSettings<MyAppSettings> ("MyApp", s => MyAppSettings.Defaults = s);
builder.ApplyToStaticFacades ();
Corresponding JSON:
{ "MyApp": { "Title": "Demo" } }
Custom sources
IConfiguration config = new ConfigurationBuilder ()
.AddTuiLibraryDefaults ()
.AddTuiUserFiles ("MyApp")
.AddJsonFile ("custom-settings.json", optional: true)
.Build ();