noctalia
Generates a custom colour palette for the Noctalia shell, a Wayland desktop shell (bar, dock, launcher, control center, notifications) for compositors like niri and Hyprland.
Noctalia ships its own Material You palette generator that derives colours from your wallpaper. This plugin doesn't replace that — it writes Noctalia's custom palette file so that, when you switch Noctalia to source = "custom", its colours match the rest of your tinct-themed desktop (terminals, niri, editors, …) instead of being generated independently.
Installation
tinct plugins install noctalia
Or build from this repo and add the binary manually:
cd contrib/plugins/output/noctalia && go build -o tinct-plugin-noctalia .
tinct plugins add ./tinct-plugin-noctalia
Quick start
tinct generate -i image -p ~/Pictures/wallpaper.jpg -o noctalia
Then point Noctalia at the generated palette once (see Integration).
Generated files
| File | Path | Role |
|---|---|---|
tinct.json | ~/.config/noctalia/palettes/tinct.json | Custom palette. A dark and light variant, each with the 16 Material-3 roles Noctalia uses plus a terminal colour block. |
Integration
Noctalia selects where its palette comes from in its config. Set the source to custom and name the palette tinct (the file is tinct.json, referenced without the extension).
Noctalia v5 (current, native — TOML at ~/.config/noctalia/*.toml):
[theme]
mode = "dark" # dark | light | auto
source = "custom" # use the palette file instead of wallpaper generation
custom_palette = "tinct" # reads ~/.config/noctalia/palettes/tinct.json
Noctalia v4 (Quickshell/QML) stores schemes at ~/.config/noctalia/colorschemes/<name>/<name>.json and selects them in Settings → Color Scheme. Point --noctalia.output-dir accordingly if you run v4 (see Flags).
Colour role mapping
tinct's role model is already Material Design 3, so the mapping is close to 1:1:
| Noctalia role | Tinct role |
|---|---|
mPrimary / mOnPrimary | accent1 / onAccent1 |
mSecondary / mOnSecondary | accent2 / onAccent2 |
mTertiary / mOnTertiary | accent3 / onAccent3 |
mError / mOnError | danger / onDanger |
mSurface / mOnSurface | surface / onSurface |
mSurfaceVariant / mOnSurfaceVariant | surfaceVariant / onSurfaceVariant |
mOutline | outline |
mShadow | shadow |
mHover / mOnHover | accent4 / onAccent4 |
terminal.normal / terminal.bright | tinct ANSI palette (16 colours) |
terminal.foreground / background | foreground / background |
Both dark and light variants are written in one file when tinct produces a dual theme; a single-theme run still writes a valid file (the required dark key is always present).
Reload behaviour
Automatic
After writing the palette the plugin runs:
noctalia msg config-reload
That forces a config reload, which re-runs Noctalia's theme resolution and — with source = "custom" — re-reads tinct.json from disk. No user action required.
The reload is skipped when the palette did not change. Generate compares the rendered palette against the file already on disk; if they are byte-identical the shell is left alone, because a reload makes Noctalia re-read its whole config tree. Regenerating from the same wallpaper therefore costs nothing.
noctalia is an optional binary — the plugin detects Noctalia by config directory, not by binary, so you can still generate into a config tree for another machine. A missing binary, or a shell that isn't running, is a non-fatal no-op, and the call runs under a timeout.
Why a reload is needed at all: Noctalia does not watch the palette file. It inotifies ~/.config/noctalia non-recursively and only treats a changed *.toml as a config change — palettes/tinct.json misses on both counts (subdirectory, and not TOML). Without the nudge the file is rewritten and the running shell keeps the colours it resolved at startup.
noctalia msg color-scheme-set custom tinct also re-reads the palette, but it persists the selection into ~/.local/state/noctalia/settings.toml, which then shadows your own config. Prefer config-reload.
Manual fallback
Noctalia v4 needs the scheme re-selected (or the shell restarted) after a new scheme file appears; existing-scheme edits reload on selection. There is no dedicated "reload colour scheme" IPC command — the known nudge to force a re-apply is toggling dark mode twice:
qs -c noctalia-shell ipc call darkMode toggle
qs -c noctalia-shell ipc call darkMode toggle
Uninstall / revert
- In Noctalia's config, set
[theme] sourceback towallpaper(orbuiltin). - Delete the palette file:
rm ~/.config/noctalia/palettes/tinct.json
tinct plugins delete noctaliato drop the plugin.
Flags
| Flag | Default | Description |
|---|---|---|
--noctalia.output-dir | ~/.config/noctalia/palettes | Output directory for the palette file (use ~/.config/noctalia/colorschemes/tinct for Noctalia v4) |
Flags can also be passed as JSON via --plugin-args, e.g. tinct generate ... -o noctalia --plugin-args noctalia='{"output-dir":"/some/path"}'.
Customising the template
tinct plugins templates dump -o noctalia -l ~/.config/tinct/templates/noctalia
This writes templates/palette.json.tmpl, rendered once per variant. tinct uses your version in preference to the embedded default.
Troubleshooting
Colours unchanged after generating
Noctalia is still on its wallpaper/builtin generator. Set [theme] source = "custom" and custom_palette = "tinct" (v5), or select the scheme in Settings (v4). Check with:
noctalia msg color-scheme-get # expect: custom tinct
If that already reports custom tinct, the reload did not reach the shell. Run noctalia msg config-reload by hand: if the colours change, noctalia was not on $PATH during the generate (tinct generate ... -o noctalia --verbose warns about the missing optional binary).
custom palette 'tinct' not found or invalid
Noctalia logs this and falls back to the builtin palette when it cannot read or parse the file. Check that ~/.config/noctalia/palettes/tinct.json exists, is readable by your user, and contains a dark key.
Plugin skipped ("required directory does not exist")
Detection is by config directory: the plugin declares ~/.config/noctalia (or $NOCTALIA_CONFIG_HOME / $XDG_CONFIG_HOME/noctalia) as a required directory, and tinct's hook runner skips the plugin when it is absent. Create the directory to enable the plugin, or pass --noctalia.output-dir — an explicit destination disables the config-directory check, which is how you generate for a machine that has no Noctalia install of its own.