nebelhaus.* options
These are the nebelhaus.* options you set in your host file at
~/.config/nix/hosts/<hostname>/default.nix. Everything here is optional
unless noted; the defaults are a complete, working system.
Apply changes with haus rebuild. Each option lists its type and
default under its name, and links to the file that declares it.
nebelhaus.git
Section titled “nebelhaus.git”Your commit identity — set your own. It stays in your host file.
nebelhaus.git.email
Section titled “nebelhaus.git.email”string · default ""
Git user.email for commits.
Example:
"ada@example.com"Declared in modules/hearth/options.nix.
nebelhaus.git.name
Section titled “nebelhaus.git.name”string · default ""
Git user.name for commits (hearth wires it into home-manager).
Example:
"Ada Lovelace"Declared in modules/hearth/options.nix.
nebelhaus.git.shellAliases
Section titled “nebelhaus.git.shellAliases”attribute set of (null or string) · default { }
Per-host additions and overrides for Hearth’s built-in Git shell aliases. Values are shell command strings; null removes a built-in. Hearth deliberately owns a compact, framework-independent default set, so this changes only Git shortcuts and does not require a shell plugin manager.
Example:
{ gst = "git status --short --branch"; # replace a built-in gsync = "git pull --rebase --autostash"; # add one gco = null; # remove one}Declared in modules/hearth/options.nix.
nebelhaus.git.signingKey
Section titled “nebelhaus.git.signingKey”string · default ""
GPG key id for signing commits/tags. Empty disables commit signing. Key material + any YubiKey/smartcard setup live outside Nix (gpg-agent + pinentry-mac).
Example:
"6F7BD6F43A7C1420"Declared in modules/hearth/options.nix.
nebelhaus.apps
Section titled “nebelhaus.apps”The shared app roster: one entry per app, driving the launcher key, its workspace, the bar pill, the cheatsheet, and optionally its Homebrew cask.
nebelhaus.apps
Section titled “nebelhaus.apps”attribute set of (submodule) · default { }
The shared app roster, keyed by a stable app id. This is the canonical, composable source for AeroSpace launcher keys and workspaces, SketchyBar pills, the pounce cheatsheet, and optional Homebrew casks.
Attribute-set entries merge across Nix modules, so a host, an imported file, and pounce’s “Install App” command can each contribute one app without parsing or replacing a monolithic list. Set an entry’s enable field to false to remove it, or override individual fields by app id.
Example:
{ slack = { key = "s"; name = "Slack"; workspace = "S"; appId = "com.tinyspeck.slackmacgap"; barIcon = ":slack:"; cask = "slack"; };}Declared in modules/options.nix.
nebelhaus.apps.<name>.appId
Section titled “nebelhaus.apps.<name>.appId”null or string · default null
Bundle id, used for the AeroSpace on-window-detected
auto-assign rule and the wake-time re-sort. null skips
auto-assignment (the app still launches, it just isn’t herded
to its workspace). Find one with osascript -e 'id of app "…"'.
Example:
"com.tinyspeck.slackmacgap"Declared in modules/options.nix.
nebelhaus.apps.<name>.barIcon
Section titled “nebelhaus.apps.<name>.barIcon”null or string · default null
The SketchyBar workspace-pill glyph. A sketchybar-app-font ligature like “:slack:” renders the app’s logo; any other string is drawn in the bar’s Nerd Font. null falls back to the workspace letter. Ignored when workspace is null.
Example:
":slack:"Declared in modules/options.nix.
nebelhaus.apps.<name>.cask
Section titled “nebelhaus.apps.<name>.cask”null or string · default null
Homebrew cask that installs this app. When set, it’s appended to homebrew.casks so declaring the app also installs it. null means “already present / installed some other way” (e.g. Safari, Music).
Example:
"slack"Declared in modules/options.nix.
nebelhaus.apps.<name>.enable
Section titled “nebelhaus.apps.<name>.enable”boolean · default true
Whether this app participates in the shared launcher roster.
Declared in modules/options.nix.
nebelhaus.apps.<name>.key
Section titled “nebelhaus.apps.<name>.key”string · no default
The leader letter for this app: tap Caps Lock then this key to launch/focus it. Must be unique across the roster.
Example:
"s"Declared in modules/options.nix.
nebelhaus.apps.<name>.label
Section titled “nebelhaus.apps.<name>.label”null or string · default null
Cheatsheet caption for the leader key. null uses name.
Example:
"Slack"Declared in modules/options.nix.
nebelhaus.apps.<name>.name
Section titled “nebelhaus.apps.<name>.name”string · no default
macOS application name, as passed to open -a.
Example:
"Slack"Declared in modules/options.nix.
nebelhaus.apps.<name>.order
Section titled “nebelhaus.apps.<name>.order”signed integer · default 1000
Roster order; lower values appear first. Ties are sorted by app id.
Declared in modules/options.nix.
nebelhaus.apps.<name>.workspace
Section titled “nebelhaus.apps.<name>.workspace”null or string · default null
The AeroSpace workspace this app owns — its window auto-moves
here, it gets a SketchyBar pill, and the leader then ⇧
Example:
"S"Declared in modules/options.nix.
nebelhaus.theme
Section titled “nebelhaus.theme”Colour and wallpaper.
nebelhaus.theme.accent
Section titled “nebelhaus.theme.accent”one of "rosewater", "flamingo", "pink", "mauve", "red", "maroon", "peach", "yellow", "green", "teal", "sky", "sapphire", "blue", "lavender" · default "mauve"
The accent colour, by Catppuccin name (the Nebelung palette is a grey-tinted Catppuccin, so the fourteen names are the same in both flavors — the hue you pick follows nebelhaus.theme.flavor). It recolours the tools nebelhaus injects colours into — lazygit, fzf, yazi, and the Zen browser — via the matching Nebelung per-accent ports.
Honest scope: this moves the accent on those tools, NOT literally everything. Single-file dotfiles that bake the palette at their own theme slot (ghostty, starship, tmux, bat, zellij, …) keep their built-in colour and don’t follow this option. The base palette stays the same Nebelung grey either way — only the accent hue changes.
Example:
"sapphire"Declared in modules/theme/options.nix.
nebelhaus.theme.contrast
Section titled “nebelhaus.theme.contrast”one of "normal", "high" · default "normal"
How far the interface separates from its background.
“high” swaps in the Nebelung high-contrast palette: the same hues and the same accents, with the neutral ramp pulled apart in OKLCH so text and background separate further at every step. Measured rather than eyeballed — body text goes from 11.3:1 to 19.9:1 against the base, clearing WCAG AAA (nebelung’s own CI asserts it).
Composes with flavor, and the boost is tuned per flavor rather than
shared: light mode has far less room above its background before the ramp
clips to white, so latte goes 7.0:1 → 9.9:1 where mocha goes 11.3 → 19.9.
Both keep all twelve ramp steps distinct, which is the property nebelung’s
tests actually assert.
Honest scope. This recolours what the rice injects colours into:
Ghostty, bat, delta, lsd, yazi, zellij, glow, starship, lazygit, the
bar, pounce and trill (at runtime, via ~/.config/{pounce,trill}/themes/ —
and unlike flavor, contrast reaches both on BOTH halves of their
light/dark pair), Zen and Obsidian. It does NOT reach:
- macOS itself. For system-wide contrast see nebelhaus.accessibility.increaseContrast — a separate, FDA-gated setting. The two are complementary, and a genuinely high-contrast machine wants both.
Example:
"high"Declared in modules/theme/options.nix.
nebelhaus.theme.flavor
Section titled “nebelhaus.theme.flavor”one of "mocha", "latte" · default "mocha"
Light or dark. “mocha” (the default) is the rice as it has always been; “latte” is light mode.
Not an inversion of the dark palette — a different SOURCE palette. Nebelung is “Catppuccin with the blue stripped out”, and those rules say nothing about dark, so they apply to Catppuccin Latte just as well: same warm-grey neutral ramp, same calmed accents, the other polarity. Light mode lands at 7.0:1 for body text on its own, so it’s legible before you reach for contrast = “high” (which takes it to 9.9:1).
It composes with contrast: the two axes give four palettes, and nebelung’s
CI measures each one’s contrast ratio rather than eyeballing it.
Honest scope, in two parts.
What follows it: every tool the rice injects colours into or points at a
rendered theme — Ghostty, bat, delta, lsd, yazi, fzf, glow, starship,
lazygit, helix, zellij, opencode, the bar, Zen and Obsidian.
These are genuinely re-rendered for the flavor, not recoloured in place:
whiskers takes different branches for a light flavor (terminal ANSI
0/7/8/15 swap, Zen switches its prefers-color-scheme block, delta sets
light = true).
What does NOT follow it:
- pounce and trill, by default. Both read their palette at runtime and
can pick per polarity, so nebelhaus.pounce.followSystemAppearance
and nebelhaus.trill.followSystemAppearance (default true) hand that
choice to macOS Light/Dark instead: the rice installs every rendered
variant into ~/.config/{pounce,trill}/themes/ and writes the
dark/light PAIR at your
contrast. Set either option false to pin that app to this flavor like everything else. - macOS’s own Light/Dark appearance. Turning ON dark mode is one typed setting, but turning it OFF means DELETING a default rather than writing one, which nix-darwin has no way to express — so the rice leaves system appearance alone in both directions and you set it in System Settings ▸ Appearance. A latte rice on a dark macOS looks half-done, and that half is currently yours — except in pounce and trill, which read the appearance themselves.
- the desktop wallpaper (nebelhaus.theme.wallpaper). The three hand-made looks have the dark palette baked in; only “bold” is generated, and it follows theme.accent rather than the flavor.
Example:
"latte"Declared in modules/theme/options.nix.
nebelhaus.theme.ports.enable
Section titled “nebelhaus.theme.ports.enable”boolean · default true
Theme the apps in your roster (nebelhaus.apps) that Nebelung ships a
port for, without wiring each one by hand.
The rice already themes every tool it installs itself — the shell, the
terminal, the git stack, Zen, Obsidian. This covers the other direction:
an app YOU added to the roster that Nebelung happens to have a theme for.
Add zed, warp or xcode to nebelhaus.apps and its Nebelung theme
lands where that app looks for themes, in the flavor and contrast you
selected, following them on every rebuild. Matching is by roster id, so
the entry has to be named after the port (zed, not zed-editor).
Honest scope, and it is the whole point of the option: this drops the
theme FILE. Whether that alone makes the theme active is the app’s
choice, not ours, and Nebelung records which is which per port. Ghostty
reads a config key we own, so it just works. Xcode, Warp, OBS and friends
offer no file interface for picking a theme — the file is put where they
look, and the one click that selects it stays yours. haus doctor lists
exactly which apps are waiting on that click, so the difference is
visible rather than something you discover months later.
Ports whose install is a merge into an existing config file, or that need a compile step first, are reported but never written: silently half-applying someone’s config is worse than saying so.
Declared in modules/theme/options.nix.
nebelhaus.theme.wallpaper
Section titled “nebelhaus.theme.wallpaper”one of "none", "orbits", "constellation", "flow", "bold" · default "none"
The desktop wallpaper, set at each home-manager activation (osascript, every desktop on the current Space). Four Nebelung looks:
orbits · constellation · flow hand-made, the palette baked in bold generated from theme.accent, so it follows the accent (a bold pink at accent = “pink”)
Default “none” leaves your current wallpaper alone — changing the desktop is visible and personal, so nothing moves unless you ask (the bootstrap interview offers the choice on a fresh install).
Example:
"orbits"Declared in modules/theme/options.nix.
nebelhaus.fonts
Section titled “nebelhaus.fonts”The terminal font. The bar keeps its own font at its own tuned sizes.
nebelhaus.fonts.mono.name
Section titled “nebelhaus.fonts.mono.name”string · default "JetBrainsMono Nerd Font Mono"
The terminal font family, as Ghostty’s font-family names it.
This should be a NERD FONT patched build: starship’s prompt, lsd’s
icons, and yazi all draw with glyphs a stock font renders as tofu.
If you change this, set package too — the rice can only install a
font it’s been given.
Example:
"Berkeley Mono"Declared in modules/den/options.nix.
nebelhaus.fonts.mono.package
Section titled “nebelhaus.fonts.mono.package”null or package · default null
The package providing name. null (the default) installs the rice’s
own JetBrains Mono Nerd Font, which is what name defaults to.
Set this whenever you change name, or the family simply won’t exist
on the machine and Ghostty will silently fall back — the rice warns if
it spots that combination.
Example:
pkgs.nerd-fonts.fira-codeDeclared in modules/den/options.nix.
nebelhaus.fonts.mono.size
Section titled “nebelhaus.fonts.mono.size”positive integer, meaning >0 · default 19, scaled by nebelhaus.ui.scale
Terminal font size in points. The single most useful knob for a larger-text machine, since it moves everything the rice actually lives in.
19 (at ui.scale = 1.0) is the base for a reason worth knowing: the Ghostty window is
tiled to a fixed pixel height by prowl, and sizes that don’t divide
that height evenly used to leave a gap under zellij’s status bar.
That’s since been fixed properly (window-padding-balance +
extend-always), so any size is safe now — 19 is simply the tuned
starting point.
Example:
24Declared in modules/den/options.nix.
nebelhaus.hearth
Section titled “nebelhaus.hearth”The shell and terminal experience.
nebelhaus.hearth.editor
Section titled “nebelhaus.hearth.editor”string · default "hx"
The ONE editor the rice uses everywhere. It’s the shell command for $EDITOR / $VISUAL (git, etc.) AND what every “open in an editor” action launches — the “Nix Config” palette command, the bar’s nix-open item, and the file-association hijack. Those open the target in a new zellij tab running this command, so a terminal editor (hx, nvim, vim, nano) is the natural fit for the rice; a GUI editor’s CLI works too (e.g. “code” or “code -w” to block).
Example:
"nvim"Declared in modules/hearth/options.nix.
nebelhaus.hearth.hijackFileAssociations
Section titled “nebelhaus.hearth.hijackFileAssociations”boolean · default false
When true, build a small opener app and make it the default handler
for ~80 text/code extensions (json, md, ts, nix, rs, go, kdl, …), so
opening or clicking those files opens them in nebelhaus.hearth.editor in
a terminal tab. The app declares the types itself (not just duti) so
extensions nothing else on the machine declares still bind. Off by
default: silently rewriting your file associations is a jarring,
hard-to-undo change, so it’s strictly opt-in. (Extensionless executables
like bench are NOT covered — macOS gates the public.unix-executable
handler behind an interactive dialog; set it by hand once if wanted:
duti -s org.nebelhaus.editoropen public.unix-executable all.)
Declared in modules/hearth/options.nix.
nebelhaus.hearth.obsidianVaults
Section titled “nebelhaus.hearth.obsidianVaults”list of string · default [ ]
Home-relative paths to existing Obsidian vaults that should use the Nebelung theme. On each activation, Hearth copies the rendered theme.css + manifest.json into each vault’s .obsidian/themes/Nebelung/ directory, selects Nebelung’s dark appearance in appearance.json, and removes the obsolete “nebelung” CSS snippet from the enabled list.
Empty (the default) leaves every vault untouched. Paths must be relative to the user’s home, may not contain ”..”, and are skipped with a warning unless their .obsidian directory already exists.
Example:
[ "Library/Mobile Documents/iCloud~md~obsidian/Documents/notes"]Declared in modules/hearth/options.nix.
nebelhaus.hearth.zellijStartLocked
Section titled “nebelhaus.hearth.zellijStartLocked”boolean · default true
When true (the default), zellij boots into Locked input mode instead of
Normal — its single-key submode leaders (pane, tab, resize, …) stay
inert until you unlock with Ctrl-g, so a stray keystroke can’t jump you
into a submode. The Super-prefixed launchers (claude / pane / tab /
yazi-peek / fullscreen) are bound in shared and keep working while
locked, as do Alt [ / Alt ] (cycle swap layouts) — the rest of
zellij’s Alt row stays inert while locked, since those keys are
readline/vim word motions the pane’s app wants. The bar’s bottom-right
quick-hint block only shows in Locked mode. Set false to start in Normal
mode (zellij’s own default).
Declared in modules/hearth/options.nix.
nebelhaus.claude
Section titled “nebelhaus.claude”Claude Code integration.
nebelhaus.claude.globalMd
Section titled “nebelhaus.claude.globalMd”strings concatenated with "\n" · default ""
Contents of Claude Code’s global memory file, written to
~/.claude/CLAUDE.md (hearth wires it into home-manager). This is your
personal, cross-project operating context. When set, the rice prepends
one short section of its own — the wt child worktree rule, since the
rice ships wt and that rule is what keeps it working — then your text.
Leave it empty to manage ~/.claude/CLAUDE.md fully by hand (nothing is
written, so the rice never clobbers a by-hand file).
Example:
'' # CLAUDE.md — global How I like to work across every repo…''Declared in modules/hearth/options.nix.
nebelhaus.claude.skill
Section titled “nebelhaus.claude.skill”boolean · default true
Install the nebelhaus Claude Code skill into
~/.claude/skills/nebelhaus, so an agent asked to “install Slack” or
“make everything bigger” edits your host file and runs haus rebuild
instead of guessing at dotfiles and brew install.
The skill’s option reference is GENERATED from the rice revision this
machine is pinned to, so it can only ever describe options that
actually exist here — and it is regenerated by haus update. It also
carries this host’s current state (which rooms are on, where the host
file is) and a starter CLAUDE.md for your config repo.
Unrelated to Claude Code’s own settings, which follow nebelhaus.developer.agents.enable. This is a plain file drop: a machine that never runs an agent just carries an unread markdown file. Set false to leave ~/.claude/skills alone entirely.
Declared in modules/hearth/options.nix.
nebelhaus.accessibility
Section titled “nebelhaus.accessibility”macOS accessibility keys the rice can actually apply. These write to a TCC-protected domain, so they take effect only when the app you run the rebuild from holds Full Disk Access — otherwise the rice warns and moves on.
nebelhaus.accessibility.differentiateWithoutColor
Section titled “nebelhaus.accessibility.differentiateWithoutColor”null or boolean · default null
macOS’s “Differentiate without colour” — native UI adds shapes and text where it would otherwise rely on hue alone. The setting to pair with a rice built for colour-blind readability.
null (the default) leaves whatever you have alone — this is a personal setting, so the rice never picks a value for you.
REACHABILITY: com.apple.universalaccess is TCC-protected. It writes
only when the app that runs the rebuild holds Full Disk Access
(System Settings ▸ Privacy & Security ▸ Full Disk Access; on macOS 26
a stale grant often needs removing and re-adding with (+)). Without
that grant the rice logs a warning and moves on — it does NOT fail
the rebuild. Worth knowing: an agent-driven haus rebuild runs under
a different app than your terminal, so it may skip this while your
own rebuild applies it.
Example:
trueDeclared in modules/den/options.nix.
nebelhaus.accessibility.increaseContrast
Section titled “nebelhaus.accessibility.increaseContrast”null or boolean · default null
macOS’s “Increase contrast” — stronger borders and reduced use of colour alone to convey state, across native apps. This is the system-level companion to a high-contrast nebelhaus theme: the theme restyles the tools nebelhaus colours, this reaches everything else.
null (the default) leaves whatever you have alone — this is a personal setting, so the rice never picks a value for you.
REACHABILITY: com.apple.universalaccess is TCC-protected. It writes
only when the app that runs the rebuild holds Full Disk Access
(System Settings ▸ Privacy & Security ▸ Full Disk Access; on macOS 26
a stale grant often needs removing and re-adding with (+)). Without
that grant the rice logs a warning and moves on — it does NOT fail
the rebuild. Worth knowing: an agent-driven haus rebuild runs under
a different app than your terminal, so it may skip this while your
own rebuild applies it.
Example:
trueDeclared in modules/den/options.nix.
nebelhaus.prowl
Section titled “nebelhaus.prowl”Tiling window management and the Caps-Lock leader launcher.
nebelhaus.prowl.enable
Section titled “nebelhaus.prowl.enable”boolean · default true
AeroSpace tiling window management + the leader-key launcher.
This is the room switch: off drops AeroSpace, its launch agent, the wake-time window re-sort and the key remap entirely. To keep the tiler but leave the keyboard alone, use nebelhaus.keys.leader = “none” and nebelhaus.keys.windowNav = “none” instead of turning the room off.
Declared in modules/prowl/options.nix.
nebelhaus.sill
Section titled “nebelhaus.sill”The menu bar, and which pills it draws.
nebelhaus.sill.aiUsage.provider
Section titled “nebelhaus.sill.aiUsage.provider”one of "latest", "claude", "codex", "opencode" · default "latest"
Which AI provider to display in the main pill: latest (default, automatically
shows whichever provider reported most recently), or one of
claude, codex, opencode.
Clicking the pill always displays the full dropdown with all reporting providers.
Note this is about usage readouts, not about which client wt can
spawn: a provider reports here whenever it has data for your account —
Codex notably does so from a ChatGPT login alone, with no CLI installed
— so it is deliberately not tied to nebelhaus.agents.clients.
Example:
"claude"Declared in modules/sill/options.nix.
nebelhaus.sill.battery.hideOver
Section titled “nebelhaus.sill.battery.hideOver”null or signed integer · default null
Hide the battery pill when charge percentage is above this threshold (e.g., set to 80 to show the battery pill only when charge is at or below 80%).
Example:
80Declared in modules/sill/options.nix.
nebelhaus.sill.clock.mode
Section titled “nebelhaus.sill.clock.mode”one of "full", "compact" · default "full"
The display mode for the clock pill: full (default, e.g. “Fri Jul 31 09:41 AM” with calendar icon)
or compact (e.g. “Fri 31/7 9:41” without icon and trimmed spacing).
Example:
"compact"Declared in modules/sill/options.nix.
nebelhaus.sill.enable
Section titled “nebelhaus.sill.enable”boolean · default true
The SketchyBar menu bar. When off, the native macOS menu bar is kept (nebelhaus stops hiding it) and no bar is drawn.
Declared in modules/sill/options.nix.
nebelhaus.sill.items
Section titled “nebelhaus.sill.items”submodule · default { }
Which SketchyBar pills to draw, one bool each. The core pills —
clock, weather, media, battery, wifi — default true; the extras
— the readouts cpu, memory, volume, calendar, caffeinate
and the personal agents, aiUsage, elgato, harvest —
default false. Set
only what you want to change:
nebelhaus.sill.items = { weather = false; # drop a default-on core pill cpu = true; # add an off-by-default readout caffeinate = true; # add the keep-awake controller };
A pill set false is never created (its update script doesn’t run either). The hush (Do-Not-Disturb) pill is separate — it rides nebelhaus.hush.enable, not this set.
Example:
{ cpu = true; weather = false;}Declared in modules/sill/options.nix.
nebelhaus.sill.items.agents
Section titled “nebelhaus.sill.items.agents”boolean · default false
A paw pill tracking your agent-worktree panes — amber when one is blocked on you, click for the per-agent list, each row marked with the client sitting in it; left-click a row to jump to that pane, ⌥/right-click for a live zellij subscribe peek. Fed by each client’s own lifecycle hooks, which all call agent-state (also installed as ~/.config/sketchybar/plugins/agents-hook.sh): Opencode’s plugin and Codex’s ~/.codex/hooks.json are written for you (Codex asks you to trust its hooks the first time it sees them), while Claude Code’s four hooks stay yours to point at it in ~/.claude/settings.json — Claude owns that file and rewrites it, so the rice never touches your hooks. A row whose zellij pane is gone drops off by itself, which is what stands in for the session-end event Codex doesn’t have. Dormant until a client fires.
Declared in modules/sill/options.nix.
nebelhaus.sill.items.aiUsage
Section titled “nebelhaus.sill.items.aiUsage”boolean · default false
A gauge pill showing AI usage (Claude Code/Codex subscription rate limits as %, or Opencode API token cost as daily $). Automatically shows whichever provider reported most recently. Click for expanded session/weekly limits and daily/monthly API costs with model breakdowns. Claude and Opencode are read off disk; Codex has no local usage data, so its row is polled from your ChatGPT account with the OAuth token in ~/.codex/auth.json (refreshed and rewritten in place) — no Codex login on the machine, no call is made. Claude’s row is pushed by its statusline; the Codex and Opencode rows are pulled by the pill itself on a 3-minute TTL, so they stay current on a machine that never opens Claude at all.
Declared in modules/sill/options.nix.
nebelhaus.sill.items.battery
Section titled “nebelhaus.sill.items.battery”boolean · default true
The battery pill.
Declared in modules/sill/options.nix.
nebelhaus.sill.items.caffeinate
Section titled “nebelhaus.sill.items.caffeinate”boolean · default false
A coffee pill that prevents idle system sleep for 1/2/4/8 hours, a custom whole-hour duration, or indefinitely. The display may still turn off; closing a MacBook lid still sleeps it. Uses macOS’s built-in caffeinate, so there is no extra package.
Declared in modules/sill/options.nix.
nebelhaus.sill.items.calendar
Section titled “nebelhaus.sill.items.calendar”boolean · default false
Your next timed event, with a click-popup of the next five. Pulls in ical-buddy automatically and reads Calendar, so macOS prompts for Calendar access on first run.
Declared in modules/sill/options.nix.
nebelhaus.sill.items.claudeUsage
Section titled “nebelhaus.sill.items.claudeUsage”boolean · default false
Deprecated alias for aiUsage.
Declared in modules/sill/options.nix.
nebelhaus.sill.items.clock
Section titled “nebelhaus.sill.items.clock”boolean · default true
The clock pill, pinned to the far right.
Declared in modules/sill/options.nix.
nebelhaus.sill.items.cpu
Section titled “nebelhaus.sill.items.cpu”boolean · default false
Total CPU load, as a percentage pill.
Declared in modules/sill/options.nix.
nebelhaus.sill.items.elgato
Section titled “nebelhaus.sill.items.elgato”boolean · default false
Toggles an Elgato Key Light on the local network.
Declared in modules/sill/options.nix.
nebelhaus.sill.items.harvest
Section titled “nebelhaus.sill.items.harvest”boolean · default false
A Harvest time-tracking pill; needs a ~/.config/sketchybar/harvest_secrets.sh you provide.
Declared in modules/sill/options.nix.
nebelhaus.sill.items.media
Section titled “nebelhaus.sill.items.media”boolean · default true
The now-playing track (scrolls; auto-hides when nothing plays).
Declared in modules/sill/options.nix.
nebelhaus.sill.items.memory
Section titled “nebelhaus.sill.items.memory”boolean · default false
Memory-pressure percentage pill.
Declared in modules/sill/options.nix.
nebelhaus.sill.items.volume
Section titled “nebelhaus.sill.items.volume”boolean · default false
Output volume / mute state.
Declared in modules/sill/options.nix.
nebelhaus.sill.items.weather
Section titled “nebelhaus.sill.items.weather”boolean · default true
The weather pill and its click-to-open forecast popover.
Declared in modules/sill/options.nix.
nebelhaus.sill.items.wifi
Section titled “nebelhaus.sill.items.wifi”boolean · default true
The Wi-Fi status pill.
Declared in modules/sill/options.nix.
nebelhaus.sill.position
Section titled “nebelhaus.sill.position”one of "top", "bottom", "auto" · default "top"
Where the bar sits. top and bottom pin it there. auto flips it
at runtime — bottom whenever an external display is attached (docked
with the lid open, or clamshell), top on the built-in display alone —
driven by a display_change hook, so the bar moves the moment you dock
or undock, without a rebuild.
The bar’s height/pill offsets are tuned for the notch, which only
exists at the top of the built-in display; at bottom there’s no notch
to tuck under, so auto conveniently keeps the notch case (top) on
the notched screen and the plain case (bottom) on the external.
Example:
"auto"Declared in modules/sill/options.nix.
nebelhaus.tour
Section titled “nebelhaus.tour”The first-run tutor.
nebelhaus.tour.enable
Section titled “nebelhaus.tour.enable”boolean · default true
The haus tour — a first-run tutor that walks the four moves (launch /
navigate / resize / palette) as ONE quiet pill in the bar, advancing
live as each move is detected. It never opens a window or steals
focus: a fresh machine just shows a dormant “new here?” hint, clicking
it (or haus tour, or ⌘Space → tour) starts the lap, right-click
hides it forever. Detection reuses signals the rice already fires (the
leader-mode scripts) — no key logging, no Accessibility.
Needs prowl + sill (it silently stays out of the bar without them);
the ⌘Space step is dropped when pounce is off. Progress lives in
~/.local/state/nebelhaus — haus tour reset re-arms a finished tour.
Declared in modules/sill/options.nix.
nebelhaus.tour.steps
Section titled “nebelhaus.tour.steps”null or (non-empty (list of (submodule))) · default null
A community-authored tour, in order. null keeps the built-in four-move
nebelhaus tour unchanged; supplying a list replaces it, so a shared rice can
teach its own workflow without shipping scripts or reaching outside the
nebelhaus.* option surface.
Detection reuses signals the rice already emits. launch, workspace,
navigate and resize need prowl; palette needs Pounce and its palette
binding. The module warns when a chosen detector’s room is disabled.
Example:
[ { detect = "palette"; hint = "Press ⌘Space, type tour, then hit ↵"; }]Declared in modules/sill/options.nix.
nebelhaus.tour.steps.*.detect
Section titled “nebelhaus.tour.steps.*.detect”one of "launch", "workspace", "navigate", "resize", "palette" · no default
The existing rice signal that completes this step: entering launch,
navigate or resize mode; changing workspace; or running the Haus Tour
command from Pounce (palette). The tour observes outcomes, never
keystrokes. Clicking the pill still skips a step that cannot be
detected in the current setup.
Example:
"palette"Declared in modules/sill/options.nix.
nebelhaus.tour.steps.*.hint
Section titled “nebelhaus.tour.steps.*.hint”string · no default
The instruction shown in the tour pill for this step.
Example:
"Press ⌘Space, type calendar, then hit ↵"Declared in modules/sill/options.nix.
nebelhaus.pounce
Section titled “nebelhaus.pounce”The ⌘Space command palette.
nebelhaus.pounce.enable
Section titled “nebelhaus.pounce.enable”boolean · default true
The pounce command palette daemon (⌘Space) + its rice commands.
Declared in modules/pounce/options.nix.
nebelhaus.pounce.followSystemAppearance
Section titled “nebelhaus.pounce.followSystemAppearance”boolean · default true
Let the palette follow macOS Light/Dark Mode instead of pinning one
polarity: pounce gets the nebelung variant AND its latte counterpart at
your nebelhaus.theme.contrast, as its theme/themeLight pair, and
picks between them per open (no rebuild, no daemon restart).
Honest scope: this makes pounce the one themed tool that does NOT follow nebelhaus.theme.flavor — a flavor pin is a palette choice, and asking to follow the system says the polarity is macOS’s call. The contrast axis still applies to both halves. Everything else on the rice keeps whatever flavor pins.
false pins pounce to the flavor like every other port, which is exactly what it did before this option existed.
Declared in modules/pounce/options.nix.
nebelhaus.pounce.items
Section titled “nebelhaus.pounce.items”attribute set of (submodule) · default { }
Per-item palette settings, keyed by the item’s own address. One entry is one row of the palette: hide it, give it a search shorthand, give it a key.
“cmd:
Those keys are pounce’s own address space (the same strings its frecency
store and pounce run use), so a key written here is also what you’d type
to invoke the thing from a script or another tool’s binding.
Hotkeys can be a single chord (“opt+e”) or a LEADER SEQUENCE — steps separated by spaces, modifiers by ”+”, the notation Emacs and VS Code use:
hotkey = “opt+space e”; # ⌥Space, then E hotkey = [ “cmd+k” “cmd+c” ]; # the same thing, step by step
Sequences are worth knowing about on a tiling rice: they open a namespace that structurally can’t collide with the ⌥/⌘ chords prowl already claims, and they need no Accessibility grant (pounce grabs the second step as an ordinary global hotkey for a couple of seconds rather than tapping events).
Two things this checks at build time, because both fail SILENTLY at
runtime: a key that names no real item shape (a “mode:” typo binds
nothing at all), and a chord already claimed by nebelhaus.keys.palette or
nebelhaus.keys.leader (whoever registers first wins, and it isn’t always
the same one). What it can’t check is whether cmd:<id> names a command
that exists — command scripts are discovered at runtime, so pounce warns
about that itself when the daemon starts, and pounce doctor lists any
binding that failed to arm.
Example:
{ "app:/Applications/Ghostty.app" = { hotkey = "opt+t"; }; "cmd:brew-services" = { listed = false; }; "cmd:emoji" = { alias = "emo"; hotkey = "opt+e"; }; "mode:clipboard" = { hotkey = "cmd+shift+v"; };}Declared in modules/pounce/options.nix.
nebelhaus.pounce.items.<name>.alias
Section titled “nebelhaus.pounce.items.<name>.alias”null or string · default null
A search shorthand, matched at a bonus over the item’s real name — so “emo” can find the Emoji Picker without renaming it.
Example:
"emo"Declared in modules/pounce/options.nix.
nebelhaus.pounce.items.<name>.caption
Section titled “nebelhaus.pounce.items.<name>.caption”null or string · default null
How this item reads on the cheatsheet page that lists your item
hotkeys (⌘Space then ⇥, or the leader’s /). Only used when the
item has a hotkey — a row without a key has nothing to teach.
Defaults to a name derived from the key, which is right often
enough to leave alone: mode:clipboard becomes “Clipboard
history”, app:/Applications/Ghostty.app becomes “Ghostty”, and
cmd:brew-services becomes “Brew services”. Set this when the
derived name isn’t what the palette actually calls the row — the
rice can’t read a command’s own # pounce: name header at
evaluation time, so that one is a guess.
Example:
"Clipboard history"Declared in modules/pounce/options.nix.
nebelhaus.pounce.items.<name>.hotkey
Section titled “nebelhaus.pounce.items.<name>.hotkey”null or string or list of string · default null
A global chord, or a leader sequence, that invokes this item directly without opening the palette first. Modifier names follow pounce’s spelling: cmd/command/super/meta · opt/option/alt · ctrl/control · shift.
Whether the KEY name is one pounce can bind is not checked here
(that vocabulary lives in the app); a chord it can’t register is
reported by pounce doctor rather than silently dropped.
Example:
"opt+space e"Declared in modules/pounce/options.nix.
nebelhaus.pounce.items.<name>.listed
Section titled “nebelhaus.pounce.items.<name>.listed”boolean · default true
Whether the item appears in the palette’s list.
Named listed rather than enable because that is precisely what
it does: false removes the ROW, and a hotkey on the same item
keeps working. It’s how you hide a command you only ever want to
reach by key — or clear the launcher of tools someone else on this
Mac has no use for, which is the closest thing to a “pack” the
surface has today. (It writes pounce’s own enabled key.)
Declared in modules/pounce/options.nix.
nebelhaus.pounce.signingIdentity
Section titled “nebelhaus.pounce.signingIdentity”string · default ""
A code-signing identity in your login keychain — either its SHA-1 or (preferred) its full common name. The pounce daemon is re-signed with it so a macOS Accessibility (TCC) grant survives rebuilds. List yours: security find-identity -v -p codesigning
Prefer a “Developer ID Application” identity passed BY NAME (e.g. “Developer ID Application: Jane Doe (TEAMID)”): its designated requirement anchors on the stable team OU, so the grant survives even a certificate renewal (the renewed cert keeps the same name/team but gets a new SHA — a hardcoded SHA would silently fall back to unsigned). This is also the identity the Homebrew build is signed with, so both install paths share one identity. An “Apple Development” cert works too but expires yearly and pins the specific cert, so it’s less durable.
Changing this once invalidates the existing grant (the requirement changes) — re-approve pounce in Accessibility a single time after.
Leave empty to run pounce unsigned (the palette works, but auto-paste and other Accessibility-gated features stay off).
Example:
"Developer ID Application: Jane Doe (ABCDE12345)"Declared in modules/pounce/options.nix.
nebelhaus.pounce.windowSwitcher
Section titled “nebelhaus.pounce.windowSwitcher”boolean · default true
Replace the stock ⌘Tab app switcher with pounce’s MRU window switcher:
tap ⌘⇥ to toggle to the last window (across workspaces), hold ⌘ and keep
tapping ⇥ to walk older ones, type while holding to fuzzy-filter
(frecency-ranked). Rows carry the window’s AeroSpace workspace, and
focusing goes through aerospace focus --window-id so a window parked
on another workspace surfaces correctly.
Needs the daemon to hold an Accessibility grant — in practice, set nebelhaus.pounce.signingIdentity so the grant survives rebuilds. Without the grant the event tap can’t install and stock ⌘Tab keeps working, so this default is safe on a fresh, not-yet-granted install. false leaves ⌘Tab native even when the grant is there.
Declared in modules/pounce/options.nix.
nebelhaus.trill
Section titled “nebelhaus.trill”The Messages client.
nebelhaus.trill.enable
Section titled “nebelhaus.trill.enable”boolean · default true
The trill Messages client, installed via the trill flake (copied to /Applications).
Declared in modules/trill/options.nix.
nebelhaus.trill.followSystemAppearance
Section titled “nebelhaus.trill.followSystemAppearance”boolean · default true
Let trill’s palette follow macOS Light/Dark Mode instead of pinning one polarity: trill gets the nebelung variant AND its latte counterpart at your nebelhaus.theme.contrast, and picks between them itself — no rebuild, no relaunch.
Same honest scope as the pounce option of the same name: with this on, trill does NOT follow nebelhaus.theme.flavor, because asking to follow the system says the polarity is macOS’s call. The contrast axis still applies to both halves. Set it false to pin trill to theme.flavor like every other themed tool.
Either way this writes only the DEFAULT: a palette chosen in trill’s own Settings ▸ Theme wins over what the rice writes, and so does trill’s appearance preference (Follow macOS / Dark / Light), which lives in its settings rather than here.
Declared in modules/trill/options.nix.
nebelhaus.hush
Section titled “nebelhaus.hush”One quiet switch: Do Not Disturb, optional Slack status, and your hooks.
nebelhaus.hush.enable
Section titled “nebelhaus.hush.enable”boolean · default true
The hush room: one quiet switch — bar pill, palette command, and a
hush CLI — that turns macOS Do Not Disturb on/off (via the
declaratively-bound symbolic hotkey 175, pressed synthetically),
optionally sets your Slack status, and runs your hooks.
Honest scope: hush flips the built-in Do Not Disturb, not named Focus
modes, and it doesn’t manage which apps break through — curate that
once in System Settings. The keypress needs an Accessibility grant on
whatever app invokes hush (palette runs inherit pounce’s; grant
sketchybar once for the pill). hush doctor walks the one-time steps.
Declared in modules/hush/options.nix.
nebelhaus.hush.hooks
Section titled “nebelhaus.hush.hooks”list of (absolute path or string) · default [ ]
Extra scripts run on every hush/unhush, each called with a single argument “on” or “off”. Paths are copied into the store; strings are run as-is (so $HOME paths work). Failures are logged, never fatal — a broken hook can’t wedge the toggle.
Example:
[ ./onair-light.sh "/Users/ada/bin/pause-music" ]Declared in modules/hush/options.nix.
nebelhaus.hush.slack.enable
Section titled “nebelhaus.hush.slack.enable”boolean · default false
Also set a Slack status and snooze Slack notifications (all devices, phone included) while hushed. Off by default: it needs a personal Slack user token (scopes users.profile:write + dnd:write) provided via tokenCommand. The previous status is saved and restored on unhush.
Declared in modules/hush/options.nix.
nebelhaus.hush.slack.snooze
Section titled “nebelhaus.hush.slack.snooze”boolean · default true
Also pause Slack’s own notifications (dnd.setSnooze) while hushed — this is what silences the phone. Ended on unhush; capped at 24h as a failsafe if you forget.
Declared in modules/hush/options.nix.
nebelhaus.hush.slack.statusEmoji
Section titled “nebelhaus.hush.slack.statusEmoji”string · default ":no_bell:"
Slack status emoji while hushed.
Declared in modules/hush/options.nix.
nebelhaus.hush.slack.statusText
Section titled “nebelhaus.hush.slack.statusText”string · default "heads down"
Slack status text while hushed.
Declared in modules/hush/options.nix.
nebelhaus.hush.slack.tokenCommand
Section titled “nebelhaus.hush.slack.tokenCommand”string · default ""
Shell command that prints the Slack user token (xoxp-…) to stdout. Keychain-first so no secret ever lands in the store or a dotfile: security add-generic-password -s hush-slack -a $USER -w ‘xoxp-…’
Example:
"security find-generic-password -s hush-slack -w"Declared in modules/hush/options.nix.
nebelhaus.snippets
Section titled “nebelhaus.snippets”Text expansion via espanso.
nebelhaus.snippets.enable
Section titled “nebelhaus.snippets.enable”boolean · default false
Text expansion via espanso: type a short trigger (say ”@@”) and it’s replaced inline with a longer string (your email), in any app — browsers, Messages, and the terminal. espanso injects keystrokes, so it works where macOS’s own text replacement doesn’t (terminals, many Electron apps).
Off by default: it installs the Espanso.app cask and needs a one-time macOS Accessibility grant (System Settings → Privacy & Security → Accessibility → enable Espanso) the first time it runs. The rice runs the SIGNED app bundle rather than a nix-store binary on purpose, so that grant is keyed to a stable identity and survives reboots and nixpkgs bumps — you grant it once, not on every rebuild (and so the espanso troubleshooting window stops popping up at login, since that window only ever meant “the grant went missing”).
Declared in modules/snippets/options.nix.
nebelhaus.snippets.matches
Section titled “nebelhaus.snippets.matches”list of (submodule) · default [ ]
The expansion table — one { trigger; replace; } per snippet, written to ~/.config/espanso/match/default.yml. Only espanso’s plain trigger→replace form is exposed here; for dynamic matches (dates, shell output, forms) drop a hand-written .yml alongside it in ~/.config/espanso/match/ — espanso loads every file in that dir.
Example:
[ { trigger = "@@"; replace = "ada@example.com"; } { trigger = "##"; replace = "+1 555 0100"; }]Declared in modules/snippets/options.nix.
nebelhaus.snippets.matches.*.replace
Section titled “nebelhaus.snippets.matches.*.replace”string · no default
What it expands to.
Example:
"ada@example.com"Declared in modules/snippets/options.nix.
nebelhaus.snippets.matches.*.trigger
Section titled “nebelhaus.snippets.matches.*.trigger”string · no default
What you type.
Example:
"@@"Declared in modules/snippets/options.nix.
nebelhaus.secrets
Section titled “nebelhaus.secrets”Where secret values come from on this machine.
nebelhaus.secrets.provider
Section titled “nebelhaus.secrets.provider”null or string · default "keyring"
The secretspec provider that supplies secret VALUES on this machine.
The secrets room writes it to ~/.config/secretspec/config.toml as the
default provider, so secretspec run / check / set work without
flags. Any provider string secretspec accepts, URIs included:
“keyring” (macOS login keychain — local, no accounts), “onepassword”,
“bws” (Bitwarden Secrets Manager), “gcsm” (Google Cloud Secret
Manager), “awssm” (AWS Secrets Manager), “vault”, “pass”,
“protonpass”, “lastpass”, “dotenv”, “env”, or a scoped URI like
“onepassword://account@vault”.
WHICH secrets exist is not declared here — that’s each project’s
committed secretspec.toml. Cloud providers authenticate with their own
credentials, configured outside Nix (e.g. gcloud auth application-default login for gcsm); that login is the one manual
step on a new Mac. null skips writing the config file entirely — run
secretspec config init yourself.
Example:
"gcsm"Declared in modules/secrets/options.nix.
nebelhaus.homebrew
Section titled “nebelhaus.homebrew”How rebuilds treat Homebrew packages you did not declare.
nebelhaus.homebrew.autoUpdate
Section titled “nebelhaus.homebrew.autoUpdate”boolean · default false
Run brew update before activating the Homebrew step on every
rebuild. Off by default — reproducible rebuilds shouldn’t silently
pull newer formulae. Turn on if you want brew to track upstream.
Declared in modules/den/options.nix.
nebelhaus.homebrew.cleanup
Section titled “nebelhaus.homebrew.cleanup”one of "none", "uninstall", "zap" · default "none"
How darwin-rebuild switch treats Homebrew casks/brews that are
installed but NOT declared anywhere in your config.
- “none” (default, safe): leave undeclared formulae/casks alone. The rice never deletes apps you installed yourself.
- “uninstall”: remove undeclared formulae/casks (keeps their data).
- “zap”: remove undeclared formulae/casks AND their app data. Fully declarative, but a stray cask you forgot to list is deleted — with no backup — on the very next rebuild. Only choose this once every app you keep is declared (bootstrap can adopt your current casks).
Declared in modules/den/options.nix.
nebelhaus.homebrew.upgrade
Section titled “nebelhaus.homebrew.upgrade”boolean · default false
Upgrade outdated Homebrew packages on every rebuild. Off by default for the same reproducibility reason as autoUpdate.
Declared in modules/den/options.nix.
nebelhaus.agents
Section titled “nebelhaus.agents”nebelhaus.agents.clients
Section titled “nebelhaus.agents.clients”list of (one of "claude", "codex", "opencode") · see below
Which coding-agent clients to install. claude is Claude Code, codex
is OpenAI Codex, opencode is OpenCode. The ⌘C terminal binding starts
whichever one agents.default names — Claude Code through its own
--worktree hook, the others through wt new.
A list rather than one bool per client, matching developer.languages
— a fourth client later doesn’t change this option’s shape.
This is the option that makes agents.default honest. Naming a client
you have not installed used to fail at spawn time, inside the pane,
after the worktree already existed: a flash of
codex is unavailable, and litter to reap. agents.default must now
be a member of this list, so the same mistake fails the rebuild
instead, with both values named.
Override the package for a client the usual Nix way — an overlay on
claude-code, codex or opencode — rather than dropping the client
here and installing your own copy alongside; two derivations shipping
the same bin/ name collide in one profile.
Example:
[ "claude" "codex"]Declared in modules/options.nix.
nebelhaus.agents.default
Section titled “nebelhaus.agents.default”one of "claude", "codex", "opencode" · default "claude"
The coding agent started by Pounce’s Spawn Agent commands, by the
⌘C / Super-c zellij binds and the c shell alias, and used to reopen
worktrees with no client recorded yet. Each spawned worktree records its
own client, so changing this affects new work but never reopens an
existing Codex or OpenCode task in Claude.
Must be one of agents.clients — see there.
Only claude can make its own worktree (its native --worktree flag,
which fires the wt create hook); for codex and opencode ⌘C runs
wt new instead, producing the same checkout, branch and registry entry
from the outside. Resuming follows the client too: codex reopens its
cwd-filtered codex resume picker, opencode continues its latest
session for that cwd. All three share one wt branch/parking/reap
lifecycle, and all three light up the agents bar pill and the zellij
tab-bar badge — the opencode plugin and the codex hooks are written for
you; only Claude Code’s stay yours to wire, because Claude owns its own
settings.json (see nebelhaus.sill.plugins).
Example:
"codex"Declared in modules/options.nix.
nebelhaus.developer
Section titled “nebelhaus.developer”nebelhaus.developer.agents.enable
Section titled “nebelhaus.developer.agents.enable”boolean · default config.nebelhaus.developer.enable
Coding-agent tooling: wt (agent worktrees), agent-state (the
pane-status writer behind the agents bar pill and the zellij tab
badge), zscratch, the agent-worktree statusline, and the client
config hearth writes (Claude Code’s settings.json keys, opencode’s
agent-state plugin). Which clients get installed is agents.clients.
Off is right for any machine not running coding agents — it’s a large
surface a non-developer never sees. It also empties agents.clients,
since a client with no wt to park it is not the deal on offer.
Declared in modules/options.nix.
nebelhaus.developer.enable
Section titled “nebelhaus.developer.enable”boolean · default true
The developer pack: the CLI toolbelt, Git tooling, coding-agent tooling, and language runtimes. On (the default) is the rice as it has always been.
false is what makes a non-developer nebelhaus possible — it strips
those tools rather than merely hiding them. What remains is the
product: haus, awake, the theme, the terminal, the bar, the tiler
and the palette.
The sub-options below each default to THIS value, so turning it off turns everything off and you can then re-enable one piece:
nebelhaus.developer.enable = false; nebelhaus.developer.git.enable = true; # …but keep git
Example:
falseDeclared in modules/options.nix.
nebelhaus.developer.git.enable
Section titled “nebelhaus.developer.git.enable”boolean · default config.nebelhaus.developer.enable
Git and its surroundings: the shell alias vocabulary, the themed git
config, delta (diff pager), lazygit, gh, and gnupg for commit
signing. Off drops all of them, and nebelhaus.git.* then has
nothing to configure.
Declared in modules/options.nix.
nebelhaus.developer.languages
Section titled “nebelhaus.developer.languages”list of value "node" (singular enum) · default [ "node" ] when developer.enable is true, else [ ]
Language runtimes to install. Currently only “node” (bun + fnm, with
fnm’s --use-on-cd shell hook).
Deliberately a list rather than one bool per language, so adding “rust” or “python” later doesn’t change this option’s shape.
Example:
[ ]Declared in modules/options.nix.
nebelhaus.developer.toolbelt.enable
Section titled “nebelhaus.developer.toolbelt.enable”boolean · default config.nebelhaus.developer.enable
The terminal toolbelt: bat, fzf, fd, yazi, zoxide, lsd, glow, jq, tree, chafa, ttyd and fastfetch — the themed replacements for cat, find, ls and friends that the rice’s shell is built around.
Off leaves a plain shell. The prompt (starship) and the colour scheme stay: these are the tools, not the appearance.
Declared in modules/options.nix.
nebelhaus.displays
Section titled “nebelhaus.displays”nebelhaus.displays
Section titled “nebelhaus.displays”attribute set of (submodule) · default { }
Per-display settings, keyed by which screen you mean:
internal the built-in panel
main whichever display is currently main
hausdisp list to print the UUIDs of what’s attached
Default is the empty set, and then nothing about your displays is touched.
A key naming a display that isn’t plugged in right now is skipped with a
note, not an error, so a displays.<uuid> entry for the monitor at the
office can’t fail a rebuild on the train.
Why this option exists at all: display scaling is the only lever macOS 26
gives us for “make EVERYTHING bigger”, system-wide, including apps the rice
knows nothing about. macOS’s own text-size setting writes a value no running
app re-reads, while the accessibility scalars that do work affect contrast
or motion rather than system-wide size — measured, not assumed (the
workshop’s notes/macos-settings-matrix.md records the sweep). So
nebelhaus.ui.scale and nebelhaus.fonts make the rice bigger, and this
makes the Mac bigger.
Example:
{ "37D8832A-2D66-02CA-B9F7-8F30A301B230" = { uiScale = "more-space"; }; internal = { uiScale = "larger-text"; };}Declared in modules/displays/options.nix.
nebelhaus.displays.<name>.uiScale
Section titled “nebelhaus.displays.<name>.uiScale”null or one of "more-space", "default", "larger-text", "largest-text" · default null
The scaled resolution, as an intent rather than a pixel count — the same four positions System Settings ▸ Displays offers, named:
more-space the largest resolution the panel offers (smallest UI) default the panel’s own default mode larger-text between the default and the smallest resolution largest-text the smallest resolution the panel offers (biggest UI)
Resolved per panel from the modes that panel actually reports, so the same value means the same thing on a 14” laptop and a 27” monitor rather than the same number of pixels. On the 14” MacBook Pro this was developed on that resolves to 1800x1169 · 1512x982 · 1147x745 · 1024x665.
Applied at each home-manager activation and set permanently, so it survives a reboot; re-applying an already-current mode is a no-op, so a rebuild doesn’t flash your screen. null (the default) leaves the display alone.
When more than one selector names the same attached panel, the more specific setting wins: UUID over internal over main. This lets a host-specific display setting refine a broad preset such as large-print without depending on activation order.
Honest scope: this is a real, system-wide size change — every app gets bigger, not just the rice’s own tools — and the cost is desk space, because a larger UI means less of it. It also can’t run from a rebuild with no GUI session attached (over SSH, say); the setting applies at the next activation you run while logged in.
Example:
"larger-text"Declared in modules/displays/options.nix.
nebelhaus.keys
Section titled “nebelhaus.keys”nebelhaus.keys.leader
Section titled “nebelhaus.keys.leader”one of "caps", "alt-space", "none" · default "caps"
What enters the launcher/leader mode — tap it, then a letter opens an
app, a digit focuses a workspace, ⇧+either throws the focused window
to that workspace and follows it there, an arrow navigates, -/=
resizes.
- “caps” (default): Caps Lock. AeroSpace can’t bind Caps Lock itself, so the rice remaps it to F18 with hidutil and binds that.
- “alt-space”: the leader without giving up Caps Lock. No remap at all.
- “none”: no leader. Caps Lock stays Caps Lock, launch mode is unreachable, and nothing is remapped — the setting for a mouse-first rice, or for a Mac you are handing to someone else. What the leader fronted is still reachable: apps through the palette, window moves through service mode’s join-with and the palette’s own commands. Workspace focus and the workspace throws go away with it — they live only in launch mode.
The remap is re-applied at every activation and does not survive a reboot, so moving off “caps” ends it — at the latest, at next boot.
Only meaningful with nebelhaus.prowl.enable (AeroSpace owns the modes).
Example:
"none"Declared in modules/options.nix.
nebelhaus.keys.leaderExtras
Section titled “nebelhaus.keys.leaderExtras”list of (submodule) · default [ ]
Extra launch-mode (leader) bindings beyond the app roster: tap the leader,
then key, to run command. Use it for leader actions that aren’t
“launch an app” — a script, an AppleScript, opening a URL.
Only meaningful with nebelhaus.prowl.enable and keys.leader != “none” (with no leader there is no launch mode to bind into).
Example:
[ { key = "enter"; command = "osascript -e 'tell application \"Things3\" to show quick entry panel'"; caption = "Things Quick Entry"; }]Declared in modules/options.nix.
nebelhaus.keys.leaderExtras.*.caption
Section titled “nebelhaus.keys.leaderExtras.*.caption”null or string · default null
The Launch Mode cheatsheet caption for this action. null falls back to the raw command, which is rarely what you want — set it.
Example:
"Things Quick Entry"Declared in modules/options.nix.
nebelhaus.keys.leaderExtras.*.command
Section titled “nebelhaus.keys.leaderExtras.*.command”string · no default
The shell command run when the leader is followed by key; launch
mode exits afterward. It’s written verbatim into a small /bin/sh
script that AeroSpace execs, so ordinary shell rules apply — $HOME
resolves, and single quotes (an osascript -e '…', say) are safe,
which they would not be inlined into AeroSpace’s own config.
Example:
"osascript -e 'tell application \"Things3\" to show quick entry panel'"Declared in modules/options.nix.
nebelhaus.keys.leaderExtras.*.key
Section titled “nebelhaus.keys.leaderExtras.*.key”string · no default
The AeroSpace key name pressed after the leader (e.g. “enter”,
“space”, “period”, or a letter). Must not collide with a roster
app’s key or a built-in launch-mode key (the digits 1-4, the
arrows, -/=, v/e/z, ,, `, /, esc) — nor with
the workspace throws, which are ⇧ + any of those digits or a
roster letter (“shift-1”, “shift-b”, …). An assertion in
modules/prowl catches a clash rather than letting one binding
silently shadow another.
Example:
"enter"Declared in modules/options.nix.
nebelhaus.keys.palette
Section titled “nebelhaus.keys.palette”one of "cmd-space", "alt-space", "ctrl-space", "none" · default "cmd-space"
What opens the pounce command palette. Registered in-process by the daemon, so it’s near-instant and doesn’t go through AeroSpace.
“cmd-space” (default) is the one value that also DISABLES Spotlight’s own ⌘Space, because the two can’t share it. Every other value leaves Spotlight alone — including “none”, which hands the palette’s job back to Spotlight entirely. That’s a fix as much as an option: the rice used to take Spotlight’s ⌘Space away unconditionally, even where nothing claimed it.
Only meaningful with nebelhaus.pounce.enable.
Example:
"none"Declared in modules/options.nix.
nebelhaus.keys.windowNav
Section titled “nebelhaus.keys.windowNav”one of "alt", "ctrl-alt", "cmd-alt", "none" · default "alt"
The modifier vocabulary for prowl’s window chords — one setting rather
than a bind-per-action, because what people need to move is the
modifier, not the letters. It drives focus (<mod> + hjkl), layouts
(<mod> + / ,), fullscreen, workspace back-and-forth, moving a
workspace to the next monitor (<mod>⇧⇥), and entering service mode
(<mod>⇧;). Anything that names a workspace — focusing one, or
throwing the focused window there — hangs off leader instead, not
this option.
“alt” (default) is ⌥. The alternatives are for non-US keyboard layouts, where ⌥+letter types accented characters — a rice that owns ⌥+letter is unusable on those, which is the concrete reason this option exists.
Whatever you pick, AeroSpace claims those chords globally, so they
stop reaching whatever owned them inside a terminal. The surface is
small now that the workspace throws moved to the leader: only hjkl,
/ ,, f, ⇥, ⇧⇥ and ⇧;, none of which a roster letter can
land on. (Under “ctrl-alt” that used to bite — the throws were ⌃⌥⇧ +
an app’s roster letter, so an app on c silently ate hearth’s zellij
Ctrl Alt Shift c in-place-agent bind. That collision is gone.)
Nothing on a stock macOS collides either: the only ⌃⌥ system hotkeys
are input-source switching (⌃⌥Space, off by default) and hyper-F13.
“none” drops the modifier chords entirely: no focus/layout chords, no
service mode. Combined with leader = "none" that’s a rice where the
tiler tiles and the keyboard is left alone — mouse-first. The cheatsheet
follows, so it never advertises a key that does nothing.
Only meaningful with nebelhaus.prowl.enable.
Example:
"ctrl-alt"Declared in modules/options.nix.
nebelhaus.perch
Section titled “nebelhaus.perch”nebelhaus.perch.enable
Section titled “nebelhaus.perch.enable”boolean · default true
The perch notch file shelf, installed via the perch flake (copied to /Applications).
Declared in modules/perch/options.nix.
nebelhaus.perch.followSystemAppearance
Section titled “nebelhaus.perch.followSystemAppearance”boolean · default true
Let the shelf’s palette follow macOS Light/Dark Mode instead of pinning one polarity: perch gets the nebelung variant AND its latte counterpart at your nebelhaus.theme.contrast, and picks between them itself — no rebuild, no relaunch.
Same honest scope as the trill and pounce options of the same name: with this on, perch does NOT follow nebelhaus.theme.flavor, because asking to follow the system says the polarity is macOS’s call. The contrast axis still applies to both halves. Set it false to pin the shelf to theme.flavor like every other themed tool.
Perch has no theme picker of its own — the shelf is a five-second surface with nowhere to put one — so unlike trill, this is the only word on its colors.
Declared in modules/perch/options.nix.
nebelhaus.ui
Section titled “nebelhaus.ui”nebelhaus.ui.scale
Section titled “nebelhaus.ui.scale”integer or floating point number between 0.5 and 3.0 (both inclusive) · default 1.0
One number for “make the interface bigger”. 1.0 is the rice as tuned; 1.35 is a comfortable large-print setting; below 1.0 tightens things up.
It sets the DEFAULT of the sizes it drives, so anything you pin by hand still wins:
nebelhaus.ui.scale = 1.5; # everything grows nebelhaus.fonts.mono.size = 18; # …except the terminal, pinned here
What it currently moves:
- the terminal font size (nebelhaus.fonts.mono.size)
- the Dock icon size (system.defaults.dock.tilesize)
- prowl’s window gaps
What it deliberately does NOT move:
- Sill’s menu bar. Its height is tuned to sit inside the macOS menu-bar band so the hover-reveal covers it exactly; scaling that linearly breaks the alignment rather than making it bigger. The bar needs its own sizing pass, not a multiplier.
- anything outside nebelhaus. macOS has no system-wide UI scale, so third-party apps follow only a display-resolution change.
Example:
1.35Declared in modules/options.nix.