How configuration works
Noctalia can be configured in two ways: files you write yourself, and settings the app saves for you.
For most people, the important rule is simple: put your own configuration in ~/.config/noctalia/. If something changed in the GUI and now seems to ignore your file, check ~/.local/state/noctalia/settings.toml.
The two layers
Section titled “The two layers”Your hand-written config lives in:
$NOCTALIA_CONFIG_HOME/noctalia/$XDG_CONFIG_HOME/noctalia/- or
~/.config/noctalia/
Noctalia reads every *.toml file in that folder, sorts them alphabetically, and merges them into one config. A single config.toml is the easiest setup:
[theme]mode = "dark"
[bar.main]position = "top"You can also split things up if you like tidy dotfiles:
~/.config/noctalia/├── bar.toml├── theme.toml└── widgets.tomlGUI-managed overrides live in:
$NOCTALIA_STATE_HOME/noctalia/settings.toml$XDG_STATE_HOME/noctalia/settings.toml- or
~/.local/state/noctalia/settings.toml
Noctalia writes this file when you change settings through the UI, setup flows, IPC-backed controls, and other runtime actions that need to persist. If the file is a symbolic link, Noctalia writes through to the link target and keeps the link in place.
NOCTALIA_CONFIG_HOME and NOCTALIA_STATE_HOME have the same “home root” shape as the XDG variables. For example, NOCTALIA_CONFIG_HOME=/tmp/profile reads /tmp/profile/noctalia/. Use these Noctalia-specific variables when you want a separate shell profile without changing the environment inherited by apps launched from Noctalia.
Including extra files
Section titled “Including extra files”Automatic loading only sees *.toml files sitting directly in the config folder. To pull in files from subdirectories, load a specific file, or control load order without renaming files, add an [include] table:
[include]files = [ "widgets/", # a directory: every *.toml inside it (sorted, non-recursive) "bars/top.toml", # a single file "~/.config/shared/base.toml", # ~ , $VAR and ${VAR} are expanded]
# the rest of this file's settings go here as usual[theme]mode = "dark"Each entry is either a directory (which loads every *.toml directly inside it, sorted alphabetically) or a single file. Relative paths resolve against the directory of the file doing the including, so a file in profiles/work.toml can reach a shared bundle with "../widgets/". Paths starting with ~, or containing $VAR / ${VAR}, are expanded.
The including file wins. Included files are merged first, as a reusable base, and then the file’s own settings are layered on top. So a value you set directly in config.toml overrides the same value pulled in from an include:
[include]files = ["bars/base.toml"] # base.toml sets bar.top.thickness = 30
[bar.top]thickness = 40 # this wins — the bar ends up 40Includes can nest (an included file can include more files), and each file is loaded at most once — if two files include the same file, it is merged once and a cycle is detected and skipped rather than looping forever.
Switching profiles
Section titled “Switching profiles”By default, every *.toml in the config folder still loads automatically alongside your includes. If you keep alternative setups in the root that should not all load at once — say profile_a.toml and profile_b.toml — set autoload = false in your entry file. Then only the file(s) that set it (plus whatever they include) load, and the other root files are ignored:
[include]autoload = falsefiles = ["profiles/work.toml"]autoload only has an effect in a file loaded directly from the config folder; it is ignored in included files. [include] is honored in your config files only — it has no effect in the app-managed settings.toml.
Which value wins?
Section titled “Which value wins?”Noctalia loads configuration in this order:
- Built-in defaults
- Your
*.tomlfiles in the resolved config directory — for each file, anything it pulls in via[include]first, then the file’s own settings on top - GUI-managed overrides in the resolved state directory’s
settings.toml
Because settings.toml loads last, it wins when it contains the same setting as your hand-written config layer.
When Settings writes a value that matches the parsed value from the lower layers, Noctalia removes that redundant key
instead of keeping it as a GUI override.
Where should I edit?
Section titled “Where should I edit?”Use ~/.config/noctalia/ for curated config: the things you want to keep in dotfiles, copy to another machine, or manage declaratively.
Treat ~/.local/state/noctalia/settings.toml as an app-managed override file. It is useful to inspect when debugging GUI changes, and safe to delete when you want to clear those overrides. Keeping it outside ~/.config also lets the GUI save changes when your config directory is read-only, for example on NixOS. Support reports include config sources and settings.toml, but omit state.toml contents because they can contain private runtime data.
Both layers are watched for changes and hot-reloaded. If neither layer exists, Noctalia uses its built-in defaults.
File locations
Section titled “File locations”Where Noctalia keeps everything, by purpose:
| What | Where | Purpose |
|---|---|---|
| Your config | ~/.config/noctalia/config.toml | hand-written / declarative — the base layer |
| GUI overrides | ~/.local/state/noctalia/settings.toml | written by Settings; wins over your config |
| Internal UI state | ~/.local/state/noctalia/state.toml | app-managed (calendar account tokens, last-used values) |
| Custom palettes | ~/.config/noctalia/palettes/ | your own color palette files |
| Local plugins | ~/.local/share/noctalia/plugins/ | plugins you install or place by hand |
| Plugin source repos | ~/.local/state/noctalia/plugins/sources/ | git-source repo caches, re-fetchable |
| Exported plugin files | ~/.local/state/noctalia/plugins/materialized/ | runtime files exported from git sources |
| Community palettes / templates | ~/.local/state/noctalia/community-*/ | downloaded catalogs, re-fetchable |
It comes down to two buckets:
- Yours —
~/.config/noctalia/(settings you write) and~/.local/share/noctalia/(plugins you install). - Noctalia’s —
~/.local/state/noctalia/(everything the app writes or fetches: GUI overrides, UI state, plugin repo caches, exported plugin files, downloaded catalogs) — app-managed and regenerable, so it’s always safe to delete.
Every path honors the standard XDG_CONFIG_HOME / XDG_STATE_HOME / XDG_DATA_HOME variables (and the
NOCTALIA_CONFIG_HOME / NOCTALIA_STATE_HOME / NOCTALIA_DATA_HOME overrides).
Exporting config
Section titled “Exporting config”Export the merged user config from the command line:
noctalia config export > noctalia-config.tomlExport the full effective config, including built-in defaults:
noctalia config export full > noctalia-full-config.tomlExport stops with an error (and writes nothing) if a config file fails to parse or an [include] points at a file that does not exist, so a broken config never produces a misleading partial export. (The running shell is more forgiving: it loads what it can and surfaces the problem as a notification.)
Because export writes TOML to stdout, you can pipe it into TOML-aware query tools. For example, with
yq:
noctalia config export full | yq -p toml -r '.theme.mode'noctalia config export full | yq -p toml -r '.shell.offline_mode'noctalia config export full | yq -p toml '.bar.default'If you prefer normal jq filters, convert the TOML stream to JSON first:
noctalia config export full | yq -p toml -o json '.' | jq -r '.theme.mode'The Settings actions menu includes Export Config…. It opens a chooser with two export modes:
- Merged User Config is recommended for dotfiles. It merges your explicit config files and GUI-managed overrides into one TOML file, while leaving built-in defaults implicit.
- Full Effective Config exports the active config snapshot, including built-in defaults. Use it for inspection or sharing an exact state, but avoid treating it as your long-term curated config because it pins defaults that could otherwise evolve.
Validating your configuration
Section titled “Validating your configuration”Run the validator to catch problems before they silently take effect:
noctalia config validateWith no argument it checks the merged configuration exactly as the shell loads it: every *.toml in ~/.config/noctalia/ (or $NOCTALIA_CONFIG_HOME), then the settings.toml overrides in ~/.local/state/noctalia/. Pass a directory to validate just that directory’s *.toml files instead:
noctalia config validate ./my-config-dirPass a file to validate only that TOML file, without scanning default locations or merging settings.toml. This is useful for generated configs, including NixOS-managed config files:
noctalia config validate ./config.tomlIt reports two severities:
- Errors — problems that stop the configuration from loading correctly: TOML syntax errors (with file, line, and column), values that fail to parse such as an invalid color, an
[include]whosefilesentry points at a path that does not exist, or a malformed[include]table (autoloadthat is not a boolean,filesthat is not a list of strings). These exit with status1. - Warnings — things the shell loads fine but quietly ignores or adjusts: unknown/obsolete sections and settings (misspelled or left over from an older version), values outside the allowed range (clamped), and invalid enum choices. Warnings are advisory and do not fail the check. Unknown widget and desktop-widget settings are checked against each widget type’s known options.
A config with only warnings still prints ✓ Config is valid and exits 0 (with the warnings listed), so unknown keys won’t break a pre-commit hook or CI step — they’re surfaced as cleanup hints. Only genuine errors exit 1.
Scripted-widget settings come from each script’s own manifest, so unknown keys under a scripted widget are not flagged.
Where next?
Section titled “Where next?”- Shell covers global behavior like fonts, scale, shadows, OSD, and keybinds.
- Hooks covers advanced event-driven automation.
- Bars and Widgets cover the top or side bar and everything inside it.
- Dock covers the optional app dock.
- Theme covers theme mode and palette source selection.
- Palette covers color roles, custom palette files, and terminal colors.
- App Theming covers generated themes for other apps.
- Template Reference covers template syntax, tokens, filters, and hooks.
- Wallpaper & backdrop covers wallpapers, per-monitor folders, automation, and overview backdrop.
- Service pages cover audio, brightness, calendar, idle, night light, notifications, and weather.
- IPC lists commands for keybinds, scripts, automation, and hooks.