Terminal.Gui loads themes, glyphs, key bindings, and view defaults from JSON using Microsoft.Extensions.Configuration via xref:Terminal.Gui.Configuration.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.
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).
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.
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.
| 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 };- xref:Terminal.Gui.Configuration.IThemeManager (
TuiConfigurationBuilder.ThemeManager) lists theme names and callsSwitchTheme. - xref:Terminal.Gui.Configuration.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 ();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" } }IConfiguration config = new ConfigurationBuilder ()
.AddTuiLibraryDefaults ()
.AddTuiUserFiles ("MyApp")
.AddJsonFile ("custom-settings.json", optional: true)
.Build ();