Theming & accents (nebelung)
The whole system shares one palette: nebelung, a silver-mist Catppuccin variant. It’s Catppuccin with the blue pulled out of the greys and the accents calmed down — a fog-grey scheme for people who find most dark themes too loud. Grey is the point.
nebelung renders that one palette onto 50+ tools — Ghostty, zellij, starship, bat, delta, lazygit, fzf, yazi, helix, btop, Slack, the Zen browser, and more — so the terminal, editor, git, and browser all speak the same colours. The rice wires up the ones it installs for you; the rest are one roster entry away (see Apps you added yourself).
Three knobs, in the order most people reach for them:
| Option | What it changes |
|---|---|
theme.accent | the one hue that tints highlights |
theme.contrast | how far text separates from its background |
theme.flavor | dark or light |
They compose, and all three take effect on the next haus rebuild.
Swapping the accent
Section titled “Swapping the accent”The neutral greys stay fixed; only the accent hue changes. Set it once in your host file:
nebelhaus.theme.accent = "sapphire";Then haus rebuild. The accent re-tints the tools that render per-accent
variants — lazygit borders, fzf highlights, yazi, and the Zen
browser — while the single-file dotfiles (Ghostty, starship, tmux, bat,
zellij) keep their built-in theme.
Available accents
Section titled “Available accents”The default is mauve. Any of the 14 Catppuccin accent names works:
rosewater · flamingo · pink · mauve · red · maroon · peach ·
yellow · green · teal · sky · sapphire · blue · lavender
See their exact hex values on the palette reference.
Contrast
Section titled “Contrast”The default greys are deliberately soft. If text doesn’t separate enough from its background — a bright room, a glossy screen, or just eyes that prefer more edge:
nebelhaus.theme.contrast = "high";Same hues, same accents; the neutral ramp is pulled apart in OKLCH so every step gains separation. Body text goes from 11.3:1 to 19.9:1 against the background, which is measured in nebelung’s CI rather than eyeballed — and having now been looked at on a real screen, it reads crisp rather than harsh.
Light mode
Section titled “Light mode”nebelhaus.theme.flavor = "latte";Light mode is not the dark palette inverted. nebelung is “Catppuccin with the blue stripped out”, and that recipe says nothing about dark — so it’s applied to Catppuccin Latte instead of Mocha to get the same theme in the other polarity: the same warm-grey neutral ramp, the same calmed accents, read the other way up.
Because it’s a real re-render rather than a recolour, tools take their light-mode
branches properly — terminal ANSI black/white swap around, the Zen browser
switches its prefers-color-scheme block, delta marks itself light = true.
Light mode lands at 7.0:1 for body text on its own, so it’s legible before you reach for contrast. The two axes compose:
contrast = "normal" | contrast = "high" | |
|---|---|---|
flavor = "mocha" | 11.3:1 | 19.9:1 |
flavor = "latte" | 7.0:1 | 9.9:1 |
Obsidian vaults
Section titled “Obsidian vaults”Obsidian keeps themes and appearance settings inside each vault, so the rice doesn’t guess which folders are yours. List the vaults you want Nebelung to manage as home-relative paths:
nebelhaus.hearth.obsidianVaults = [ "Library/Mobile Documents/iCloud~md~obsidian/Documents/notes"];Then haus rebuild. For every listed vault, Hearth:
- copies the generated full Nebelung theme into
.obsidian/themes/Nebelung/; - selects Nebelung’s appearance (dark today, regardless of
theme.flavor— Obsidian is one of the places light mode does not yet reach); and - disables the obsolete
nebelungCSS snippet if it was enabled.
The rest of appearance.json is merged and preserved. A path is skipped with a
warning unless it already contains .obsidian, so a typo won’t create an empty
lookalike vault. List multiple paths to keep several vaults in sync; the default
[] touches none.
Apps you added yourself
Section titled “Apps you added yourself”Everything above covers the tools the rice installs — it owns their configs and themes each one properly. Apps you put in your roster get the same treatment automatically, as long as the name you keyed the entry under matches a nebelung port:
nebelhaus.apps = { zed = { key = "e"; name = "Zed"; appId = "dev.zed.Zed"; cask = "zed"; }; warp = { key = "w"; name = "Warp"; appId = "dev.warp.Warp-Stable"; cask = "warp"; };};On the next haus rebuild, each one’s Nebelung theme is written where that app
looks for themes — ~/.config/zed/themes/, ~/.warp/themes/ — in your current
flavor, contrast and accent, and re-written whenever you change them. Nothing
else to wire.
The key is the roster id, not the display name: zed, not zed-editor. Set
nebelhaus.theme.ports.enable = false to turn the whole pass off.
Which ones need a click
Section titled “Which ones need a click”Dropping a theme file is enough for apps that read a fixed path. Plenty of others — Xcode, Warp, OBS, JetBrains, Tabby — have no file interface for choosing a theme; the file is put where they look, and the one-time pick stays yours. A handful more (Slack, Raycast, qBittorrent) can’t be installed by file at all.
Rather than leave you to discover that months later wondering why an app still
looks stock, haus doctor tells you exactly where each one stands:
🌫 Nebelung theme ✓ gitui — themed (~/.config/gitui/theme.ron) ⓘ Xcode — placed at ~/Library/…/Catppuccin Mocha.xccolortheme — pick it in the app's settings ⓘ Slack — not installed — copy the comma-separated hex string → Slack ▸ Preferences ▸ Themes ▸ pasteA ✓ is live now. A ⓘ tells you the one move left. nebelung publishes which is which per tool — the full table is in its ports documentation.
Why bake, not load at runtime?
Section titled “Why bake, not load at runtime?”Colours are generated at build time from a single source, not loaded from
loose theme files. That means the palette can never drift out of sync: change
nebelung, nix flake update, rebuild, and every tool gets the exact same new
values at once. No “I updated the terminal but forgot lazygit” surprises.
Using nebelung outside the rice
Section titled “Using nebelung outside the rice”nebelung is a standalone colour system — you can theme any tool without the rest of nebelhaus. Two ways:
-
Copy a rendered theme. Each tool’s theme is generated into the flake’s output tree; grab the file for your tool and point its config at it. See the palette reference for the per-tool paths.
-
Consume the flake. Add the input and reference the built output:
inputs.nebelung.url = "github:nebelhaus/nebelung";# then: ${nebelung.packages.${system}.default}/<tool>/...The flake also exposes a raw
paletteattrset (name → "#hex") for configs you generate yourself.
Tuning the palette itself
Section titled “Tuning the palette itself”Want a different fog? The palette is computed in
OKLCH space from a handful of knobs in nebelung’s
scripts/generate-palette.mjs — the grey’s hue and chroma, how much the accents
are calmed, which Catppuccin flavor to strip, and how far to push the contrast —
then rebuilt with ./build.sh. That’s a nebelung-repo
change rather than a host-file one; the palette reference
covers the details.