v5-configuration.md
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.
Section titled “The two layers”
Your hand-written config lives in:
$NOCTALIA_CONFIG_HOME/noctalia/$XDG_CONFIG_HOME/noctalia/~/.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:
~/.config/noctalia/config.toml
[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.toml
GUI-managed overrides live in:
$NOCTALIA_STATE_HOME/noctalia/settings.toml$XDG_STATE_HOME/noctalia/settings.toml~/.local/state/noctalia/settings.tomlNoctalia 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.
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:
~/.config/noctalia/config.toml
[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 40
Includes 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.
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:
~/.config/noctalia/config.toml
[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.
Section titled “Which value wins?”
Noctalia loads configuration in this order:
*.toml files in the resolved config directory - for each file, anything it pulls in via [include] first, then the file’s own settings on topsettings.tomlBecause 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.
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.
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 :
~/.config/noctalia/ (settings you write) and ~/.local/share/noctalia/ (plugins you install).~/.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).
Section titled “Exporting config”
Export the merged user config from the command line:
Terminal window
noctalia config export > noctalia-config.toml
Export the full effective config, including built-in defaults:
Terminal window
noctalia config export full > noctalia-full-config.toml
Export 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:
Terminal window
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:
Terminal window
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:
Section titled “Validating your configuration”
Run the validator to catch problems before they silently take effect:
Terminal window
noctalia config validate
With 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:
Terminal window
noctalia config validate ./my-config-dir
Pass 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:
Terminal window
noctalia config validate ./config.toml
It reports two severities:
[include] whose files entry points at a path that does not exist, or a malformed [include] table (autoload that is not a boolean, files that is not a list of strings). These exit with status 1.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.