The timer's OnCalendar now bakes the configured times (falling back like _hhmm_to_min on a hand-edited state), so the switch lands at the configured minute instead of up to 15 minutes late. The original poll's robustness case is covered without it: Persistent catches transitions missed while powered off, systemd fires elapsed calendar timers on resume, and OnStartupSec settles the theme after login. Baked times mean a time edit must rebuild: the menu's Sunrise/Sunset writes now run `auto --force` when enabled (one rebuild re-bakes the timer and lands on the right theme, same as the enable flow). Day and night slugs stay live reads — but with no poll to catch them up, editing the slot currently on screen applies immediately via a plain `auto`. New eval check `auto-theme-timer` asserts the bake state-bridges-style: configured times reach OnCalendar, garbage falls back to 07:00/20:00, disabled installs no unit. Docs + hardware-queue entry updated to the new semantics. V2: checks.auto-theme (KVM VM, passed) covers the auto engine the timer ticks; checks.auto-theme-timer (eval, passed) covers the unit; OnCalendar strings systemd-analyze-validated; the rebuilt menu script passes bash -n with the new branches in place. V3 pending: live timer firing at the exact configured minute on hardware (existing "Auto-theme pair flip" queue entry, refreshed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
7.9 KiB
Overriding Nomarchy's defaults
You consume Nomarchy as a flake input and own two files: system.nix and
home.nix. Your config is merged with Nomarchy's modules, so changing a
default is just a matter of knowing which of three knobs to reach for. The
rule of thumb:
Appearance → the CLI. Behaviour →
home.nix. Whole component → toggle it off.
1. Appearance (gaps, colors, rounding, fonts, opacity) — use the CLI
Everything that defines the look flows from state.json, the single
source of truth. Change it with nomarchy-state-sync, which writes the JSON
and rebuilds — one generation, applied to Hyprland, Waybar, Kitty, btop and
Stylix at once:
nomarchy-state-sync set ui.gapsOut 16 # gaps, borders, rounding, opacity
nomarchy-state-sync set ui.rounding 0
nomarchy-state-sync set fonts.mono "FiraCode Nerd Font"
nomarchy-state-sync apply gruvbox # whole palette
Icon pack
Icons follow the active theme's light/dark mode using Papirus — the only icon pack shipped by default (Papirus alone is ~1 GiB, so extra packs are opt-in rather than a cost every install pays). To switch to another pack:
nomarchy-state-sync set icons "Tela-dark" # or "" to return to Papirus-by-mode
Only the pack you name is pulled into your system (the first switch downloads it). Known packs and an example theme name from each:
Set icons to… |
Pack |
|---|---|
Papirus, Papirus-Dark, Papirus-Light |
Papirus (default; "" auto-picks Dark/Light by mode) |
Tela, Tela-dark, Tela-<color>[-dark] |
Tela (colors: blue, green, red, purple, nord, dracula, …) |
Qogir, Qogir-Dark, Qogir-Light |
Qogir (note the capital D/L) |
Reversal, Reversal-dark |
Reversal |
Numix-Circle, Numix-Circle-Light |
Numix Circle |
The choice is a sticky global override — it survives apply <palette>
switches (presets don't carry an icon field). To add a pack that isn't listed,
append a row to iconPacks in modules/home/theme.nix. Set icons to ""
any time to drop back to Papirus with automatic Dark/Light.
Auto theme (day/night)
Switch automatically between a light day theme and a dark night theme
on a schedule — the same one engine as a manual apply, no second pipeline.
Turn it on from Look & Feel › Auto theme (SUPER+M): toggle it, pick the
day and night themes, and set the sunrise/sunset times. The same from a shell:
nomarchy-state-sync set settings.autoTheme.day summer-day --no-switch
nomarchy-state-sync set settings.autoTheme.night summer-night --no-switch
nomarchy-state-sync set settings.autoTheme.sunset 20:00 --no-switch
nomarchy-state-sync set settings.autoTheme.enable true --no-switch
nomarchy-state-sync auto --force # one rebuild: installs the timer + applies now
State lives in settings.autoTheme:
| Field | Meaning |
|---|---|
enable |
on / off |
day / night |
theme slugs (see nomarchy-state-sync list) — the exclusive pairs are made for this: boreal-dawn/boreal, executive-ivory/executive-slate, kiln-clay/kiln, summer-day/summer-night |
sunrise / sunset |
switch times, "HH:MM" (24-hour) |
A timer fires exactly at the configured sunrise and sunset (plus once shortly
after login, and it catches up on a transition missed while the machine was
off or asleep) — it only rebuilds when the active theme actually needs to
change. The times are baked into the timer, so editing them (or enabling)
rebuilds once; disabling is instant. Preview the current decision without
switching with nomarchy-state-sync auto --which.
These values are deliberately kept at normal priority in the modules, so they
stay owned by the theme system. If you insist on pinning one in home.nix
regardless of the active theme, use lib.mkForce (see §4) — but then the CLI
can no longer change that knob.
2. Behaviour (input, misc, monitor, animations, terminal chrome) — home.nix
Non-appearance defaults are set with lib.mkDefault, so a plain assignment
in your home.nix wins — no mkForce needed:
# home.nix
{ ... }:
{
wayland.windowManager.hyprland.settings = {
input.follow_mouse = 0; # was 1
input.touchpad.natural_scroll = false;
misc.disable_splash_rendering = false;
monitor = [ "DP-1,2560x1440@144,0x0,1" ]; # raw rule — replaces the default
animations.enabled = false;
};
programs.kitty.settings = {
window_padding_width = 4; # was 12
};
}
For monitor layout, prefer the friendlier nomarchy.monitors (a list of
per-output submodules — resolution/position/scale/rotation — turned into
Hyprland rules and applied on hotplug; run nwg-displays to find the values
interactively). Assigning settings.monitor directly, as above, replaces it.
Adding vs. overriding lists
bind, bindel, bindl, bindm and exec-once are lists kept at normal
priority, so anything you add concatenates with Nomarchy's — your binds and
autostarts run alongside the defaults:
{
wayland.windowManager.hyprland.settings = {
bind = [
"$mod, B, exec, firefox"
"$mod SHIFT, S, exec, grim -g \"$(slurp)\" - | satty --filename -"
];
exec-once = [ "nm-applet --indicator" ];
};
}
To remove or replace a default bind, override the whole bind list with
lib.mkForce [ … ] (you then own the full list), or rebind the key to
something else (last definition for a key wins in Hyprland).
You can also drop raw config that doesn't fit the Nix schema:
{ wayland.windowManager.hyprland.extraConfig = ''
bindl = , switch:Lid Switch, exec, hyprlock
'';
}
Waybar
For a themed bar identity, ship whole-swap assets
(themes/<slug>/waybar.jsonc and waybar.css) — see the main README. To
replace the bar wholesale from home.nix, assign programs.waybar.settings. mainBar / programs.waybar.style (both mkDefault, so a plain assignment
wins). For a one-off tweak of a single generated key, lib.mkForce it.
3. Whole component — toggle it off and bring your own
Each desktop piece has an enable flag (all default true). Turn one off and
Nomarchy contributes nothing for it, leaving the field clear for your own:
# home.nix
{
nomarchy.hyprland.enable = false; # then write your own wayland.windowManager.hyprland
nomarchy.waybar.enable = false;
nomarchy.swaync.enable = false;
nomarchy.idle.enable = false; # no hyprlock/hypridle
}
# system.nix
{
nomarchy.system.plymouth.enable = false;
nomarchy.system.greeter.enable = false; # bring your own login manager
}
See the option tables in the README for the full list.
4. Last resort: lib.mkForce
To override a value Nomarchy sets at normal priority (an appearance value, or a whole list), raise your definition's priority:
{ lib, ... }:
{
# hardcode rounding against the theme (the CLI can no longer change it)
wayland.windowManager.hyprland.settings.decoration.rounding = lib.mkForce 0;
# own the entire keybind list
wayland.windowManager.hyprland.settings.bind = lib.mkForce [ "$mod, Return, exec, kitty" ];
}
If a plain assignment errors with "has conflicting definition values", that
value is theme-owned at normal priority — either change it via the CLI (§1) or
mkForce it here.
Quick reference
| You want to… | Do this |
|---|---|
| Change gaps / colors / rounding / fonts | nomarchy-state-sync set … or apply |
| Change input / misc / monitor / animations / terminal chrome | plain assignment in home.nix |
| Arrange monitors declaratively | nomarchy.monitors (values via nwg-displays) |
| Add keybinds / autostarts | add to the bind / exec-once list (concatenates) |
| Replace all keybinds | bind = lib.mkForce [ … ] |
| Hardcode an appearance value against the theme | lib.mkForce in home.nix |
| Drop a whole component | nomarchy.<component>.enable = false |
| Raw Hyprland lines | wayland.windowManager.hyprland.extraConfig |