The menu/Waybar toggle stops hyprsunset for the session only — it's WantedBy=graphical-session.target, so the next login auto-starts it and the off-state doesn't persist (deliberate "true colours for now" behaviour). Record the persistent-off option (a state marker honoured via the unit's ConditionPathExists) as an optional follow-up so it isn't forgotten. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
35 KiB
Roadmap & changelog
Forward-looking plans, plus a running log of shipped fixes (the "Known issues & follow-ups" section). Split out of the README so that stays a focused entry point — what Nomarchy is, how to install it, and how to override it. Items marked ✓ are shipped.
Roadmap
-
Menu system (apps launcher + theme switching + system actions), built on rofi 2.0 (native Wayland on 26.05) — its
.rasitheme is baked from theme-state.json like every other app, with rich per-element styling:- ✓ shipped:
modules/home/rofi.nix(per-element theme generated from the palette,themes/<slug>/rofi.rasiwhole-swap) and thenomarchy-menudispatcher: root picker (no args) ·power(lock/logout/suspend/hibernate/reboot/shutdown, SUPER+X) ·theme(SUPER+T) ·clipboard(cliphist, SUPER+CTRL+V) ·calc(rofi-calc, live, SUPER+CTRL+C) ·files(fd → xdg-open, SUPER+CTRL+F) ·emoji(rofi-emoji, SUPER+CTRL+E) ·web(Google). SUPER+D isrofi -show drun. - ✓ shipped modules:
network(nmtui in$TERMINAL) ·bluetooth(blueman-manager) ·capture(grim/slurp submenu: region/full → clipboard/file, saved to~/Pictures/Screenshots) ·keybinds(the cheatsheet, see below) ·ask(free-text → claude CLI in a terminal; auths via OAuth, no API key; pulled fresh vianpx @anthropic-ai/claude-code@latestrather than the nixpkgs package, which lags model releases —nodejsis bundled for npx; REPL stays open) - ✓ keybindings cheatsheet:
modules/home/keybinds.nixis the single source for both the Hyprland binds and the SUPER+? rofi list, so they can't drift;nomarchy-menu keybindsrenders the padded two-column sheet (generated/mouse binds carried in itsextrarows) - ✓ shipped binds:
SUPER+Space→rofi -show drun(quick launch) ·SUPER+M→nomarchy-menu(main menu) ·SUPER+?→ the cheatsheet;SUPER+Dstays-show drun - launcher icons: ✓
show-iconson, drawing from the theme's icon set (Papirus, via the icon-themes work below) - decision record: resolves the old Walker/Lua question — no GTK4 launcher, no second theming pipeline; the dispatcher owns the menu structure, so the renderer stays swappable (we moved fuzzel → rofi 2.0 once mainline gained native Wayland, for its richer theming)
- ✓ Organize the picker into category submenus: the root picker had grown
into a long flat list of 16 entries. It's now six: Apps · Theme · Tools ›
· System › · Power · Keybindings.
Tools(Calculator, Clipboard, Emoji, Files, Web, Capture, Ask) andSystem(Network, Bluetooth, DND, and the self-gated Snapshots / Power-profile) are submenus the dispatcher routes vianomarchy-menu tools|system, each ending in a← Backentry that re-opens the root. The directSUPER+CTRL+<mnemonic>binds still hit the leaves straight (bypassing the menu), and the self-gated entries still hide when unavailable. Remaining (optional): a Look & Feel category once there are more appearance toggles to group with Theme (night-light, wallpaper). General pattern (ongoing): the grouping is a standing convention, not a one-off — any new feature that earns a menu entry must be placed in the right submenu (don't let the root creep back to a flat list), with its directSUPER+CTRL+<mnemonic>bind and self-gating as applicable.
- ✓ shipped:
-
✓ Menu modules from rofi plugins: the old
calcflow committed the expression blind (result only in the next menu's-mesg) andqalc -tmisparsed common phrasings (15% of 200→rem(15, 1 B), the natural- language "of" tripping the CLI). Resolved by adopting purpose-built rofi modi (programs.rofi.plugins), all themed through the same.rasi:- calc → rofi-calc: live results as you type via libqalculate directly (dodging the qalc-CLI "of" bug), Enter copies, menu persists to chain calculations.
- emoji → rofi-emoji (new module, SUPER+CTRL+E): glyph picker, copies via the plugin's Wayland clipboard adapter.
- files stays the hand-rolled
fd→rofi -dmenu→ xdg-open fuzzy search: rofi-file-browser-extended was tried and dropped — its navigate-a-tree model felt worse than flat fuzzy-find for a quick launcher, and yazi (SUPER+E) already covers real browsing.
-
More menu modules from rofi tools: the script-based counterparts (run via
rofi -dmenu, like the hand-rolled modules), each a deliberate replacement of an existing flow: rofi-network-manager (a keyboard wifi/VPN picker vs today'snmtui-in-terminalnetwork), rofi-rbw / rofi-pass (a secrets module — Bitwarden via rbw, orpass— pairs withkeys.nix), and rofi-pulse-select (an audio sink/source switcher). Decide per-module whether it earns replacing the current path. -
Theme parity with legacy: summer-day/night now carry their legacy bar layouts as
waybar.jsoncwhole-swaps (adapted: dead legacy script modules dropped, Nerd-Fonts-v2 codepoints remapped to FontAwesome/v3, logo button opens nomarchy-menu); the other four identity themes are palette recolors and already match. Remaining: a visual pass over all six on the live ISO -
Per-theme rofi identity: the
themes/<slug>/rofi.rasiwhole-swap ships, and summer-day/night carry their legacy designs (inverted window, green inputbar, yellow bottom-border). Remaining: author.rasiidentities for the other four ported themes if/when they want one (the generated palette theme is the default and looks fine) -
Faster switches: move
backgrounds/out of the flake source (the 86 MB re-copy on every state write is the main eval tax), then pre-built theme variants if still needed -
Greeter (tuigreet/SDDM) theming from the same JSON (Plymouth ships since v1:
nomarchy.system.plymouth.*, background tinted from the state file) -
Installer round 2: multi-disk BTRFS RAID, impermanence, BIOS/legacy boot (v1
nomarchy-installis single-disk UEFI — seepkgs/nomarchy-install) -
launch-or-focus UX scripts (swayosd volume/brightness OSD ships since v1:
nomarchy.osd.*, media keys driveswayosd-client, themed from the JSON) -
Distro branding, round 2:
distroName = "Nomarchy"ships (os-releasePRETTY_NAME, systemd-boot entries, ISO menu label). ✓ tuigreet greeting (Welcome to <distroName>) and a brandedusers.motd(doubling as a helper cheat sheet), both keyed offdistroName. ✓isoImage.splashImage— the vendored vector logo (modules/nixos/branding/logo.svg, from legacy) recolored to the palette accent on the theme base, built at ISO-build time (hosts/live.nix). Remaining:isoImage.grubThemeso UEFI boot matches the isolinux splash (needs a full grub theme dir), and thedistroIdquestion (it changesDEFAULT_HOSTNAMEand upstreamisNixoschecks — needs a test pass; nixos-* CLI names stay regardless) -
✓ fastfetch branding:
modules/home/fastfetch.nix(nomarchy.fastfetch.enable) — the vendored vector logo, recolored to the palette accent and rendered to compact block-art via chafa at build time (tracks the theme), fronting a curated module list. Replaces the oversized legacy ASCII with a themed, sized logo. -
✓ Nomarchy logo font in Waybar: vendored
Nomarchy.ttf(modules/nixos/branding/), installed viafonts.packages, and the summer-day/night menu buttons now use itsU+F000glyph withfont-family: Nomarchypinned in their CSS (Nerd Fonts also occupy U+F000, so the pin is required). The other themes have no logo button. -
✓ Quality-of-life command aliases: a curated set ships on by default in
modules/home/shell.nix— navigation (../.../....), a git block (g,gst,ga/gaa,gc/gcm,gco/gsw,gb,gd/gds,gl/glg,gp/gpl,gf), and a nix block (ns,nr,nfu,nfc,nsearch,ngc), pluspathandreload. Scope decision: short where it helps but never shadow a real binary (same rule as rg/fd — the git block deliberately avoidsgs/ghostscript); system/home rebuilds keep their fullsys-update/home-updatenames rather than getting cryptic aliases. The set is documented in README §5 (Day-to-day), andaliaslists them in-shell. -
Theme-switch feedback: ✓ the "rebuilding…" notification is now persistent (timeout 0) and replaced in place by "applied ✓" / failure via a synchronous tag, so a multi-minute switch never reads as a failed selection. (An honest indeterminate indicator — HM gives no % — a literal progress widget would be cosmetic; revisit only if wanted.)
-
Icon themes: ✓ ships
papirus-icon-theme; the resolved name lives onnomarchy.theme.iconTheme(the JSON's optionaliconsfield, else Papirus-Dark/Light bymode) and feeds both Stylix'sgtk.iconTheme(Thunar/GTK apps) and rofi'sshow-icons. Remaining (optional): per-themeiconsoverrides for the presets, or shipping more icon packs. -
Nicer shell out of the box: ✓ zsh is the default login shell, with a starship prompt themed from the JSON, autosuggestions + syntax highlighting, and modern-CLI ergonomics —
cat→bat (theme "ansi", so it tracks the palette),ls→eza,cd→zoxide, pluslt/tree.nomarchy.shell.enable. (Deliberately did NOT alias grep→rg / find→fd: their flags differ enough to surprise;rg/fdship as themselves.) -
✓ Default application suite: a starter complete-workstation set —
libreoffice-fresh,vscode,gimp,inkscape— ships active in the downstreamtemplates/downstream/home.nixhome.packages, with the heavier opt-ins (texliveFull— multi-GB;texliveMediumis lighter — plus browser/email) commented just below. Decision: nonomarchy.apps.*option surface. Unlikenomarchy.services.*(real config behind each toggle — systemd units, subuid ranges, the Flathub oneshot), a bare package install has nothing behind the toggle:mkIf x { environment.systemPackages = [p]; }just reinholds what a package list already gives, and the honest opt-out for a package is deleting the line. So the suite is the user's own curated list (extending the existing# firefoxconvention), not a distro-module feature — which also keeps the apps out of the live ISO automatically (it never starts from the template) and respects that editor/office/graphics are personal-taste choices, not defaults to impose. Unfreevscodeevaluates fine —mkFlakeand the system both setallowUnfree = true. -
✓ Plymouth logo contrast: the shipped art was a fixed navy that vanished on dark bases.
modules/nixos/plymouth.nixnow recolors every element from the palette at build time (flat fill, alpha kept): logo/lock/bullet → text, entry/progress-box → surface, progress-bar → accent. Reads on light and dark; follows the theme as of the last system rebuild (like the background tint). -
✓ Hibernate double-unlock: on resume from hibernate the LUKS passphrase already gates the machine, but locking hyprlock before sleep meant a second password. Fixed by not locking before an encrypted hibernate: a
nomarchy-lock-before-sleepsystemd unit (modules/nixos/default.nix) takes over from hypridle'sbefore_sleep_cmdand locks on the RAM-resume sleeps (suspend / hybrid-sleep / suspend-then- hibernate) always, but skipshibernate.targetwhen the disk is LUKS- encrypted. (A first attempt that dismissed hyprlock after resume was wrong — killing a Wayland session-lock client trips its "go to a tty" crash failsafe instead of unlocking, which is the error screen it caused.) -
✓ Key agents & pinentry: ships
modules/home/keys.nix(nomarchy.keys.enable): one agent —services.gpg-agentwithenableSshSupportfronts SSH, so a singlepinentry-qt(native-Wayland, Stylix-themed Qt) handles GPG and SSH passphrases alike.SSH_AUTH_SOCKcomes from the agent's zsh integration; cache TTLs (30 min / 2 h) govern re-prompting. gnome-keyring stays the Secret Service (modern versions run no SSH agent, so no socket contention); screen lock doesn't flush the cache. Remaining (optional): a session-levelSSH_AUTH_SOCKexport so GUI clients launched outside a shell also see the agent. -
Sanitize & organize the repo: a housekeeping pass for consistency and clarity.
- ✓ pruned now-redundant config: the installer no longer writes
console.useXkbConfig/boot.initrd.systemd.enableintosystem.nix(distro-wide defaults since the LUKS-keymap fix), nor the offline-pin test fixture inflake.nix. - ✓ reconciled the README option tables with the live
nomarchy.*surface (added keys/fastfetch/snapper/greeter.autoLogin). - ✓ untracked
.claude/settings.local.json(machine-local) + gitignored. - ✓ branch/release model:
mainis the development default;v1is the release pointer downstreams pin (?ref=v1), advanced to main once a batch is tested — rolling, no tags. Broughtmaincurrent (it was a stale legacy-merge), and deleted the deadrefactor/wave/nixos-26.05branches (keptlegacyfor history). See the comment inflake.nix. - ✓ re-checked that every file earns its place under the
modules/hosts/themes/pkgs/toolsrule of thumb: no orphaned modules (keybinds.nixis a data moduleimport-ed by hyprland/rofi, so correctly absent fromdefault.nix), no dead-code markers, no editor/backup cruft, eachthemes/<slug>.jsonpalette pairs with its optional<slug>/overrides dir, andhosts/{default,live}are the documented reference + ISO hosts. Structure is clean as-is. - Open decision (deferred): the repo declares no formatter (no flake
formatter, no.editorconfig);.nixfiles use deliberate aligned hand-formatting, sonixfmt-rfc-style --checkflags ~33 files. Adopting a formatter would be a one-time repo-wide reformat that flattens that alignment — a maintainer call, not a silent cleanup, so left untouched.
- ✓ pruned now-redundant config: the installer no longer writes
-
Full docs review & restructure: a dedicated pass over all the prose, not just the code-adjacent cleanup the repo-sanitize item covers. The README has grown to ~540 lines with a ~200-line roadmap inline — the biggest single move is likely splitting the roadmap out (e.g.
ROADMAP.md/docs/) so the README stays a focused "what it is / how to install / how to override" entry point. Also: reconcile every option table against the livenomarchy.*surface (snapper and others are missing); a pass overdocs/OVERRIDES.md+docs/TESTING.mdand thetemplates/downstream/README.mdfor drift; check the install/first-run story reads cleanly end to end; and decide whether anything wants a real docs site vs. staying Markdown-in-repo. Pairs with the first-boot welcome and control-center items (shared "how do I…" surface). -
Laptop power / battery management: a real power story behind a
nomarchy.system.power.*surface (modules/nixos/power.nix), replacing the old "onlyservices.upowerfor Waybar reporting" baseline:- ✓ profiles:
power-profiles-daemonships by default (the upstream- aligned choice — power-saver/balanced/performance viapowerprofilesctl, switched through polkit so no root prompt). Apower-profilemenu module (in the SUPER+M picker) and the first Waybarcustom/*indicator (click to cycle) both self-gate on a battery being present + PPD running, so they hide on desktops and under TLP — no system→home wiring. TLP is the opt-in (backend = "tlp") for deeper battery tuning; the two are mutually exclusive (asserted). - ✓ thermal:
thermaldbehindpower.thermal.enable; the installer turns it on for aGenuineIntelCPU. - ✓ longevity:
power.batteryChargeLimit(e.g. 80) — a backend- independent sysfs oneshot writescharge_control_end_threshold. Off by default; the installer scaffolds it commented-out on laptops. - ✓ installer: writes
power.laptop = true(battery probe) andpower.thermal.enable(Intel) into the generatedsystem.nix. - ✓ idle cohesion:
modules/home/idle.nixnow suspends only on battery (and sooner — 15 min vs the old fixed 30), gating the hypridle suspend listener on anomarchy-on-acprobe so a plugged-in machine stays up mid-idle; lock/screen-off are unchanged on both sources. logind's lid handling is left at its defaults (suspend on lid close, ignore when docked) — an explicit "I'm done" that coheres with the idle behaviour. - Remaining: a boot-only→event-driven charge-limit re-apply (udev) if a firmware resets the threshold on unplug.
- ✓ Waybar parity: the
custom/powerprofileindicator now shows in the summer-day/night whole-swap themes too.powerProfileStatus/Cycleare namedwriteShellScriptBins on PATH (waybar.nixhome.packages), so the generated config and the staticwaybar.jsoncboth exec them by bare name (the same parity the DND bell has). General pattern: any new generated-config module needs adding to the whole-swap themes too.
- ✓ profiles:
-
Full hardware enablement (beyond nixos-hardware): nixos-hardware profiles cover basic per-model functionality (quirks, drivers), but the advanced features of a machine — keyed more on the CPU/GPU generation than the model — are left for the user to wire up by hand. Close that gap without making it finnicky: extend the installer's existing autodetection (DMI → nixos-hardware profile today; add CPU vendor/arch, GPU, NPU, fingerprint reader, SSD) to switch on the safe, broadly-beneficial features automatically, and expose a small
nomarchy.hardware.*surface (per-vendor where it helps, e.g.nomarchy.hardware.amd.*) for the heavy or experimental bits. Goal: full utilisation out of the box — opt-out for the safe defaults, opt-in for the multi-GB / experimental extras. Complements nixos-hardware (model quirks) rather than replacing it; keep the detection in the installer'shardware-dbso an installed machine bakes the right defaults, all overridable throughnomarchy.hardware.*.- ✓ Mechanism + broad seed shipped (
modules/nixos/hardware.nix): a vendor-keyednomarchy.hardware.*surface (intel,amd,fingerprint,npu),hardware-db.shextended to detect Intel/AMD, a fingerprint reader (libfprint USB vendor IDs) and an NPU (Intel VPU / AMD XDNA PCI IDs), and the installer bakes the matching toggles intosystem.nix— safe defaults active (GuC/HuC, amd-pstate, AMD VA-API env, fprintd), heavy/experimental opt-ins commented (Intel compute-runtime, ROCm, fingerprint PAM, NPU driver). Audited against the nixos-hardware commons so it only fills the gap above them — microcode / the media-driver VA-API stack / weekly fstrim already come fromcommon-cpu-*/common-gpu-*/common-pc-ssd. Exercised live on the dev machine's detection (an AMD Ryzen-AI laptop: AMD- fingerprint + NPU all detected) and a toggles-on build (
amd_pstate=active i915.enable_guc=3in kernel-params,fprintd.servicepresent). Remaining: on-hardware verification of the runtime bits (AMD/NPU/Intel GPU-compute) — none are testable in CI or on the Intel Latitudes for the AMD paths. SSD TRIM is intentionally left tocommon-pc-ssd.
- fingerprint + NPU all detected) and a toggles-on build (
- ✓ Hardening (driver-gen + kernel awareness):
intel.gucemits the i915 param, so the installer turns it off when the GPU is on the newerxedriver (Lunar Lake / Battlemage / Panther Lake — GuC is default-on there); the NPU detector matches the PCI accelerator class (not just a device-ID list) so new gens are caught without a code change; and anomarchy.hardware.latestKernelescape hatch (+ a build-time warning whennpu.enablepredates the shipped kernel) covers very-new hardware whose drivers only just landed. A config-assertion VM test guards the wiring (checks.hardware-toggles: kernel cmdline + fprintd + PAM, booted in a VM). Worked example — ThinkPad T14s (Ryzen 7 PRO 7840U + Radeon 780M): - GPU compute — ROCm: the 780M is an RDNA3 iGPU (gfx1103) ROCm doesn't
officially list, so it needs
HSA_OVERRIDE_GFX_VERSION=11.0.0. Multi-GB closure → opt-in (nomarchy.hardware.amd.rocm.enable); unlocks GPU PyTorch / Ollama. - Ryzen AI NPU (XDNA): the
amdxdnakernel driver (mainline 6.14+) + the XRT/xdna userspace runtime + firmware. Niche/experimental → opt-in. - AMD P-State EPP (Zen 4 power):
amd_pstate=activefor the EPP governor, which power-profiles-daemon (already shipped,power.nix) drives per profile. Broadly beneficial on Zen 2+ → default on when the installer sees an AMD CPU. - Hardware video acceleration (VA-API): mesa's radeonsi exposes VA-API
on AMD (
LIBVA_DRIVER_NAME=radeonsi, libva + drivers inhardware.graphics.extraPackages); Intel usesintel-media-driver. Broadly beneficial → default on, vendor-detected. - LVFS firmware & biometrics: fwupd already ships (✓,
services.fwupd). Add fingerprint:services.fprintdwhen a reader is detected, with opt-in PAM integration for login/sudo (password-only stays the default for the cautious). - SSD periodic TRIM:
services.fstrim.enable(weekly) — safe and beneficial, so default on (trivial enough it may warrant being distro-wide regardless). Sub-items here can graduate into their own roadmap entries as they're scoped; the unifying work is the detection +nomarchy.hardware.*surface.
- ✓ Mechanism + broad seed shipped (
-
Opt-in services & integrations: the counterpart to the opt-out application suite above — heavier or more personal integrations shipped off by default, each a
nomarchy.services.<name>.enabletoggle a downstream flips on in one line. Keeps the base lean while making common additions trivial. ✓ Seventeen shipped inmodules/nixos/services.nix(system-side), each with a commented example in the downstreamsystem.nixtemplate:tailscale,syncthing(runs as the login user, GUI on 127.0.0.1:8384),podman(rootless,dockeraliased, user subuid/subgid),flatpak(+ Flathub remote added by a oneshot),pika(Pika Backup GUI),steam(programs.steam— the 32-bit stack, controller udev, Remote-Play ports a bare package can't),libvirt(libvirtd + virt-manager, user added to thelibvirtdgroup),obs(OBS Studio + a v4l2loopback virtual camera usable as a webcam in Zoom/Teams),docker(rootful; asserts against the podman docker-compat),kdeconnect,gamemode,adb(android-tools; systemd handles the udev rules),wireshark(Qt GUI + thewiresharkgroup),ollama(local LLM API on 127.0.0.1:11434),printing(CUPS + Avahi mDNS),openrgb(RGB lighting daemon), andrestic(scheduled daily backup — a small option surface:repository/passwordFile/paths, 7/4/6 retention). More candidates by area:- ✓ cloud/sync: Syncthing (
services.syncthing); Nextcloud client is a bare tray app (in the app-suite menu, not a service) - ✓ local AI: Ollama (
nomarchy.services.ollama, optional GPU accel) ships; LM Studio is a (commented) app-suite package (a bare GUI, no service) — pairs with the menu's Ask-Claude philosophy - ✓ containers/VMs: Podman (
virtualisation.podman); libvirt + virt-manager (nomarchy.services.libvirt); Docker (nomarchy.services.docker) - ✓ networking: Tailscale (
services.tailscale); WireGuard needs no toggle — NetworkManager (on by default) imports.conftunnels natively; thewireguard-toolsCLI is in the app-suite menu - ✓ gaming/media: Steam (
nomarchy.services.steam); OBS Studio (nomarchy.services.obs, with the v4l2loopback virtual camera); GameMode (nomarchy.services.gamemode) - ✓ devices: printing (CUPS + Avahi,
nomarchy.services.printing); KDE Connect (nomarchy.services.kdeconnect); OpenRGB (nomarchy.services.openrgb). Plus dev tooling — Androidadbandwiresharktoggles - ✓ backup: Pika Backup (
pika-backup, GUI over Borg); scheduled headless restic (nomarchy.services.restic) - ✓ escape hatch: Flatpak (
services.flatpak) + Flathub, for apps outside nixpkgs
Surface decided:
nomarchy.services.*, system-side for system services (home-side ones can extend the same prefix later). Remaining: curate the rest (Ollama, containers, Steam/OBS, printing, backups, Flatpak …). The opt-out application suite is deliberately not a parallelnomarchy.apps.*surface — it's a curatedhome.packageslist in the downstream template (see "Default application suite" above), since a bare package install has no config to put behind a toggle. Unfree entries are already covered (allowUnfree = true). - ✓ cloud/sync: Syncthing (
-
✓ Display / monitor management: declarative
nomarchy.monitors(a per-output schema — name/resolution/position/scale/transform/mirror/ bitdepth/vrr/disable) generates Hyprlandmonitorrules, keeping the,preferred,auto,1wildcard as the fallback; Hyprland applies them on hotplug, so a declared external/dock output arranges itself on connect (no kanshi — it fights Hyprland's own output management).nwg-displaysships behindnomarchy.displays.enableas an interactive arranger (a helper to find values; the declarative config stays the source of truth — its output file isn't sourced). Remaining: true docked/undocked profile switching of the same outputs (Hyprland's per-output rules cover the common "external connects → arrange" case, not multi-layout toggles), and optionally workspace-to-monitor binding. -
✓ Night light / blue-light filter:
nomarchy.nightlight(opt-in) — a scheduled colour-temperature shift viahyprsunset(Hyprland-native), warm at night, identity (no shift) by day.modules/home/nightlight.nixdrives the HMservices.hyprsunsetwith two time-based profiles (sunrise→ identity,sunset→temperature), so hyprsunset handles the schedule and the on-login state. Active-profile-at-session-start was confirmed on hardware (2026-06-18). ✓ Menu + Waybar toggle:nomarchy-nightlight(innightlight.nix, on PATH) starts/stops the hyprsunset service —systemctl --user is-activeis the single source of truth, the screen restores to true colours when stopped, and it forces the filter off for colour-sensitive work and back on without touching config. Anomarchy-menu nightlightentry (System submenu, self-gated on the unit existing) and a self-gating Waybarcustom/nightlightindicator (moon = on, sun = off; in the generated bar and both summer whole-swaps) drive it. The toggle is session-scoped by design:stophalts the running unit but it'sWantedBy=graphical-session.target, so the next login auto-starts it and night-light returns to its schedule (off never persists). Remaining (optional): (1) persistent off — a state marker (~/.local/state/nomarchy/nightlight-off) the unit honours viaConditionPathExists=!%h/…, so a manual off survives logout/reboot until toggled back; (2) geo (lat/long) auto sunset/sunrise (would mean wlsunset, which schedules by location). Pending an on-machine check that stopping hyprsunset cleanly restores the gamma. -
Keyboard layouts (per-device + switching):
- ✓ Per-device declarative layout:
nomarchy.keyboard.devices({ "<hyprctl-device-name>" = { layout; variant; }; }) generates Hyprlanddeviceblocks that override the sessionnomarchy.keyboard.layoutfor a named keyboard — e.g. an external board that's physically a different layout than the laptop's. Hyprland applies it whenever that device connects (the "external keyboard remembers its layout" case, done the declarative way). A Waybarhyprland/languageindicator shows the active layout, gated on more than one layout being in play (comma in the session layout, or any per-device override) so single-layout bars stay clean. - ✓ Interactive new-keyboard prompt (runtime + persist): set
nomarchy.keyboard.layouts(candidate layouts) and anomarchy-keyboard- watchdaemon runs (exec-once): it pollshyprctl devices, and when a keyboard connects after login that isn't inkeyboard.devicesand hasn't been chosen before, it pops a rofi layout picker, applies the choice as a per-devicehyprctl keyword device[<name>]:kb_layout(the runtime twin of the declarativedevice{}blocks — so it isolates that one keyboard and never touches the built-in board), and remembers it per-device in~/.local/state/nomarchy/keyboard-layouts— re-applied silently on later reconnects. The boot-time set (incl. the built-in keyboard) is never prompted. The runtime-remember complement to the declarativekeyboard.devices; a stateful runtime piece by design. Picker verified on hardware (2026-06-18); the first cut applied the choice withswitchxkblayout(a global layout-index flip) and merged the candidate pool intoinput.kb_layout, so a selection leaked onto the laptop keyboard and stuck after unplug — fixed by the per-device keyword + keeping the pool out of the session layout. Remaining (bonus): offer to write a choice intokeyboard.devicesso it graduates to the reproducible config; re-verify the per-device isolation on hardware. - Remaining: a multi-layout cycle bind (
hyprctl switchxkblayout/ xkbgrp:options) for switching layouts on one keyboard; add thehyprland/languagemodule to the summer whole-swap themes for parity (the gating doesn't translate to their static JSON). Keep the system (console/initrd) and session layouts in sync (the LUKS-keymap work).
- ✓ Per-device declarative layout:
-
✓ Do-Not-Disturb: swaync DND toggle wired into the menu (
nomarchy-menu dnd, in the picker, SUPER+CTRL+D) and a Waybar bell indicator (custom/notificationviaswaync-client -swb: shows the notification count + DND state, left-click toggles the panel, right-click toggles DND). Turning DND off confirms with a toast; turning it on is silent (notifications are suppressed — the bell-off glyph is the cue). -
✓ Snapshot browse/restore UX:
nomarchy-menu snapshot(in the SUPER+M picker, self-gated on snapper) launches btrfs-assistant — the desktop browse/diff/restore/rollback UI, elevating via polkit (the safe choice for a destructive, root-only op vs a fat-fingerable rofi rollback). Shipped system-side gated onnomarchy.system.snapper. Also extended snapper to snapshot /home by default (hourly 5 / daily 7 / weekly 4) when it's its own BTRFS subvolume; a boot oneshot creates the required/home/.snapshotssubvolume if missing (covers existing installs, no disko change). The backend is VM-verified (a full BTRFS+LUKS install: bothroot+homeconfigs, a/hometimeline snapshot taken,/home/.snapshotsa real subvolume, the oneshotResult=success).- ⚠ Known bug — btrfs-assistant 2.2 segfaults on launch in nixpkgs
26.05: it crashes inside
libbtrfsutil.so.1.4.0(a library ABI mismatch, confirmed in the VM regardless of GL/Qt platform — so it's not a VM/GL artifact and will crash on hardware too). The menu wiring is correct and the app is installed, but the GUI doesn't open. The snapshot backend (the actual snapshots) is unaffected. Fix path: a nixpkgs override aligning its libbtrfsutil, or wait for an upstream bump; meanwhile the menu entry is a no-op when the binary crashes. Fallback if it lingers: a rofi-based snapshot menu (no btrfs-assistant dependency). - Remaining (optional): a keyboard-driven rofi browse for quick glances; boot-from-snapshot needs a systemd-boot equivalent of grub-btrfs.
- ⚠ Known bug — btrfs-assistant 2.2 segfaults on launch in nixpkgs
26.05: it crashes inside
-
Update awareness: updates are manual today (
sys-update/home-update); add a Waybar indicator / notification when flake inputs are stale or a new nixpkgs rev is available (optionally with a pending-change count). Augments, never replaces, the explicit rebuild flow. -
"nomarchy" control center: a single TUI/GUI front-end over the common toggles — theme, power profile, opt-in services, display, DND — built on the same
nomarchy-theme-sync/nomarchy.*surface the menu already uses. Plus a first-boot welcome that lands new installs in a guided "pick your theme / essentials" flow (ties into the branding work).
Known issues & follow-ups
- ✓ Yazi TOML parse error on startup: yazi 26.x made fetchers'
groupfield required, so[[plugin.prepend_fetchers]]failed to parse and yazi fell back to presets. Fixed by addinggroup = "git"to both git fetcher entries inmodules/home/yazi.nix(the git plugin'ssetup()only renders the linemode; the fetcher still needs registering). - ✓ Starship prompt styling: dropped the powerline look (the
[]separator glyph +bg:fills) for a flat prompt — bold-accent directory, warn git branch, subtext status/duration,❯character, all plain colored text (modules/home/shell.nix). Also wired incmd_duration, which was configured but never referenced informat. - ✓ xfce deprecation warnings: moved
xfce.exo→pkgs.xfce4-exoand the three Thunar plugins to their new top-level names inmodules/nixos/file-manager.nix; the eval warnings are gone. - ✓ Rofi function keybindings: direct
SUPER+CTRL+<mnemonic>binds jump straight to eachnomarchy-menumodule — V clipboard · C calc · W web · F files · N network · B bluetooth · S capture · A ask — added tomodules/home/keybinds.nix, so they also show in the SUPER+? cheatsheet. - ✓ Enable nix-ld by default:
programs.nix-ld.enableis on distro-wide (modules/nixos/default.nix), so prebuilt/foreign dynamically-linked binaries run out of the box. - ✓ Hyprland border colors off for some themes: the cause was v1
forcing an
accent→accentAltgradient on every theme; legacy used a solid border (accent for nord/retro-82/lumon, the text tone for kanagawa/summer-day/summer-night). Added a palette-resolvedborderfield ({active, inactive}) to the theme schema (theme.nix), consumed solid inhyprland.nix, and declared it in every preset so a switch always replaces it. All six identity themes now match legacy exactly. - ✓ Waybar shows non-existent workspaces: the v1 summer port "fixed"
legacy's deprecated
persistent_workspaces(underscore — silently ignored by current Waybar, so legacy only ever showed existing workspaces) into the modernpersistent-workspaces(hyphen), which Waybar honours → all 10 rendered as phantoms. Dropped the block fromthemes/summer-{day,night}/waybar.jsonc; the other themes use the generatedwaybar.nix, which never had it, so they already match. - ✓ GTK/Qt ignore the theme's light/dark mode: Stylix set
polaritybut not theorg.freedesktop.appearance color-schemethat GTK4/libadwaita and Qt6 read via the portal, so a light theme could still render apps dark.stylix.nixnow setsdconforg/gnome/desktop/interface color-scheme=prefer-light/prefer-darkfromt.mode(xdg-desktop-portal-gtk already ships, andprograms.dconfis on system-side), so libadwaita/Qt follow the palette. Confirmed in a live session (headless QEMU): the portal'sorg.freedesktop.appearancecolor-schemereads1on a dark theme and flips to2after switching to a light one (catppuccin-latte) — so xdg-desktop-portal-gtk does relay the dconf value GTK4/Qt apps read.