From 3d5cb2130286394adb42895fbc1b1cc76146397d Mon Sep 17 00:00:00 2001 From: Bernardo Magri Date: Fri, 10 Jul 2026 13:32:50 +0100 Subject: [PATCH] feat(cli): nomarchy-pull / nomarchy-rebuild / nomarchy-home Split lifecycle into three clear commands (user pick): nomarchy-pull git pull (if checkout) + flake.lock update nomarchy-rebuild system switch on current lock (snap + nvd) nomarchy-home Home Manager switch Full upgrade: pull && rebuild && home. Legacy sys-update / sys-rebuild / home-update remain as wrappers. nixos-rebuild-snap uses NOMARCHY_PATH. V0: flake check --no-build green. --- README.md | 45 +++++++------ agent/MEMORY.md | 5 +- docs/RECOVERY.md | 6 +- docs/ROADMAP.md | 6 +- modules/home/options.nix | 4 +- modules/home/rofi.nix | 4 +- modules/home/shell.nix | 6 +- modules/home/updates.nix | 18 +++-- modules/nixos/default.nix | 134 +++++++++++++++++++++----------------- 9 files changed, 127 insertions(+), 101 deletions(-) diff --git a/README.md b/README.md index e8a0945..ce9b36f 100644 --- a/README.md +++ b/README.md @@ -182,22 +182,29 @@ home-manager switch --flake .#me # desktop: every theme change, no Day-to-day you'll use the shipped shortcuts instead: ```sh -sys-update # nix flake update + system rebuild (BTRFS snapshot first when available) -sys-rebuild # system rebuild against the CURRENT lock (config changes only, no update) - # …both end with a package-level diff of what the rebuild changed (nvd) -home-update # home-manager switch (no flake update, no sudo) +nomarchy-pull # git pull (if checkout) + nix flake update — no rebuild +nomarchy-rebuild # system rebuild against the CURRENT lock (sudo inside; + # BTRFS snapshot first when snapper is on; nvd diff after) +nomarchy-home # home-manager switch — desktop only, no sudo, no lock bump ``` -**Order matters when pulling distro updates.** `home-update` does *not* -touch the lock — it rebuilds the desktop against the **current** -`flake.lock`. A new Nomarchy revision (new keybinds, theming, modules) -arrives only when the lock is updated, which `sys-update` does -(`nix flake update`). So to pull an update that affects the desktop layer: -run `sys-update` **first** (updates the lock + rebuilds the system), **then** -`home-update` (re-applies the desktop against the new lock). Doing them in -the other order rebuilds the desktop against the *old* inputs and silently -skips the new home-side changes. After a home-side keybind/config change, -also `hyprctl reload` (or relogin) so the running session re-reads it. +| When | Run | +|---|---| +| Pull newer Nomarchy / nixpkgs / inputs | `nomarchy-pull` | +| You changed `system.nix` (or after pull) | `nomarchy-rebuild` | +| You changed `home.nix` / theme / desktop | `nomarchy-home` | +| Full upgrade (inputs + both layers) | `nomarchy-pull && nomarchy-rebuild && nomarchy-home` | + +**Order matters for distro updates.** `nomarchy-home` rebuilds against the +**current** `flake.lock` — it never updates inputs. A new Nomarchy revision +lands only when the lock is updated (`nomarchy-pull`). So for an upstream +desktop change: **pull → rebuild → home**. Home before pull rebuilds against +the old inputs and silently skips new home-side changes. After a home-side +keybind/config change, also `hyprctl reload` (or relogin) so the session +re-reads it. + +Legacy aliases still work: `sys-update` → pull+rebuild, `sys-rebuild` → +`nomarchy-rebuild`, `home-update` → `nomarchy-home`. Override anything via the `nomarchy.*` surface or plain NixOS/HM options: appearance (gaps/colors/fonts) changes through `nomarchy-theme-sync`, @@ -397,9 +404,9 @@ nomarchy-theme-sync set ui.gapsOut 16 # tweak one knob (also a switch) nomarchy-theme-sync bg next # cycle wallpapers — instant, no rebuild nomarchy-theme-sync bg auto # back to the theme's default wallpaper nomarchy-theme-sync get colors.accent -sys-update # update inputs + rebuild the system (snapshots first) -sys-rebuild # rebuild the system, current lock (no update) -home-update # rebuild just the desktop layer +nomarchy-pull # git pull + flake input update (no rebuild) +nomarchy-rebuild # rebuild the system, current lock +nomarchy-home # rebuild just the desktop layer nomarchy-doctor # read-only health sheet (also: menu › System › Doctor) ``` @@ -429,9 +436,9 @@ gd gds # diff · diff --staged gl glg # log graph (last 20 · all branches) gp gpl gf # push · pull · fetch --all --prune -# nix (system/home rebuilds keep their full sys-update / home-update names) +# nix (lifecycle: nomarchy-pull / nomarchy-rebuild / nomarchy-home — full names) ns nr # nix shell · nix run (e.g. ns nixpkgs#ripgrep) -nfu nfc # nix flake update · check +nfu nfc # nix flake update · check (prefer nomarchy-pull for day-to-day) nsearch ngc # nix search nixpkgs · nix-collect-garbage -d # misc diff --git a/agent/MEMORY.md b/agent/MEMORY.md index 53f9d99..5f5ce7c 100644 --- a/agent/MEMORY.md +++ b/agent/MEMORY.md @@ -124,8 +124,9 @@ iteration would otherwise rediscover. - GTK4/libadwaita/Qt6 read light/dark from the portal's `org.freedesktop.appearance color-scheme` (dconf), not Stylix polarity (§ GTK/Qt ignore the theme's mode). -- Update order matters downstream: `sys-update` (lock) before - `home-update`, or desktop changes are silently skipped against the old +- Update order matters downstream: `nomarchy-pull` (lock) then + `nomarchy-rebuild` then `nomarchy-home`, or desktop changes are silently + skipped against the old lock (README § 3). - Hyprland 0.53 rewrote window rules: `windowrulev2` is a hard error and the old rule-first `float, class:^…$` no longer parses — both surface a diff --git a/docs/RECOVERY.md b/docs/RECOVERY.md index 28ad9f2..e613292 100644 --- a/docs/RECOVERY.md +++ b/docs/RECOVERY.md @@ -27,11 +27,11 @@ recent desktop generations — pick one and it activates. Or simply apply a theme you know is good: `nomarchy-theme-sync apply boreal` (or any preset). If a switch failed halfway, the state file is written *before* the rebuild — fix the cause and re-run -`home-manager switch --flake ~/.nomarchy` (or `home-update`). +`home-manager switch --flake ~/.nomarchy` (or `nomarchy-home`). Your flake checkout is a git repo, and with auto-commit enabled every apply is a commit: `git -C ~/.nomarchy log` to see what changed, -`git revert` the culprit, then `home-update`. +`git revert` the culprit, then `nomarchy-home`. ## 2. The desktop won't start at all @@ -59,7 +59,7 @@ last 10 generations are kept). That boots yesterday's system unchanged. Booting an old generation is temporary — the default entry is still the broken one. Make the fix stick from the working boot: revert the change in `~/.nomarchy` (`git -C ~/.nomarchy revert …` or edit `system.nix` -back), then `sys-rebuild`. +back), then `nomarchy-rebuild`. ## 4. Files went missing or wrong — snapshots (BTRFS installs) diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index f77d01a..45bd807 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -264,9 +264,9 @@ Design/decision records and a running log of shipped work (items marked `gl`/`glg`, `gp`/`gpl`, `gf`), and a nix block (`ns`, `nr`, `nfu`, `nfc`, `nsearch`, `ngc`), plus `path` and `reload`. Scope decision: short where it helps but **never shadow a real binary** (same rule as rg/fd — the git block - deliberately avoids `gs`/ghostscript); system/home rebuilds keep their full - `sys-update`/`home-update` names rather than getting cryptic aliases. The set - is documented in README §5 (Day-to-day), and `alias` lists them in-shell. + deliberately avoids `gs`/ghostscript); lifecycle is `nomarchy-pull` / + `nomarchy-rebuild` / `nomarchy-home` (full names on PATH, not aliases). The + set is documented in README §5 (Day-to-day), and `alias` lists shell shortcuts. - **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 diff --git a/modules/home/options.nix b/modules/home/options.nix index f637d8a..5c77555 100644 --- a/modules/home/options.nix +++ b/modules/home/options.nix @@ -223,8 +223,8 @@ in compares the flake's locked inputs (nixpkgs, the Nomarchy input, …) against upstream and — when Flatpak is enabled — counts Flatpak updates, surfacing a Waybar indicator + a notification when something - is available. It never changes anything; you still run sys-update / - home-update / flatpak update yourself'' // { default = config.nomarchy.settings.updates.enable or false; }; + is available. It never changes anything; you still run nomarchy-pull / + nomarchy-rebuild / nomarchy-home / flatpak update yourself'' // { default = config.nomarchy.settings.updates.enable or false; }; interval = lib.mkOption { type = lib.types.str; diff --git a/modules/home/rofi.nix b/modules/home/rofi.nix index 20f4e12..ce6e514 100644 --- a/modules/home/rofi.nix +++ b/modules/home/rofi.nix @@ -798,7 +798,7 @@ ${themeRows} fi fi nomarchy-theme-sync --quiet set settings.fingerprint.pam "$new" --no-switch - notify-send "Fingerprint" "Use for login: $new — applies on next sys-rebuild." + notify-send "Fingerprint" "Use for login: $new — applies on next nomarchy-rebuild." ;; esac ;; @@ -843,7 +843,7 @@ ${themeRows} printf 'Enter to close.'; read -r _" ;; *Snapshots*) exec "$0" snapshot ;; *"older generation"*) - notify-send "System rollback" "Reboot and pick an older NixOS generation in the boot menu (the last 10 are kept). Make it stick: revert the change in ~/.nomarchy, then sys-rebuild. Details: docs/RECOVERY.md §3." ;; + notify-send "System rollback" "Reboot and pick an older NixOS generation in the boot menu (the last 10 are kept). Make it stick: revert the change in ~/.nomarchy, then nomarchy-rebuild. Details: docs/RECOVERY.md §3." ;; esac ;; tools) diff --git a/modules/home/shell.nix b/modules/home/shell.nix index d4d3780..6834f55 100644 --- a/modules/home/shell.nix +++ b/modules/home/shell.nix @@ -69,11 +69,11 @@ in gpl = "git pull"; gf = "git fetch --all --prune"; - # Nix — the flake/store verbs (system/home rebuilds already have the - # sys-update / home-update commands, so they're not re-aliased here). + # Nix — store/flake verbs. Lifecycle is nomarchy-pull / + # nomarchy-rebuild / nomarchy-home (full names on PATH, not aliases). ns = "nix shell"; # ns nixpkgs#ripgrep nr = "nix run"; # nr nixpkgs#cowsay - nfu = "nix flake update"; + nfu = "nix flake update"; # prefer nomarchy-pull day-to-day nfc = "nix flake check"; nsearch = "nix search nixpkgs"; ngc = "nix-collect-garbage -d"; # user generations; sudo for system roots diff --git a/modules/home/updates.nix b/modules/home/updates.nix index 976a84c..f39364b 100644 --- a/modules/home/updates.nix +++ b/modules/home/updates.nix @@ -1,7 +1,7 @@ # Update awareness (opt-in, nomarchy.updates.enable) — a passive background # check that surfaces a Waybar indicator + a notification when updates are -# available, without ever changing anything (you still run sys-update / -# home-update / flatpak update). It counts: +# available, without ever changing anything (you still run nomarchy-pull / +# nomarchy-rebuild / nomarchy-home / flatpak update). It counts: # • flake inputs whose locked rev is behind upstream (nixpkgs, the Nomarchy # input, home-manager …) — via `git ls-remote` on each branch-tracking # github/git input in flake.lock; offline → skipped, never a false alarm. @@ -83,7 +83,7 @@ let msg="$nix flake input(s)" [ "$fp" -gt 0 ] && msg="$msg · $fp Flatpak(s)" ${pkgs.libnotify}/bin/notify-send -a Nomarchy "Updates available" \ - "$msg — click the bar icon, or run sys-update." + "$msg — click the bar icon, or: nomarchy-pull && nomarchy-rebuild && nomarchy-home" fi refresh_bar ;; status) @@ -91,7 +91,7 @@ let [ "$total" -gt 0 ] 2>/dev/null || exit 0 # up to date / unchecked → hide nix=$("$JQ" -r '.nix // 0' "$state"); fp=$("$JQ" -r '.flatpak // 0' "$state") tip="Updates available" - [ "$nix" -gt 0 ] && tip="$tip\n• $nix flake input(s) — sys-update" + [ "$nix" -gt 0 ] && tip="$tip\n• $nix flake input(s) — nomarchy-pull && nomarchy-rebuild && nomarchy-home" [ "$fp" -gt 0 ] && tip="$tip\n• $fp Flatpak(s) — flatpak update" printf '{"text":"󰚰 %d","tooltip":"%s","class":"available"}\n' "$total" "$tip" ;; upgrade) @@ -99,9 +99,13 @@ let nix=$("$JQ" -r '.nix // 0' "$state" 2>/dev/null || echo 0) fp=$("$JQ" -r '.flatpak // 0' "$state" 2>/dev/null || echo 0) echo "Pending: $nix flake input(s), $fp Flatpak(s)." - if [ "$nix" -gt 0 ] && command -v sys-update >/dev/null 2>&1; then - read -rp "Run sys-update (flake update + system rebuild)? [y/N] " a - [ "$a" = y ] && sys-update + if [ "$nix" -gt 0 ] && command -v nomarchy-pull >/dev/null 2>&1; then + read -rp "Run nomarchy-pull && nomarchy-rebuild && nomarchy-home? [y/N] " a + if [ "$a" = y ]; then + nomarchy-pull + nomarchy-rebuild + command -v nomarchy-home >/dev/null 2>&1 && nomarchy-home + fi fi if [ "$fp" -gt 0 ] && command -v flatpak >/dev/null 2>&1; then read -rp "Run flatpak update? [y/N] " a diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix index 58d978c..2f90900 100644 --- a/modules/nixos/default.nix +++ b/modules/nixos/default.nix @@ -54,9 +54,9 @@ in ${distroName} — a NixOS desktop, themed from one JSON. - sys-update update inputs + rebuild the system - sys-rebuild rebuild the system, no input update - home-update apply home/theme changes (no sudo) + nomarchy-pull git pull + flake input update (no rebuild) + nomarchy-rebuild rebuild the system (current lock) + nomarchy-home rebuild the desktop / Home Manager nomarchy-theme-sync apply switch the whole palette nomarchy-doctor read-only health check SUPER+? keybindings cheatsheet @@ -333,25 +333,63 @@ in nomarchy-control-center # TUI control center nomarchy-detect-hw # post-install hardware re-probe (HARDWARE.md §8) - # Friendly wrappers for the two rebuild paths (README §3). Run as - # your user: `nix flake update` must NOT run as root (libgit2 - # refuses the user-owned flake repo) — sudo happens inside, only - # for the system switch. - (pkgs.writeShellScriptBin "sys-update" '' + # Day-to-day lifecycle (README §3). Always run as your user — + # `nix flake update` / git must not run as root (libgit2 refuses a + # user-owned flake); sudo is only for the system switch. + # + # nomarchy-pull git pull (if checkout) + flake.lock update + # nomarchy-rebuild system switch against the *current* lock + # nomarchy-home Home Manager switch (desktop layer) + # + # Full distro upgrade: nomarchy-pull && nomarchy-rebuild && nomarchy-home + # Config-only system: nomarchy-rebuild + # Theme/desktop only: nomarchy-home + # + # Legacy names (sys-update / sys-rebuild / home-update) stay as + # thin wrappers so old docs and muscle memory keep working. + (pkgs.writeShellScriptBin "nomarchy-pull" '' set -euo pipefail if [ "$(id -u)" -eq 0 ]; then - echo "sys-update: run as your normal user (it sudos the rebuild itself)" >&2 + echo "nomarchy-pull: run as your normal user" >&2 exit 1 fi flake="''${NOMARCHY_PATH:-$HOME/.nomarchy}" - echo "sys-update: updating flake inputs in $flake" + if [ ! -d "$flake" ]; then + echo "nomarchy-pull: flake path not found: $flake" >&2 + echo " Set NOMARCHY_PATH or clone/symlink your flake to ~/.nomarchy." >&2 + exit 1 + fi + # 1) Your checkout (system.nix / home.nix / local edits). + if [ -d "$flake/.git" ]; then + echo "nomarchy-pull: git pull --ff-only in $flake" + git -C "$flake" pull --ff-only + else + echo "nomarchy-pull: $flake is not a git checkout — skipping git pull" + fi + # 2) Flake inputs (nixpkgs, nomarchy, home-manager, …). + echo "nomarchy-pull: nix flake update in $flake" nix flake update --flake "$flake" + echo "nomarchy-pull: done — next: nomarchy-rebuild then nomarchy-home" + '') + (pkgs.writeShellScriptBin "nomarchy-rebuild" '' + set -euo pipefail + if [ "$(id -u)" -eq 0 ]; then + echo "nomarchy-rebuild: run as your normal user (it sudos the rebuild itself)" >&2 + exit 1 + fi + flake="''${NOMARCHY_PATH:-$HOME/.nomarchy}" + if [ ! -d "$flake" ]; then + echo "nomarchy-rebuild: flake path not found: $flake" >&2 + exit 1 + fi before=$(readlink -f /run/current-system) log=$(mktemp) trap 'rm -f "$log"' EXIT set +e + # Snapshot-first when snapper is on; pass flake path through sudo + # (nixos-rebuild-snap used to hardcode /etc/nixos). if command -v nixos-rebuild-snap >/dev/null 2>&1; then - sudo nixos-rebuild-snap "$@" 2>&1 | tee "$log" + sudo env NOMARCHY_PATH="$flake" nixos-rebuild-snap "$@" 2>&1 | tee "$log" else sudo nixos-rebuild switch --flake "$flake#default" "$@" 2>&1 | tee "$log" fi @@ -359,71 +397,32 @@ in set -e if [ "$rc" -ne 0 ]; then echo - echo "sys-update: rebuild FAILED (exit $rc). Last lines:" + echo "nomarchy-rebuild: FAILED (exit $rc). Last lines:" tail -n 40 "$log" || true echo echo "Diagnose: nomarchy-doctor" echo "Recovery: docs/RECOVERY.md (boot menu generations / snapper)" exit "$rc" fi - # What did that update actually change? Package-level diff of the - # old vs new generation (the informative half of "informative + - # rock-stable"); never fails the run. after=$(readlink -f /run/current-system) if [ "$before" = "$after" ]; then - echo "sys-update: no changes — the system is identical." + echo "nomarchy-rebuild: no changes — the system is identical." else - echo "sys-update: what changed:" + echo "nomarchy-rebuild: what changed:" ${pkgs.nvd}/bin/nvd diff "$before" "$after" || true fi '') - # The no-update twin (hardware-QA request): rebuild the system - # against the CURRENT lock — config changes only, no `nix flake - # update` — mirroring how home-update never touches the lock. - # Same snapshot-first path when available. - (pkgs.writeShellScriptBin "sys-rebuild" '' + (pkgs.writeShellScriptBin "nomarchy-home" '' set -euo pipefail if [ "$(id -u)" -eq 0 ]; then - echo "sys-rebuild: run as your normal user (it sudos the rebuild itself)" >&2 + echo "nomarchy-home: run as your normal user" >&2 exit 1 fi flake="''${NOMARCHY_PATH:-$HOME/.nomarchy}" - before=$(readlink -f /run/current-system) - log=$(mktemp) - trap 'rm -f "$log"' EXIT - set +e - if command -v nixos-rebuild-snap >/dev/null 2>&1; then - sudo nixos-rebuild-snap "$@" 2>&1 | tee "$log" - else - sudo nixos-rebuild switch --flake "$flake#default" "$@" 2>&1 | tee "$log" - fi - rc=''${PIPESTATUS[0]} - set -e - if [ "$rc" -ne 0 ]; then - echo - echo "sys-rebuild: rebuild FAILED (exit $rc). Last lines:" - tail -n 40 "$log" || true - echo - echo "Diagnose: nomarchy-doctor" - echo "Recovery: docs/RECOVERY.md (boot menu generations / snapper)" - exit "$rc" - fi - # Same what-changed diff as sys-update (the twins stay twins). - after=$(readlink -f /run/current-system) - if [ "$before" = "$after" ]; then - echo "sys-rebuild: no changes — the system is identical." - else - echo "sys-rebuild: what changed:" - ${pkgs.nvd}/bin/nvd diff "$before" "$after" || true - fi - '') - (pkgs.writeShellScriptBin "home-update" '' - set -euo pipefail - if [ "$(id -u)" -eq 0 ]; then - echo "home-update: run as your normal user" >&2 + if [ ! -d "$flake" ]; then + echo "nomarchy-home: flake path not found: $flake" >&2 exit 1 fi - flake="''${NOMARCHY_PATH:-$HOME/.nomarchy}" log=$(mktemp) trap 'rm -f "$log"' EXIT set +e @@ -432,13 +431,25 @@ in set -e if [ "$rc" -ne 0 ]; then echo - echo "home-update: switch FAILED (exit $rc). Last lines:" + echo "nomarchy-home: FAILED (exit $rc). Last lines:" tail -n 40 "$log" || true echo echo "Diagnose: nomarchy-doctor" echo "Recovery: home-manager generations (or docs/RECOVERY.md)" exit "$rc" fi + echo "nomarchy-home: desktop applied." + '') + # Legacy aliases — same behaviour, old names. + (pkgs.writeShellScriptBin "sys-update" '' + # Was: flake update + system rebuild. Now the two explicit steps. + nomarchy-pull && nomarchy-rebuild "$@" + '') + (pkgs.writeShellScriptBin "sys-rebuild" '' + exec nomarchy-rebuild "$@" + '') + (pkgs.writeShellScriptBin "home-update" '' + exec nomarchy-home "$@" '') git @@ -461,12 +472,15 @@ in echo "This script must be run as root (use sudo)" >&2 exit 1 fi + # Prefer the path nomarchy-rebuild passes through sudo; fall back + # for hand invocations. + flake="''${NOMARCHY_PATH:-/etc/nixos}" echo "Creating pre-rebuild snapshot..." ${pkgs.snapper}/bin/snapper -c root create \ -d "Pre-rebuild $(date +'%Y-%m-%d %H:%M:%S')" \ --cleanup-algorithm number - echo "Rebuilding..." - nixos-rebuild switch --flake /etc/nixos#default "$@" + echo "Rebuilding $flake#default ..." + nixos-rebuild switch --flake "$flake#default" "$@" '') # The desktop snapshot manager (browse / diff / restore / rollback over # snapper, elevating via polkit) — the primary `nomarchy-menu snapshot`