Compare commits

..

220 Commits

Author SHA1 Message Date
Bernardo Magri
82659566ac chore: untrack config.rasi (scratch reference committed by mistake)
config.rasi was the rofi theme dropped in to show the desired style; it's
not part of the distro. Remove it from tracking (the file stays on disk,
untracked). Its content informed 994025f and remains in that history.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 22:12:02 +01:00
Bernardo Magri
994025f0c8 feat(rofi): real icons, zebra rows, content-fit menus across all themes
Reworked the menu look, palette-driven so it lands on every theme:

  - Real Papirus icons in place of Nerd Font glyphs: a row() helper emits
    rofi's per-row icon protocol, and the five static menus (root, Tools,
    System, Power, Capture) map each entry to a freedesktop icon name
    (verified present in Papirus). Entry text is now clean ("Apps"), the
    case-matching is unchanged.
  - Larger icons via a new t.ui.iconSize knob (36px, generated theme); the
    summer whole-swaps keep their 40px identity.
  - Rounded, roomy rows with subtle zebra striping: alternate rows lift to
    @surface (a faint bg0 wash on the summer cream/slate windows), the
    selected row to @accent — using rofi's normal/alternate/selected row
    parities.
  - Content-fit windows: fixed-num-lines=false so a 6-entry menu stops
    reserving 8 rows of empty space (the launcher still fills + scrolls).
    Dropped the fixed height:50% from the summer .rasi so they size to
    content too — which also unhid their clipped Power/Keybindings rows.
  - Title-cased the menu prompts.

Verified by building the HM config and rendering the generated theme plus
both summer whole-swaps headlessly (sway + grim): icons resolve, zebra
shows, every menu hugs its rows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 22:11:25 +01:00
Bernardo Magri
b0b2a4d732 docs(services): note the restic-nomarchy list/restore wrapper
VM-verified the full batch of opt-in service toggles (libvirt, docker, obs
+ v4l2loopback, ollama, printing, openrgb, wireshark, adb, gamemode,
kdeconnect, restic) in a headless nixosTest — all green, no module bugs.

The one thing worth surfacing: services.restic ships a pre-configured
`restic-nomarchy` wrapper (repository + passwordFile baked in) for listing
and restoring snapshots. Mention it in the option description and README so
the restore path is discoverable — a backup you can't restore is half a
feature.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 21:18:49 +01:00
Bernardo Magri
964a5c98b7 feat(services): openrgb + restic toggles; close out the opt-in services item
Finishing the four remaining "opt-in services" candidates — but two of
them aren't service-shaped, so the package-vs-toggle principle applies:

  - Nextcloud client  → a bare tray app; already in the app-suite menu,
                        not a service.
  - WireGuard         → NetworkManager (on distro-wide) imports .conf
                        tunnels natively, so there's no daemon to "just
                        enable". Only the wg/wg-quick CLI is missing →
                        wireguard-tools added to the app-suite menu.

The two that ARE config-backed become nomarchy.services.* toggles:

  - openrgb → services.hardware.openrgb (daemon + device udev rules).
  - restic  → a small scaffolded surface (repository / passwordFile /
              paths) over services.restic.backups: daily timer, 7/4/6
              retention, --exclude-caches, repo auto-init. Asserts that
              repository + passwordFile are set when enabled. passwordFile
              is typed `str`, not `path`, so a flake-relative secret can't
              be copied into the world-readable store.

README option table and ROADMAP (services now "Seventeen shipped";
cloud-sync / networking / backup / devices areas updated) + the downstream
system.nix examples. Both branches eval-verified; the restic assertions
confirmed firing when repo/password are unset.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 21:02:20 +01:00
Bernardo Magri
c45fb80b79 feat(services): full optional app menu + 7 more opt-in service toggles
Make the whole workstation menu available, all off/commented by default.

home.nix: the bare GUI apps become a categorized commented menu (~50
suggestions across browsers, comms, office, notes, code, graphics, A/V,
media, gaming, files/sync, security, system, local AI) — uncomment to add.

services.nix: the members that need system config (not just a package)
become opt-in nomarchy.services.* toggles, each with a commented example
in the downstream system.nix:
  - docker     → rootful Docker + user in docker group; asserts against the
                 podman docker-compat (both provide the `docker` command)
  - kdeconnect → programs.kdeconnect (opens phone-pairing ports)
  - gamemode   → Feral GameMode daemon
  - adb        → android-tools (programs.adb was removed; systemd ≥258 does
                 the device uaccess udev rules, so no group needed)
  - wireshark  → Qt GUI + user in wireshark group (capture without root)
  - ollama     → local LLM runtime on 127.0.0.1:11434
  - printing   → CUPS + Avahi/mDNS network printer discovery

README option table and ROADMAP (services item now "Fifteen shipped";
local-AI / containers / gaming / devices areas marked) updated. All seven
branches eval-verified with the toggles forced on; the docker/podman
assertion confirmed firing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 20:52:38 +01:00
Bernardo Magri
0c668c2eb1 feat(apps): starter workstation app suite + steam/libvirt/obs services
The "default application suite" roadmap item, but deliberately NOT a
nomarchy.apps.* option surface: a bare package install has no config to
put behind a toggle, so a thin `mkIf x { systemPackages = [p]; }` only
reinvents what a package list already gives. Instead the suite is a
curated home.packages list in templates/downstream/home.nix (extending
the existing `# firefox` convention) — active staples (libreoffice,
vscode, gimp, inkscape, mpv, amberol) plus commented suggestions. The
opt-out is deleting a line; it also keeps the apps out of the live ISO
automatically (the ISO never scaffolds from the template).

The members that DO need system config become nomarchy.services.* opt-in
toggles instead (config behind the switch, like the existing services):
  - steam   → programs.steam (32-bit stack, controller udev, RP ports)
  - libvirt → libvirtd + virt-manager, login user added to libvirtd group
  - obs     → obs-studio + a v4l2loopback virtual camera (exclusive_caps=1)
              selectable as a webcam in Zoom/Teams

README option table, ROADMAP (services item now "Eight shipped"; suite
item marked done with the no-surface rationale) and the downstream
system.nix examples updated to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 20:45:10 +01:00
Bernardo Magri
1f4bd3d5fa docs(readme): document the curated shell aliases in §5 Day-to-day
List the on-by-default zsh aliases (navigation, git, nix, misc) in the
Day-to-day section so they're discoverable from the README, not just by
running `alias`. Note the doc location in the roadmap item.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:48:22 +01:00
Bernardo Magri
017bb1aa41 feat(shell): curated git/nix/navigation aliases on by default
Extend the zsh shellAliases in shell.nix with a curated, on-by-default
set: navigation (.., ..., ....), a git block (g, gst, ga/gaa, gc/gcm,
gco/gsw, gb, gd/gds, gl/glg, gp/gpl, gf), a nix block (ns, nr, nfu, nfc,
nsearch, ngc), and path/reload. Same restraint as rg/fd: short where it
helps but never shadowing a real binary — the git set keeps off gs
(ghostscript), and the system/home rebuilds keep their sys-update /
home-update names rather than cryptic aliases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:46:17 +01:00
Bernardo Magri
b856bb93e8 docs(roadmap): close the sanitize file-audit; menu grouping is ongoing
The repo-organization re-check found nothing to move: no orphaned modules
(keybinds.nix is a data import, not a HM module), no dead-code markers or
editor/backup cruft, every themes/<slug>.json pairs with its optional
overrides dir, and hosts/{default,live} are the reference + ISO hosts.
Recorded the one open decision: no formatter is declared and the .nix
hand-formatting is deliberate, so adopting nixfmt is a maintainer call,
left untouched. Also marked the menu category grouping a standing
convention — new menu-facing features get placed in the right submenu.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:40:50 +01:00
Bernardo Magri
e0ee5b9e7e feat(menu): group the rofi picker into Tools / System submenus
The root picker had grown to 16 flat entries. Collapse it to six —
Apps · Theme · Tools › · System › · Power · Keybindings — with Tools
(Calculator, Clipboard, Emoji, Files, Web, Capture, Ask) and System
(Network, Bluetooth, DND, plus the self-gated Snapshots / Power-profile)
as submenus the dispatcher routes via `nomarchy-menu tools|system`. Each
submenu ends in a ← Back entry that re-opens the root. The direct
SUPER+CTRL+<mnemonic> binds still reach the leaves straight (bypassing
the menu), and the gated entries still hide when unavailable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:35:03 +01:00
Bernardo Magri
f68b245d92 feat(services): add podman, flatpak (+ Flathub) and pika backup
Extend nomarchy.services.* with three more opt-in toggles:
- podman: rootless containers, `docker` aliased to it, container DNS, and a
  subuid/subgid range for the login user.
- flatpak: services.flatpak + a oneshot that adds the Flathub remote
  system-wide (idempotent, retries when online).
- pika: ships pika-backup, the GUI for scheduled Borg backups.
Commented examples in the downstream system.nix template, per convention.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:15:45 +01:00
Bernardo Magri
fb748c217c feat(services): opt-in Tailscale + Syncthing (nomarchy.services.*)
Start the opt-in services surface: nomarchy.services.{tailscale,syncthing},
off by default, in modules/nixos/services.nix. Tailscale ships the daemon
(authenticate with `sudo tailscale up`); Syncthing runs as the login user
with its GUI on 127.0.0.1:8384 (overrideDevices/Folders off so GUI-managed
folders survive rebuilds). username is read lazily, only when Syncthing is
on. Commented examples in the downstream system.nix template per the opt-in
convention.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:08:41 +01:00
Bernardo Magri
8d3911de1a docs(template): ship opt-in features as commented examples downstream
Convention: an off-by-default feature that needs nomarchy.* settings in the
downstream files should appear commented-out in templates/downstream/{home,
system}.nix, so a new install enables it by uncommenting + tweaking rather
than hunting the docs for the option name. Apply it now: night light,
nomarchy.monitors, per-device keyboard layouts (home.nix) and power
management (system.nix). Also fix the stale keyboard.layout note
(console/LUKS follow xkb automatically now). Documented in README S6.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 16:53:13 +01:00
Bernardo Magri
6ad80c045e feat(nightlight): scheduled blue-light filter via hyprsunset
Add nomarchy.nightlight (opt-in): a scheduled colour-temperature shift via
the HM services.hyprsunset module -- warm (.temperature, default 4000K) at
night, identity (no shift) by day, switching at .sunset / .sunrise. Two
time-based hyprsunset profiles, so hyprsunset handles the schedule and the
on-login state. New modules/home/nightlight.nix, imported in the home module.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 16:37:03 +01:00
Bernardo Magri
54c6e100fb docs(roadmap): organize the menu picker into category submenus
The root picker has grown into a long flat list; group it into category
submenus (System / Tools / Look & Feel / Power) with the dispatcher routing
nomarchy-menu <category> to its leaf modules, keeping the SUPER+CTRL+<mnemonic>
binds as direct fast paths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 16:29:30 +01:00
Bernardo Magri
eb76bd61b4 docs(roadmap): note btrfs-assistant segfault; snapper backend VM-verified
A VM regression test caught that btrfs-assistant 2.2 segfaults on launch
inside libbtrfsutil.so.1.4.0 -- a library ABI mismatch in nixpkgs 26.05, not
a GL/VM artifact (crashes with software GL and every Qt platform; the fault
is in a btrfs library). The snapshot menu wiring is correct and the app is
installed, but the GUI doesn't open. The snapshot backend is unaffected and
is itself VM-verified (full BTRFS+LUKS install: root+home snapper configs, a
/home timeline snapshot, /home/.snapshots a real subvolume, the oneshot
Result=success). Keep the entry, document the bug pending a nixpkgs fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 15:43:46 +01:00
Bernardo Magri
71f37bfc30 feat(keyboard): interactive new-keyboard layout prompt + persist
The runtime-remember complement to nomarchy.keyboard.devices. Set
nomarchy.keyboard.layouts (candidate layouts) and a nomarchy-keyboard-watch
daemon runs (exec-once): it polls hyprctl devices, and when a keyboard
connects after login that isn't declared and hasn't been chosen before, it
pops a rofi layout picker, applies the choice via hyprctl switchxkblayout (an
index into the candidate set carried by input.kb_layout), and remembers it
per-device in ~/.local/state -- re-applied silently on later reconnects. The
boot-time set (incl. the built-in keyboard) is never prompted.

Pure bash + jq/hyprctl/rofi (all in the session PATH); state lives outside
the flake (a stateful runtime piece by design). Eval + bash-syntax verified;
the hotplug behaviour needs an on-hardware test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 17:43:59 +01:00
Bernardo Magri
69f959365e docs(roadmap): interactive new-keyboard layout prompt + persist
A runtime-remember complement to the declarative nomarchy.keyboard.devices:
a daemon watches Hyprland's socket, pops a rofi layout picker when an unknown
keyboard connects, applies it, and persists per-device so it re-applies on
reconnect — optionally writing the choice back into nomarchy.keyboard.devices.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 17:32:05 +01:00
Bernardo Magri
aef45b3c8d feat(keyboard): per-device layout for external keyboards
Add nomarchy.keyboard.devices ({ "<hyprctl-device-name>" = { layout; variant; }; })
generating Hyprland `device` blocks that override the session
nomarchy.keyboard.layout for a named keyboard -- e.g. an external board
that's physically a different layout than the laptop's built-in one.
Hyprland applies it whenever that device connects, so the external keyboard
"remembers" its layout the declarative way. A Waybar hyprland/language
indicator shows the active layout, placed only when more than one layout is
in play (a comma in the session layout, or any per-device override) so
single-layout bars stay clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 17:27:28 +01:00
Bernardo Magri
0897391cfb feat(snapshots): desktop browse/restore + snapshot /home by default
Surface snapper snapshots from the desktop: `nomarchy-menu snapshot` (in the
SUPER+M picker, self-gated) launches btrfs-assistant, the polkit-aware
browse/diff/restore/rollback UI -- safer than a fat-fingerable rofi rollback
for a destructive root-only op. Shipped system-side gated on
nomarchy.system.snapper.

Also snapshot /home by default (hourly 5 / daily 7 / weekly 4) when it's its
own BTRFS subvolume -- the installer only set up snapper for /. A boot
oneshot creates the required /home/.snapshots subvolume if missing, so
already-installed machines get it too (no disko change).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 17:14:05 +01:00
Bernardo Magri
5c83b52727 docs: mark the GTK/Qt color-scheme portal confirmed in a live session
Verified this session in headless QEMU: the org.freedesktop.appearance
color-scheme portal reads 1 on a dark theme and 2 after switching to a light
one, so the dconf value reaches GTK4/Qt apps. Removes the stale "needs a
live session to confirm" note.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 16:47:59 +01:00
Bernardo Magri
0751102915 fix(waybar): show the power-profile indicator in the summer themes
custom/powerprofile only appeared in the generated bar -- its exec was a
writeShellScript store path, which can't go in the summer themes' static
whole-swap waybar.jsonc, so summer-day/night were missing it (the DND bell
already had parity). Promote powerProfileStatus/Cycle to named
writeShellScriptBins on PATH (waybar.nix home.packages) and reference them
by bare name, then add custom/powerprofile to both summer waybar.jsonc +
their waybar.css. Same pattern as the swaync bell.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 16:46:45 +01:00
Bernardo Magri
5c59da73e7 docs(roadmap): full hardware enablement beyond nixos-hardware
nixos-hardware covers basic per-model enablement, but advanced features
(keyed on CPU/GPU generation) are left to the user. Capture a big item:
extend the installer's autodetection + a nomarchy.hardware.* surface to turn
on safe features automatically (opt-out) and gate the heavy/experimental
ones (opt-in), without per-feature fiddling. Worked example on the ThinkPad
T14s (Ryzen 7 PRO 7840U + Radeon 780M): ROCm (gfx1103 override), Ryzen AI
NPU/XDNA, AMD P-State EPP, VA-API, fprintd biometrics (fwupd already ships),
SSD fstrim.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 10:35:07 +01:00
Bernardo Magri
42801548b7 feat(displays): declarative nomarchy.monitors + nwg-displays arranger
Add a per-output monitor schema (name / resolution / position / scale /
transform / mirror / bitdepth / vrr / disable) that generates Hyprland
`monitor` rules, keeping the ,preferred,auto,1 wildcard as the fallback.
Hyprland applies the rules on hotplug, so a declared external/dock output
arranges itself on connect (no kanshi -- it fights Hyprland's own output
management). Default [] -> wildcard only, so no change for existing setups;
set wayland.windowManager.hyprland.settings.monitor directly to override.

nwg-displays ships behind nomarchy.displays.enable (default true) as an
interactive arranger -- a helper to discover values; the declarative config
stays the source of truth (its output file isn't sourced).

Remaining (roadmap): docked/undocked profile switching, workspace-to-monitor
binding.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 10:22:18 +01:00
Bernardo Magri
1b0eeeaf6c fix(idle): don't lock before an encrypted hibernate (was: unlock after)
The previous nomarchy-hibernate-unlock ran `pkill hyprlock` after a
hibernate resume, but killing a Wayland session-lock client without
releasing the lock trips hyprlock's "go to a tty" crash failsafe -- the
compositor keeps the screen locked for safety. So resume showed a hyprlock
error screen instead of unlocking.

Fix it the right way: never engage the lock before an encrypted hibernate
(the LUKS passphrase at resume is the gate). Replace the post-resume unlock
with a nomarchy-lock-before-sleep unit that takes over hypridle's
before_sleep_cmd: it locks on the RAM-resume sleeps (suspend / hybrid-sleep
/ suspend-then-hibernate) always, and on hibernate.target only when the disk
is unencrypted. idle.nix drops before_sleep_cmd accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 10:15:31 +01:00
a606c0d498 docs: log power-profile Waybar parity as a follow-up
The custom/powerprofile indicator is missing from the whole-swap summer
themes (its exec uses Nix-built script paths that can't go in static
JSON). Note the fix (promote the scripts to named bins on PATH) and the
general "new module → also add to whole-swap themes" rule.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 21:12:38 +01:00
cd495d1720 fix(dnd): add the notification bell to the whole-swap summer themes
The DND bell only landed in the generated Waybar config; summer-day and
summer-night ship waybar.jsonc whole-swaps that replace it entirely, so
they'd have shown no bell. Add custom/notification (swaync-client -swb,
left-click panel / right-click DND) to both legacy layouts with their
FontAwesome bell / bell-slash glyphs, and style it alongside the other
right-side modules in each waybar.css.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 21:08:01 +01:00
dbcb8efd1e feat(dnd): swaync Do-Not-Disturb toggle + Waybar bell indicator
Adds a Do-Not-Disturb story on top of swaync:

- Waybar `custom/notification` module via `swaync-client -swb` — streams
  the notification count + DND state (no polling). Left-click toggles the
  panel, right-click toggles DND; bell-off glyph + muted color when DND is
  on, accent when notifications are waiting.
- `nomarchy-menu dnd` toggle in the root picker and bound to SUPER+CTRL+D
  (so it shows in the SUPER+? cheatsheet). Turning DND off confirms with a
  toast; turning it on is silent — notifications are suppressed and the
  bell-off icon is the cue.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 21:01:11 +01:00
07e467027b feat(nix): silence the "Git tree is dirty" warning on rebuilds
The downstream flake at ~/.nomarchy is a live working tree by design —
nomarchy-theme-sync rewrites theme-state.json on every switch — so Nix's
dirty-tree warning fired on every sys-update/home-update and was just
noise. Default nix.settings.warn-dirty to false (mkDefault, overridable).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 20:53:18 +01:00
9a5473e179 docs: record the branch/release model + sanitize progress
Document the main=dev / v1=release-pointer model in flake.nix (where the
v1 ref is defined) and mark the repo-sanitize roadmap items shipped
(installer prune, option-table reconcile, settings untrack, branch
realignment).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 20:48:06 +01:00
db6a0ba455 chore: untrack .claude/settings.local.json (machine-local)
It holds this machine's Claude Code permission allowlist — local by
convention (the `.local` suffix; settings.json is the shared one), so it
shouldn't be versioned. Remove from tracking (keeping the working file)
and gitignore it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 20:45:54 +01:00
8c47716f9a chore(install): stop writing distro-default config into system.nix
console.useXkbConfig and boot.initrd.systemd.enable are set distro-wide
(lib.mkDefault true in modules/nixos/default.nix, since the LUKS-keymap
fix), so the installer rewriting them in the generated system.nix was
redundant. Drop them there and from the offline-pin test fixture in
flake.nix — the nomarchy module still defaults them on, so the closure
(and the pin set) is unchanged; verified the values still resolve true
and `nix flake check` passes. Only the machine-specific xkb layout is
written now. Adjusts the README keyboard-option wording to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 20:42:36 +01:00
f60f3655f9 merge: adopt the v1 development line onto main
Brings main current with the 51 commits of post-rewrite feature work
(laptop power, idle cohesion, menu plugins, fwupd, docs restructure)
that had been accumulating on v1. New model: main is the development
default; v1 is the release pointer downstreams pin (?ref=v1), advanced
to main once a batch is tested. Rolling, no tags.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 20:38:36 +01:00
afdb928ed7 docs: split roadmap into docs/ROADMAP.md, reconcile README
The roadmap + known-issues had grown to ~280 lines, nearly half the
README. Moved both into docs/ROADMAP.md (forward-looking plans + a log of
shipped fixes) and left a short pointer, so the README is back to a
focused entry point (572 -> 302 lines).

Also fixed drift surfaced in the pass:
- layout tree: add modules/nixos/power.nix, modules/home/{keybinds,keys,
  fastfetch}.nix and docs/ROADMAP.md, which were missing.
- option table: add keys.enable, fastfetch.enable, system.snapper.enable
  (default false — the installer opts in) and system.greeter.autoLogin.

OVERRIDES.md, TESTING.md and the downstream template README were checked
and are accurate (.#default / .#me names and the 21-preset count match),
so they're left as-is. Docs stay Markdown-in-repo — no docs site.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 18:29:16 +01:00
882ba6646b revert(menu): keep the hand-rolled fd files module, drop rofi-file-browser
The rofi-file-browser-extended navigate-a-tree model felt worse than flat
fuzzy-find for a quick launcher (yazi already covers real browsing), so
`files` goes back to `fd` → `rofi -dmenu` → xdg-open. calc (rofi-calc)
and emoji (rofi-emoji) stay. Re-adds `fd` to the module's packages and
notes the dropped plugin in the roadmap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 18:16:06 +01:00
db202f90e4 feat(menu): adopt rofi plugins for calc, files, emoji
Replace the hand-rolled calc/files modules with purpose-built rofi modi
(via programs.rofi.plugins) and add an emoji picker — all themed through
the same .rasi as every other modi:

- calc -> rofi-calc: live results as you type via libqalculate directly,
  which also dodges the qalc CLI's "15% of 200" -> rem(15, 1 B) misparse.
  Enter copies; the menu persists to chain calculations. Drops the
  libqalculate (qalc CLI) dependency.
- files -> rofi-file-browser-extended: live directory navigation +
  xdg-open, replacing the flat 50k-cap `fd` dump of $HOME. yazi (SUPER+E)
  stays the power browser; `fd` already ships via shell.nix.
- emoji -> rofi-emoji (new module): glyph picker, copies through the
  plugin's Wayland clipboard adapter. Bound to SUPER+CTRL+E in
  keybinds.nix (so it lands in the SUPER+? cheatsheet too).

rofi 2.0 rebuilds cleanly with all three plugin .so (ABI-matched, same
nixpkgs). README roadmap updated: calc rework marked shipped, with a
follow-up item for the script-based plugins (network/secrets/audio).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 18:09:11 +01:00
51c11e1df3 feat(idle): suspend on battery only, cohering with power management
hypridle's suspend listener now runs `nomarchy-on-ac || systemctl
suspend`, so a plugged-in machine no longer suspends itself mid-idle
(long builds, media, presentations survive). It also fires sooner —
15 min, vs the old fixed 30 — since it now only applies unplugged.
Lock and screen-off are unchanged on both power sources, and logind's
lid handling stays at its sensible defaults (suspend on lid close,
ignore when docked).

Closes the idle-cohesion follow-up under the laptop-power roadmap item.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 17:53:49 +01:00
6a22eba0c4 docs: add roadmap item for a full docs review & restructure
A dedicated prose pass distinct from the repo-sanitize item: split the
~200-line roadmap out of the README, reconcile the option tables with the
live nomarchy.* surface, and review docs/ + the downstream template for
drift.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 17:46:30 +01:00
c47eb5f688 feat(system): enable fwupd by default; document power options
Ship `services.fwupd.enable` distro-wide (mkDefault) for firmware updates
via LVFS — the daemon + metadata-refresh timer only, no automatic
flashing, so applying an update stays an explicit `fwupdmgr update`. A
no-op where LVFS sees no devices; overridable natively. Sits with the
other mkDefault desktop services rather than a nomarchy toggle (it's a
single service, like upower).

Also documents the `nomarchy.system.power.*` options in the README table
(missed when the power module landed) and adds a short note on the
fwupd default.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 17:44:23 +01:00
00f5311499 feat(power): laptop power management (power-profiles-daemon + TLP)
Adds a `nomarchy.system.power.*` surface (modules/nixos/power.nix),
replacing the bare `services.upower` (Waybar reporting only) baseline:

- power-profiles-daemon ships by default; switched through polkit (no
  root prompt). TLP is the opt-in `backend = "tlp"` for deeper battery
  tuning — the two are mutually exclusive (asserted).
- thermald behind `power.thermal.enable` (Intel-only).
- `power.batteryChargeLimit` (e.g. 80): a backend-independent sysfs
  oneshot writes charge_control_end_threshold; gated on `power.laptop`.

Switcher + indicator live home-side and self-gate on a battery being
present + powerprofilesctl running, so they hide on desktops and under
TLP — no system->home wiring (like the Waybar battery widget):

- rofi.nix: `nomarchy-menu power-profile` module + a picker entry shown
  only on laptops with PPD.
- waybar.nix: first `custom/*` module — click cycles the profile.

Installer writes `power.laptop = true` (battery probe) and
`power.thermal.enable` (GenuineIntel) into the generated system.nix, and
scaffolds the charge limit commented-out.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 17:35:42 +01:00
Bernardo Magri
8853f6ae49 feat(idle): no double-unlock after an encrypted hibernate resume
hypridle locks hyprlock before every sleep -- right for suspend, but
redundant for hibernate: the LUKS passphrase entered at boot already gates
the resume, so the user typed a password twice. Add a nomarchy-hibernate-
unlock systemd unit (WantedBy hibernate.target, After systemd-hibernate.service
=> runs post-resume) that dismisses hyprlock, gated on the disk being LUKS-
encrypted. Suspend (and the RAM-resume phase of suspend-then-hibernate) keep
locking -- they have no passphrase gate; an unencrypted hibernate keeps its
lock too. idle.nix gains a pointer comment; roadmap item marked done.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 13:06:10 +01:00
Bernardo Magri
e0182ae7dd docs: explain the sys-update -> home-update ordering
home-update rebuilds the desktop against the current flake.lock and never
touches it; only sys-update runs `nix flake update`. So pulling a distro
change that affects the home layer requires sys-update first (updates the
lock), then home-update -- the reverse order rebuilds against stale inputs
and silently skips the new home-side changes (hit while testing the mic
fix). Also note hyprctl reload after a home-side keybind change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 12:51:01 +01:00
Bernardo Magri
58096c09ed fix(hyprland): show the mic level in the mute OSD
The wpctl-based mic toggle lost the volume bar the native swayosd input OSD
used to draw -- it only showed an icon + text. swayosd 0.3.x exposes
--custom-progress (0.0-1.0), so read the level back from wpctl after the
toggle and render icon + bar (muted/active glyph via --custom-icon),
matching the output-volume OSD. Parsing is pure bash builtins so the script
needs no PATH beyond the two pinned tools.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 12:51:01 +01:00
Bernardo Magri
7da6bb979e docs: expand roadmap (power, opt-in services, display/UX, control center)
Captures a batch of new roadmap items from a planning pass:
- repo sanitize/organize (incl. the now-redundant console.useXkbConfig /
  boot.initrd.systemd.enable the installer writes, post LUKS-keymap fix)
- laptop power/battery management (PPD-vs-TLP, thermald, charge thresholds)
- opt-in services & integrations (Nextcloud/Syncthing, LM Studio/Ollama,
  containers, Tailscale, Steam/OBS, printing, backups, Flatpak)
- display/monitor management (hotplug profiles, dock story)
- night light (hyprsunset), runtime keyboard-layout switching, swaync DND
- snapshot browse/restore UX, update-awareness indicator
- a "nomarchy" control center + first-boot welcome

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 12:27:32 +01:00
Bernardo Magri
3f36183021 feat(menu): Google web search; note calc rework in the roadmap
The web module now opens google.com/search instead of DuckDuckGo. Also log
a roadmap item to rework calc: qalc -t misparses common phrasings (15% of
200 -> rem(15, 1 B)) and the result only shows in the next menu's -mesg
line -- move toward live results as you type.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 12:11:20 +01:00
Bernardo Magri
d9301ad954 fix(yazi): previewer match field name -> url (yazi 26.x)
yazi 26.x renamed the previewer/fetcher match key from name to url. The
fetchers were updated but the markdown previewer still used name, so the
whole [plugin] config failed to parse ("at least one of 'url' or 'mime'
must be specified") and yazi fell back to its presets.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 12:11:20 +01:00
Bernardo Magri
66f58fa228 fix(hyprland): mic mute via wpctl -- swayosd 0.2.1 input-mute is a no-op
swayosd-client --input-volume mute-toggle draws the OSD but never flips the
default source's mute (its output-mute path works; input does not). Confirmed
on hardware: wpctl set-mute @DEFAULT_SOURCE@ toggle flips the state, swayosd
does not. Do the real toggle with wpctl and keep an OSD via swayosd's
--custom-icon/--custom-message.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 12:11:20 +01:00
Bernardo Magri
2c8e0b47f9 fix(keyboard): carry the configured layout to the LUKS prompt
Setting only services.xserver.xkb.layout moves the graphical session but
leaves console.useXkbConfig unset, so the virtual-console keymap -- and the
systemd initrd the LUKS passphrase prompt runs in -- fall back to US (seen
on a Latitude 5410: X11 Layout gb, VC Keymap unset, LUKS prompt US).

Default console.useXkbConfig + console.earlySetup + boot.initrd.systemd.enable
distro-wide, so xkb.layout alone reaches the console and the encrypted-disk
prompt. Moved the latter two out of plymouth.nix -- they no longer hinge on
the splash being enabled. All mkDefault: an explicit console.keyMap or a
scripted initrd still wins.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 12:11:20 +01:00
Bernardo Magri
69f7ae9051 feat(branding): fastfetch logo + Nomarchy.ttf glyph in the Waybar button
Two branding follow-ups, using the vendored legacy assets:

- fastfetch (modules/home/fastfetch.nix, nomarchy.fastfetch.enable): the
  vector logo recolored to the palette accent and rendered to compact
  block-art via chafa at build time (so it tracks the theme), fronting a
  curated module list. Replaces the oversized legacy ASCII.
- Waybar logo glyph: vendor Nomarchy.ttf (modules/nixos/branding/),
  install it via fonts.packages, and switch the summer-day/night menu
  buttons to its U+F000 mark with `font-family: Nomarchy` pinned in CSS
  (Nerd Fonts also occupy U+F000, so the pin is required). Glyph stored as
  the  JSON escape for robustness.

Also log a roadmap item for a quality-of-life alias collection.

Verified: font family resolves as "Nomarchy" and the ttf maps U+F000;
both summer jsonc parse; chafa logo builds headless; nix flake check passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 22:07:28 +01:00
Bernardo Magri
4017b6cff6 fix(stylix): drive GTK4/Qt dark-light from the palette via color-scheme
Stylix set polarity and the GTK theme but not the XDG portal's
org.freedesktop.appearance color-scheme, which GTK4/libadwaita and Qt6
apps actually read to choose dark vs light — so a light theme could still
render those apps dark (and vice-versa).

Set dconf org/gnome/desktop/interface color-scheme to
prefer-light/prefer-dark from theme.mode in stylix.nix.
xdg-desktop-portal-gtk already ships and programs.dconf is on system-side,
so the portal exposes it to apps.

Also log two branding follow-ups from the legacy assets: fastfetch ASCII
logo (logo.txt) and the Nomarchy.ttf glyph for the Waybar menu button.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 21:53:08 +01:00
Bernardo Magri
cde279af0b feat(branding): ISO boot splash from the vendored Nomarchy logo
Vendor the vector logo from the legacy branch
(modules/nixos/branding/logo.svg) and use it for the live ISO's isolinux
splash: rsvg-convert renders it, recolored to the palette accent and
centred on the theme base (from theme-state.json) at build time, wired via
isoImage.splashImage in hosts/live.nix. Verified the generated PNG by
building it in the sandbox.

UEFI/GRUB still uses the stock theme (grubTheme needs a full theme dir —
left on the roadmap), as does the distroId switch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 21:46:40 +01:00
Bernardo Magri
6513908067 feat(branding): tuigreet greeting + branded MOTD
Round 2 of distro branding, text half: tuigreet now shows
'Welcome to <distroName>', and users.motd carries a branded banner that
doubles as a cheat sheet for the distro helpers (sys-update, home-update,
nomarchy-theme-sync, SUPER+?). Both key off system.nixos.distroName so the
brand name stays in one place.

Deferred (need an asset / a boot test): ISO splashImage/grubTheme art and
the distroId switch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 21:35:47 +01:00
Bernardo Magri
fdb0685eec docs: mark plymouth contrast done; log GTK/Qt light-dark issue
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 21:18:37 +01:00
Bernardo Magri
e411d35544 fix(plymouth): recolor splash art from the palette for contrast
The shipped boot art was a fixed navy that vanished against dark theme
bases. Recolor each element from theme-state.json at build time (flat
fill, alpha preserved): foreground glyphs (logo, padlock, password dots)
→ text, the field/track boxes (entry, progress_box) → surface, and the
progress fill → accent. text/surface both contrast with base in either
polarity, so the splash now reads on light and dark themes alike.

Adds imagemagick as a build-time input to the theme derivation. Like the
background tint, this follows the theme as of the last system rebuild.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 21:17:42 +01:00
Bernardo Magri
3757e7d66f feat(keys): SSH + GPG agent via gpg-agent, pinentry-qt
Add modules/home/keys.nix (nomarchy.keys.enable, default on): one agent —
services.gpg-agent with enableSshSupport fronts SSH, so a single pinentry
handles every passphrase (GPG signing/decryption and SSH key unlocks).
pinentry-qt for a reliable native-Wayland prompt under Hyprland, themed by
Stylix's Qt config. Cache TTLs 30 min / 2 h.

SSH_AUTH_SOCK is exported by the agent's zsh integration (terminal git/ssh
is the supported path). gnome-keyring stays the Secret Service — modern
versions run no SSH agent, so there's no socket contention; screen lock
doesn't flush the agent cache.

nix flake check passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 20:50:45 +01:00
Bernardo Magri
05d995f8e0 feat(keybinds): direct SUPER+CTRL binds for the menu functions
Each nomarchy-menu module is now reachable directly, not just through the
SUPER+M picker: SUPER+CTRL+ V clipboard · C calc · W web · F files ·
N network · B bluetooth · S capture · A ask. Added to keybinds.nix (the
single source), so they render in the SUPER+? cheatsheet too. No key
collisions; nix flake check passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 20:39:12 +01:00
Bernardo Magri
f6c4a2a591 fix(waybar): stop summer themes rendering phantom workspaces
summer-day/summer-night showed all 10 workspace icons up-front. The cause:
legacy used the deprecated `persistent_workspaces` (underscore), which
current Waybar silently ignores — so legacy only ever showed *existing*
workspaces. The v1 port rewrote it to the modern `persistent-workspaces`
(hyphen), which Waybar honours, surfacing all ten as phantoms.

Drop the block from both summer waybar.jsonc whole-swaps. The other themes
render from waybar.nix, which never declared persistent-workspaces, so they
already only show existing workspaces — no change needed there.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 20:35:25 +01:00
Bernardo Magri
7c34eed2ca fix(theme): solid per-theme hyprland borders, matching legacy
v1 forced an accent→accentAlt 45deg gradient on every theme's window
border; the legacy identity themes all used a *solid* border — accent for
nord/retro-82/lumon, the text tone for kanagawa/summer-day/summer-night.

Add a palette-resolved `border` field ({active, inactive}, each a palette
key or literal hex) to the theme schema with accent/overlay defaults in
theme.nix, consume it solid in hyprland.nix, and declare it in every
preset (and the live state). Declaring it everywhere is required because
`nomarchy-theme-sync apply` deep-merges presets — an omitted field would
stick across switches, like colors already are fully specified per theme.

All six identity themes resolve to their exact legacy active border
(verified: nord #81a1c1, retro-82 #faa968, lumon #f2fcff, kanagawa
#dcd7ba, summer-night #d3c6aa, summer-day #5c6a72). nix flake check passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 20:32:18 +01:00
Bernardo Magri
d252f01f17 feat(shell): flat starship prompt, drop the powerline styling
The powerline look (the `[]` separator glyph + bg-filled segments) didn't
read well. Switch to a flat prompt: bold-accent directory, warn git
branch, subtext git-status/duration, `❯` character — plain colored text,
no background fills, each module carrying its own trailing space so there
are no stray gaps. Also reference cmd_duration in `format` (it was
configured but never shown).

Generated starship.toml verified valid; nix flake check passes. Visual
pass still wants a live terminal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 20:18:46 +01:00
Bernardo Magri
28a2f5d5ae fix: yazi fetcher group field, xfce package renames, enable nix-ld
Three quick known-issue fixes:

- yazi: 26.x made the fetcher `group` field required, so the git
  prepend_fetchers failed to parse and yazi fell back to presets. Add
  `group = "git"` to both entries (the git plugin's setup() only renders
  the linemode — the fetcher still needs registering here).
- file-manager: xfce.exo and the three Thunar plugins moved to top-level;
  use pkgs.xfce4-exo / pkgs.thunar-{archive-plugin,volman,media-tags-plugin}.
  Clears the eval-time deprecation warnings.
- nix-ld: enable programs.nix-ld distro-wide so foreign dynamically-linked
  binaries (downloaded tools, npx-fetched claude-code, language servers)
  run without patchelf.

Also drops the now-stale claude-code mention from the allowUnfree comment
(the ask module uses npx). nix flake check passes; xfce warnings gone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 20:14:11 +01:00
Bernardo Magri
f06d7f361c docs: roadmap item for SSH/GPG agent + graphical pinentry
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 20:06:06 +01:00
Bernardo Magri
58d79aad17 feat(menu): network/bluetooth/capture/ask modules + keybindings cheatsheet
Build out the rofi menu system roadmap item:

- New nomarchy-menu modules: network (nmtui), bluetooth (blueman-manager),
  capture (grim/slurp submenu → clipboard/file), ask (free-text → claude
  CLI in a terminal), and keybinds (the SUPER+? cheatsheet).
- modules/home/keybinds.nix is now the single source of truth for both the
  Hyprland bind strings and the cheatsheet, so the two can't drift —
  hyprland.nix maps it into `bind`, rofi.nix renders the padded two-column
  sheet (generated/mouse binds live in its `extra` rows).
- New binds: SUPER+Space (quick launch), SUPER+M (main menu), SUPER+?
  (cheatsheet). SUPER+D stays rofi -show drun.
- Ask Claude pulls claude-code fresh from npm via `npx
  @anthropic-ai/claude-code@latest` (the nixpkgs package lags model
  releases); nodejs is bundled for npx.

nix flake check passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 19:59:46 +01:00
Bernardo Magri
60138e20d0 docs: log known issues & follow-ups in the roadmap
Yazi prepend_fetchers group field, starship powerline removal, xfce
package deprecations, rofi function keybinds, nix-ld default, hyprland
border colors, and waybar phantom workspaces.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 19:25:40 +01:00
Bernardo Magri
df7c0ef7ae feat: zsh default shell + starship/bat/eza/zoxide shell experience
zsh is now the default login shell (programs.zsh.enable +
users.defaultUserShell, mkOverride 500 to beat bash.nix's mkDefault;
per-user shell= still overrides). modules/home/shell.nix configures the
interactive experience (nomarchy.shell.enable):

- zsh: completion, autosuggestions, syntax highlighting, big shared
  history, autocd.
- starship prompt themed from the palette (a `nomarchy` palette built
  from theme-state.json colors).
- bat as cat (theme "ansi" → tracks the terminal/theme palette), eza as
  ls (icons + git + dirs-first), zoxide as cd (--cmd cd).
- rg/fd shipped as themselves — deliberately NOT aliased over grep/find
  (flag differences surprise).

home.shell.enableZshIntegration = true is the single lever; starship,
eza, zoxide, ghostty and yazi all emit their zsh hooks from it (no
per-module edits). Verified: flake check green, default shell resolves
to zsh, .zshrc carries the starship/zoxide/eza/yazi hooks + aliases,
starship palette renders, all tools in the live ISO closure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 16:25:21 +01:00
Bernardo Magri
f97054c804 feat: icon themes — Papirus, resolved from the JSON, for GTK + rofi
Ships papirus-icon-theme and resolves an icon-theme name once in
theme.nix → nomarchy.theme.iconTheme: the JSON's optional `icons` field,
else Papirus-Dark/Light picked by `mode`. That single value feeds:
- Stylix `stylix.icons` → gtk.iconTheme (Thunar and GTK apps)
- rofi `show-icons` + `icon-theme` (the launcher now shows app icons)

A preset or theme-state.json can set `icons` to any theme in the icon
package to override per theme.

Verified: flake check green; iconTheme resolves Papirus-Dark for
tokyo-night and Papirus-Light for summer-day; gtk.enable true with
gtk.iconTheme.name set; papirus in home.packages and the live ISO
closure; rofi config.rasi carries icon-theme + show-icons:true. The
rendered icons need a real session to see.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 16:12:19 +01:00
Bernardo Magri
520c878bb3 feat: swayosd on-screen display for volume/brightness/mute
The media keys called wpctl/brightnessctl directly with no visual
feedback — changing volume showed nothing on screen. Now they drive
swayosd-client, which performs the action AND shows a themed OSD.

- modules/home/osd.nix: services.swayosd, style.css generated from the
  palette (base bg, accent progress/border); nomarchy.osd.enable.
- hyprland media binds → swayosd-client (--output-volume raise/lower/
  mute-toggle, --input-volume mute-toggle, --brightness raise/lower).
- modules/nixos: services.udev.packages = [ swayosd ] installs the
  backlight rule (chgrp video + g+w) so brightness works for video-group
  users without root (the installer/live user is in video).

swaync is unaffected (it was already running — this was purely the
missing OSD). Verified: flake check green, swayosd.service bound to
graphical-session.target, hyprland config verifies, swayosd in the live
ISO closure. On-screen rendering needs a real session to confirm.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 16:04:55 +01:00
Bernardo Magri
084b2a0500 feat(theme-sync): persistent switch notification so slow switches read as progress
The "Applying theme — rebuilding…" toast used the default timeout, so it
vanished seconds into a multi-minute home-manager switch — leaving the
user with no signal and the impression the selection failed. Now it's
persistent (timeout 0) and all theme notifications share a synchronous
tag, so swaync REPLACES it in place with "Theme applied ✓" (or a critical
failure toast that persists) when the rebuild finishes.

notify() grew persistent/urgency/summary params. Honest indeterminate
feedback — HM exposes no percentage, so no fake progress bar.

Verified: py_compile clean; the full apply→switch→notify path runs end to
end (dummy NOMARCHY_REBUILD). The in-place replacement is visible only in
a real swaync session.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 15:52:41 +01:00
Bernardo Magri
20df0d8a60 docs: fold todo.md items into the roadmap
Theme-switch progress feedback; per-theme icon themes (unblocks rofi
show-icons); starship prompt + modern-CLI aliases (bat/eza/rg/fd/zoxide);
opt-out default app suite (nomarchy.apps.*); Plymouth logo contrast fix;
hibernate double-unlock (hyprlock redundant after LUKS resume); plus a
keybindings-cheatsheet menu module and the SUPER+Space / SUPER+M binds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 15:48:50 +01:00
Bernardo Magri
abfe872109 feat(themes): port legacy rofi identities for summer-day/night
themes/<slug>/rofi.rasi whole-swaps for the two themes that had a
distinct launcher look in the legacy branch — inverted window (bg=fg),
green inputbar, yellow bottom-border accent, rounded. Adapted: dropped
the configuration{} block (rofi.nix owns modi/terminal/show-icons) and
swapped the unshipped Iosevka 17 for a shipped Nerd Font.

Verified: both .rasi parse under `rofi -dump-theme`; the whole-swap
selects per active theme (summer-night → #2d353b/#a7c080, summer-day →
#fdf6e3, others → the generated palette theme); flake check green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 15:45:39 +01:00
Bernardo Magri
961314ea86 feat(home): switch launcher/menu from fuzzel to rofi 2.0
rofi 2.0 landed in nixpkgs 26.05 with native Wayland (mainline upstreamed
the lbonn rofi-wayland fork — `wayland enabled`), so the original reason
to prefer fuzzel (rofi being X11-only / needing a community fork) is gone.
rofi's `.rasi` is far more expressive than fuzzel's flat INI, which lets
the launcher be a proper themed hero surface and revives the legacy
per-theme launcher designs.

- modules/home/rofi.nix replaces fuzzel.nix: per-element theme generated
  from theme-state.json (accent border, highlighted selection, rounded
  inputbar) via lib.formats.rasi.mkLiteral; themes/<slug>/rofi.rasi
  whole-swap; the nomarchy-menu dispatcher re-pointed to `rofi -dmenu`
  (power/theme/clipboard/calc with -mesg/files/web + root picker).
- SUPER+D is now `rofi -show drun`; the menu binds are unchanged.
- nomarchy.fuzzel.enable → nomarchy.rofi.enable; fuzzel dropped from
  home.packages. Pango handles nf-glyph fallback (no explicit font list
  needed as fuzzel's fcft did). show-icons off until an icon theme ships.

Verified: flake check green, HM generation builds, the generated
theme.rasi parses under `rofi -dump-theme`, Hyprland config verifies.
Not verified: rofi's on-screen rendering needs a real session.

Docs: README menu/override/roadmap sections and the module tree updated;
the per-theme launcher roadmap item now points at porting the legacy
rofi.rasi designs (the whole-swap mechanism is in place).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 14:41:46 +01:00
Bernardo Magri
76582c1ee9 feat: file manager — yazi (flagship TUI) + Thunar (GUI)
Legacy shipped only Thunar (and a stray nautilus extension, mid-migration).
This pairs a keyboard-driven TUI flagship that fits the distro's identity
with the GUI half for point-and-click + the "open folder" handler.

yazi (modules/home/yazi.nix, nomarchy.yazi.enable, SUPER+E, `y` shell
wrapper cd's on exit): themed from theme-state.json (mgr/mode/status
mapped from the palette; merges over yazi's defaults so it tracks the
theme) with a curated, correctly-wired plugin set —
  full-border, git (setup + prepend_fetchers), smart-enter (l/Enter),
  chmod (cm), mount (M), compress (caa), mediainfo (audio/subtitle only —
  images/videos keep native thumbnails), glow (markdown previews).
Preview/tooling deps: ffmpegthumbnailer, poppler-utils, p7zip, jq, fd,
ripgrep, fzf, chafa, mediainfo, glow.

Thunar (modules/nixos/file-manager.nix, nomarchy.system.fileManager.enable):
GTK file manager (Stylix-themed) + archive/volman/media-tags plugins +
gvfs/tumbler/udisks2 backends + thumbnailers + exo. udisks2 also backs
yazi's mount plugin.

Verified: flake check green, HM generation builds (yazi TOML/init.lua
render, all 8 plugins resolve), every package present in the live ISO
closure (offline install draws from it — no source-build leak).
Not verified: yazi's runtime preview/plugin behaviour needs a real
session (TUI; can't drive in CI here).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 14:32:11 +01:00
Bernardo Magri
d06373b155 feat(home): mkDefault behaviour settings so downstream can plain-override
Nomarchy's Hyprland/Ghostty/Waybar settings were set at normal priority,
so a downstream `home.nix` setting any value Nomarchy already set threw a
"conflicting definition values" error — overriding required lib.mkForce,
contradicting the README's "mkDefault throughout" claim.

Now: behaviour/chrome leaves (input, misc, monitor, animations, dwindle,
gesture, decoration.blur sizing, ghostty padding/decoration, waybar
settings+style) are lib.mkDefault — a plain home.nix assignment wins.
Appearance values that flow from theme-state.json (gaps, colors,
rounding, opacity, fonts) stay at normal priority on purpose: change them
via nomarchy-theme-sync (their source of truth) or lib.mkForce to
hardcode. bind/exec-once lists stay normal priority so additions
concatenate rather than replace.

Verified: behaviour/ghostty plain overrides build; theme values still
conflict (steering to the CLI); default rendered config is byte-identical.

New docs/OVERRIDES.md with the appearance→CLI / behaviour→home.nix /
component→toggle model and worked examples; linked from the README.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 14:05:59 +01:00
Bernardo Magri
bd42462291 fix(home): power menu on SUPER+X, not SUPER+Escape
Super+Escape didn't fire on real hardware (Latitude 5410) while its
neighbour binds did — the chord gets swallowed before reaching
Hyprland's dispatcher on some setups. SUPER+X is unambiguous.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 13:44:22 +01:00
Bernardo Magri
583708d78c docs: README for the v1 QA batch (menu, swaync, idle, Plymouth, sys-update)
Options/keybinds/layout tables, sys-update/home-update workflow, the new
module tree, and roadmap updates (menu system + nm-applet shipped; theme
parity, branding round 2, swayosd, ask-Claude module remain).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 07:38:31 +01:00
Bernardo Magri
6763bef73e fix(install): pre-activation, writable home.nix, keyboard/locale selection
- Pre-activation failure ("desktop pre-activation failed"): the in-chroot
  HM build hard-coded `--option substituters ""`, which only works on
  OFFLINE installs (where the ISO store is copied in). Online installs
  (now common — wifi works) had no pins and built from source. Fix: build
  the generation in the live env (its store always has the pins), nix copy
  the closure to the target, chroot only activates. In-chroot build kept
  as fallback. Uses path: (not git+file:) to sidestep libgit2 ownership.
- Read-only home.nix: templates come out of the store mode 0444 and cp
  preserves it — chmod -R u+w after staging so the user can edit it.
- Keyboard + locale selection: gum prompts (localectl layouts/variants +
  curated UTF-8 locale list) and NOMARCHY_LOCALE/KB_LAYOUT/KB_VARIANT for
  unattended. One choice flows everywhere — services.xserver.xkb (source
  of truth) + console.useXkbConfig (tty/greeter) + boot.initrd.systemd
  (so the LUKS passphrase prompt uses the layout; script initrd can't) +
  the generated home.nix's nomarchy.keyboard.* for the Hyprland session.
- test-install.sh: NOMARCHY_OVMF env override for sandboxed OVMF paths.

Verified end-to-end in QEMU: offline LUKS install completes, boots to a
themed desktop (no autogenerated-config banner), Plymouth renders the LUKS
prompt on the theme-tinted background.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 07:38:31 +01:00
Bernardo Magri
465f013155 feat(home): menu system, swaync, idle/lock, nm-applet, theme parity
- Themed fuzzel (modules/home/fuzzel.nix): palette/fonts/border from the
  JSON, themes/<slug>/fuzzel.ini whole-swap mechanism. Plus the
  nomarchy-menu dispatcher: root picker · power (SUPER+Escape) · theme
  (SUPER+T) · clipboard (SUPER+CTRL+V, cliphist) · calc (qalc) · files
  (fd→xdg-open) · web (DuckDuckGo).
- swaync notifications themed from the JSON (SUPER+N) — until now nothing
  rendered notify-send (theme toasts, font warnings, welcome msg).
- hyprlock + hypridle (modules/home/idle.nix): lock 5min, dpms off 10,
  suspend 30; enables the power menu's Lock entry. cliphist daemon on.
- NetworkManager applet in waybar's tray (preferStatusNotifierItems);
  network module on-click → $TERMINAL -e nmtui.
- nomarchy.keyboard.layout/.variant option → Hyprland kb_layout/kb_variant
  (the installer writes it; pairs with system-side xkb for tty/LUKS).
- Media-key/audio on-click moved to wpctl (pamixer was inconsistent).
- Theme parity: summer-day/night carry their legacy bar LAYOUTS as
  waybar.jsonc whole-swaps (the original import took waybar.css but not
  config.jsonc, so identity themes styled nonexistent modules). Dead
  legacy script-modules dropped, Nerd-Fonts-v2 codepoints → FontAwesome/v3
  (font-awesome now shipped), logo buttons open nomarchy-menu.

New toggles: nomarchy.{fuzzel,swaync,idle}.enable (all default true).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 07:37:47 +01:00
Bernardo Magri
eda8461304 feat(system): Plymouth splash, distroName, allowUnfree, offline-pin hardening
- Plymouth boot splash ported from the legacy branch (modules/nixos/
  plymouth/): logo + eased progress + LUKS entry, background tinted from
  theme-state.json via the new nomarchy.system.stateFile (wired by
  mkFlake/lib.nix; null → Tokyo Night fallback). Default on; OFF on the
  live ISO (boot-message visibility on the install medium). Pulls
  boot.initrd.systemd, which also drives the keyboard-at-LUKS feature.
- system.nixos.distroName = "Nomarchy" (os-release PRETTY_NAME,
  systemd-boot entries, ISO menu label). distroId left "nixos" (feeds
  DEFAULT_HOSTNAME + upstream isNixos checks — roadmapped).
- nixpkgs.config.allowUnfree distro-wide (here + both import-nixpkgs
  sites) — unblocks claude-code for the menu's ask-Claude module.
- systemd-boot.configurationLimit = 10 so entries don't fill the ESP.
- Live ISO: nomarchy.idle.enable = false — hypridle was suspending the
  VM mid-install (the install-hung regression); installed systems keep it.
- flake.nix offline pins (verified 0-leak via a foreign-identity
  gap-analysis probe): the repo's own standalone HM gen + inputDerivations,
  mustache-go + stdenv (stylix re-renders base16 per switch), microcode-amd/
  intel (enableRedistributableFirmware activated updateMicrocode →
  source-build cascade), buildEnv's builder.pl, findXMLCatalogs, and the
  representativeInstall mirror (xkb/initrd-systemd/microcode).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 07:37:32 +01:00
Bernardo Magri
1ba1eeed64 fix(live): re-enable fontconfig + xdg integration the minimal-CD profile strips
installation-cd-minimal forces fonts.fontconfig.enable = false
(mkOverride 500) to slim a console-only installer — but this ISO is the
desktop. Without fontconfig no family resolves: Waybar's nf-md icons
rendered as tofu boxes and Ghostty silently fell back to the wrong
font (reported on the Latitude 5410, reproduced + fix verified in QEMU
via VNC screenshots: icons render, fc-match resolves JetBrainsMono
Nerd Font). Also restore xdg icons/mime/autostart and man pages.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 20:23:28 +01:00
Bernardo Magri
c1781f45ca feat: allow unfree packages distro-wide
nixpkgs.config.allowUnfree in the system module (covers the live ISO
via useGlobalPkgs and every mkFlake machine) plus the two explicit
`import nixpkgs` sites (repo + lib.nix) so the standalone HM desktop
sees the same package set. Unblocks claude-code for the menu system's
ask-Claude module, vendor drivers, etc. Opt out with
`nixpkgs.config = lib.mkForce { allowUnfree = false; }`.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 18:16:20 +01:00
Bernardo Magri
ed7be0206d docs: roadmap — menu script modules: calc, clipboard, files, web, ask-Claude
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 18:11:28 +01:00
Bernardo Magri
009bdbad8f docs: roadmap — menu system design: fuzzel dmenu dispatcher, themed from the JSON
Resolves the old Walker/Lua previews-vs-simplicity question in favor of
fuzzel: already shipped, nested menus via dmenu mode, INI theme bakeable
from theme-state.json like every other app.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 18:03:58 +01:00
Bernardo Magri
a33127cd3c docs: roadmap — Nomarchy distro branding (os-release, ISO boot menu, splash)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 17:59:52 +01:00
Bernardo Magri
dccceb4c48 fix: real-hardware QA sweep — wifi, fonts, firmware, Hyprland 0.55, offline switching
Roadmap items 1+2 plus the issues found testing on a Latitude 5410:

- Ship the 10 most popular Nerd Fonts by default (iosevka swapped for
  mononoki: 1.1 GB vs 27 MB) and warn from nomarchy-theme-sync when a
  configured fonts.mono/fonts.ui family isn't installed (fc-match) —
  fontconfig substitutes silently otherwise.
- hardware.enableRedistributableFirmware: installed systems shipped NO
  firmware blobs (wifi/SOF audio/BT) — nixos-generate-config only emits
  microcode lines referencing this flag, it never sets it.
- Live ISO wifi: networking.wireless.enable = mkForce false killed
  NetworkManager's supplicant — since 26.05 the NM module drives its
  wifi backend THROUGH networking.wireless (dbusControlled). Devices
  vanished from nmtui with iwlwifi loaded and no rfkill block.
- Hyprland 0.55: launch sessions via start-hyprland (watchdog; bare
  binary warns), add the new gesture keyword (workspace_swipe is gone —
  touchpads had no gestures at all), media keys via wpctl/bindel/bindl
  plus the missing mic/play/next/prev binds.
- Offline theme switching: pin mustache-go + stdenv + the repo's own
  standalone HM generation (incl. home-files inputDerivation) into the
  ISO — stylix re-renders base16 templates per switch and an offline
  `apply` cascaded into building stdenv from source (1107 drvs).
  Verified with tools/vm/gap-analysis.py: 17 config drvs, zero fetches.
- Stylix: track release-26.05 (kills the HM version-skew warning and
  the stale home-manager follows), lock updated.
- Roadmap: swaync (no notification daemon ships today).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 17:50:55 +01:00
bc5faec6b8 Update README.md 2026-06-12 14:05:10 +01:00
Bernardo Magri
77a0e70146 Nomarchy v1: the NixOS 26.05 ground-up rewrite replaces the legacy distro
main now carries the new distro (theme-state.json engine, mkFlake
downstream API, nomarchy-install with verified offline installs). The
old distro's history stays reachable here and lives on as the `legacy`
branch. Tree is identical to refactor/v1 @ 37819bb.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 13:14:44 +01:00
Bernardo Magri
37819bb50f feat: v1 release branch — generated flakes and template track ?ref=v1
Installed machines and the downstream template now resolve nomarchy from
git+https://git.bemagri.xyz/bernardo/nomarchy.git?ref=v1 (the lock's
original node carries the ref too), so `nix flake update` follows the
release branch instead of the forge's default branch. README quickstart
points at the real forge.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 09:50:09 +01:00
Bernardo Magri
a50e9793ea feat(tools): commit the VM test harness + one-command installer regression
Promotes the throwaway harness that verified the installer into tools/:
- tools/vm/qmp.py        QMP keystroke injection / typing / quit
- tools/vm/vncshot.py    GL-safe screenshots via VNC readback (QMP
                         screendump shows "no surface" with virtio-vga-gl)
- tools/vm/gap-analysis.py  drv-graph diff that converged the offline
                         pin set; run it when offline installs build
                         from source
- tools/test-install.sh  the full offline regression: build ISO, boot
                         offline, unattended LUKS+swap install via a
                         config disk (typed long commands drop keys),
                         wait for poweroff, boot the installed disk,
                         screenshot the first boot for visual verdict

docs/TESTING.md §4 now points at the script.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 08:05:13 +01:00
Bernardo Magri
7b5a22c800 fix(install): run a nix-daemon for the chroot HM activation + backup collisions
The pre-activation log (now persisted) showed activate dying at its
profile operation: as the target user with no daemon in the chroot,
nix can't open the store db ("big-lock: Permission denied"). Run a
temporary nix-daemon inside the chroot and point activate at it via
NIX_REMOTE=daemon. HOME_MANAGER_BACKUP_EXT=bak makes file collisions
(e.g. a stray autogenerated hyprland.conf) move aside instead of
aborting. Verified in the chroot on a real installed disk: HM symlinks
land, collision backed up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 21:51:28 +01:00
Bernardo Magri
134695806c fix(install): stage the pre-activation script in /root — nixos-enter tmpfs-mounts /tmp
The HM pre-activation never ran: the script was written to /mnt/tmp and
nixos-enter mounts a fresh tmpfs over /tmp inside the chroot, so `bash
/tmp/...` found nothing and the best-effort guard swallowed it. Verified
interactively that every inner step (path: build as root, runuser leg)
works in the chroot — only the staging path was broken. Now staged in
/root, with set -x logging persisted to /var/log/nomarchy-hm-preactivate.log
on the target and the tail echoed into the install transcript on failure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 20:53:21 +01:00
Bernardo Magri
727f21005d fix(install): root-side flake refs must be path:, not git+file
The chown fix made the flake user-owned, and root's libgit2 then refuses
git+file fetches of it ("not owned by current user") — which silently
killed the seeding step under set -e and would equally break
nixos-install --flake. Use path: refs for the live-side archive and the
nixos-install invocation (path flakes read flake.lock, skip libgit2),
and make seeding failure non-fatal as intended.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 19:39:09 +01:00
Bernardo Magri
1403ea82b2 fix(install): chown the generated flake to the user; harden HM pre-activation
End-to-end VM verification found the installed system perfect (LUKS,
auto-login, swapfile+resume, snapper) except: ~/.nomarchy was root-owned,
so libgit2 refused every `home-manager switch` ("repository not owned by
current user"). chown 1000:users after generation (the account doesn't
exist in the target yet — numeric ids).

The chroot pre-activation now builds via path: instead of git+file —
no libgit2, no ownership sensitivity — and the fallback message suggests
-b bak (a default-config Hyprland session leaves an autogenerated
hyprland.conf in the way otherwise; observed live).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 11:17:38 +01:00
Bernardo Magri
29818d2fb6 fix(install): offline installs copy the ISO store into the target up front
Substituter plumbing through nixos-install proved unreliable (env config
is overridden by its hardcoded flags; the forwarded --substituters flag
still left the plan building gcc from source). Make every ISO path valid
in the target store with one nix copy --all before nixos-install — the
in-target build then resolves everything locally and only the per-machine
config drvs are built.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 10:01:49 +01:00
Bernardo Magri
77dba7ca5d fix(install): pass --substituters through nixos-install, not just the env
nixos-install hardcodes --extra-substituters "auto?trusted=1" as a CLI
flag, and flags override NIX_CONFIG for the same setting — so the env
fix never reached the in-target build. nixos-install forwards a
--substituters flag verbatim; use that.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 09:24:00 +01:00
Bernardo Magri
dba349a539 fix(install): substitute from the live daemon store during the target build
nixos-install builds with --store /mnt and passes its own substituter as
"auto?trusted=1", which in that context resolves to the target store
itself — so nothing flowed from the ISO and nix fell back to a
full-source bootstrap (gcc/python/bash tarball fetches → offline death).
Host-store simulation (fresh local?root, substituters cleared) proves
"daemon?trusted=1" makes the whole install substitute + build offline:
1125 paths copied, only the per-machine config drvs built locally.

Also drop --offline from the chroot HM build (that flag disables ALL
substituters; plain empty substituters does what we want without it).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 08:51:30 +01:00
Bernardo Magri
3b0b2872aa fix(install): seed target store via nix copy --no-check-sigs
`nix flake archive --to` rejects locally-evaluated source paths ("lacks
a signature by a trusted key"); enumerate the archive tree as JSON and
copy with --no-check-sigs instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 08:02:52 +01:00
Bernardo Magri
804d708f87 fix(install): pin the common nixos-hardware profile stacks into the ISO
Round 7 in-VM: autodetection emitted common-cpu-intel, whose nixos-hardware
module pulls the whole Intel graphics stack (intel-media-driver,
compute-runtime, libva, level-zero…) — none of it on the ISO, so the
offline install built graphics drivers from source. The representative
pin now imports the common-* profiles (intel+amd cpu/gpu, laptop, ssd,
pc), covering what the detector emits on ordinary machines.
Model-specific profiles may still need network.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 07:59:02 +01:00
Bernardo Magri
8da429d611 fix(install): converge the offline pin set via derivation-graph gap analysis
Walking the install-shaped toplevel's drv graph against the ISO's actual
path set (tools/gap analysis) found why offline installs kept building
from source:

- system-path is rebuilt on EVERY machine: buildEnv's package-list order
  follows module-graph order, which any hardware profile reshuffles →
  pin its builders (texinfo, getconf)
- greetd.toml embeds the auto-login user and is generated by remarshal;
  building remarshal offline drags its test closure (matplotlib → ffmpeg
  → x265…, ~1900 drvs) → pin pkgs.remarshal
- second-level tools for the always-rebuilt drvs: kmod.dev +
  nukeReferences (modules-shrunk), xorg.lndir (unit dirs), libxslt.bin
  (dbus config), python3Minimal (etc)
- the representative pin now has a vfat /boot like a real install
  (mtools/dosfstools enter systemPackages via the vfat fs-type gate)

Verified on the host: the remaining offline build set for a foreign
username/hostname/UUID config is 66 trivial config drvs + eval-time file
copies from the pinned nixpkgs tree — zero network. Same check for the
per-username HM activation: 15 drvs, offline-clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 22:36:46 +01:00
Bernardo Magri
996fdc28c9 revert(install): includeBuildDependencies was a 134 GB hammer
The full system build closure adds ~134 GB to the store and would have
produced an unusable multi-ten-GB ISO. Back to targeted inputDerivation
pins; the still-missing second-level build tools get pinned explicitly
next, from a clean committed-tree gap analysis.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 22:09:22 +01:00
Bernardo Magri
609bb7e7dc fix(install): carry the full system build closure on the ISO
Round 6 still hit a from-source cascade: every per-machine drv (units,
initrd pieces, dbus config, modules-shrunk) needs its own build tools
(lndir, builder.pl, kmod-dev, nuke-refs, libxslt-bin, …), one level
deeper than targeted inputDerivation pins reach. Use the documented
mechanism instead: system.includeBuildDependencies = true on the
representative install pin. Bigger ISO, networkless installs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 19:41:37 +01:00
Bernardo Magri
ecf94e84ab fix(install): pin build-time deps of per-install drvs; no substituters offline
Offline nixos-install still built from source: the drvs that embed the
user's hostname/username/UUIDs (etc, initrd, toplevel, HM activation)
must be REBUILT, and their builders need tools outside every runtime
closure (etc → python3-minimal, initrd → packing tools). Pin each drv's
inputDerivation into the ISO — the standard nixos-test offline trick.

Also: with no network every substituter query is a DNS retry storm that
ends in a nix goal.cc assertion crash (core dump observed); the installer
now probes connectivity and disables substituters when offline, both on
the live system and inside the nixos-enter HM pre-activation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 19:05:17 +01:00
Bernardo Magri
c813055578 fix(install): pin the install-shaped system into the ISO, not the bare template
The offline nixos-install failed building from source: the generated
config enables snapper/auto-login/LUKS-initrd/swapfile-resume on a BTRFS
root, none of which the bare template (ext4 placeholder!) pulls in — so
snapper, nixos-rebuild-snap, btrfs-progs-lib and cryptsetup-bin were
absent from the ISO. The pinned system now mirrors the installer's output
(closure-diff verified).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 18:33:15 +01:00
Bernardo Magri
8881ad3bae fix(install): rewrite follows paths when grafting the upstream lock
Lock follows paths are absolute from the root node; nomarchy's nodes move
one level down in the composed downstream lock, so ["nixpkgs"] must
become ["nomarchy","nixpkgs"] — otherwise every follows dangles
("input 'nomarchy/home-manager/nixpkgs' follows a non-existent input").
Verified: the composed lock now resolves the full input tree with
`nix flake metadata --offline`.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 17:53:11 +01:00
Bernardo Magri
7aba5fa0a8 fix(install): pin a representative disko script into the ISO closure
disko builds its format/mount script at install time; offline, the
script's tool closure (file, which, wrapper hooks) wasn't on the ISO and
nix tried to build it from source — which needs the network. Pre-building
one representative script (luks + swap variant) pins every input; the
user's actual invocation then differs only in the final text-generation
derivation, which builds offline in seconds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 17:09:08 +01:00
Bernardo Magri
479193b10b fix(install): survive the live ISO offline and its non-interactive bash
Found by running the unattended install in an offline QEMU VM:
- compgen is missing from nixpkgs' non-interactive bash (the package
  shebang) — replaced with plain glob tests in hardware-db and prewipe
- disko's eval resolves <nixpkgs> via NIX_PATH (a dead channel on the
  ISO) and tried channels.nixos.org — export NIX_PATH to the pinned
  nixpkgs source and point the flake registry at an empty baked file
- lock nomarchy by path (the source the ISO carries) instead of
  git+https: git inputs clone even when narHash is known, which kills
  offline installs; `original` keeps the forge URL so a later
  `nix flake update` re-resolves normally. Works from dirty-tree ISOs too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 16:48:33 +01:00
Bernardo Magri
71614fa6ca feat(install): LUKS by default → auto-login, snapper snapshots, hibernation swapfile
- LUKS2 is the installer default; in exchange the generated config sets
  the new nomarchy.system.greeter.autoLogin (greetd initial_session) —
  the disk passphrase already gates the machine.
- @snapshots subvolume + nomarchy.system.snapper.enable: hourly/daily
  timeline snapshots of / and the nixos-rebuild-snap helper, ported from
  the previous iteration (3bdfc35), guarded to no-op on non-BTRFS roots.
- @swap subvolume with a swapfile sized to RAM by default (disko
  mkswapfile handles NOCOW); the installer computes the resume offset
  and wires boot.resumeDevice + resume_offset for hibernation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 16:19:14 +01:00
Bernardo Magri
f3707357a6 feat: nomarchy-install — guided live-ISO installer (disko + mkFlake)
Ported from the previous iteration's installer (3bdfc35), adapted to the
mkFlake world. gum TUI: disk pick, optional LUKS2, user/hostname/timezone,
DMI → nixos-hardware autodetection (hardware-db.sh). disko partitions
GPT + 1 GiB ESP + BTRFS subvolumes; the generated machine flake lands at
~user/.nomarchy (one mkFlake call, /etc/nixos symlinks to it) and
nixos-install makes it bootable (UEFI/systemd-boot, v1 single disk).

Offline by construction: the target flake.lock is composed from the rev
the ISO was built from (compose-lock.py), `nix flake archive` seeds the
target store, and the ISO pre-builds the template system + desktop.
First boot lands themed: the HM generation is pre-activated in chroot.

mkFlake grows two things for this: hardwareProfile now also takes a list
(autodetection emits several common-* modules), and installed systems get
the standalone home-manager CLI from the pinned input. Unattended mode
(NOMARCHY_UNATTENDED=1 + env) documented in docs/TESTING.md §4.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 16:05:29 +01:00
Bernardo Magri
8ded92ea63 chore: drop renamed package aliases (swww→awww, greetd.tuigreet→tuigreet)
Silences nixpkgs' rename warnings on every eval.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 15:43:16 +01:00
Bernardo Magri
1f22e996dc feat: nomarchy.lib.mkFlake — one-call downstream wrapper + hardware profiles
Downstream users now own only system.nix and home.nix; their flake.nix is
generated once from the template and never hand-edited. mkFlake (lib.nix)
wires both layers and maps hardwareProfile = "<name>" to nixos-hardware
modules (new input, pinned here, nixpkgs follows ours; unknown names fail
with did-you-mean suggestions). Flake checks evaluate the template through
mkFlake — including a real profile — so drift fails `nix flake check`.

Also from the live-VM testing session: install the home-manager CLI in the
live ISO and pin flake inputs transitively (offline theme switching needs
stylix's own inputs too), plus swww→awww doc updates.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 15:39:21 +01:00
Bernardo Magri
8a0ec763e0 fix: live-VM desktop fixes — Hyprland 0.55 compat + swww→awww rename
Found by booting the live ISO (docs/TESTING.md checklist):
- pin HM configType = "hyprlang" (26.05 stateVersion defaults to the new
  Lua config and renders these settings as broken hl.$mod(...) calls,
  booting Hyprland into emergency mode)
- drop dwindle:pseudotile (removed in Hyprland 0.55; aborts config parse)
- disable splash rendering alongside the logo
- launch awww-daemon and call awww with swww fallback (nixpkgs' swww is
  the renamed awww fork; no `swww` binary exists anymore)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 15:38:32 +01:00
Bernardo Magri
f211ef0d09 feat: Nomarchy ground-up rewrite on NixOS 26.05
Full replacement of the previous iteration, rebuilt around three ideas:

- Pure evaluation: theme-state.json lives inside the flake and is read
  via the nomarchy.stateFile option — no --impure, ever.
- All-Home-Manager theming: `nomarchy-theme-sync apply` writes the JSON
  and runs `home-manager switch`; every theme change is one atomic,
  rollbackable generation. Wallpaper (swww) is the sole runtime piece.
- Flat, downstream-first layout: modules/{nixos,home} with one
  options.nix each, exported as nixosModules/homeModules + overlay +
  flake template; system (nixos-rebuild) and desktop (home-manager
  switch) rebuild paths are fully split.

Ships 21 themes imported from the previous iteration (palettes,
wallpapers, btop themes, six whole-swap Waybar identities), Stylix for
the GTK/Qt/cursor long tail, a live ISO target with offline theme
switching, and docs/TESTING.md with the QEMU verification workflow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 10:59:13 +01:00
Bernardo Magri
83218a01f3 docs: add "Working on Nomarchy" orientation guide
Some checks failed
Check / eval-and-lint (push) Failing after 6m21s
A short, task-indexed guide for navigating the repo: the core/features/themes
mental model, the two app-config namespaces, the four script locations (incl.
themes/engine/scripts/), the build/test loop, how theming works, and a
Walker+elephant deep-dive covering the dmenu vs custom-provider menu paths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 13:32:24 +01:00
Bernardo Magri
9fe6d9e405 fix(walker): don't spawn a duplicate elephant alongside the service
nomarchy-launch-walker guarded its manual elephant start with
`pgrep -x elephant`, which never matches the Home Manager service's actual
process name `.elephant-wrapped` (Linux truncates comm to 15 chars). So every
menu invocation spawned a second elephant that races elephant.service for the
socket — a latent source of menus intermittently coming up empty.

Gate on `systemctl --user is-active elephant.service` first, with a working
`pgrep -f elephant-wrapped` fallback for non-service setups; do the same for
walker.service. Verified in a headless system.build.vm: opening the theme menu
now keeps the elephant process count at 1 (was 2) and the menu still renders.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 13:32:12 +01:00
Bernardo Magri
8a302e8771 chore: drop omarchy pkg-* compatibility shims
Some checks failed
Check / eval-and-lint (push) Failing after 6m15s
These existed only to ease muscle-memory from Arch-based distros and add
no behavior on a Nix-native system:

- nomarchy-pkg-install — alias for nomarchy-pkg-add
- nomarchy-pkg-drop    — alias for nomarchy-pkg-remove
- nomarchy-pkg-aur-add — stub that only printed "AUR doesn't exist on NixOS"

The single code caller (nomarchy-voxtype-remove) was removed in the prior
commit, so the shims have no remaining references. SKILL.md updated to use
nomarchy-pkg-add and to point at `nix search nixpkgs` instead of the AUR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 19:52:19 +01:00
Bernardo Magri
698d8593cd feat: remove unused voxtype dictation feature
Voxtype voice-typing was a full feature (5 scripts, a waybar widget, a
keybind, and a NixOS option) that this install does not use. The
nomarchy.system.voxtype option had no consumer — nothing read it — so the
widget and SUPER+CTRL+X bind were never actually gated by it.

Removes the scripts, default config, the SUPER+CTRL+X bind, the waybar
module (main + summer-night theme + css), the dead option, the installer
comment, and the docs. SCRIPTS.md/KEYBINDINGS.md regenerated; OPTIONS.md
and SKILL.md hand-updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 19:51:46 +01:00
Bernardo Magri
4b509c271a fix(scripts): remove stale duplicate nomarchy-update
Some checks failed
Check / eval-and-lint (push) Failing after 6m14s
Two scripts named nomarchy-update shipped from different derivations
(core/system/scripts + features/scripts/utils), both landing on PATH so
which one ran depended on PATH ordering. The core/system one never stripped
the install-time `?rev=` pin and rebuilt a nonexistent `#default` attr,
silently keeping installs frozen instead of following rolling main. Keep the
features/scripts/utils version (unpins, queries upstream HEAD, calls
nomarchy-sys-update) and drop the stale one. Regenerated docs/SCRIPTS.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 20:55:04 +01:00
Bernardo Magri
2bdcc0aba0 fix(live): enable VM guest agents so Hyprland boots at full resolution
The nomarchy-live ISO imported ./core and hosts/nomarchy-live.nix but not
core/system/vm-guest.nix, which is the only place spice-vdagentd/qemuGuest
were enabled. Without those agents a VM's virtio-gpu only advertises its
1024x768 fallback mode, so Hyprland's `monitor = , highres, auto` rule picks
that as the highest mode and the live session boots tiny.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 20:55:04 +01:00
Bernardo Magri
27821c270f fix(impermanence): mark /persist and /home neededForBoot
Some checks failed
Check / eval-and-lint (push) Failing after 5m56s
The impermanence module asserts that the persistent-storage volume and
every volume it bind-mounts into are available in early boot. Persisted
user dirs land under /home, so both /persist and the @home subvolume
must have neededForBoot = true. disko and nixos-generate-config leave it
at the default (false), so a fresh install with impermanence enabled
aborted with:

    All filesystems used for persistent storage must have the option
    "neededForBoot" set to true.
    Please fix the following filesystems: /persist /home

Declare neededForBoot in the module that imposes the requirement.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 19:34:04 +01:00
Bernardo Magri
a84e903ae1 fix(live): allow empty-password hyprlock unlock on live ISO
pam_unix rejects empty passwords by default, so if hypridle locked the
live session there was nothing the user could type to unlock it. Set
allowNullPassword on the hyprlock PAM service so a bare Enter dismisses
the locker, matching the empty live account passwords. Scoped to the
live host so installed systems still reject empty unlocks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 19:24:42 +01:00
Bernardo Magri
5ea369d73c fix(installer): declare extra LUKS devices for multi-disk boot
All checks were successful
Check / eval-and-lint (push) Successful in 6m51s
A multi-disk install builds one LUKS container per drive joined into a
single multi-device BTRFS (-d single -m raid1). nixos-generate-config
only emits boot.initrd.luks.devices for the main drive — every subvolume
mounts through /dev/mapper/crypted_main, so the other members are
invisible to it. The installed system then unlocked only the main drive,
the array never assembled, and boot hung. Invisible single-disk, fatal
multi-disk (matches a real-hardware report).

generate_flake_config now writes, into hardware-selection.nix, a
boot.initrd.luks.devices entry for each extra drive (UUID resolved via
disko's partlabel; mapper name mirrors disko-config.nix's sanitize) and
re-asserts the x-systemd.requires= mount options disko sets but which
nixos-generate-config strips.

Verified end-to-end in a 3-disk UEFI QEMU VM: reproduced the bug, applied
the fix, ran a real nixos-install onto the array, and rebooted from the
disks — one passphrase unlocked all three containers, the 3-device BTRFS
assembled, and the system reached login.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 18:50:10 +01:00
Bernardo Magri
fdd74a0e4f fix(installer): resolve /etc/nomarchy symlink before getFlake
`generate_state` loads `nixpkgs.lib` for the state-schema eval via
`builtins.getFlake "$NOMARCHY_REPO"`. On the live ISO that path is a
symlink chain (/etc/nomarchy -> /etc/static/nomarchy -> /nix/store/…-source),
and Nix 2.31+ rejects getFlake on a symlink ("path '…-source' is a
symlink"), aborting every real-hardware install right after hardware
config generation — single or multi disk.

Resolve the repo to its real store directory with `realpath` at
detection so getFlake receives a plain directory. The dev-checkout
branch already used realpath, so only the live-ISO path was affected.
Reproduced and fixed in a live VM (Nix 2.31.4).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 18:49:43 +01:00
Bernardo Magri
431dd98967 feat(theme): implement declarative Stylix-driven theming for Walker
All checks were successful
Check / eval-and-lint (push) Successful in 6m58s
2026-06-01 21:09:54 +01:00
Bernardo Magri
fa71e03f88 docs: move remaining Ironclad verifications to Shipped
All checks were successful
Check / eval-and-lint (push) Successful in 6m45s
2026-06-01 21:00:09 +01:00
Bernardo Magri
e3002d49ad fix(waybar): ensure update module is visible in summer-night theme
All checks were successful
Check / eval-and-lint (push) Successful in 6m37s
2026-06-01 20:36:04 +01:00
Bernardo Magri
dc7a3e2a29 feat(update): add interactive confirmation prompt to nomarchy-update and expose in all themes
Some checks failed
Check / eval-and-lint (push) Has been cancelled
2026-06-01 20:35:06 +01:00
Bernardo Magri
dd72110b9a docs: finalize roadmap entries for flake updates and offline resilience
All checks were successful
Check / eval-and-lint (push) Successful in 6m43s
2026-06-01 20:27:25 +01:00
Bernardo Magri
1e6becd42d fix(scripts): improve offline resilience and restore missing update scripts
All checks were successful
Check / eval-and-lint (push) Successful in 7m5s
2026-06-01 20:07:08 +01:00
Bernardo Magri
6ed2ca3d78 fix(scripts): resolve race condition in state-sync and mark stress test as complete
All checks were successful
Check / eval-and-lint (push) Successful in 7m9s
2026-06-01 18:48:17 +01:00
Bernardo Magri
d242d1ea88 fix(waybar): reconcile tooltips with keybindings and fix stale references
Some checks failed
Check / eval-and-lint (push) Failing after 1m52s
2026-05-31 21:59:08 +01:00
Bernardo Magri
3a0164feb7 docs: mark Round 2 Interactive Script Audit as complete
All checks were successful
Check / eval-and-lint (push) Successful in 6m43s
2026-05-31 21:45:41 +01:00
Bernardo Magri
8dc6ba0a21 docs: mark App Integration Polish as complete
All checks were successful
Check / eval-and-lint (push) Successful in 6m38s
2026-05-31 20:59:26 +01:00
Bernardo Magri
5d558a3cc6 fix(system): enable Polkit for Thunar drive management
Some checks failed
Check / eval-and-lint (push) Has been cancelled
2026-05-31 20:59:04 +01:00
Bernardo Magri
ea34a7ac1f fix(apps): improve Thunar and Mako integration
Some checks failed
Check / eval-and-lint (push) Has been cancelled
2026-05-31 20:58:10 +01:00
Bernardo Magri
878c11bd41 docs: add RUNTIME_HOOKS.md and link from README
All checks were successful
Check / eval-and-lint (push) Successful in 6m35s
2026-05-31 20:35:58 +01:00
Bernardo Magri
3a42b664a1 feat: wire up post-update and post-install hooks
Some checks failed
Check / eval-and-lint (push) Has been cancelled
2026-05-31 20:34:01 +01:00
Bernardo Magri
1301873bc0 docs: finalize declarative-state migration in roadmap
Some checks failed
Check / eval-and-lint (push) Failing after 6m45s
2026-05-31 20:09:31 +01:00
Bernardo Magri
dc3346bc55 feat: implement hybrid declarative state with automatic Nix sync
Some checks failed
Check / eval-and-lint (push) Has been cancelled
2026-05-31 20:09:12 +01:00
Bernardo Magri
624023c1d5 docs: move declarative-state migration batch 1 and monitor scaling to Shipped
Some checks failed
Check / eval-and-lint (push) Failing after 6m42s
2026-05-31 19:33:57 +01:00
Bernardo Magri
130ae80f3e feat: migrate theme and font to declarative Nix options
Some checks failed
Check / eval-and-lint (push) Has been cancelled
2026-05-31 19:33:33 +01:00
Bernardo Magri
a2649728d3 feat(hyprland): implement declarative monitor scaling and add scale picker to welcome wizard
Some checks failed
Check / eval-and-lint (push) Failing after 6m36s
2026-05-31 19:21:52 +01:00
Bernardo Magri
8911ffa4e8 feat(calendar): ship calcurse and wire waybar clock clicks
Some checks failed
Check / eval-and-lint (push) Failing after 6m22s
2026-05-31 16:43:47 +01:00
Bernardo Magri
395c839ed0 fix(waybar): retarget broken clicks in summer-day/night themes to nomarchy scripts
Some checks failed
Check / eval-and-lint (push) Has been cancelled
2026-05-31 16:42:31 +01:00
Bernardo Magri
a9cc39f3fe fix(input-method): update fcitx5-chinese-addons to kdePackages.fcitx5-chinese-addons
All checks were successful
Check / eval-and-lint (push) Successful in 6m51s
2026-05-31 16:12:17 +01:00
Bernardo Magri
e6b7269b3c feat: move core apps to downstream and make app modules opt-in
All checks were successful
Check / eval-and-lint (push) Successful in 6m39s
2026-05-31 15:44:50 +01:00
Bernardo Magri
51a0f920be docs: mark Pillar 9 Component 6 graphical pass as complete 2026-05-31 15:35:30 +01:00
Bernardo Magri
2c86074893 fix(waybar): drop the dead summer-night date on-click (kitty calcurse)
All checks were successful
Check / eval-and-lint (push) Successful in 6m51s
The default theme's clock#date wired on-click to `kitty calcurse`, but
kitty isn't a default-installed app (alacritty is the terminal) and
calcurse isn't installed anywhere — so clicking the date did nothing.
The default config.jsonc uses xdg-terminal-exec/alacritty for its
clicks and summer-day's date has no on-click. Drop the dead action
(tooltip: false), matching summer-day.

Found during the Pillar 9 Component 6 (apps) pass, which confirmed
btop/ghostty/kitty/lazygit/tmux ship config-only by design (the
installer/user picks the binary) — not a bug. Logged two follow-ups:
summer-day's wofi --term=kitty launcher, and shipping a calendar app.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 15:16:39 +01:00
Bernardo Magri
43b0cbcd65 fix(waybar): show the battery widget on the default summer-night theme
All checks were successful
Check / eval-and-lint (push) Successful in 6m46s
The summer-night waybar config defined a custom/battery module
(exec nomarchy-battery-status) but never listed it in any modules-*
slot, so it was orphaned and never rendered. summer-night is the
default theme, so a laptop on a stock install had no battery
indicator — the default fallback config and the summer-day theme
both place battery in modules-right; only summer-night omitted it.

Add custom/battery to summer-night's modules-right. The formFactor
filter (laptopOnlyModules) already lists custom/battery, so it shows
on laptop and is dropped on desktop. Found during the Pillar 9
Component 9 (form-factor split) verification pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 15:03:49 +01:00
Bernardo Magri
3d931a6455 fix(menu): repair three dead nomarchy-menu leaf actions (Pillar 9 / Component 3)
All checks were successful
Check / eval-and-lint (push) Successful in 6m41s
Found by driving the menu's observable actions live in a VM with the real
session env imported. All three are also bound to keybindings.

1. nomarchy-hyprland-window-single-square-aspect-toggle (1-Window Ratio,
   SUPER CTRL BACKSPACE): read/set layout:single_window_aspect_ratio, which
   is "no such option" in Hyprland 0.52.1 — the option lives under dwindle:.
   The getoption returned nothing and the keyword set was silently dropped,
   so the toggle did nothing. Point it at dwindle:single_window_aspect_ratio.

2. nomarchy-hyprland-workspace-layout-toggle (Workspace Layout, SUPER L):
   read .tiledLayout off `hyprctl activeworkspace -j` (no such key → always
   null) and switched to "scrolling" (not a built-in layout — hyprctl
   layouts lists only dwindle/master), so it silently no-op'd. Rewrite to
   toggle the real general:layout between dwindle and master.

3. show_setup_menu offered Power Profile unconditionally, but powerprofilesctl
   is absent everywhere (power-profiles-daemon is force-off on laptop in
   favour of TLP and never enabled on desktop), so the entry died with
   "command not found". Gate it behind `command -v powerprofilesctl`.

Verified (1) and (2) against live Hyprland in the VM: aspect flips
[0,0]<->[1,1], layout flips dwindle<->master.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 14:48:37 +01:00
Bernardo Magri
0fbc3d9c82 fix: ground + fix three Pillar-9 candidate bugs from the script sweep
All checks were successful
Check / eval-and-lint (push) Successful in 6m40s
All three confirmed real on inspection.

1. nomarchy-refresh-config was dead on every system: it read
   /etc/nixos/nomarchy/{core/home/config,features} (the source tree never
   lands there — only /etc/nomarchy on VM-guest/live ISO) and fell back to
   ~/.local/share/nomarchy/config, which nothing deployed despite SKILL.md
   documenting it. Deploy the pristine core/home/config tree to
   ~/.local/share/nomarchy/config via xdg.dataFile and read from there, so it
   works without a source checkout; its live caller nomarchy-refresh-fastfetch
   now succeeds. Fix two stale SKILL.md examples (waybar/, hypr/) that pointed
   at non-existent stock paths.

2. nomarchy-docs-scripts shipped a stale divergent copy in
   features/scripts/utils/ (in the user nomarchy-system-scripts package)
   beside the canonical bin/utils dev tool — it errored outside the repo.
   Grounding it surfaced the identical bug in nomarchy-docs-keybindings.
   Delete both duplicates, add them to the generator's self-reference
   denylist so they don't show as false `missing`, regenerate docs/SCRIPTS.md.

3. Home ~/.config/nomarchy/state.json was never seeded on non-installer
   systems, so nomarchy-installed-summary rendered "—" for theme/font/panel.
   Add an idempotent home-manager activation seed in core/home/state.nix that
   backfills the resolved values (defaults * existing — user choices and
   runtime-only keys like welcome_done always win).

Verified: flake check + full eval matrix clean; refresh-config happy/error
paths and the seed deep-merge proven by hand.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 14:25:02 +01:00
Bernardo Magri
00b8214cb1 docs(agent): guardrail — never mkDefault a list/attrset option that merges
Some checks failed
Check / eval-and-lint (push) Failing after 7m7s
The "mkDefault everywhere user might override" rule is what caused the
home.packages bug. Clarify: mkDefault is for scalars; on list/attrset
options that other modules contribute to, a mkDefault def is dropped
entirely (filterOverrides) rather than merged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 14:00:29 +01:00
Bernardo Magri
f34f59c2aa fix: drop mkDefault on three more list options it was silently dropping
Some checks failed
Check / eval-and-lint (push) Has been cancelled
Same footgun as the home.packages fix, found by sweeping the tree for
`mkDefault` on list options that other modules contribute to at normal
priority (so filterOverrides discards the mkDefault def entirely):

  * themes/engine/sddm.nix — environment.systemPackages = mkDefault
    [ nomarchy-sddm-theme ] was dropped, so the SDDM greeter theme package
    was never installed (unthemed login).
  * themes/engine/plymouth.nix — boot.kernelParams = mkDefault [ quiet
    splash loglevel=3 … ] was dropped, so boots weren't quiet/clean.
  * features/desktop/waybar/default.nix — home.packages = mkDefault
    [ font-awesome ] was dropped, so waybar's icon font was missing.

Verified via eval: nomarchy-sddm-theme now in systemPackages, "quiet" in
kernelParams, font-awesome in home.packages. Left the genuinely-safe
single-definition mkDefaults alone (plymouth.themePackages,
resolved.fallbackDns, hyprsunset.extraArgs) and the hybridGPU videoDrivers
mkDefault (it outranks nixpkgs' mkOptionDefault on real hardware).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 13:59:46 +01:00
Bernardo Magri
b029edb5b4 docs(roadmap): log the mkDefault-on-home.packages bug found chasing the D-Bus error
Some checks failed
Check / eval-and-lint (push) Failing after 6m51s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 10:43:41 +01:00
Bernardo Magri
1117dcfc37 fix(home): drop mkDefault on home.packages — it discarded the whole app list
Some checks failed
Check / eval-and-lint (push) Has been cancelled
Chasing a "DBus.Error … name is not activatable" from notify-send (mako),
the root cause turned out to be far bigger: home.packages in
features/default.nix was wrapped in lib.mkDefault. home.packages is a
list, and the module system's filterOverrides keeps only the
highest-priority definitions — so the moment any other module sets
home.packages at normal priority (features/scripts/default.nix's
`[ nomarchy-scripts ]`, the installer's profile packages), this entire
mkDefault list was DROPPED. Every install was silently missing firefox,
thunar, imv, mpv, swww, mako, hyprlock, rofi, etc. — which broke
notifications (mako never installed → exec-once fails → notify-send dead)
and the lock screen (hyprlock missing), and hid a stale `rofi-wayland`
reference (merged into `rofi` upstream) that only errored once the list
was live again. Remove the mkDefault so the list merges (home.packages =
52 pkgs, up from 31; mako/hyprlock/firefox/… now present) and fix
rofi-wayland -> rofi.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 10:40:44 +01:00
Bernardo Magri
6e391b1843 docs(roadmap): log Pillar 9 walker menu verification + two fixes
Some checks failed
Check / eval-and-lint (push) Failing after 6m40s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 10:05:35 +01:00
Bernardo Magri
c5fe0e09fa fix(walker): background selector must follow symlinks (find -L)
Some checks failed
Check / eval-and-lint (push) Has been cancelled
Pillar 9 VM test: after the menu-registration fix, the walker background
selector menu opened but still showed "No Results". Its GetEntries ran
`find <dir> -type f`, but home-manager deploys the per-theme background
images as symlinks into the nix store, and `-type f` doesn't follow
symlinks. Add -L (the sibling nomarchy_themes.lua already uses `find -L`).
Verified in the VM: `find -type f` -> 0, `find -L` -> the backgrounds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 10:05:05 +01:00
Bernardo Magri
c831b01b0a fix(walker): deploy elephant theme/background menus where elephant loads them
Some checks failed
Check / eval-and-lint (push) Failing after 6m40s
Pillar 9 VM test: the walker theme picker (and background selector)
returned "No Results". Root cause: nomarchy_themes.lua and
nomarchy_background_selector.lua (elephant lua menu providers named
"nomarchythemes" / "nomarchyBackgroundSelector") were deployed via the
bulk nomarchy config to ~/.config/nomarchy/default/elephant/ — outside
elephant's provider search path, so elephant never registered them and
`nomarchy-launch-walker -m menus:nomarchythemes` (used by nomarchy-theme,
nomarchy-wallpaper, and nomarchy-menu Style submenu) had no backing menu.

Move them into the elephant config (features/apps/elephant/config/menus/)
so they deploy to ~/.config/elephant/menus/. Verified on a fresh VM boot:
`elephant listproviders` now lists menus:nomarchythemes +
menus:nomarchyBackgroundSelector, and the walker theme picker renders all
21 palettes with per-theme preview images.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 09:54:06 +01:00
Bernardo Magri
704cc70c84 docs(roadmap): log full installer end-to-end VM install + boot verification
Some checks failed
Check / eval-and-lint (push) Failing after 6m34s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 09:33:26 +01:00
Bernardo Magri
aaae29fb4d docs(roadmap): log Pillar 9 script sweep + theme visual pass progress
Some checks failed
Check / eval-and-lint (push) Failing after 6m51s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 08:36:00 +01:00
Bernardo Magri
23d432f279 fix(scripts): add python3 so the XPS haptic-touchpad service runs
Some checks failed
Check / eval-and-lint (push) Failing after 6m43s
Pillar 9 VM script sweep: nomarchy-haptic-touchpad failed with
"env: 'python3': No such file or directory". It's a python3 script
(#!/usr/bin/env python3) wired as systemd.services.nomarchy-haptic-touchpad
in core/system/hardware.nix (Dell XPS haptic feedback), run from the
nomarchy-system-scripts wrapper — but python3 wasn't in systemScriptDeps,
so the wrapper's PATH lacked it and the service died on every XPS. Add
python3 (stdlib-only script, plain pkgs.python3 suffices). Verified the
rebuilt wrapper resolves python3 and the script runs to its clean
"no device found" exit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 22:21:04 +01:00
Bernardo Magri
8e2c27087f docs(roadmap): add Pillar 9 — live VM runtime QA
All checks were successful
Check / eval-and-lint (push) Successful in 7m3s
New pillar to drive the distro running in a VM and verify what actually
works vs. what only looks right in source: run every nomarchy-* command,
walk every menu entry, switch through all 22 palettes and eyeball
rendering, fire every keybinding, drive the installer. Documents the
method (build -> boot headless -> screendump/sendkey) proven in the first
VM-boot pass, the per-component checklist, and the deliverable format. The
old "Pillar 8 runtime verification" Now-board punch-list folds into it.
AGENT.md's verify step now points at the headless VM screenshot flow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:58:27 +01:00
Bernardo Magri
70d0b56259 docs(roadmap): log Pillar 8 first VM-boot verification pass
Some checks failed
Check / eval-and-lint (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:53:47 +01:00
Bernardo Magri
e98ebe5d8c fix(hypr): correct invalid window-rule syntax in pip/retroarch/steam/system
Some checks failed
Check / eval-and-lint (push) Has been cancelled
Booting the VM peeled back two more layers of Hyprland config errors after
the geforce/moonlight fix:

  * pip.conf used underscored rule names with stray values —
    `keep_aspect_ratio on` and `border_size 0`. Hyprland's rules are
    `keepaspectratio` (boolean, no value) and `bordersize 0`.
  * retroarch/steam/system.conf wrote `idleinhibit, <mode>` with a comma,
    so Hyprland read <mode> as a selector ("Invalid value: always/
    fullscreen"). The mode is space-separated: `idleinhibit always`.

Verified clean in a rebuilt VM — the boot-time config-error overlay is
gone. All Omarchy-era rule-syntax holdovers, exposed once Component 5
wired apps.conf to source every app rule file.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:52:40 +01:00
Bernardo Magri
8e5e63facb fix(installed-summary): drop compgen (absent in wrapped bash)
Booting the VM showed "line 31: compgen: command not found" from
nomarchy-installed-summary on first boot. compgen is a bash
programmable-completion builtin, and the non-interactive bash the script
gets wrapped with (via makeWrapper + patchShebangs) is compiled without
progcomp. Beyond the visible error, the battery-presence check silently
failed to the else branch, so a laptop was always reported as "desktop".
Replace `compgen -G` with a nullglob array (a shopt, always available).
The installer's identical check runs under the ISO's interactive bash, so
it was unaffected — this script is the only compgen user.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:30:35 +01:00
Bernardo Magri
14c22cbbaa fix(hypr): valid windowrulev2 syntax for geforce/moonlight
Booting the desktop VM surfaced Hyprland config errors on every start:
"config option <windowrule:name> does not exist" from apps/geforce.conf
and apps/moonlight.conf. Both used an invalid `windowrule { name=…;
class:=…; idle_inhibit=… }` block form (an Omarchy-era holdover) that
Hyprland rejects line-by-line — exposed once Component 5 wired apps.conf
to source all 17 app rule files. Rewrite as single-line windowrulev2
rules matching every other apps/*.conf: idle-inhibit on fullscreen for
GeForceNOW; open-fullscreen + idle-inhibit for Moonlight.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:30:35 +01:00
Bernardo Magri
dc9e74ca12 fix(scripts): use mktemp for state.json writes, not a fixed /tmp path
All checks were successful
Check / eval-and-lint (push) Successful in 6m57s
Ten state-mutating sites across seven scripts wrote through a predictable,
world-writable temp path (`/tmp/state.json`, `/tmp/system-state.json`)
before the atomic `sudo mv`. Because the `>` redirect runs as the invoking
user (sudo doesn't cover redirects), the shared fixed path is a symlink/
TOCTOU target and collides if two of these run concurrently. Switch each
to a per-invocation `mktemp`; the atomic rename into place is unchanged.
nomarchy-theme-set already used a temp var for its home-state write — this
makes its system-state write consistent and cleans the temp up on failure.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:05:04 +01:00
Bernardo Magri
95d36f8ec7 docs(options): document nomarchy.hyprland.{gaps_in,gaps_out,border_size}
These three home options (Hyprland inner/outer gaps + active-border width,
read from state.json, wired in features/desktop/hyprland/default.nix) were
the only real options missing from OPTIONS.md — a guardrail violation
(every nomarchy.* option must be documented). Found via a full diff of the
live option tree against the doc's headings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:02:21 +01:00
Bernardo Magri
9751da2523 fix(docs-scripts): pin LC_ALL=C so SCRIPTS.md ordering is deterministic
All checks were successful
Check / eval-and-lint (push) Successful in 6m35s
CI's drift check failed on pure ordering noise: the generator's `sort`
collated rows and caller lists by the ambient locale (en_GB.UTF-8 on the
dev box that committed the file, C in the CI container), so `-` vs `/` and
`-` vs `s` ordered differently (e.g. theme-update vs themes-prebuild,
caller-list order). Force LC_ALL=C in the generator and regenerate
docs/SCRIPTS.md in that collation, so the committed copy and any
regeneration — dev box or CI — are byte-identical.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 08:17:41 +01:00
Bernardo Magri
e8cb346759 ci: collapse eval matrix from ~39 evals to ~3 (was timing out at 3h)
Some checks failed
Check / eval-and-lint (push) Failing after 6m40s
The per-toggle + per-palette matrix did ~39 full-system evaluations (16
toggle toplevels + 21 palettes each via a full extendModules eval + 2
home) and ran ~2h55m on the small self-hosted runner — long enough to hit
act_runner's 3h container lifetime (sleep 10800) and get killed.

Redesign:
  * Combine compatible toggles into 3 configs (laptop-stack, desktop-stack,
    impermanence-multi) instead of one eval per toggle. A failure means
    re-run the suspect toggle alone; the trace hint covers that.
  * Check palettes directly via the lib — the per-palette risk is the pure
    base00 -> RGB hex math in plymouth.nix, which needs no module-system
    instantiation. Forcing the palette attrset also catches a missing one.
  * Drop the home configs; the per-output flake-check step already forces
    both homeConfigurations.

~39 full evals -> 3, plus a near-instant palette pass. Runs in ~1m locally
(warm). AGENT.md updated for the new combined-scenario structure.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 08:09:23 +01:00
Bernardo Magri
2dda8e2bb5 ci: check flake outputs per-output to skip the OOM-heavy package
Some checks failed
Check / eval-and-lint (push) Failing after 3h0m3s
`nix flake check --no-build` also evaluates packages.allThemeVariants, a
linkFarm whose drvPath forces all 22 home generations into memory at once
— the runner OOM-killed there ("Killed" after allThemeVariants). Replace
it with an explicit per-output eval that forces all 4 system closures
(incl. assertions), both standalone home generations, the installer VM
package, the overlay and the app, and skips only allThemeVariants/default.
Each tryEval is GC'd before the next, so peak memory is one config rather
than twenty-two. The eval matrix already validates every palette
one-at-a-time, so dropping that package from CI loses no real coverage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 22:51:05 +01:00
Bernardo Magri
6c66db9b88 ci: realize walker src via nix build to prime cold store
Some checks failed
Check / eval-and-lint (push) Failing after 9m24s
Diagnosed the persistent "path '…-source' is not valid": it's walker's
flake reading its own source at eval time — importTOML
resources/config.toml in its home-manager module and lib.fileset.toSource
for the package src. On a cold store the walker input source isn't
materialized, and neither --no-build flake check nor `nix flake archive`
makes the fileset-derived src readable. Replace the archive step with a
`nix build` of walker's src attribute, which eagerly realizes it (and the
input it reads from) so the subsequent flake check / eval matrix find
every path valid.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 22:27:15 +01:00
Bernardo Magri
ebdd32265b ci: nix flake archive before check to materialize input sources
Some checks failed
Check / eval-and-lint (push) Failing after 1m11s
flake check kept failing on a cold store with "path '…-source' is not
valid" while evaluating Stylix's import-from-derivation in the
home-manager fontconfig text. Nix keeps flake-input sources in a git
cache and only materializes the -source store paths lazily; IFD readFile
needs them as real store paths. Works locally only because prior builds
already materialized them. Add a `nix flake archive` step that copies
every transitive input into the store before the check (and before the
eval matrix, which has the same need).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 22:13:58 +01:00
Bernardo Magri
7980c2f5ff ci: pin Nix to 2.31.5 to fix lazy-trees IFD failure
Some checks failed
Check / eval-and-lint (push) Failing after 1m5s
flake check kept failing with "path '…-source' is not valid" while
evaluating the home-manager fontconfig text (Stylix/base16.nix do
import-from-derivation). Root cause: the installer pulled the latest Nix
(2.34), whose lazy-trees / git-cache behaviour doesn't materialise
flake-input source paths into the store, so the IFD reads can't find
them. Pin the install to 2.31.5 — the version that wrote flake.lock
locally and evaluates the flake cleanly all session.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 22:09:17 +01:00
Bernardo Magri
f24d49be08 ci: disable Nix sandbox so Stylix IFD can realize sources
Some checks failed
Check / eval-and-lint (push) Failing after 1m3s
flake check evaluates the home-manager fontconfig text, which via
Stylix/base16.nix does import-from-derivation — eval must realize fetched
`-source` paths. The single-user Nix in the runner container can't set up
the build sandbox (no user namespaces), so realization failed with
"path '…-source' is not valid". Set sandbox = false for the runner
(safe in a throwaway CI container).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 22:05:12 +01:00
Bernardo Magri
da5e5cf2aa ci: create nixbld build users for root single-user Nix install
Some checks failed
Check / eval-and-lint (push) Failing after 1m13s
Empty group wasn't enough — this Nix version errors with "build users
group 'nixbld' has no members". Create the nixbld group plus 10 build
users (what a multi-user install does) before running the installer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 22:01:46 +01:00
Bernardo Magri
b676f43afe ci: fix root single-user Nix install (nixbld group + SSL cert)
Some checks failed
Check / eval-and-lint (push) Failing after 7s
The single-user installer, running as root in the catthehacker container,
aborts because its bundled nix.conf sets build-users-group=nixbld and the
group doesn't exist ("the group 'nixbld' ... does not exist"). Pre-create
an empty nixbld group so config validation passes; single-user builds run
as root and never use it. Also set NIX_SSL_CERT_FILE at the job level
since we add nix to PATH without sourcing the installer profile that would
otherwise export it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 22:00:03 +01:00
Bernardo Magri
9767a5c5dd ci: install Nix via shell step instead of node24 JS action
Some checks failed
Check / eval-and-lint (push) Failing after 7s
act_runner v0.2.11 bundles an `act` that supports up to node20, but
DeterminateSystems/nix-installer-action@main moved to the node24 runtime,
so the job died with "runs.using ... got node24". Replace the JS action
with a plain single-user Nix install (--no-daemon, no systemd needed in
the catthehacker container) and set NIX_CONFIG at the job level so the
bare `nix flake check` still gets flakes. A run step has no node-runtime
coupling, so this won't break again when an action bumps its runtime.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 21:56:53 +01:00
Bernardo Magri
1dd0e2f4b9 ci: move workflow to .gitea/workflows so Gitea picks it up
Some checks failed
Check / eval-and-lint (push) Failing after 2s
Gitea only scans .gitea/workflows and .github/workflows; it does not scan
.forgejo/workflows (that path is Forgejo-only). The CI was therefore
dormant on a Gitea instance regardless of whether Actions was enabled.
git mv to .gitea/workflows/ (scanned by both Gitea and Forgejo). Updated
the live references in STRUCTURE.md (Gitea + act_runner), AGENT.md, and
today's ROADMAP entry; left the dated historical Shipped entries as the
changelog they are.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 21:36:51 +01:00
Bernardo Magri
8547fa70d9 feat(ci): eval matrix for opt-in nomarchy.* toggles
nix flake check --no-build only evaluates the four default configs, so a
bug that only fires when a nomarchy.* toggle is flipped sails through —
exactly how the vscode option rename and the impermanence systemd-stage-1
assertion both reached main undetected.

Add bin/utils/nomarchy-eval-matrix: layers each opt-in scenario (16
toggles, both system and home halves) onto nixosConfigurations.default
via extendModules and forces system.build.toplevel.drvPath (which forces
assertion checks); also forces all 21 palettes through the system-side
Plymouth base00->RGB math that the home-only allThemeVariants never
reaches, plus both standalone homeConfigurations. Per-scenario results
come from builtins.tryEval so one failure doesn't mask the rest; verified
it goes red on a re-injected assertion failure and a bad option ref, green
on the current tree.

Wired into .forgejo/workflows/check.yml after flake check (jq via nix
shell so it doesn't depend on the runner image). AGENT.md §5 now tells
future agents to add a scenario when they add/rename an opt-in option.

nomarchy-docs-scripts: filter systemd-service declarations (.services.
nomarchy-) and denylist the eval-matrix repo tool so neither shows as a
dangling "missing" reference; also retroactively clears the latent
nomarchy-flathub-init drift from the gaming-flathub commit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 21:21:28 +01:00
Bernardo Magri
38c70e4aaf fix(impermanence): rollback as systemd initrd service, not postDeviceCommands
themes/engine/plymouth.nix enables systemd stage-1 initrd
(boot.initrd.systemd.enable) distro-wide, and Plymouth is imported
unconditionally from core/system/default.nix. systemd stage 1 hard-rejects
boot.initrd.postDeviceCommands with a failed assertion, so every config
with nomarchy.system.impermanence.enable = true — including installs that
chose impermanence at the installer prompt — failed to evaluate.

Convert the Erase-Your-Darlings rollback to a boot.initrd.systemd.services
oneshot unit ordered after the LUKS mapping opens and before sysroot.mount,
and add boot.initrd.systemd.initrdBin for btrfs-progs/coreutils/util-linux/
findutils (the systemd initrd doesn't ship them by default). Script body is
unchanged. Verified eval via extendModules on nixosConfigurations.default;
boot-time wipe semantics still need a real wipe-boot cycle (Pillar 8).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 18:24:01 +01:00
Bernardo Magri
905ed4f6d8 fix(vscode): move extensions under profiles.default
programs.vscode.extensions was renamed to
programs.vscode.profiles.default.extensions in home-manager. The bare
option still worked via the compat shim but emitted a deprecation
warning on every eval (21× — once per home evaluation in flake check)
and will break when the alias is dropped. userSettings already lived
under profiles.default; extensions now joins it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 18:11:29 +01:00
Bernardo Magri
9b26eda388 fix(vscode): pin theme extensions for 10 marketplace palettes
Before this fix, only the 6 palettes whose theme extensions ship in
pkgs.vscode-extensions had working VSCode theming. Every other palette
had `workbench.colorTheme` set to a name VSCode couldn't find, so it
silently fell back to its built-in default. Including the DEFAULT
summer-night palette (sainnhe.everforest) — the default install had
broken VSCode theming.

Probed the 13 unique extensions against the VSCode marketplace
extensionquery API:

  - 10 exist and are pinnable: sainnhe.everforest,
    shadesOfBuntu.flexoki-light, qufiwefefwoyn.kanagawa,
    oldjobobo.{lumon,miasma,retro-82}-theme, TahaYVR.matteblack,
    jovejonovski.ocean-green, monokai.theme-monokai-pro-vscode,
    Bjarne.white-theme.
  - 3 don't exist on the marketplace and are unpublished custom
    Nomarchy themes: Bjarne.{ethereal,hackerman,vantablack}-nomarchy.
    Logged as a new Later row.

For the 10, fetched version + sha256 via:

  URL='https://${publisher}.gallery.vsassets.io/_apis/public/gallery/publisher/${publisher}/extension/${name}/${version}/assetbyname/Microsoft.VisualStudio.Services.VSIXPackage'
  nix store prefetch-file --hash-type sha256 "$URL"

Added a marketplaceExtensions list to features/apps/vscode.nix that
wraps each in pkgs.vscode-utils.extensionFromVscodeMarketplace and
concatenates with the existing nixpkgs-packaged list — so 10 more
palettes (including the default) now get correct VSCode theming on
first launch. Smoke-built sainnhe.everforest end-to-end. Module
comment documents the version-bump procedure.

docs/OPTIONS.md updated: the nomarchy.vscode.devExtensions entry
drops the "still break" caveat for everything except the three
unpublished Bjarne palettes.

`nix flake check --no-build` clean.
2026-05-22 20:21:43 +01:00
Bernardo Magri
a901b1db0b chore(chromium): delete broken static Default/Preferences deployment
features/apps/chromium/default.nix was deploying a 204-byte static
Default/Preferences via Home Manager symlink into Chromium's mutable
profile directory. The deployment is structurally broken — Chromium
expects to write that file at runtime, so either the symlink is
silently replaced on first save (losing the static defaults) or the
write fails silently.

The contents are also redundant + incorrect:

  - `extensions.theme.{use_system,use_custom} = false` — already
    superseded by the managed-policy approach (BrowserThemeColor
    overrides any user-installed theme extension regardless).
  - `browser.theme.{color_scheme,user_color} = 2` — hardcoded "dark"
    via Chromium's color_scheme enum, conflicting with the dynamic
    BrowserColorScheme = isLightTheme ? "light" : "dark" set by
    core/system/browser.nix. A user on flexoki-light / summer-day /
    catppuccin-latte / rose-pine / white would have had a static-vs-
    policy mismatch every time.

Removed the entire features/apps/chromium/ directory (default.nix +
config/Default/Preferences) and dropped the import from
features/default.nix. Chromium theming continues to flow through the
system-level managed policy, which is the canonical chromium-on-NixOS
path.

`nix flake check --no-build` clean.
2026-05-22 19:32:51 +01:00
Bernardo Magri
7e25ae637d docs(roadmap): ship Plymouth per-palette templating
Moved the Next-column row → Shipped following commit 474bc16
("feat(plymouth): boot splash background follows the active palette").
Next column is now empty.
2026-05-22 19:27:30 +01:00
Bernardo Magri
474bc16eb3 feat(plymouth): boot splash background follows the active palette
themes/engine/plymouth/nomarchy.script had
`Window.SetBackgroundTopColor(0.101, 0.105, 0.149)` hardcoded — a
Tokyo-Night-ish #1a1b26 — and nomarchy.plymouth had a matching
`ConsoleLogBackgroundColor=0x1a1b26`. Both were frozen regardless of
the active nomarchy.system.theme.

Replaced the literals with placeholders (@BG_R@, @BG_G@, @BG_B@,
@BG_HEX@) in the source files. themes/engine/plymouth.nix now reads
the active palette via `nomarchyLib.getPalette
config.nomarchy.system.theme`, converts palette.base00 into three
0.0–1.0 floats (Nix has no floating-point math, so `(byte * 1000) /
255` integer division formatted as `0.XXX`), and `sed`-substitutes
both files during installPhase.

Smoke-built the derivation against the default summer-night palette:

  $ cat .../nomarchy.script | grep BackgroundTopColor
  Window.SetBackgroundTopColor(0.176, 0.207, 0.231);
  $ cat .../nomarchy.plymouth | grep ConsoleLogBackgroundColor
  ConsoleLogBackgroundColor=0x2d353b

Both match the expected byte→float conversion from base00=2d353b.

Closes the "Plymouth theme variants per palette" Next-column item.
`nix flake check --no-build` clean.
2026-05-22 19:27:04 +01:00
Bernardo Magri
a14491b1cc docs(roadmap): ship nomarchy.overrides loader
Moved the Next-column row → Shipped following commit 38429a3
("feat(overrides): wire nomarchy.overrides.paths into xdg.configFile").
2026-05-22 18:49:49 +01:00
Bernardo Magri
38429a32df feat(overrides): wire nomarchy.overrides.paths into xdg.configFile
The option surface (`enable`, `paths`) lived in core/home/overrides.nix
since 2026-05-18 but didn't do anything — paths was a reserved
attrset that never reached xdg.configFile.

Now wired: every entry in nomarchy.overrides.paths substitutes the
matching xdg.configFile.<key>.source at lib.mkForce priority, beating
Nomarchy's own lib.mkDefault writes. Other fields on the original
entry (recursive, etc.) survive via the standard module-system merge.

  nomarchy.overrides.paths = {
    "nomarchy/default/hypr/looknfeel.conf" = ./looknfeel.conf;
    "waybar/style.css"                     = ./waybar.css;
  };

Picked the attrset model from the row's two options rather than
runtime ~/.config/nomarchy/overrides/ directory discovery — Nix needs
every managed file declared at evaluation time, and the attrset
matches the explicit-config shape used everywhere else in the
Nomarchy surface.

docs/OPTIONS.md updated: both overrides.{enable,paths} entries get
real content + an example, the configOverrides row now contrasts
bulk-vs-per-file accurately, and the "Where these are defined" footer
drops the (reserved) tag.

`nix flake check --no-build` clean.
2026-05-22 18:49:19 +01:00
Bernardo Magri
ce7010bb67 feat(accessibility): home-side Hyprland companion
New nomarchy.accessibility.enable home option mirroring
nomarchy.system.accessibility.enable. When enabled, core/home/
accessibility.nix contributes a Hyprland extraConfig block via
lib.mkAfter:

  - input.repeat_rate = 25 (from 40)
  - input.repeat_delay = 1000 ms (from 600)
    Holding a key isn't a runaway machine-gun for low-mobility users.

  - bindd = SUPER ALT, S, Launch Orca, exec, orca
    The system preset already puts orca on PATH.

mkAfter guarantees the slowdown wins over the templated input.conf.
Documented in docs/OPTIONS.md. The third item from the original Next
row — a high-contrast palette — is split into its own Later row
because it's a design task (24-colour WCAG AAA palette + icon family
choice) that wants its own review.

`nix flake check --no-build` clean.
2026-05-22 18:42:13 +01:00
Bernardo Magri
099d81f11e docs(roadmap): ship Gaming flathub remote
Moved the entry from Next → Shipped following commit 2948dc4
("feat(gaming): register Flathub remote via one-shot systemd unit").
2026-05-22 18:34:22 +01:00
Bernardo Magri
2948dc4dbf feat(gaming): register Flathub remote via one-shot systemd unit
services.flatpak.enable = true (set inside core/system/gaming.nix's
mkIf cfg.enable block) ships flatpak but doesn't add any remotes, so
`flatpak install` and the Discover GUI returned empty results until
the user ran the manual `flatpak remote-add` one-liner. nixpkgs has
no declarative remote-add API yet.

Added systemd.services.nomarchy-flathub-init: a Type=oneshot,
RemainAfterExit=true unit that runs
`flatpak remote-add --if-not-exists flathub
  https://dl.flathub.org/repo/flathub.flatpakrepo`
after network-online.target. The --if-not-exists flag keeps it
idempotent across reboots and re-runs.

Lives under the gaming preset (where flatpak is wired today); lift
to a dedicated module when another preset needs flatpak.

Closes the "Gaming — declarative flathub remote" Next-column item.
`nix flake check --no-build` clean.
2026-05-22 18:33:51 +01:00
Bernardo Magri
90f9a29cb6 fix(menu): remove "Setup → Config" submenu
show_setup_config_menu was an Omarchy holdover where users edited
mutable config files at runtime. In Nomarchy:

  - hyprland.conf, hypridle.conf, hyprsunset.conf, walker/config.toml,
    waybar/config.jsonc are all Home-Manager-generated from declarative
    settings — a `home-manager switch` clobbers any edit.
  - hyprlock.conf and swayosd/config.toml point at paths the modules
    don't deploy at all; open_in_editor created empty files.
  - ~/.XCompose is a HM symlink into /nix/store — read-only.

Dropped the entire submenu function and the "  Config" item from
show_setup_menu (and the matching *Config*) case branch). Persistent
settings go through the relevant nomarchy.* option in
/etc/nixos/home.nix (or system.nix); when the nomarchy.overrides.*
loader ships, a successor menu can route through
~/.config/nomarchy/overrides/.

Side effect (caught by the SCRIPTS.md regen): nomarchy-restart-xcompose
is now `unused?` — its only caller was the XCompose case I just
removed. Left for a future Pillar 3 cleanup rather than widening
this PR.

`bash -n` clean.
2026-05-22 18:30:48 +01:00
Bernardo Magri
055832e916 fix(waybar): gate enable on toggles.waybar (Nix-level, not session-local)
features/desktop/waybar/default.nix previously set
`programs.waybar.{enable,systemd.enable} = lib.mkDefault true`
unconditionally. The toggle script wrote .waybar to state.json and
pkill/exec'd waybar for instant feedback, but the next rebuild
re-enabled it because the Nix module didn't read the toggle. Result:
the bar came back on every rebuild/reboot regardless of the persisted
state — inconsistent with toggles.idle (gates services.hypridle.enable)
and now toggles.nightlight (gates services.hyprsunset.enable).

programs.waybar.{enable,systemd.enable} now follow
config.nomarchy.toggles.waybar. nomarchy-toggle-waybar flips the
running systemd user unit (`systemctl --user start/stop waybar.service`)
for instant feedback and writes .waybar back to state.json so the next
rebuild realigns. Disabled toggle now means no waybar across rebuilds
+ reboots, matching the option's documented meaning ("Whether the top
bar is enabled").

`nix flake check --no-build` + `bash -n` clean.
2026-05-22 18:23:35 +01:00
Bernardo Magri
161542c420 fix(nightlight): gate hyprsunset on the toggle, drop hardcoded temperature
features/desktop/nightlight.nix previously set
`services.hyprsunset.enable = lib.mkDefault true` unconditionally and
baked the temperature (4000K when toggles.nightlight, 6500K otherwise)
into extraArgs at Nix-eval time. The toggle script bypassed systemd:
pkill on disable, `hyprctl dispatch exec hyprsunset --temperature 4000`
on enable — racing the systemd-managed instance and hardcoding 4000K
regardless of nomarchy.nightlightTemperature. The "Always enabled, we
control via IPC and state" comment was misleading: no IPC, the
temperature was rebuild-time, and the script forked a parallel
process.

Path (b) from the Later row:

  - services.hyprsunset.enable now follows config.nomarchy.toggles.
    nightlight — symmetric with services.hypridle.enable ← toggles.idle.
    Disabled toggle = no process running.
  - extraArgs always reads from config.nomarchy.nightlightTemperature.
    Drops the 6500K neutralising fork; when off the unit just doesn't
    start.
  - nomarchy-toggle-nightlight flips the running systemd user unit via
    `systemctl --user start/stop hyprsunset.service` for instant
    feedback, reads nightlightTemperature from state.json for the
    notify-send line, and writes .nightlight back to state.json so the
    next rebuild realigns services.hyprsunset.enable.

`nix flake check --no-build` + `bash -n` clean.
2026-05-22 18:20:44 +01:00
Bernardo Magri
3bcd92df02 feat(keymap): route installer layout choice into Hyprland's Wayland session
core/home/config/nomarchy/default/hypr/input.conf hardcoded
`kb_layout = us`, so the installer's services.xserver.xkb.layout and
console.keyMap writes (both set from the installer's KEYMAP_LAYOUT
prompt) only reached XWayland apps and the TTY console. Native-Wayland
apps — i.e. almost everything in a Nomarchy desktop — fell back to US
regardless of what the user picked. Surprising for any non-US user.

Path (a) from the Later row:

  - Added nomarchy.keymap.{layout,variant} to core/home/options.nix
    (defaults "us" / "").
  - Deleted the static input.conf from the bulk nomarchy/ deploy.
  - Replaced it with an explicit
    xdg.configFile."nomarchy/default/hypr/input.conf".text in
    core/home/configs.nix that interpolates the option values into
    kb_layout / kb_variant.
  - Installer's home.nix heredoc now writes
      nomarchy.keymap = { layout = "$KEYMAP_LAYOUT"; variant = "$KEYMAP_VARIANT"; };
    alongside nomarchy.formFactor, so the layout reaches Hyprland
    consistently with system.nix's xkb.layout / console.keyMap.

Documented in docs/OPTIONS.md (new `nomarchy.keymap.layout` /
`nomarchy.keymap.variant` entry). `nix flake check --no-build` clean.
2026-05-22 18:14:17 +01:00
Bernardo Magri
be597571ad refactor(flake): consolidate palette imports through nomarchyLib
flake.nix was re-importing ./themes/palettes and recomputing
themeNames via builtins.attrNames in its outputs `let`, even though
lib/default.nix already exports both. Two evaluations of the same
data, same result today — drift risk tomorrow as soon as one
computation grows extra logic the other doesn't.

Added `nomarchyLib = import ./lib { inherit lib; }` once and reused
it via `inherit (nomarchyLib) themeNames;` for the allThemeVariants
linkFarm. The local `palettes` binding wasn't read by anything else in
the outputs so it goes away with the rewrite. lib/default.nix is now
the single source of truth for the theme list; modules under core/
and themes/engine/ already import ../../lib the same way and resolve
to the identical evaluation.

`nix flake check --no-build` clean.
2026-05-22 18:07:18 +01:00
Bernardo Magri
8828f1fb3c refactor(system): move programs.uwsm to its own session.nix
The session-manager wiring (uwsm + the Hyprland Wayland-compositor
entry that gives Hyprland a proper graphical-session.target so user
services like nomarchy-wallpaper, walker, and elephant chain off it)
had lived in core/system/virtualization.nix by historical accident —
loaded unconditionally on every install, nothing to do with libvirt
or docker.

Lifted into a dedicated core/system/session.nix and imported from
core/system/default.nix between systemd.nix and virtualization.nix.
virtualization.nix now contains only the libvirt + docker branches
its filename implies.

`nix flake check --no-build` clean. No behaviour change.
2026-05-22 18:04:28 +01:00
Bernardo Magri
e7e89b8333 chore(theme): prune 9 dead templates, document the 2 that ship
themes/templates/ shipped 11 mustache templates, but
nomarchy-theme-set-templates only writes to a path when no file is
already there — and a careful trace shows 9 of the 11 outputs are
either preempted by an earlier write or never read at all:

  - kitty.conf.tpl, ghostty.conf.tpl
      → shadowed by the per-palette generators in
        themes/engine/files.nix added in 8d3ce2d.
  - hyprland.conf.tpl
      → shadowed by files.nix:100, which always writes
        ~/.config/nomarchy/current/theme/hyprland.conf from the
        palette/feature/nord fallback chain.
  - hyprlock.conf.tpl, alacritty.toml.tpl, btop.theme.tpl,
    chromium.theme.tpl, swayosd.css.tpl
      → output paths nothing reads. alacritty + swayosd are themed
        via Stylix / declarative HM options inline. btop reads from
        ~/.config/btop/themes/nomarchy.theme (loader.nix:72), not
        from the theme symlink. chromium is themed via the managed-
        policy module in core/system/browser.nix. hyprlock has no
        consumer of theme/hyprlock.conf anywhere in the tree.
  - hyprland-preview-share-picker.css.tpl
      → orphaned when the share-picker dir was deleted in 20de3d4.

obsidian.css.tpl and keyboard.rgb.tpl stay: the first is consumed by
nomarchy-theme-set-obsidian (copied into every Obsidian vault), the
second by nomarchy-theme-set-keyboard-asus-rog (sets the ROG
keyboard tint via asusctl).

Rewrote Step 6 of docs/creating-themes.md to describe the two live
templates by name and corrected a path bug ("~/.config/nomarchy/themed/"
→ "~/.config/nomarchy/themes/templates/" — the script actually reads
the latter).

`nix flake check --no-build` clean.
2026-05-22 17:59:15 +01:00
Bernardo Magri
c25fe2191a docs(roadmap): drop optional non-LUKS install row
Per user decision: not supporting a non-LUKS install path. Removed
the Now-column entry and the Pillar 4 bullet that tracked it. FDE
stays the only supported install shape.
2026-05-22 17:48:20 +01:00
Bernardo Magri
10f3b312a3 docs(roadmap): ship "What's installed?" summary
Moved the entry from the Now column → Shipped. Pillar 4's
"What's installed?" bullet flipped from (Now) to (Shipped).
2026-05-22 17:46:13 +01:00
Bernardo Magri
0f22c48c45 feat(welcome): show "What's installed?" summary on first boot
New nomarchy-installed-summary script renders a markdown table via
gum format with the install shape the user should verify before they
start customising:

  - theme / font / panel position    (~/.config/nomarchy/state.json)
  - timezone / DNS / hybrid GPU      (/etc/nixos/state.json)
  - form factor                      (BAT* sysfs presence)
  - software profiles                (presence of marker packages)
  - FDE                              (any crypt entry in lsblk)
  - drives                           (lsblk filtered to disk/part/crypt)

nomarchy-welcome calls it as Step 0 — before the theme/font/panel
pickers — and gates progression on a gum input prompt so the user has
to acknowledge before customisation rewrites anything. The script is
also callable standalone from any terminal: `nomarchy-installed-summary`.

Self-contained — no installer-side changes. Software profiles are
detected heuristically (the installer bakes the user's pick into the
generated home.nix as concrete home.packages rather than persisting a
profile list), which is good enough for verification but won't catch
manually-removed profile packages. gum is in the existing categoryDeps
so no new tools are needed; falls back to plain markdown when gum
isn't on PATH (recovery contexts).

Closes the "Installer: What's installed? summary on first boot"
Now-column item from Pillar 4.
2026-05-22 17:45:24 +01:00
Bernardo Magri
802acfdc86 docs(roadmap): close out Pillar 8 / Component 9 (ISOs) + retire QA Now item
Component 9 (ISOs) closeout entry covers the two inline cleanups
(unreachable else branches in nomarchy-build-{iso,live-iso}) and the
regression-class verification: every tool install.sh calls is provided
by either the explicit host packages, the upstream profiles/base.nix
chain (gptfdisk, util-linux, kbd, systemd), or the nrun nix-run
fallback.

With Components 1–10 all shipped, the "Full QA audit" Now-column item
has done its job. Replaced it with a runtime-verification punch-list
entry that consolidates the "needs runtime verification" notes carried
forward by each component's closeout — boot the live ISO and walk
through waybar/menu/option-toggle paths on real hardware.
2026-05-21 21:14:30 +01:00
Bernardo Magri
1ae27cd302 chore(iso): drop unreachable else branches in build helpers
nomarchy-build-iso and nomarchy-build-live-iso both ran under set -e
but then wrapped nix build in an if [ \$? -eq 0 ] block with an else
that printed "Error: ISO build failed." and exit 1. set -e aborts the
script the instant nix build returns non-zero, so the else branch was
never reached — the user saw nix build's own error output and the
script exited.

Removed the dead conditional. Behaviour is identical.
2026-05-21 21:13:41 +01:00
Bernardo Magri
67e5cd6014 docs(roadmap): close out Pillar 8 / Component 8 + log setup-config UX issue
Component 8 (Scripts runtime behavior) closeout entry summarises the
four inline fixes: omacom URL in nomarchy-menu "Learn → Nomarchy",
looknfeel.conf path drift, unreachable Overrides case branch, and
schema-vs-script default drift for the theme fallback in
nomarchy-theme-bg-next.

New Later row tracks an interaction-pattern bug in
show_setup_config_menu: five of nine entries edit files that Home
Manager generates from declarative options, so the next rebuild
clobbers the edit. Two more open paths the modules don't deploy.
Either rewire the menu or surface the ephemerality.
2026-05-21 21:07:34 +01:00
Bernardo Magri
af2d9ffd8e fix(theme): align nomarchy-theme-bg-next default with the schema
The script's jq fallback for .theme was hardcoded to "nord", which
drifted from the lib/state-schema.nix default of "summer-night". With
no state.json (or a blank one), nomarchy-theme-bg-next would look up
backgrounds under themes/palettes/nord/ while the rest of the system
treated summer-night as active — a quiet inconsistency that produced
"no backgrounds found" errors on a system that hadn't yet written a
theme to state.

Matched it to the schema default. lib/state-schema.nix remains the
single source of truth.
2026-05-21 21:07:00 +01:00
Bernardo Magri
b078be3209 fix(menu): route Nomarchy help locally, fix looknfeel path, drop dead branch
Three issues in features/scripts/utils/nomarchy-menu:

(1) "Learn → Nomarchy" called nomarchy-launch-webapp on
https://learn.omacom.io/2/the-nomarchy-manual — an upstream Omarchy
URL, the same one fixed in nomarchy-manual on 2026-05-18. Now calls
nomarchy-manual, which opens the local ~/.local/share/nomarchy/
README.md (or notifies if the source tree isn't synced).

(2) "Style → Hyprland" tried to open ~/.config/hypr/looknfeel.conf,
which is not the path looknfeel.conf is deployed to. The actual file
lives at ~/.config/nomarchy/default/hypr/looknfeel.conf (sourced by
nomarchy.conf via the chain). Updated the path.

(3) The setup-config case statement had an *Overrides* branch but no
matching menu option, so it was unreachable. The overrides loader
(nomarchy.overrides.*) is still in the Next column of the roadmap;
when it ships, both the option AND the case will get added together.
2026-05-21 20:46:21 +01:00
Bernardo Magri
3a269d73eb docs(roadmap): close out Pillar 8 / Component 7 + correct templates row
Component 7 (Theme engine + palettes) closeout entry summarises the
three inline fixes (theme-set early-exit on missing dir; bg-set
state.json persistence + path validation; palette dead-surface
cleanup) plus the script-comment correction.

Updated the existing `themes/templates/*.tpl` Later row: the original
claim "no script in the tree consumes them" was wrong —
nomarchy-theme-set-templates does. Replaced with a concrete
categorisation: (a) functionally dead (alacritty/btop/chromium/swayosd
write to paths nothing reads), (b) superseded by Nix-side generators
(kitty/ghostty after 8d3ce2d), (c) still relevant
(hyprland/hyprlock/obsidian/keyboard.rgb plus the now-orphan
share-picker tpl to verify).
2026-05-21 20:42:33 +01:00
Bernardo Magri
fb4755fdbf docs(theme): correct nomarchy-themes-prebuild header comment
The header said "Run once after install (the installer wires this
up)". The installer doesn't actually wire it up — install.sh:1848
prints a final-screen tip telling the user to run it, but doesn't
invoke it (pre-realising every theme adds significant install time
and the user can opt in later). Corrected the comment to match.
2026-05-21 20:41:43 +01:00
Bernardo Magri
9b06b6c243 chore(palettes): remove dead per-palette files
Two clusters of palette-tree dead surface:

(1) themes/palettes/{flexoki-light,lumon,retro-82,rose-pine}/apps/
chromium.theme — 9-byte comma-separated RGB strings that no script
or Nix module reads. Chromium theming is driven by managed policies
in core/system/browser.nix (BrowserThemeColor / BrowserColorScheme
derived from the active palette's base00 + light-mode flag), not by
per-palette files. The chromium.theme files were vestigial from an
earlier chromium-theming mechanism.

(2) themes/palettes/summer-day/apps/kitty/{kitty.conf,everforest-
light.conf} — a 76KB stray kitty config in a nested apps/kitty/
subdirectory. features/apps/kitty/config/kitty.conf includes
~/.config/nomarchy/current/theme/kitty.conf (root of theme dir, not
under apps/), and themes/engine/files.nix now generates that file
from the active palette's base16 colors (commit 8d3ce2d). So the
summer-day file was at the wrong path AND superseded by the
generator.

`nix flake check --no-build` passes.
2026-05-21 20:39:38 +01:00
Bernardo Magri
893fa91fbf fix(theme): exit on missing theme; persist bg picks across rebuilds
Two related bugs in the theme switcher scripts:

(1) nomarchy-theme-set printed a warning when the theme directory didn't
exist but kept going — it wrote the bad name into state.json and ran
nomarchy-env-update on a broken state. Added an exit 1 after the
warning.

(2) nomarchy-theme-bg-set updated the live ~/.config/nomarchy/current/
background symlink + restarted swaybg but never wrote state.json. The
script is called by the walker background-selector menu
(elephant/nomarchy_background_selector.lua) and by the nomarchy-
wallpaper CLI wrapper, so every wallpaper picked via either path
silently reverted to the active theme's default on the next
home-manager switch — themes/engine/files.nix re-resolves
config.nomarchy.wallpaper at every rebuild. Now writes the chosen path
into state.json's wallpaper field, mirroring nomarchy-theme-bg-next.
Also added a file-exists check so a bogus path fails loudly instead of
leaving a dangling symlink + a failed swaybg process.
2026-05-21 20:35:52 +01:00
Bernardo Magri
4de8afbea9 docs(roadmap): close out Pillar 8 / Component 6 + log VSCode marketplace gap
Component 6 (Apps) closeout entry covers the three inline theming
fixes (kitty/ghostty per-palette colors, btop color_theme name match,
VSCode theme extensions split). One new Later row tracks the 15
palettes — including the default summer-night (sainnhe.everforest) —
whose theme extensions aren't in nixpkgs and need
pkgs.vscode-utils.extensionFromVscodeMarketplace per-palette pinning.

Chromium's static Default/Preferences symlink was confirmed redundant
with the managed-policy intent in core/system/browser.nix, but left
under the existing Later entry (the user already hedged on deletion
without chromium-internals confirmation).
2026-05-21 20:32:38 +01:00
Bernardo Magri
577b3aeb91 fix(vscode): always install palette theme extensions
programs.vscode.profiles.default.userSettings.workbench.colorTheme is
set unconditionally to the active palette's theme name (read from
themes/palettes/<theme>/apps/vscode.json), but the matching theme
extensions were bundled with devExtensions — which defaults to false.
So out of the box, VSCode silently fell back to the built-in dark
theme on every palette.

Split themeExtensions out as always-installed and devExtensions as
opt-in via nomarchy.vscode.devExtensions. themeExtensions covers the 6
palettes whose VSCode theme is packaged in nixpkgs (catppuccin,
catppuccin-latte, nord, tokyo-night, rose-pine, gruvbox).

The other 15 palettes (including the default summer-night, which uses
sainnhe.everforest) still break because their theme extensions are on
the VSCode marketplace but not yet in nixpkgs — handling that needs
pkgs.vscode-utils.extensionFromVscodeMarketplace plus per-palette
publisher/name/version/sha256 metadata. Logged separately.
2026-05-21 20:31:50 +01:00
Bernardo Magri
b52aec28ce fix(btop): point color_theme at the deployed nomarchy.theme
themes/engine/loader.nix:72 deploys the active palette's btop theme to
~/.config/btop/themes/nomarchy.theme, but btop.conf had
color_theme = "current" — btop looked for themes/current.theme, didn't
find it, and silently fell back to the built-in Default theme. So every
palette rendered btop in the same default colors regardless of the
selected Nomarchy theme.

Renamed the config reference to match the deployed file name.

lazygit and tmux both inherit terminal ANSI colors (verified: the tmux
status bar config uses blue/brightblack/etc., not hex), so the kitty +
ghostty + alacritty theming changes from 8d3ce2d cover them
transitively — no module fix needed.
2026-05-21 20:27:12 +01:00
Bernardo Magri
8d3ce2d841 fix(theme): generate per-palette kitty.conf + ghostty.conf
features/apps/kitty/config/kitty.conf:1 contains
  include ~/.config/nomarchy/current/theme/kitty.conf
and features/apps/ghostty/config/config:2 contains
  config-file = ?"~/.config/nomarchy/current/theme/ghostty.conf"

Neither file existed for any of the 22 palettes. The kitty include
failed silently and the ghostty include is optional (?-prefix), so both
terminals rendered with built-in default colors regardless of the
active Nomarchy theme.

Stylix has kitty.enable = true in themes/engine/stylix.nix but the
kitty module uses xdg.configFile rather than programs.kitty, so the
Stylix target had nothing to hook into. ghostty has no Stylix target at
all.

Generated both files from the active palette's base16 colors in
themes/engine/files.nix, mirroring the waybar.css pattern already there.
Color mapping reproduces the original colors.toml fields (background,
foreground, cursor, selection_*, color0..15) via base16 indices —
verified against the inverse mapping in themes/palettes/default.nix.

themes/palettes/summer-day/apps/kitty/kitty.conf (a 76KB stray file in
the wrong tree location) is unaffected by this fix — it was already
dead surface since the include path never resolved to it.
2026-05-21 20:26:13 +01:00
Bernardo Magri
0486e037df docs(roadmap): close out Pillar 8 / Component 5 + log hyprsunset finding
Pillar 8 Component 5 (Desktop stack) closeout entry covers the five inline
fixes from this sweep (hyprland apps.conf wiring, NNOMARCHY typo pair,
broken waybar palette overrides, dead bindings files, mako post-fix verify)
plus the doc reconciles (SCRIPTS.md, KEYBINDINGS.md). One new Later row
captures the nightlight/hyprsunset toggle-vs-systemd inconsistency — Nix
always enables the systemd unit with a rebuild-time temperature while the
toggle script pkills/exec's hyprsunset directly and hardcodes 4000K
instead of reading nightlightTemperature.

Runtime verification (boot live ISO; eyeball waybar across panel
positions × form factors × all 22 palettes, walker launcher modes, the
screensaver at idle) remains on the user before declaring Component 5
fully closed.
2026-05-21 20:19:31 +01:00
Bernardo Magri
40b62124e6 fix(scripts): correct \$NNOMARCHY_TOGGLE_* typos breaking 2 toggles
nomarchy-menu:330 and nomarchy-launch-screensaver:16 referenced
\$NNOMARCHY_TOGGLE_SUSPEND and \$NNOMARCHY_TOGGLE_SCREENSAVER with a
double-N. The real env vars injected by features/scripts/default.nix:69-73
are single-N. Both reads always resolved to the empty string, so:

  - nomarchy.toggles.suspend = false; still showed "Suspend" in the
    system menu (the condition is "!= false", so empty != false → true).
  - nomarchy.toggles.screensaver = false; still launched the screensaver
    on hypridle's 150s timeout (the gate "== false" never hit on empty,
    so the early-exit was skipped).

Both toggles documented in docs/OPTIONS.md were vacuous in practice.
2026-05-21 20:13:34 +01:00
Bernardo Magri
72443fd69f fix(waybar): drop 4 broken per-palette style.css overrides
themes/{catppuccin,lumon,nord,retro-82}/style.css fully replaced the
default style.css (no @import) but defined only 2–14 lines — just
@define-color declarations and, for nord, a minimal window#waybar block.
The default style ships ~110 lines covering #workspaces, #tray, #cpu,
#custom-nomarchy's Nomarchy-font override, margins/padding, the indicator
.active states, etc. So picking any of those four palettes produced a
waybar with zero structural styling.

The default style at features/desktop/waybar/config/style.css already
@imports ../nomarchy/current/theme/waybar.css — which themes/engine/
files.nix:30-34 generates with @background/@foreground/@accent from the
active palette. So removing the broken overrides restores per-palette
colors via the default-style path. summer-day and summer-night are kept
because their 100+-line style.css files are intentional, self-contained
visual redesigns (the case the themes/engine/loader.nix:76-79 comment
explicitly carves out for "themes that need significantly different
styling").
2026-05-21 20:07:25 +01:00
Bernardo Magri
641ab0cfb0 chore(hyprland): drop two dead bindings files in default/hypr/
bindings.conf was explicitly labeled "Deprecated bindings file. New
installations include everything directly." and was sourced by nothing.
plain-bindings.conf referenced \$terminal/\$browser/\$fileManager/\$music/
\$messenger/\$passwordManager — Hyprland variables that aren't defined
anywhere in the loaded config tree — and was likewise sourced by nothing.
Both files have been superseded by features/desktop/hyprland/config/
bindings.conf (the user-overrideable, mkDefault-deployed one at
~/.config/hypr/bindings.conf) and the entries already inside
default/hypr/bindings/{utilities,media,clipboard,tiling-v2}.conf.

Regenerated docs/SCRIPTS.md; the diff drops the stale plain-bindings.conf
callers and incidentally corrects four scripts whose Origin column was
out of date after they moved from core/system/scripts/ to
features/scripts/utils/ (nomarchy-env-update, nomarchy-pkg-add,
nomarchy-pkg-remove, nomarchy-preflight-migration).
2026-05-21 20:03:09 +01:00
Bernardo Magri
0297ec268f fix(hyprland): source the 9 unwired window-rule files in apps.conf
9 of the 17 .conf files under core/home/config/nomarchy/default/hypr/apps/
were deployed but never sourced. apps/system.conf carried the load-bearing
"tag +floating-window" rule that the bluetui/impala/btop/satty/screensaver
classes rely on, plus the "fullscreen, class:org.nomarchy.screensaver" rule
hypridle's 150s on-timeout depends on. apps/pip.conf carried the picture-
in-picture pin/float/size rules. Neither set of rules fired today — the
screensaver came up tiled, PiP windows didn't pin, and the floating-window
helpers shipped degraded.

Sourcing all 17 unconditionally; every rule is class- or title-gated so
the conditional ones (steam, qemu, 1password, etc.) no-op cleanly when the
app isn't installed — same pattern as the already-sourced telegram /
retroarch / localsend entries.
2026-05-21 20:00:30 +01:00
Bernardo Magri
72f7e7b93d docs(roadmap): log Hyprland keymap + waybar-toggle inconsistencies
Two behavioral wrinkles found during the Pillar 8 desktop-stack sweep
that need a design decision before they can be fixed. Logged as Later
rows so the audit doesn't lose them.

1. The Hyprland Wayland keymap is hardcoded to `us` in
   `core/home/config/nomarchy/default/hypr/input.conf:3`, ignoring the
   installer-chosen layout for native Wayland apps. Fix needs either a
   templated input.conf driven by a new home option, or session-level
   `XKB_DEFAULT_LAYOUT` propagation. Either path touches the installer
   heredoc and the home modules, so not a same-PR fix.

2. `nomarchy.toggles.waybar` is exported only as an env var consumed
   by the runtime toggle script. The Nix module always sets
   `programs.waybar.enable = lib.mkDefault true`, so the toggle is
   session-only — waybar comes back on every rebuild/reboot.
   Inconsistent with `toggles.idle` which correctly gates
   `services.hypridle.enable`. Needs a behavioral call (persistent
   gate vs intentional runtime-only with a clearer name).
2026-05-19 20:24:27 +01:00
Bernardo Magri
20de3d4f97 chore(hyprland): delete orphan config files + share-picker dir
Six unreferenced files surfaced under features/desktop/hyprland/config/
during the Pillar 8 sweep:

- `looknfeel.conf` and `autostart.conf` were deployed to ~/.config/hypr/
  but never sourced by nomarchy.conf. The substantive versions live in
  core/home/config/nomarchy/default/hypr/ and are sourced from there.
  Removed the deployment lines in features/desktop/hyprland/default.nix
  alongside the file deletes.
- `hyprlock.conf`, `hyprsunset.conf`, `xdph.conf` weren't deployed at
  all and weren't referenced anywhere. Pure leftovers.

The entire `features/desktop/hyprland-preview-share-picker/` directory
was also orphan: no `default.nix`, no Nix module imports the
`config.yaml`. Only mention was inside the (now-deleted) `xdph.conf`.
Deleted the directory.

No behavioral change — these files weren't being used. Just removes
dead surface that confuses contributors looking for the "real" config
location.
2026-05-19 20:24:16 +01:00
Bernardo Magri
2a301a049f fix(mako): deploy themed config to ~/.config/mako/config
`core/home/config/nomarchy/default/mako/core.ini` defines the Nomarchy
notification UX — urgency rules, app filters (Spotify silenced),
do-not-disturb mode, and button handlers for "Setup Wi-Fi" / "Update
System" / "Learn Keybindings" notifications. The file was deployed via
the bulk `nomarchy/` dir to
`~/.config/nomarchy/default/mako/core.ini`, but mako reads
`~/.config/mako/config` by default and `autostart.conf` launches it
without `--config`. So mako ran with stock defaults and the entire
themed UX was inert.

Added an explicit `xdg.configFile."mako/config".source` line in
core/home/configs.nix pointing at the existing themed file. mako now
picks up the Nomarchy rules out of the box.

Found during Pillar 8 audit of the desktop stack.
2026-05-19 20:24:06 +01:00
bd7e5a5706 Merge pull request 'wave/qa-core-system' (#3) from wave/qa-core-system into main
Reviewed-on: #3
2026-05-19 19:17:22 +01:00
668 changed files with 8481 additions and 22213 deletions

View File

@@ -1,102 +0,0 @@
# Nomarchy CI — eval + lint.
#
# Catches the regressions that hurt today:
# 1. Flake stops evaluating (broken option ref, missing import, etc.).
# 2. A `nomarchy-*` shell script has a syntax error or a shellcheck
# error-severity issue.
# 3. `docs/SCRIPTS.md` drifts from the repo state because somebody
# added / removed / renamed a script and didn't run the generator
# (the pre-commit hook handles this, but only when enabled per-clone).
#
# Doesn't build ISOs — that needs a binary cache. Add a separate job
# once Cachix/Attic is in place.
name: Check
on:
push:
branches: [main]
pull_request:
jobs:
eval-and-lint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main
with:
# Match the runner's effective channel. Nomarchy itself tracks
# nixos-25.11 via flake.nix; the installer-action default is fine.
extra-conf: |
experimental-features = nix-command flakes
- name: nix flake check --no-build
run: nix flake check --no-build
- name: Lint nomarchy-* scripts (bash -n + shellcheck)
run: |
# Mirror what .githooks/pre-commit runs locally, but across the
# whole tree instead of just changed files. Pre-commit gates
# individual commits; CI gates branches (including --no-verify
# bypasses).
set -e
fail=0
while IFS= read -r script; do
[[ -f "$script" ]] || continue
# Python helpers ship under the same nomarchy- prefix
# (e.g. nomarchy-haptic-touchpad). Skip non-bash.
head -1 "$script" | grep -qE '^#!.*\bbash\b' || continue
if ! bash -n "$script"; then
echo "::error file=$script::bash syntax error"
fail=1
fi
if ! nix shell nixpkgs#shellcheck --command shellcheck \
--severity=error --shell=bash "$script"; then
echo "::error file=$script::shellcheck error-severity issue"
fail=1
fi
done < <(find features/scripts/utils core/system/scripts \
themes/engine/scripts \
-maxdepth 1 -type f -name 'nomarchy-*')
exit "$fail"
- name: docs/SCRIPTS.md is up to date
run: |
# Regenerate to a temp file and compare. If different, the
# contributor forgot to run the generator (or skipped the
# pre-commit hook). Fail loudly and tell them the fix.
./bin/utils/nomarchy-docs-scripts --out /tmp/SCRIPTS.regen.md
if ! diff -q docs/SCRIPTS.md /tmp/SCRIPTS.regen.md >/dev/null; then
echo "::error::docs/SCRIPTS.md is stale."
echo "Run: ./bin/utils/nomarchy-docs-scripts --out docs/SCRIPTS.md"
echo "Then commit the regenerated file."
echo "--- diff ---"
diff -u docs/SCRIPTS.md /tmp/SCRIPTS.regen.md || true
exit 1
fi
- name: installer/hardware-db.sh references real nixos-hardware modules
run: |
# Every 4th-pipe-field in HARDWARE_DB is a nixos-hardware module
# name. Half the DB used to point at modules that don't exist
# (e.g. microsoft-surface-pro-8 — there's only -pro-intel and
# -pro-9), which made the install fail at eval time with
# cryptic "attribute not found" errors on real laptops. This
# step catches that regression class.
awk -F'|' '/^ "/ { gsub(/"/,"",$4); gsub(/^[[:space:]]+|[[:space:]]+$/,"",$4); if ($4) print $4 }' \
installer/hardware-db.sh | sort -u > /tmp/db-refs.txt
nix eval --impure --json --expr '
let
nh = (builtins.getFlake (toString ./.)).inputs.nixos-hardware.nixosModules;
in builtins.attrNames nh' \
| nix shell nixpkgs#jq --command jq -r '.[]' | sort -u > /tmp/db-real.txt
missing=$(comm -23 /tmp/db-refs.txt /tmp/db-real.txt)
if [[ -n "$missing" ]]; then
echo "::error::hardware-db.sh references nixos-hardware modules that don't exist:"
printf ' - %s\n' $missing
echo "Either fix the name (check the actual attr in nixos-hardware) or drop the row."
exit 1
fi

View File

@@ -1,54 +0,0 @@
#!/usr/bin/env bash
# Nomarchy pre-commit hook.
#
# Enable per-clone with:
# git config core.hooksPath .githooks
#
# Two responsibilities:
# 1. Lint changed nomarchy-* scripts (bash -n + shellcheck if available)
# so syntax errors and unquoted-var bugs don't ship.
# 2. Regenerate docs/SCRIPTS.md when any nomarchy-* script under the three
# script directories is added, modified, or deleted in this commit, and
# stage the refreshed file so it lands with the change.
set -e
repo_root="$(git rev-parse --show-toplevel)"
cd "$repo_root"
script_dirs_re='^(features/scripts/utils|core/system/scripts|themes/engine/scripts)/nomarchy-'
# 1. Lint changed scripts. bash -n catches syntax errors (always fatal).
# shellcheck catches unquoted-var, use-before-define, missing-shebang, etc.
# We only fail on severity=error so the long tail of pre-existing warnings
# (info / style / warning) doesn't block commits — those can be cleaned up
# incrementally without a flag day.
changed_scripts=$(git diff --cached --name-only --diff-filter=ACMR \
| grep -E "$script_dirs_re" || true)
if [[ -n "$changed_scripts" ]]; then
while IFS= read -r script; do
[[ -f "$script" ]] || continue
# Only lint scripts with a bash shebang. nomarchy-* is a name
# convention, not a language guarantee — at least one Python helper
# ships under the same prefix (nomarchy-haptic-touchpad).
head -1 "$script" | grep -qE '^#!.*\bbash\b' || continue
if ! bash -n "$script"; then
echo "pre-commit: bash syntax error in $script — aborting commit." >&2
exit 1
fi
if command -v shellcheck >/dev/null 2>&1; then
if ! shellcheck --severity=error --shell=bash "$script"; then
echo "pre-commit: shellcheck found error-level issues in $script — aborting commit." >&2
echo "pre-commit: fix the reported issues, or rerun with --no-verify after a deliberate decision to ship." >&2
exit 1
fi
fi
done <<< "$changed_scripts"
fi
# 2. Regenerate the script audit doc.
if git diff --cached --name-only --diff-filter=ACMRD | grep -qE "$script_dirs_re"; then
echo "pre-commit: regenerating docs/SCRIPTS.md (script change detected)…"
./bin/utils/nomarchy-docs-scripts --out docs/SCRIPTS.md
git add docs/SCRIPTS.md
fi

20
.gitignore vendored
View File

@@ -1,15 +1,13 @@
# ---> Nix
# Ignore build outputs from performing a nix-build or `nix build` command
# Study material from the previous iteration — not part of the flake.
# Delete the directory once everything worth porting has been ported.
old_distro/
# Nix build artifacts
result
result-*
# Ignore automatically generated direnv output
.direnv
__pycache__/
.DS_Store
# Local IDE settings
.claude/
# VM and ISO artifacts
*.qcow2
*.qcow
*.iso
# Claude Code machine-local settings (permissions etc.)
.claude/settings.local.json

430
README.md
View File

@@ -1,118 +1,362 @@
# 👑 Nomarchy
# Nomarchy
**Nomarchy** is a professional-grade NixOS distribution that ships a highly curated Hyprland desktop on a strictly declarative, flake-based foundation. It provides a highly polished, "it just works" experience for power users who want a beautiful Wayland environment without sacrificing the reliability of NixOS.
**The rock-solid reproducibility of NixOS 26.05. The out-of-the-box polish of
Omarchy/Omakub.** One JSON file rules the look of the entire desktop; every
theme change is a Home Manager generation — atomic, rollbackable, never
partial.
## ✨ Key Features
- **Purely Declarative:** Your entire desktop—themes, fonts, wallpapers, and toolchains—is defined in code.
- **Modular Merging Architecture:** Distro code and user code are strictly separated. You can update the distro core without ever touching or breaking your personal configurations.
- **Interactive "Smart" Installer:** Detects hardware, sets up networking, localizes timezones/keymaps, and offers multi-select software profiles.
- **Erase Your Darlings (Optional):** Optional BTRFS root-wipe on boot ensures your system stays pristine and 100% declarative.
- **Dynamic Theming Engine:** 20+ built-in themes with instant UI feedback via IPC (swww, waybar, and stylix).
- **Portable State (`nomarchy-sync`):** Easily backup and sync your declarative config and dynamic state (theme/wallpaper choices) to a private Git repo.
---
## 📂 Component-Based Architecture
Nomarchy uses a **Feature-Centric Directory Structure**. For a comprehensive breakdown of the system architecture, folder roles, and module logic, see the [Detailed Architecture Documentation](docs/STRUCTURE.md).
Configuration, modules, and utilities are strictly organized to maintain sanity as the system grows.
- **`core/`**: Foundational OS & User defaults (Bootloader, Audio, Bluetooth, core system features).
- **`features/`**: Isolated modules containing Nix logic and raw dotfiles.
- **`features/apps/`**: App-specific configs (e.g., `features/apps/btop/`, `features/apps/kitty/`), each containing their own `default.nix` and standalone `config/` directory mapped via Home Manager.
- **`features/desktop/`**: Desktop environment components (e.g., Hyprland, Waybar).
- **`features/scripts/utils/`**: Consolidated repository for all custom Nomarchy bash scripts, centrally packaged and injected into the user's `PATH` with correct dependencies.
- **`themes/`**: The global theming engine. It holds pure color data and logic. *Theme-specific app layouts* (like a custom Waybar layout) are stored directly inside the app's feature folder, solving the matrix problem of theming.
---
## 📥 Installation
### 1. Try it in a VM (Recommended)
Verify the experience without touching your hardware:
```bash
./bin/utils/nomarchy-test-installer
```
This builds a full graphical VM of the installer environment. Once inside, click the **Install Nomarchy** icon or run `nomarchy-install`.
### 2. Build the Installer ISO
To install on physical hardware, generate your own bootable image:
```bash
./features/scripts/utils/nomarchy-build-iso # Minimal TTY installer
./features/scripts/utils/nomarchy-build-live-iso # Graphical try-before-install
┌──────────────────────────────────────────────────────────────────────────┐
│ theme-state.json (single source of truth) │
│ lives INSIDE your flake checkout, git-tracked │
└───────────────────────────────────┬──────────────────────────────────────┘
nomarchy-theme-sync apply gruvbox
1. merges the preset into the JSON (atomic write)
2. runs `home-manager switch` (no sudo, no system rebuild)
▼ pure read (nomarchy.stateFile)
┌──────────────────────────────────────────────────────────────────────────┐
│ Home Manager bakes EVERYTHING into one read-only generation: │
│ Hyprland (colors/gaps/borders) Waybar (palette or whole-swap) │
│ Ghostty (full ANSI palette) btop (asset or generated) │
│ Stylix → GTK, Qt, cursors, fonts │
└───────────────────────────────────┬──────────────────────────────────────┘
wallpaper via awww (the one runtime piece:
applied post-switch + at session start, `bg next` cycles)
```
The ISO will be located at `./result/iso/nixos-*.iso`. Flash it to a USB drive and boot.
### 3. Run the Installer
Once booted into the Live environment, launch the installer:
```bash
nomarchy-install
## 1. Layout
Flat on purpose. Two module trees, one options file each, no hidden layers.
```
.
├── flake.nix # inputs + the downstream API (exports below)
├── lib.nix # nomarchy.lib.mkFlake — one-call downstream wrapper
├── theme-state.json # ★ THE single source of truth (git-tracked!)
├── themes/ # 21 presets: <slug>.json + optional <slug>/ assets
│ ├── nord.json # palette (required, works alone)
│ └── nord/ # assets (optional, fixed filenames)
│ ├── backgrounds/ # wallpapers (auto-picked, SUPER+SHIFT+T cycles)
│ ├── btop.theme # hand-made config drop (else generated)
│ └── waybar.css # whole-swap: replaces the generated bar style
├── modules/
│ ├── nixos/ # the distro, system side
│ │ ├── default.nix # Hyprland session, Pipewire, greetd, fonts
│ │ ├── options.nix # nomarchy.system.* toggles
│ │ ├── plymouth.nix # boot splash, tinted from the JSON
│ │ ├── file-manager.nix # Thunar GUI + gvfs/tumbler/udisks2
│ │ └── power.nix # power-profiles-daemon/TLP, thermald, charge limit
│ └── home/ # the distro, user side
│ ├── default.nix # entry point
│ ├── options.nix # nomarchy.* option surface
│ ├── theme.nix # JSON ingestion + wallpaper hook
│ ├── stylix.nix # GTK/Qt/cursors/fonts from the same JSON
│ ├── hyprland.nix # all JSON-driven
│ ├── waybar.nix
│ ├── ghostty.nix
│ ├── btop.nix
│ ├── rofi.nix # launcher + nomarchy-menu (calc, emoji, clip…)
│ ├── keybinds.nix # single source: Hyprland binds + SUPER+? sheet
│ ├── swaync.nix # notifications, same JSON
│ ├── idle.nix # hyprlock + hypridle, same JSON
│ ├── yazi.nix # flagship TUI file manager + plugins
│ ├── osd.nix # swayosd volume/brightness OSD
│ ├── shell.nix # zsh + starship + bat/eza/zoxide
│ ├── keys.nix # gpg-agent fronting SSH, pinentry-qt
│ └── fastfetch.nix # themed Nomarchy logo + system info
├── hosts/
│ ├── default/ # reference machine (thin: boot, user, hostname)
│ └── live.nix # bootable live ISO (try the distro, no install)
├── pkgs/
│ ├── nomarchy-theme-sync/ # state writer + rebuild dispatcher (Python)
│ └── nomarchy-install/ # live-ISO installer (gum + disko + mkFlake)
├── templates/downstream/ # `nix flake init -t` starter for users
├── docs/TESTING.md # how to verify changes (incl. AI-agent rules)
├── docs/OVERRIDES.md # how downstream users override defaults
├── docs/ROADMAP.md # forward-looking plans + shipped-fixes log
└── tools/ # maintainer-only
├── import-palettes.py # converts old-distro themes → JSON + assets
├── test-live-iso.sh # build the ISO + boot it in QEMU
├── test-install.sh # full offline-install regression in QEMU
└── vm/ # headless-VM helpers (QMP keys, VNC shots,
# offline-pin gap analysis)
```
The wizard will guide you through:
- **Networking:** An interactive wizard to connect to Wi-Fi if needed.
- **Hardware:** Optimized profiles for Dell XPS, Framework, Apple T2, and more.
- **Storage:** Choice between Standard Ext4 or Encrypted BTRFS with optional **Impermanence**.
- **Localization:** Searchable timezones and keyboard layout selection.
### Already on NixOS?
Layer Nomarchy onto an existing 25.11 install without reformatting — see the [Migration Guide](docs/MIGRATION.md).
**Rule of thumb:** `modules/` is the distro (reusable, no machine specifics),
`hosts/` is a machine, `themes/` is data, `pkgs/` is code, `tools/` is
maintainer-only. If a new file doesn't obviously belong to one of those, it
probably shouldn't exist.
---
## 2. Try it first (live ISO)
## 🛠️ Configuration & Usage
Boot the full desktop from a USB stick or VM without installing anything:
Nomarchy uses a "Downstream" model. After installation, your configuration lives in `/etc/nixos/` and is split into three main parts:
```sh
nix build .#nixosConfigurations.nomarchy-live.config.system.build.isoImage
# → result/iso/*.iso — dd to a stick, or boot it in QEMU:
tools/test-live-iso.sh
```
### 1. Distro Core (Upstream)
Managed via the public Git repository. This is the engine. You should generally not modify files here.
The live session auto-logs-in, seeds the flake at `~/.nomarchy`, and pins
the locked inputs into the ISO store — so theme switching (including the
`home-manager switch` it triggers) works **offline**, exactly like on an
installed system. Verification checklist: [docs/TESTING.md](docs/TESTING.md).
Like what you see? **`nomarchy-install`** (in a terminal) walks you through
installing to disk: pick a disk, LUKS2 full-disk encryption **by default**
(in exchange the desktop logs in passwordless — the passphrase already
gates the machine), user + hostname + timezone, hardware autodetection
(DMI → nixos-hardware profile), a hibernation-ready swapfile sized to RAM,
then disko partitions (GPT + ESP + BTRFS subvolumes incl. `@snapshots`
snapper timeline snapshots are on) and `nixos-install` runs — **without a
network** when the ISO was built from a clean tree (the target's
`flake.lock` is composed from the rev the ISO carries). The installed
machine gets the standard downstream layout: the flake at `~/.nomarchy`
(`/etc/nixos` symlinks to it), one `mkFlake` call, your
`system.nix`/`home.nix`. First boot lands in the fully themed desktop —
the installer pre-activates the Home Manager generation. UEFI only for now.
## 3. Using Nomarchy on your machine (downstream)
Nomarchy is consumed as a flake input — you never fork or edit this repo:
```sh
mkdir my-machine && cd my-machine
nix flake init -t "git+https://git.bemagri.xyz/bernardo/nomarchy.git?ref=v1"
```
You own two files day-to-day: `system.nix` and `home.nix` (plus
`theme-state.json`, written by the CLI). Your `flake.nix` is set up once —
later by the installer — and never hand-edited; it's a single call:
### 2. Your System (`system.nix`)
Add system-wide packages, services, and hardware tweaks here.
*Example: Adding a persistent directory for Docker if using Impermanence:*
```nix
environment.persistence."/persist" = {
directories = [ "/var/lib/docker" ];
};
outputs = { nomarchy, ... }:
nomarchy.lib.mkFlake {
src = ./.;
username = "me";
hardwareProfile = "framework-13-7040-amd"; # optional, nixos-hardware name
};
```
### 3. Your User Environment (`home.nix`)
Add user-level packages, aliases, and dotfiles here.
*Example: Overriding the default terminal:*
```nix
nomarchy.home.terminal = "kitty";
| `mkFlake` arg | Default | Purpose |
|---|---|---|
| `src` | — (required) | Your flake directory (`./.`) |
| `username` | — (required) | Login name; flows into `system.nix` and names the HM config |
| `hardwareProfile` | `null` | One [nixos-hardware](https://github.com/NixOS/nixos-hardware) module name, or a list of them (pinned + tested by Nomarchy; unknown names fail with suggestions) |
| `system` | `"x86_64-linux"` | Platform |
(Power users can skip `mkFlake` and wire `nixosModules.nomarchy` /
`homeModules.nomarchy` / `overlays.default` by hand — the wrapper is sugar.)
Two deliberately separate rebuild paths:
```sh
sudo nixos-rebuild switch --flake .#default # system: rare
home-manager switch --flake .#me # desktop: every theme change, no sudo
```
For the full list of `nomarchy.*` options you can set in `system.nix` and `home.nix`, see the [Options Reference](docs/OPTIONS.md). Hit a rebuild error? Check [Troubleshooting](docs/TROUBLESHOOTING.md). For where the project is heading next, see the [Roadmap](docs/ROADMAP.md).
Day-to-day you'll use the shipped shortcuts instead:
### Applying Changes
After editing your files, apply them instantly. **IMPORTANT:** Nomarchy requires the `--impure` flag for evaluation. You **MUST** use the following aliases rather than standard NixOS commands:
```bash
sys-update # Rebuilds the NixOS system (Runs: sudo nixos-rebuild switch --flake .#default --impure)
env-update # Reloads your Home Manager environment (Runs: home-manager switch --flake .#default --impure)
```sh
sys-update # nix flake update + system rebuild (BTRFS snapshot first when available)
home-update # home-manager switch (no flake update, no sudo)
```
---
**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.
## 🚀 Commands & Keybindings
Override anything via the `nomarchy.*` surface or plain NixOS/HM options:
appearance (gaps/colors/fonts) changes through `nomarchy-theme-sync`,
behaviour (input/misc/monitor/chrome) is `mkDefault` so a plain `home.nix`
assignment wins, and bind/exec-once lists concatenate. Full guide with
examples: **[docs/OVERRIDES.md](docs/OVERRIDES.md)**.
The full list lives in [`docs/KEYBINDINGS.md`](docs/KEYBINDINGS.md) (auto-generated from the Hyprland configs). A few highlights:
| Option | Default | Purpose |
|---|---|---|
| `nomarchy.stateFile` | — (required) | Path to your theme-state.json |
| `nomarchy.terminal` | `"ghostty"` | Terminal for keybinds and `$TERMINAL` |
| `nomarchy.keyboard.layout` | `"us"` | XKB layout for the Hyprland session (installer writes the matching `services.xserver.xkb` in system.nix; the console + LUKS prompt follow via the distro default) |
| `nomarchy.keyboard.variant` | `""` | XKB variant for the session |
| `nomarchy.keyboard.devices` | `{}` | Per-device layout overrides (Hyprland `device` blocks keyed by `hyprctl devices` name) — e.g. an external keyboard with its own layout/variant |
| `nomarchy.keyboard.layouts` | `[]` | Extra candidate layouts; when set, a watcher prompts (rofi) for a layout on a newly-connected keyboard and remembers it per-device |
| `nomarchy.nightlight.enable` | `false` | Scheduled blue-light filter (hyprsunset) — warm at night (`.temperature`, default 4000K) between `.sunset`/`.sunrise`, no shift by day |
| `nomarchy.hyprland.enable` | `true` | Nomarchy's Hyprland config |
| `nomarchy.waybar.enable` | `true` | Nomarchy's Waybar |
| `nomarchy.rofi.enable` | `true` | Themed rofi launcher + `nomarchy-menu` dispatcher |
| `nomarchy.swaync.enable` | `true` | swaync notifications, themed |
| `nomarchy.idle.enable` | `true` | hyprlock + hypridle (idle lock 5 min, display off 10, suspend 30) |
| `nomarchy.yazi.enable` | `true` | yazi TUI file manager, themed + curated plugins |
| `nomarchy.osd.enable` | `true` | swayosd on-screen display for volume/brightness/mute |
| `nomarchy.shell.enable` | `true` | zsh + starship prompt + bat/eza/zoxide (zsh is the default login shell) |
| `nomarchy.ghostty.enable` | `true` | Nomarchy's Ghostty |
| `nomarchy.btop.enable` | `true` | btop with per-theme colors |
| `nomarchy.stylix.enable` | `true` | GTK/Qt/cursor theming |
| `nomarchy.fastfetch.enable` | `true` | fastfetch fronted by the themed Nomarchy logo |
| `nomarchy.keys.enable` | `true` | gpg-agent fronting SSH + pinentry-qt |
| `nomarchy.displays.enable` | `true` | nwg-displays interactive monitor arranger (helper for `nomarchy.monitors`) |
| `nomarchy.monitors` | `[]` | Declarative per-output layout → Hyprland `monitor` rules (applied on hotplug); `,preferred,auto,1` wildcard kept as fallback |
| `nomarchy.themesDir` | Nomarchy's `themes/` | Where per-theme app overrides are probed |
| `nomarchy.system.plymouth.enable` | `true` | Branded boot splash, background from the theme JSON (recolors on system rebuilds) |
| `nomarchy.system.fileManager.enable` | `true` | Thunar GUI + gvfs/tumbler/udisks2 (the "open folder" handler) |
| `nomarchy.system.greeter.enable` | `true` | greetd/tuigreet |
| `nomarchy.system.greeter.autoLogin` | `null` | Auto-login this user into Hyprland (installer sets it on LUKS machines) |
| `nomarchy.system.audio.enable` | `true` | Pipewire stack |
| `nomarchy.system.bluetooth.enable` | `true` | Bluetooth + blueman |
| `nomarchy.system.snapper.enable` | `false` | Hourly/daily BTRFS timeline snapshots + `nixos-rebuild-snap` (installer enables it; no-op unless root is BTRFS) |
| `nomarchy.system.power.enable` | `true` | Active power management (see below) |
| `nomarchy.system.power.backend` | `"ppd"` | `"ppd"` (power-profiles-daemon + menu/Waybar switcher) or `"tlp"` (deeper battery tuning, no switcher) — mutually exclusive |
| `nomarchy.system.power.laptop` | `false` | Marks a laptop, gating battery-only features; the installer sets it when a battery is present |
| `nomarchy.system.power.thermal.enable` | `false` | thermald (Intel-only); the installer enables it on a GenuineIntel CPU |
| `nomarchy.system.power.batteryChargeLimit` | `null` | Stop charging at this % (e.g. `80`) where the hardware supports it; needs `power.laptop` |
| `nomarchy.services.tailscale.enable` | `false` | Opt-in: Tailscale mesh VPN (then `sudo tailscale up`) |
| `nomarchy.services.syncthing.enable` | `false` | Opt-in: Syncthing file sync as the login user (GUI at `127.0.0.1:8384`) |
| `nomarchy.services.podman.enable` | `false` | Opt-in: rootless Podman (`docker` aliased to it) |
| `nomarchy.services.flatpak.enable` | `false` | Opt-in: Flatpak + the Flathub remote |
| `nomarchy.services.pika.enable` | `false` | Opt-in: Pika Backup (GUI Borg backups) |
| `nomarchy.services.steam.enable` | `false` | Opt-in: Steam via `programs.steam` (32-bit libs, controller udev, Remote-Play ports) |
| `nomarchy.services.libvirt.enable` | `false` | Opt-in: libvirt/KVM + virt-manager GUI (login user added to `libvirtd`) |
| `nomarchy.services.obs.enable` | `false` | Opt-in: OBS Studio + a v4l2loopback virtual camera (selectable as a webcam in Zoom/Teams) |
| `nomarchy.services.docker.enable` | `false` | Opt-in: rootful Docker (user in `docker` group); don't enable alongside podman |
| `nomarchy.services.kdeconnect.enable` | `false` | Opt-in: KDE Connect phone integration (opens its firewall ports) |
| `nomarchy.services.gamemode.enable` | `false` | Opt-in: Feral GameMode performance daemon (`gamemoderun`) |
| `nomarchy.services.adb.enable` | `false` | Opt-in: Android adb/fastboot tools (systemd handles device udev rules) |
| `nomarchy.services.wireshark.enable` | `false` | Opt-in: Wireshark Qt GUI (user in `wireshark` group, capture without root) |
| `nomarchy.services.ollama.enable` | `false` | Opt-in: Ollama local LLM runtime on `127.0.0.1:11434` (CPU; GPU via `services.ollama.acceleration`) |
| `nomarchy.services.printing.enable` | `false` | Opt-in: CUPS + Avahi/mDNS network printer discovery |
| `nomarchy.services.openrgb.enable` | `false` | Opt-in: OpenRGB daemon for RGB peripheral/motherboard lighting |
| `nomarchy.services.restic.enable` | `false` | Opt-in: scheduled daily restic backup (set `.repository` + `.passwordFile`; 7/4/6 retention; list/restore via the `restic-nomarchy` wrapper) |
| Keybinding | Action |
| :--- | :--- |
| `Super + Space` | **App Launcher** (Walker) |
| `Super + Shift + Space` | **Nomarchy Menu** (Walker) |
| `Super + Alt + Space` | **Toggle Top Bar** (Waybar) |
| `Super + Return` | Open Terminal |
| `Super + Q` | Close Window |
Beyond the `nomarchy.*` surface, the system layer turns on the usual
desktop services with `lib.mkDefault` (override natively). One worth
calling out: **`services.fwupd.enable`** is on by default for firmware
updates via LVFS — it only refreshes metadata, never flashes on its own,
so run `fwupdmgr update` to apply. Disable with `services.fwupd.enable =
false;` on machines without real firmware (VMs/headless).
### Utility Scripts
Nomarchy includes dozens of productivity scripts available in your PATH. Some highlights:
- `nomarchy-sync push <repo>`: Backup your setup to Git.
- `nomarchy-theme-bg-next`: Cycle to the next wallpaper in the current theme.
- `nomarchy-menu`: The central hub for all utilities and pickers.
## 4. How theming works
---
*Built with ❤️ using NixOS, Hyprland, Stylix, and the Nomarchy Community.*
### Pure JSON ingestion
The trap with "read a mutable file from Nix" is pure evaluation: flakes
cannot read arbitrary `$HOME` paths without `--impure` (the old prototype
required it — never again). Nomarchy's convention: **the state file lives
inside the consuming flake** and is wired via
`nomarchy.stateFile = ./theme-state.json;`. Reading it is pure — it's flake
source. It must be git-tracked (`nomarchy-theme-sync` runs
`git add --intent-to-add` after every write as a safety net).
### One change = one generation
`nomarchy-theme-sync apply <theme>` merges the preset into the JSON and runs
`home-manager switch` (override the command with `$NOMARCHY_REBUILD`, or pass
`--no-switch` to only write). Everything is baked: Hyprland, Waybar, Ghostty,
btop, and — via Stylix, mapped onto base16 roles — GTK, Qt, cursors and
fonts. No runtime patching means no partial states, and `home-manager
generations` is also your theme history. Waybar even restyles in place: it
re-reads `style.css` when the symlink flips.
The **wallpaper** is the one runtime piece (awww — nixpkgs' swww — is
imperative; nothing in Nix consumes the path): applied at session start and
after every switch via a tiny activation hook, cycled instantly with
`bg next`.
### Per-theme app assets (`themes/<slug>/`)
Recoloring covers 95% of theming; the rest is one optional assets directory
per theme — a single place to look, unlike the old distro's split:
| Asset | Mechanism |
|---|---|
| `backgrounds/` | wallpapers; empty `wallpaper` in the state means "first one"; `bg next` cycles |
| `btop.theme` | baked into the generation (generated from the palette when absent) |
| `waybar.css` | **whole-swap**: replaces the generated bar style entirely (probed at eval time, self-contained) |
| `waybar.jsonc` | whole-swap for the bar *layout* (must be plain JSON) |
| `rofi.rasi` | **whole-swap**: replaces the generated launcher/menu theme entirely |
Six ported themes ship a `waybar.css` identity (catppuccin, lumon, nord,
retro-82, summer-day, summer-night). Custom user themes can live in
`$NOMARCHY_PATH/themes/` (preset lookup) and `nomarchy.themesDir` (eval-time
asset probe).
## 5. Day-to-day
```sh
nomarchy-theme-sync list # 21 presets (nord, gruvbox, rose-pine, …)
nomarchy-theme-sync apply kanagawa # whole desktop, one generation (~a switch)
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)
home-update # rebuild just the desktop layer
```
Keybinds: `SUPER+Return` terminal · `SUPER+D` launcher · `SUPER+T` theme
picker · `SUPER+SHIFT+T` next wallpaper · `SUPER+X` power menu ·
`SUPER+E` file manager (yazi) · `SUPER+N` notifications · `SUPER+CTRL+V`
clipboard history · `SUPER+Q`
close · `SUPER+1..9` workspaces · `Print` region screenshot.
Shell aliases (zsh, gated on `nomarchy.shell.enable`) — `alias` lists them
all; the curated set:
```sh
# navigation
.. ... .... # cd up 1 / 2 / 3 levels
# git
g gst # git · git status -sb
ga gaa # git add · git add -A
gc gcm # git commit · git commit -m
gco gsw gb # checkout · switch · branch
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)
ns nr # nix shell · nix run (e.g. ns nixpkgs#ripgrep)
nfu nfc # nix flake update · check
nsearch ngc # nix search nixpkgs · nix-collect-garbage -d
# misc
path # print $PATH, one entry per line
reload # exec zsh (reload the shell)
```
## 6. Extending
- **New theme:** drop a JSON into `themes/` (schema = any existing preset),
plus an optional `themes/<slug>/` assets directory.
- **New themed value:** add the key to `theme-state.json` and consume it in
the Nix modules. One place — there is no second renderer to keep in sync.
- **Importing more old-distro palettes:**
`tools/import-palettes.py <palettes-dir> themes/`.
- **New opt-in feature (convention):** when a feature is off by default and
needs the user to set `nomarchy.*` options (e.g. night light, per-device
keyboard layouts, monitor layout, power management), ship a **commented**
example of it in `templates/downstream/home.nix` or `system.nix`. New
installs then enable it by uncommenting + tweaking, rather than hunting the
docs for the option name.
- **Applications:** the starter complete-workstation set (LibreOffice, VS
Code, GIMP, Inkscape) lives in the `home.packages` list in your
`home.nix` — it's a plain package list, so curate it directly: delete a
line to slim the machine, uncomment an extra (a browser, email, full TeX
Live), or add your own. No `nomarchy.apps.*` toggles — a package list is
already its own opt-out, so the distro doesn't impose these or wrap them.
## Roadmap & known issues
See **[docs/ROADMAP.md](docs/ROADMAP.md)** — forward-looking plans plus the
log of shipped fixes. Kept out of the README so this stays a focused entry
point.

View File

@@ -1,109 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# nomarchy-docs-keybindings
#
# Regenerates docs/KEYBINDINGS.md from the Hyprland binding files. Run from the
# repo root or anywhere — paths are resolved relative to this script.
#
# nomarchy-docs-keybindings # write to stdout
# nomarchy-docs-keybindings --out docs/KEYBINDINGS.md
#
# Source files in render order. Each entry is "<repo-relative path>|<title>".
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
sources=(
"core/home/config/nomarchy/default/hypr/bindings/utilities.conf|Utilities"
"core/home/config/nomarchy/default/hypr/bindings/tiling-v2.conf|Tiling"
"core/home/config/nomarchy/default/hypr/bindings/clipboard.conf|Clipboard"
"core/home/config/nomarchy/default/hypr/bindings/media.conf|Media keys"
"features/desktop/hyprland/config/bindings.conf|Apps & web shortcuts"
)
prettify_key() {
case "$1" in
code:10) echo "1" ;; code:11) echo "2" ;; code:12) echo "3" ;;
code:13) echo "4" ;; code:14) echo "5" ;; code:15) echo "6" ;;
code:16) echo "7" ;; code:17) echo "8" ;; code:18) echo "9" ;;
code:19) echo "0" ;;
XF86AudioRaiseVolume) echo "Volume Up" ;;
XF86AudioLowerVolume) echo "Volume Down" ;;
XF86AudioMute) echo "Mute" ;;
XF86AudioMicMute) echo "Mic Mute" ;;
XF86AudioPlay) echo "Play/Pause" ;;
XF86AudioStop) echo "Stop" ;;
XF86AudioNext) echo "Next Track" ;;
XF86AudioPrev) echo "Previous Track" ;;
XF86MonBrightnessUp) echo "Brightness Up" ;;
XF86MonBrightnessDown) echo "Brightness Down" ;;
XF86KbdBrightnessUp) echo "Kbd Brightness Up" ;;
XF86KbdBrightnessDown) echo "Kbd Brightness Down" ;;
XF86KbdLightOnOff) echo "Kbd Backlight" ;;
*) echo "$1" ;;
esac
}
trim() { sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//'; }
render_section() {
local file="$1" title="$2"
[[ ! -f "$repo_root/$file" ]] && return
local rows
rows=$(grep -E '^[[:space:]]*bind[a-z]*[[:space:]]*=' "$repo_root/$file" || true)
[[ -z "$rows" ]] && return
local body=""
while IFS= read -r line; do
# Strip the "bindXXX =" prefix.
local rhs="${line#*=}"
local mods key desc
IFS=',' read -r mods key desc _ <<<"$rhs"
mods=$(printf '%s' "${mods:-}" | trim)
key=$(printf '%s' "${key:-}" | trim)
desc=$(printf '%s' "${desc:-}" | trim)
[[ -z "$desc" ]] && continue # skip non-descriptive bindings
[[ -z "$mods" ]] && mods="—"
key=$(prettify_key "$key")
body+=$(printf '| %s | %s | %s |\n' "$mods" "$key" "$desc")
body+=$'\n'
done <<<"$rows"
[[ -z "$body" ]] && return
printf '\n## %s\n\n' "$title"
printf '_Source: `%s`_\n\n' "$file"
printf '| Modifiers | Key | Action |\n'
printf '| --- | --- | --- |\n'
printf '%s' "$body"
}
main() {
cat <<'HEADER'
# Nomarchy Keybindings
Auto-generated from the Hyprland binding files. **Do not edit by hand.**
Re-run the generator after changing any `bindings/*.conf`:
```bash
./bin/utils/nomarchy-docs-keybindings --out docs/KEYBINDINGS.md
```
`SUPER` is the Meta / Win key. `code:NN` keys (X11 digit keycodes) are
shown as the digit they correspond to. Media keys (`XF86Audio*`,
`XF86MonBrightness*`, …) are prettified.
HEADER
for entry in "${sources[@]}"; do
render_section "${entry%|*}" "${entry#*|}"
done
}
out=""
if [[ "${1:-}" == "--out" ]]; then
out="${2:?--out needs a path}"; shift 2
fi
if [[ -n "$out" ]]; then
main >"$out"
else
main
fi

View File

@@ -1,276 +0,0 @@
#!/usr/bin/env bash
# Generator tolerates "no matches" exit codes from grep | sort.
# pipefail and -e off; -u stays.
set -u
# nomarchy-docs-scripts
#
# Regenerates docs/SCRIPTS.md from the repo state. Produces:
# 1. Header + status legend + regen instructions.
# 2. Table of every nomarchy-* script (location, callers, status).
# 3. Table of every menu entry in features/scripts/utils/nomarchy-menu
# (submenu, label, target command, status).
# 4. Snapshot list of orphaned references (called somewhere, no script).
#
# Status heuristic in Phase A:
# kept — file exists AND is called from at least one *.nix / *.conf /
# shell file outside its own directory.
# unused? — file exists but no caller found. Phase B decides delete-dead
# vs intentional public API.
# missing — referenced but no file. Phase B decides port-from-omarchy
# vs delete-dead vs stub-with-notify.
#
# nomarchy-docs-scripts # write to stdout
# nomarchy-docs-scripts --out docs/SCRIPTS.md
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
cd "$repo_root"
# --- Inventory -------------------------------------------------------------
# Where scripts live, in render order.
declare -A loc_label=(
["features/scripts/utils"]="features/scripts/utils"
["core/system/scripts"]="core/system/scripts"
["themes/engine/scripts"]="themes/engine/scripts"
)
script_dirs=(features/scripts/utils core/system/scripts themes/engine/scripts)
# Build name → location map (associative array of basename → repo-relative dir).
declare -A script_loc
for dir in "${script_dirs[@]}"; do
[[ -d "$dir" ]] || continue
while IFS= read -r f; do
script_loc["$(basename "$f")"]="$dir"
done < <(find "$dir" -maxdepth 1 -type f -name 'nomarchy-*')
done
# Find every nomarchy-* token referenced anywhere outside the script dirs.
# (We exclude the script files themselves so they don't list themselves as
# their own caller.)
# File types we search for references. *.md catches docs and README;
# branding/hook/extension files have varied or no extensions.
# *.lua catches elephant providers; *.ini catches mako on-button-* hooks;
# *.desktop catches MimeType-registered URL handlers.
grep_includes=(
--include='*.nix' --include='*.conf' --include='*.sh' --include='*.md'
--include='nomarchy-*' --include='*.jsonc' --include='*.json'
--include='*.toml' --include='*.ini' --include='*.lua'
--include='*.desktop' --include='*.txt' --include='*.sample'
)
search_dirs=(core features themes installer hosts bin lib README.md)
# Files whose mentions of nomarchy-* are documentation about the scripts,
# not real callers. Excluded from caller discovery so they don't promote
# every script to `kept`.
self_refs=(docs/SCRIPTS.md docs/ROADMAP.md docs/AGENT.md)
ref_files_per_cmd() {
local cmd="$1"
local self_pattern
self_pattern=$(IFS='|'; echo "${self_refs[*]}")
grep -rlE "\\b${cmd}\\b" \
"${grep_includes[@]}" \
"${search_dirs[@]}" 2>/dev/null \
| grep -vE "^(features/scripts/utils|core/system/scripts|themes/engine/scripts)/${cmd}$" \
| grep -vE "^(${self_pattern})$" \
| sort -u
}
# All distinct nomarchy-* tokens we see anywhere in the repo.
# Final char must be alphanumeric — dropping trailing-dash matches like
# `nomarchy-pkg-` that come from glob references (`for c in nomarchy-pkg-*`).
# Restrict to grep_includes so binaries / tmpfiles don't pollute the set.
# The first `grep -vE` drops lines where `nomarchy-*` is a derivation /
# tmp file / sudoers basename / systemd unit / flake output / docker
# container identifier rather than a shell invocation.
# The second `grep -vE` is a token-level safety net for prefix-only
# tokens left over from wildcards/expansions (e.g. `nomarchy-pkg-*`).
all_refs=$(grep -rhE 'nomarchy-[a-z0-9]([a-z0-9-]*[a-z0-9])?' \
"${grep_includes[@]}" \
"${search_dirs[@]}" 2>/dev/null \
| grep -vE \
-e '(pname|name)[[:space:]]*=[[:space:]]*"nomarchy-' \
-e '/tmp/nomarchy-' \
-e '/etc/sudoers\.d/[^"[:space:]]*nomarchy-' \
-e 'nixosConfigurations\.nomarchy-' \
-e 'packages\.[^.]+\.nomarchy-' \
-e '\./result/bin/run-nomarchy-' \
-e 'mktemp[[:space:]]+[^|]*-t[[:space:]]+nomarchy-' \
-e '(TIMER_NAME|NOPASSWD_FILE|UNIT_NAME)=.*nomarchy-' \
-e 'docker[[:space:]]+[^|]*nomarchy-' \
| grep -oE 'nomarchy-[a-z0-9]([a-z0-9-]*[a-z0-9])?' \
| grep -vE '^(nomarchy-launch|nomarchy-brightness|nomarchy-cmd|nomarchy-pkg|nomarchy-restart|nomarchy-toggle|nomarchy-theme|nomarchy-webapp-handler|nomarchy-font-selector|nomarchy-theme-selector|nomarchy-wallpaper-selector|nomarchy-setup|nomarchy-refresh|nomarchy-scripts|nomarchy-system-scripts|nomarchy-theme-engine-scripts)$' \
| grep -vE '^(nomarchy-plymouth|nomarchy-sddm-theme|nomarchy-live|nomarchy-rev|nomarchy-windows)$' \
| sort -u)
# The second denylist covers identifiers whose ambiguity survives the line
# filter: `nomarchy-plymouth` / `nomarchy-sddm-theme` are Nix derivation
# names referenced as bare idents in `[...]` lists, `nomarchy-live` is an
# ISO label that shows up in comments, `nomarchy-rev` is `/etc/nomarchy-rev`
# (written by the ISO), and `nomarchy-windows` is a docker container name
# in compose heredocs.
# --- Render: header --------------------------------------------------------
main() {
cat <<'HEADER'
# Nomarchy Script & Menu Audit
Auto-generated table for [Pillar 3 of the roadmap](ROADMAP.md#3-pillar-script--menu-audit).
**Do not edit by hand.** Regenerate after script or menu changes:
```bash
./bin/utils/nomarchy-docs-scripts --out docs/SCRIPTS.md
```
The status column uses a Phase A heuristic — `kept` / `unused?` / `missing`.
Phase B (per-batch PRs) refines those into `port-from-omarchy`,
`delete-dead`, or `stub-with-notify` and updates the rows.
## Status legend
- `kept` — script exists and is called from somewhere outside its own directory.
- `unused?` — script exists but no caller was found. Could be dead, could be
intentional public API. Phase B triage decides.
- `missing` — referenced from code but no script file exists. Phase B triage
decides whether to port from Omarchy upstream, delete the caller, or stub
with `notify-send`.
- `port-from-omarchy` — Phase B verdict: lift the upstream Omarchy script,
rewrite for NixOS paths.
- `delete-dead` — Phase B verdict: remove and update callers.
- `stub-with-notify` — Phase B verdict: temporary `notify-send` stub.
HEADER
# --- Render: scripts table ----------------------------------------------
printf '## Scripts (%d)\n\n' "${#script_loc[@]}"
printf '| Script | Location | Callers | Status | Notes |\n'
printf '| --- | --- | --- | --- | --- |\n'
# Sort scripts by name.
for name in $(printf '%s\n' "${!script_loc[@]}" | sort); do
local dir="${script_loc[$name]}"
local callers status callers_str
callers=$(ref_files_per_cmd "$name")
if [[ -z "$callers" ]]; then
status='`unused?`'
callers_str='—'
else
status='`kept`'
# Trim caller list to 2 entries + count.
local count
count=$(printf '%s\n' "$callers" | wc -l)
if (( count > 2 )); then
callers_str=$(printf '%s\n' "$callers" | head -2 | paste -sd, -)
callers_str="$callers_str, +$((count - 2)) more"
else
callers_str=$(printf '%s\n' "$callers" | paste -sd, -)
fi
fi
printf '| `%s` | `%s` | %s | %s | |\n' \
"$name" "$dir" "$callers_str" "$status"
done
echo
# --- Render: missing references -----------------------------------------
printf '## Missing references\n\n'
printf 'Tokens grepped from `core/`, `features/`, `themes/`, `installer/`, `hosts/`, `bin/`, `lib/` that have no matching script file.\n\n'
printf '| Token | Referenced in | Status |\n'
printf '| --- | --- | --- |\n'
while IFS= read -r token; do
[[ -z "$token" ]] && continue
[[ -n "${script_loc[$token]:-}" ]] && continue
local refs
self_pattern=$(IFS='|'; echo "${self_refs[*]}")
refs=$(grep -rlE "\\b${token}\\b" \
"${grep_includes[@]}" \
"${search_dirs[@]}" 2>/dev/null \
| grep -vE "^(${self_pattern})$" \
| sort -u)
[[ -z "$refs" ]] && continue
local count refs_str
count=$(printf '%s\n' "$refs" | wc -l)
if (( count > 2 )); then
refs_str=$(printf '%s\n' "$refs" | head -2 | paste -sd, -)
refs_str="$refs_str, +$((count - 2)) more"
else
refs_str=$(printf '%s\n' "$refs" | paste -sd, -)
fi
printf '| `%s` | %s | `missing` |\n' "$token" "$refs_str"
done <<<"$all_refs"
echo
# --- Render: menu items -------------------------------------------------
printf '## Menu items\n\n'
printf 'Walked from `features/scripts/utils/nomarchy-menu`. Each `case` arm in a `show_*_menu` function becomes one row.\n\n'
printf '| Submenu | Entry | Calls | Status |\n'
printf '| --- | --- | --- | --- |\n'
awk '
/^show_[a-z_]+_menu\(\) {/ { sub(/\(\) {/, ""); current=$1; in_func=1; next }
/^[a-z_]+\(\) {/ && !/^show_/ { current=""; in_func=0; next }
/^}$/ { current=""; in_func=0; next }
!in_func { next }
/^ case \$\(menu / {
# extract the menu title between the first pair of double quotes
match($0, /menu "[^"]+" "[^"]+"/);
if (RSTART == 0) next;
title=substr($0, RSTART, RLENGTH);
# second quoted string is the option list
n=split(title, parts, "\"");
title=parts[2];
options=parts[4];
# split options on \n
split(options, opts, "\\\\n");
pending_submenu=current;
pending_title=title;
for (i=1;i<=length(opts);i++) pending_opts[i]=opts[i];
pending_count=length(opts);
next
}
/^ \*[A-Za-z]/ {
# case arm — extract pattern between the first * and the closing )
match($0, /\*[^)]*\)/);
if (RSTART == 0) next;
arm=substr($0, RSTART, RLENGTH);
gsub(/[*)]/, "", arm);
gsub(/^[[:space:]]+|[[:space:]]+$/, "", arm);
# action follows the )
rest=substr($0, RSTART+RLENGTH);
sub(/^[[:space:]]+/, "", rest);
sub(/[[:space:]]*;;[[:space:]]*$/, "", rest);
# match the first nomarchy-* token in the action
cmd=""
if (match(rest, /nomarchy-[a-z0-9-]+/)) {
cmd=substr(rest, RSTART, RLENGTH);
}
printf "%s|%s|%s\n", pending_submenu, arm, cmd;
}
' features/scripts/utils/nomarchy-menu > /tmp/nomarchy-menu-rows.$$
while IFS='|' read -r submenu entry cmd; do
[[ -z "$entry" ]] && continue
[[ "$entry" =~ ^\) ]] && continue
status='`kept`'
if [[ -n "$cmd" ]]; then
if [[ -z "${script_loc[$cmd]:-}" ]]; then
status='`missing`'
fi
else
cmd='_(inline)_'
fi
printf '| `%s` | %s | `%s` | %s |\n' "$submenu" "$entry" "$cmd" "$status"
done < /tmp/nomarchy-menu-rows.$$
rm -f /tmp/nomarchy-menu-rows.$$
echo
}
out=""
if [[ "${1:-}" == "--out" ]]; then
out="${2:?--out needs a path}"; shift 2
fi
if [[ -n "$out" ]]; then
main >"$out"
else
main
fi

View File

@@ -1,16 +0,0 @@
# About Nomarchy
Nomarchy is a highly curated, NixOS-based distribution designed for power users.
It features a customized Hyprland desktop environment with a declarative
theming engine and a suite of integrated utility scripts.
Built on a foundation of:
- NixOS (Linux)
- Hyprland (Window Manager)
- Waybar (Status Bar)
- Walker (Application Launcher & Menu)
- Stylix (Theming Engine)
Version: 2026.05.04
Docs: https://github.com/nomarchy/nomarchy/docs
Manual: nomarchy-manual (Command)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -1,56 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg1"
xml:space="preserve"
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
sodipodi:docname="icon.svg"
inkscape:export-filename="logo.svg"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="0.82803284"
inkscape:cx="215.57116"
inkscape:cy="452.27675"
inkscape:window-width="1025"
inkscape:window-height="1012"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="layer1" /><defs
id="defs1" /><g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"><g
id="g4"
transform="translate(3.1953242,-22.686801)"
style="fill:#000088;fill-opacity:1"><path
style="fill:#000088;stroke-width:0.264583;fill-opacity:1"
d="M 25.136891,85.823024 25.557592,210.77125 88.452409,174.38061 67.417351,160.49747 57.110174,166.38729 V 105.80633 Z"
id="path1" /><path
style="fill:#000088;stroke-width:0.264583;fill-opacity:1"
d="M 67.728991,112.41131 182.54178,185.60757 153.16137,202.85259 67.830432,148.17947 Z"
id="path2" /><path
style="fill:#000088;stroke-width:0.264583;fill-opacity:1"
d="M 139.74857,145.88014 140.00405,110.4959 54.800856,56.333749 25.675926,73.32329 Z"
id="path3" /><path
style="fill:#000088;stroke-width:0.264583;fill-opacity:1"
d="M 182.2863,172.70573 V 48.286069 l -62.59305,36.406166 20.82177,13.668277 10.21927,-5.74834 0.12774,60.165978 z"
id="path4" /></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -1,34 +0,0 @@
${2},,,
${1},, ${2},,,,,,
${1},,,,,,,, ${2},,,,,,,,,,
${1},,,,,,,,,,,,,, ${2}.,,,,,,,,,,,,
${1},,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,,,,,
${1},,,,,,,,,,,,,,,,,,,,,,,. ${2},,,,,,,,,,,,,,,,,,,
${1}.,,,,,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,,,,,,,,,,,,
${1}, ${1},,,,,,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,,,,,,,,,,,,,
${1},,, ${1},,,,,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,,,,,,,,,,,,,
${1},,,,,, ${1}.,,,,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,,,,,,,,,
${1},,,,,,,,,. ${1},,,,,,,,,,,,,,,,,,,,,,,,, ${2},,, ${2}.,,,,,,,,,,,,
${1},,,,,,,,,,,, ${1}.,,,,,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,,
${1},,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,,,,. ${2},,,,,,,,,,,,,
${1},,,,,,,,,,,,, ${1},, ${1},,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,
${1},,,,,,,,,,,,, ${1},,,,, ${1},,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,
${1},,,,,,,,,,,,, ${1},,,,,,,, ${1},,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,
${1},,,,,,,,,,,,, ${1},,,,,,,,,, ${1},,,,,,,,,,,,, ${2},,,,,,,,,,,,
${1},,,,,,,,,,,,, ${1},,,,,,,,,,,,,, ${1},,,,,,,,,, ${2},,,,,,,,,,,,
${1},,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,, ${1},,,,,,, ${2},,,,,,,,,,,,
${1},,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,, ${1},,,, ${2},,,,,,,,,,,,
${1},,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,, ${1},, ${2},,,,,,,,,,,,
${1},,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,
${1},,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,
${1},,,,,,,,,,,,, ${1},,, ${1},,,,,,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,
${1},,,,,,,,,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,,,, ${2}.,,,,,
${1},,,,,,,,,,,,,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,,,,, ${2},,,
${1},,,,,,,,,,,,,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,,,,,
${1},,,,,,,,,,,,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,,,,,
${1},,,,,,,,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,,,
${1},,,,,,,,,,,,,,,, ${1}.,,,,,,,,,,,,,,,,,,,
${1},,,,,,,,,,,,, ${1},,,,,,,,,,,,,,
${1},,,,,,,,,, ${1},,,,,,,,,.
${1},,,,,, ${1},,
${1},,,,

View File

@@ -1,34 +0,0 @@
,,,
,, ,,,,,,
,,,,,,,, ,,,,,,,,,,
,,,,,,,,,,,,,, .,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,. ,,,,,,,,,,,,,,,,,,,
.,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,
, ,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,
,,, ,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,, .,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,. ,,,,,,,,,,,,,,,,,,,,,,,,, ,,, .,,,,,,,,,,,,
,,,,,,,,,,,, .,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,
,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,. ,,,,,,,,,,,,,
,,,,,,,,,,,,, ,, ,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,
,,,,,,,,,,,,, ,,,,, ,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,
,,,,,,,,,,,,, ,,,,,,,, ,,,,,,,,,,,,,,,, ,,,,,,,,,,,,
,,,,,,,,,,,,, ,,,,,,,,,, ,,,,,,,,,,,,, ,,,,,,,,,,,,
,,,,,,,,,,,,, ,,,,,,,,,,,,,, ,,,,,,,,,, ,,,,,,,,,,,,
,,,,,,,,,,,,, ,,,,,,,,,,,,,,,, ,,,,,,, ,,,,,,,,,,,,
,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,, ,,,, ,,,,,,,,,,,,
,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,, ,, ,,,,,,,,,,,,
,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,
,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,
,,,,,,,,,,,,, ,,, ,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,
,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,, .,,,,,
,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,, ,,,
,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,, .,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,, ,,,,,,,,,,,,,,
,,,,,,,,,, ,,,,,,,,,.
,,,,,, ,,
,,,,

View File

@@ -1,11 +0,0 @@
# Nomarchy Screensaver Configuration
Nomarchy uses hyprlock for locking and hypridle for idle management.
To configure the screensaver/lock screen visuals, edit:
~/.config/hypr/hyprlock.conf
To configure idle timeouts and actions, edit:
~/.config/hypr/hypridle.conf
You can also toggle the screensaver/idle management via the Nomarchy Menu:
Trigger > Toggle > Idle Lock

View File

@@ -1,5 +0,0 @@
{ ... }:
{
imports = [ ./system ];
}

View File

@@ -1,39 +0,0 @@
{ config, lib, ... }:
{
programs.bash = {
enable = true;
bashrcExtra = ''
if [[ -f ~/.config/nomarchy/default/bash/rc ]]; then
source ~/.config/nomarchy/default/bash/rc
fi
'';
shellAliases = lib.mkDefault {
# File system
lsa = "ls -a";
# Directories
".." = "cd ..";
"..." = "cd ../..";
"...." = "cd ../../..";
# Tools
c = "opencode";
d = "docker";
r = "rails";
t = "tmux attach || tmux new -s Work";
# Git
g = "git";
gcm = "git commit -m";
gcam = "git commit -a -m";
gcad = "git commit -a --amend";
# NixOS commands
sys-update = "nomarchy-sys-update";
env-update = "nomarchy-env-update";
};
};
}

View File

@@ -1,4 +0,0 @@
--ozone-platform=wayland
--ozone-platform-hint=wayland
--enable-features=TouchpadOverscrollHistoryNavigation
--load-extension=~/.config/nomarchy/default/chromium/extensions/copy-url

View File

@@ -1,4 +0,0 @@
--ozone-platform=wayland
--ozone-platform-hint=wayland
--enable-features=TouchpadOverscrollHistoryNavigation
--load-extension=~/.config/nomarchy/default/chromium/extensions/copy-url

View File

@@ -1,137 +0,0 @@
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": {
"type": "file",
"source": "~/.config/nomarchy/branding/icon.txt",
"color": { "1": "green", "2": "blue" },
"padding": {
"top": 2,
"right": 6,
"left": 2
}
},
"modules": [
"break",
{
"type": "custom",
"format": "\u001b[90m┌──────────────────────Hardware──────────────────────┐"
},
{
"type": "host",
"key": " PC",
"keyColor": "green"
},
{
"type": "cpu",
"key": "│ ├",
"showPeCoreCount": true,
"keyColor": "green"
},
{
"type": "gpu",
"key": "│ ├",
"detectionMethod": "pci",
"keyColor": "green"
},
{
"type": "display",
"key": "│ ├󱄄",
"keyColor": "green"
},
{
"type": "disk",
"key": "│ ├󰋊",
"keyColor": "green"
},
{
"type": "memory",
"key": "│ ├",
"keyColor": "green"
},
{
"type": "swap",
"key": "└ └󰓡 ",
"keyColor": "green"
},
{
"type": "custom",
"format": "\u001b[90m└────────────────────────────────────────────────────┘"
},
"break",
{
"type": "custom",
"format": "\u001b[90m┌──────────────────────Software──────────────────────┐"
},
{
"type": "os",
"key": "\ue900 OS",
"keyColor": "blue"
},
{
"type": "kernel",
"key": "│ ├",
"keyColor": "blue"
},
{
"type": "wm",
"key": "│ ├",
"keyColor": "blue"
},
{
"type": "de",
"key": " DE",
"keyColor": "blue"
},
{
"type": "terminal",
"key": "│ ├",
"keyColor": "blue"
},
{
"type": "packages",
"key": "│ ├󰏖",
"keyColor": "blue"
},
{
"type": "wmtheme",
"key": "│ ├󰉼",
"keyColor": "blue"
},
{
"type": "command",
"key": "│ ├󰸌",
"keyColor": "blue",
"text": "theme=$(cat ~/.config/nomarchy/current/theme.name); echo -e \"$theme \\e[38m●\\e[37m●\\e[36m●\\e[35m●\\e[34m●\\e[33m●\\e[32m●\\e[31m●\""
},
{
"type": "terminalfont",
"key": "└ └",
"keyColor": "blue"
},
{
"type": "custom",
"format": "\u001b[90m└────────────────────────────────────────────────────┘"
},
"break",
{
"type": "custom",
"format": "\u001b[90m┌────────────────Age / Uptime / Update───────────────┐"
},
{
"type": "command",
"key": "󱦟 OS Age",
"keyColor": "magenta",
"text": "echo $(( ($(date +%s) - $(stat -c %W /)) / 86400 )) days"
},
{
"type": "uptime",
"key": "󱫐 Uptime",
"keyColor": "magenta"
},
{
"type": "custom",
"format": "\u001b[90m└────────────────────────────────────────────────────┘"
},
"break"
]
}

View File

@@ -1,2 +0,0 @@
TriggerKey=
PastePrimaryKey=

View File

@@ -1 +0,0 @@
Allow Overriding System XKB Settings=False

View File

@@ -1,79 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<match target="pattern">
<test name="family" qual="any">
<string>sans-serif</string>
</test>
<edit name="family" mode="assign" binding="strong">
<string>Liberation Sans</string>
</edit>
</match>
<match target="pattern">
<test name="family" qual="any">
<string>serif</string>
</test>
<edit name="family" mode="assign" binding="strong">
<string>Liberation Serif</string>
</edit>
</match>
<match target="pattern">
<test name="family" qual="any">
<string>monospace</string>
</test>
<edit name="family" mode="assign" binding="strong">
<string>JetBrainsMono Nerd Font</string>
</edit>
</match>
<alias>
<family>system-ui</family>
<prefer>
<family>Liberation Sans</family>
</prefer>
</alias>
<alias>
<family>ui-monospace</family>
<default>
<family>monospace</family>
</default>
</alias>
<alias>
<family>-apple-system</family>
<prefer>
<family>Liberation Sans</family>
</prefer>
</alias>
<alias>
<family>BlinkMacSystemFont</family>
<prefer>
<family>Liberation Sans</family>
</prefer>
</alias>
<alias>
<family>sans-serif</family>
<accept>
<family>Noto Color Emoji</family>
</accept>
</alias>
<alias>
<family>serif</family>
<accept>
<family>Noto Color Emoji</family>
</accept>
</alias>
<alias>
<family>monospace</family>
<accept>
<family>Noto Color Emoji</family>
</accept>
</alias>
</fontconfig>

View File

@@ -1,28 +0,0 @@
# See https://git-scm.com/docs/git-config
[alias]
co = checkout
br = branch
ci = commit
st = status
[init]
defaultBranch = master
[pull]
rebase = true # Rebase (instead of merge) on pull
[push]
autoSetupRemote = true # Automatically set upstream branch on push
[diff]
algorithm = histogram # Clearer diffs on moved/edited lines
colorMoved = plain # Highlight moved blocks in diffs
mnemonicPrefix = true # More intuitive refs in diff output
[commit]
verbose = true # Include diff comment in commit message template
[column]
ui = auto # Output in columns when possible
[branch]
sort = -committerdate # Sort branches by most recent commit first
[tag]
sort = -version:refname # Sort version numbers as you would expect
[rerere]
enabled = true # Record and reuse conflict resolutions
autoupdate = true # Apply stored conflict resolutions automatically

View File

@@ -1,13 +0,0 @@
[binds]
# Print the current image file
<Ctrl+p> = exec lp "$imv_current_file"
# Delete the current image and quit the viewer
<Ctrl+x> = exec rm "$imv_current_file"; quit
# Delete the current image and move to the next one
<Ctrl+Shift+X> = exec rm "$imv_current_file"; close
# Rotate the currently open image by 90 degrees
<Ctrl+r> = exec mogrify -rotate 90 "$imv_current_file"

View File

@@ -1,84 +0,0 @@
import os
import shutil
from gi import require_version
require_version("Nautilus", "4.1")
from gi.repository import GObject, Gio, Nautilus
class SendViaLocalSendAction(GObject.GObject, Nautilus.MenuProvider):
def _launch_localsend(self, paths):
command = self._resolve_command()
if not command:
return
if command[-1] == "@@":
command = command + paths + ["@@"]
else:
command = command + paths
Gio.Subprocess.new(command, Gio.SubprocessFlags.NONE)
def _resolve_command(self):
localsend = shutil.which("localsend")
if localsend:
return [localsend, "--headless", "send"]
flatpak = shutil.which("flatpak")
if flatpak and self._has_flatpak_app(flatpak, "org.localsend.localsend_app"):
return [
flatpak,
"run",
"--file-forwarding",
"org.localsend.localsend_app",
"@@",
]
return None
def _has_flatpak_app(self, flatpak, app_id):
process = Gio.Subprocess.new(
[flatpak, "info", app_id],
Gio.SubprocessFlags.STDOUT_SILENCE | Gio.SubprocessFlags.STDERR_SILENCE,
)
return process.wait_check()
def _selected_paths(self, files):
paths = []
for file in files:
location = file.get_location()
if not location:
continue
path = location.get_path()
if path and path not in paths:
paths.append(path)
return paths
def _make_item(self, paths):
label = (
"Send via LocalSend" if len(paths) == 1 else "Send selected via LocalSend"
)
item = Nautilus.MenuItem(
name="LocalSendNautilus::send_via_localsend",
label=label,
icon="localsend",
)
item.connect("activate", self._on_activate, paths)
return item
def _on_activate(self, _menu, paths):
self._launch_localsend(paths)
def get_file_items(self, *args):
files = args[0] if len(args) == 1 else args[1]
paths = self._selected_paths(files)
if not paths or not self._resolve_command():
return []
return [self._make_item(paths)]

View File

@@ -1,408 +0,0 @@
---
name: nomarchy
description: >
REQUIRED for end-user customization of Linux desktop, window manager, or system config.
Use when editing ~/.config/hypr/, ~/.config/waybar/, ~/.config/walker/,
~/.config/alacritty/, ~/.config/kitty/, ~/.config/ghostty/, ~/.config/mako/,
or ~/.config/nomarchy/. Triggers: Hyprland, window rules, animations, keybindings,
monitors, gaps, borders, blur, opacity, waybar, walker, terminal config, themes,
wallpaper, night light, idle, lock screen, screenshots, layer rules, workspace
settings, display config, and user-facing nomarchy commands. Excludes Nomarchy
source development in ~/.local/share/nomarchy/ and repo-internal workflows.
---
# Nomarchy Skill
Manage [Nomarchy](https://nomarchy.org/) Linux systems - a beautiful, modern, opinionated Arch Linux distribution with Hyprland.
This skill is for end-user customization on installed systems.
It is not for contributing to Nomarchy source code.
## When This Skill MUST Be Used
**ALWAYS invoke this skill for end-user requests involving ANY of these:**
- Editing ANY file in `~/.config/hypr/` (window rules, animations, keybindings, monitors, etc.)
- Editing ANY file in `~/.config/waybar/`, `~/.config/walker/`, `~/.config/mako/`
- Editing terminal configs (alacritty, kitty, ghostty)
- Editing ANY file in `~/.config/nomarchy/`
- Window behavior, animations, opacity, blur, gaps, borders
- Layer rules, workspace settings, display/monitor configuration
- Themes, wallpapers, fonts, appearance changes
- User-facing `nomarchy-*` commands (`nomarchy-theme-*`, `nomarchy-refresh-*`, `nomarchy-restart-*`, etc.)
- Screenshots, screen recording, night light, idle behavior, lock screen
**If you're about to edit a config file in ~/.config/ on this system, STOP and use this skill first.**
**Do NOT use this skill for Nomarchy development tasks** — editing files in `~/.local/share/nomarchy/` or modifying repo internals.
## Critical Safety Rules
**For end-user customization tasks, NEVER modify anything in `~/.local/share/nomarchy/`** - but READING is safe and encouraged.
This directory contains Nomarchy's source files managed by git. Any changes will be:
- Lost on next `nomarchy-update`
- Cause conflicts with upstream
- Break the system's update mechanism
```
~/.local/share/nomarchy/ # READ-ONLY - NEVER EDIT (reading is OK)
├── bin/ # Source scripts (symlinked to PATH)
├── config/ # Default config templates
├── themes/ # Stock themes
├── default/ # System defaults
├── migrations/ # Update migrations
└── install/ # Installation scripts
```
**Reading `~/.local/share/nomarchy/` is SAFE and useful** - do it freely to:
- Understand how nomarchy commands work: `cat $(which nomarchy-theme-set)`
- See default configs before customizing: `cat ~/.local/share/nomarchy/config/waybar/config.jsonc`
- Check stock theme files to copy for customization
- Reference default hyprland settings: `cat ~/.config/nomarchy/default/hypr/*`
**Always use these safe locations instead:**
- `~/.config/` - User configuration (safe to edit)
- `~/.config/nomarchy/themes/<custom-name>/` - Custom themes (must be real directories)
- `~/.config/nomarchy/hooks/` - Custom automation hooks
If the request is to develop Nomarchy itself, this skill is out of scope. Follow repository development instructions instead of this skill.
## System Architecture
Nomarchy is built on:
| Component | Purpose | Config Location |
|-----------|---------|-----------------|
| **Arch Linux** | Base OS | `/etc/`, `~/.config/` |
| **Hyprland** | Wayland compositor/WM | `~/.config/hypr/` |
| **Waybar** | Status bar | `~/.config/waybar/` |
| **Walker** | App launcher | `~/.config/walker/` |
| **Alacritty/Kitty/Ghostty** | Terminals | `~/.config/<terminal>/` |
| **Mako** | Notifications | `~/.config/mako/` |
| **SwayOSD** | On-screen display | `~/.config/swayosd/` |
## Command Discovery
Nomarchy provides ~145 commands following `nomarchy-<category>-<action>` pattern.
```bash
# List all nomarchy commands
compgen -c | grep -E '^nomarchy-' | sort -u
# Find commands by category
compgen -c | grep -E '^nomarchy-theme'
compgen -c | grep -E '^nomarchy-restart'
# Read a command's source to understand it
cat $(which nomarchy-theme-set)
```
### Command Categories
| Prefix | Purpose | Example |
|--------|---------|---------|
| `nomarchy-refresh-*` | Reset config to defaults (backs up first) | `nomarchy-refresh-waybar` |
| `nomarchy-restart-*` | Restart a service/app | `nomarchy-restart-waybar` |
| `nomarchy-toggle-*` | Toggle feature on/off | `nomarchy-toggle-nightlight` |
| `nomarchy-theme-*` | Theme management | `nomarchy-theme-set <name>` |
| `nomarchy-install-*` | Install optional software | `nomarchy-install-docker-dbs` |
| `nomarchy-launch-*` | Launch apps | `nomarchy-launch-browser` |
| `nomarchy-cmd-*` | System commands | `nomarchy-cmd-screenshot` |
| `nomarchy-pkg-*` | Package management | `nomarchy-pkg-install <pkg>` |
| `nomarchy-setup-*` | Initial setup tasks | `nomarchy-setup-fingerprint` |
| `nomarchy-update-*` | System updates | `nomarchy-update` |
## Configuration Locations
### Hyprland (Window Manager)
```
~/.config/hypr/
├── hyprland.conf # Main config (sources others)
├── bindings.conf # Keybindings
├── monitors.conf # Display configuration
├── input.conf # Keyboard/mouse settings
├── looknfeel.conf # Appearance (gaps, borders, animations)
├── envs.conf # Environment variables
├── autostart.conf # Startup applications
├── hypridle.conf # Idle behavior (screen off, lock, suspend)
├── hyprlock.conf # Lock screen appearance
└── hyprsunset.conf # Night light / blue light filter
```
**Key behaviors:**
- Hyprland auto-reloads on config save (no restart needed for most changes)
- Use `hyprctl reload` to force reload
- Use `nomarchy-refresh-hyprland` to reset to defaults
### Waybar (Status Bar)
```
~/.config/waybar/
├── config.jsonc # Bar layout and modules (JSONC format)
└── style.css # Styling
```
**Waybar does NOT auto-reload.** You MUST run `nomarchy-restart-waybar` after any config changes.
**Commands:** `nomarchy-restart-waybar`, `nomarchy-refresh-waybar`, `nomarchy-toggle-waybar`
### Terminals
```
~/.config/alacritty/alacritty.toml
~/.config/kitty/kitty.conf
~/.config/ghostty/config
```
**Command:** `nomarchy-restart-terminal`
### Other Configs
| App | Location |
|-----|----------|
| btop | `~/.config/btop/btop.conf` |
| fastfetch | `~/.config/fastfetch/config.jsonc` |
| lazygit | `~/.config/lazygit/config.yml` |
| starship | `~/.config/starship.toml` |
| git | `~/.config/git/config` |
| walker | `~/.config/walker/config.toml` |
## Safe Customization Patterns
### Pattern 1: Edit User Config Directly
For simple changes, edit files in `~/.config/`:
```bash
# 1. Read current config
cat ~/.config/hypr/bindings.conf
# 2. Backup before changes
cp ~/.config/hypr/bindings.conf ~/.config/hypr/bindings.conf.bak.$(date +%s)
# 3. Make changes with Edit tool
# 4. Apply changes
# - Hyprland: auto-reloads on save (no restart needed)
# - Waybar: MUST restart with nomarchy-restart-waybar
# - Walker: MUST restart with nomarchy-restart-walker
# - Terminals: MUST restart with nomarchy-restart-terminal
```
### Pattern 2: Make a new theme
1. Create a directory under ~/.config/nomarchy/themes.
2. See how an existing theme is done via ~/.local/share/nomarchy/themes/catppuccin.
3. Download a matching background (or several) from the internet and put them in ~/.config/nomarchy/themes/[name-of-new-theme]
4. When done with the theme, run nomarchy-theme-set "Name of new theme"
### Pattern 3: Use Hooks for Automation
Create scripts in `~/.config/nomarchy/hooks/` to run automatically on events:
```bash
# Available hooks (see samples in ~/.config/nomarchy/hooks/):
~/.config/nomarchy/hooks/
├── theme-set # Runs after theme change (receives theme name as $1)
├── font-set # Runs after font change
└── post-update # Runs after nomarchy-update
```
Example hook (`~/.config/nomarchy/hooks/theme-set`):
```bash
#!/bin/bash
THEME_NAME=$1
echo "Theme changed to: $THEME_NAME"
# Add custom actions here
```
### Pattern 4: Reset to Defaults -- ALWAYS SEEK USER CONFIRMATION BEFORE RUNNING
When customizations go wrong:
```bash
# Reset specific config (creates backup automatically)
nomarchy-refresh-waybar
nomarchy-refresh-hyprland
# The refresh command:
# 1. Backs up current config with timestamp
# 2. Copies default from ~/.local/share/nomarchy/config/
# 3. Restarts the component
```
## Common Tasks
### Themes
```bash
nomarchy-theme-list # Show available themes
nomarchy-theme-current # Show current theme
nomarchy-theme-set <name> # Apply theme (use "Tokyo Night" not "tokyo-night")
nomarchy-theme-next # Cycle to next theme
nomarchy-theme-bg-next # Cycle wallpaper
nomarchy-theme-install <url> # Install from git repo
nomarchy-theme-remove <name> # Remove an installed extra theme
nomarchy-theme-refresh # Re-apply current theme from templates
nomarchy-theme-bg-install # Open backgrounds dir to drop in custom images
```
### Keybindings
Edit `~/.config/hypr/bindings.conf`. Format:
```
bind = SUPER, Return, exec, xdg-terminal-exec
bind = SUPER, Q, killactive
bind = SUPER SHIFT, E, exit
```
View current bindings: `nomarchy-menu-keybindings --print`
**IMPORTANT: When re-binding an existing key:**
1. First check existing bindings: `nomarchy-menu-keybindings --print`
2. If the key is already bound, you MUST add an `unbind` directive BEFORE your new `bind`
3. Inform the user what the key was previously bound to
Example - rebinding SUPER+F (which is bound to fullscreen by default):
```
# Unbind existing SUPER+F (was: fullscreen)
unbind = SUPER, F
# New binding for file manager
bind = SUPER, F, exec, nautilus
```
Always tell the user: "Note: SUPER+F was previously bound to fullscreen. I've added an unbind directive to override it."
### Display/Monitors
Edit `~/.config/hypr/monitors.conf`. Format:
```
monitor = eDP-1, 1920x1080@60, 0x0, 1
monitor = HDMI-A-1, 2560x1440@144, 1920x0, 1
```
List monitors: `hyprctl monitors`
### Window Rules
**CRITICAL: Hyprland window rules syntax changes frequently between versions.**
Before writing ANY window rules, you MUST fetch the current documentation from the official Hyprland wiki:
- https://github.com/hyprwm/hyprland-wiki/blob/main/content/Configuring/Window-Rules.md
DO NOT rely on cached or memorized window rule syntax. The format has changed multiple times and using outdated syntax will cause errors or unexpected behavior.
Window rules go in `~/.config/hypr/hyprland.conf` or a sourced file. Always verify the current syntax from the wiki first.
### Fonts
```bash
nomarchy-font-list # Available fonts
nomarchy-font-current # Current font
nomarchy-font-set <name> # Change font
```
### System
```bash
nomarchy-update # Full system update
nomarchy-version # Show Nomarchy version
nomarchy-debug --no-sudo --print # Debug info (ALWAYS use these flags)
nomarchy-lock-screen # Lock screen
nomarchy-system-shutdown # Shutdown
nomarchy-system-reboot # Reboot
nomarchy-sudo-passwordless-toggle # Toggle 15-min passwordless sudo
nomarchy-sudo-reset # Clear sudo lockout / faillock
nomarchy-restart-trackpad # Reload intel_quicki2c (fixes dead THC trackpad)
```
**IMPORTANT:** Always run `nomarchy-debug` with `--no-sudo --print` flags to avoid interactive sudo prompts that will hang the terminal.
### Custom App Launchers
```bash
nomarchy-webapp-install # Add a web app launcher (interactive)
nomarchy-webapp-remove [name...] # Remove web apps (interactive if no name)
nomarchy-webapp-remove-all # Bulk-remove every web app
nomarchy-tui-install # Add a TUI launcher for a terminal program
nomarchy-tui-remove [name...] # Remove TUI launchers
nomarchy-tui-remove-all # Bulk-remove every TUI launcher
```
Both families write `.desktop` files into `~/.local/share/applications/` so they appear in the app launcher (walker / rofi).
### Voice dictation (Voxtype)
```bash
nomarchy-voxtype-install # Install Voxtype + AI model (~150MB)
nomarchy-voxtype-remove # Uninstall Voxtype
nomarchy-voxtype-status # Running state (also shown in waybar)
```
Toggle dictation with `SUPER+CTRL+X` after install.
### Virtualization
```bash
nomarchy-windows-vm install # Provision a Windows VM via docker-compose
nomarchy-windows-vm launch # Connect to the VM (auto-stop on disconnect)
nomarchy-windows-vm launch -k # Connect, keep VM running after disconnect
nomarchy-windows-vm stop # Shut the VM down
nomarchy-windows-vm status # Show current state
```
Requires KVM (`/dev/kvm`) and Docker (enable via `nomarchy.system.virtualization.docker`).
## Troubleshooting
```bash
# Get debug information (ALWAYS use these flags to avoid interactive prompts)
nomarchy-debug --no-sudo --print
# Upload logs for support
nomarchy-upload-log
# Reset specific config to defaults
# Examples: nomarchy-refresh-fastfetch, nomarchy-refresh-hyprland, nomarchy-refresh-waybar
nomarchy-refresh-<app>
# Refresh specific config file
# config-file path is relative to ~/.config/
# eg. nomarchy-refresh-config hypr/hyprlock.conf will refresh ~/.config/hypr/hyprlock.conf
nomarchy-refresh-config <config-file>
# Full reinstall of configs (nuclear option)
nomarchy-reinstall
```
## Decision Framework
When user requests system changes:
1. **Is it a stock nomarchy command?** Use it directly
2. **Is it a config edit?** Edit in `~/.config/`, never `~/.local/share/nomarchy/`
3. **Is it a theme customization?** Create a NEW custom theme directory
4. **Is it automation?** Use hooks in `~/.config/nomarchy/hooks/`
5. **Is it a package install?** Use `nomarchy-pkg-add` (or `nomarchy-pkg-aur-add` for AUR-only packages)
6. **Unsure if command exists?** Search with `compgen -c | grep nomarchy`
## Out of Scope
This skill intentionally does not cover Nomarchy source development. Do not use this skill for:
- Editing files in `~/.local/share/nomarchy/` (`bin/`, `config/`, `default/`, `themes/`, `migrations/`, etc.)
- Creating or editing migrations
- Modifying Nomarchy's own source tree
## Example Requests
- "Change my theme to catppuccin" -> `nomarchy-theme-set catppuccin`
- "Add a keybinding for Super+E to open file manager" -> Check existing bindings first, add `unbind` if needed, then add `bind` in `~/.config/hypr/bindings.conf`
- "Configure my external monitor" -> Edit `~/.config/hypr/monitors.conf`
- "Make the window gaps smaller" -> Edit `~/.config/hypr/looknfeel.conf`
- "Set up night light to turn on at sunset" -> `nomarchy-toggle-nightlight` or edit `~/.config/hypr/hyprsunset.conf`
- "Customize the catppuccin theme colors" -> Create `~/.config/nomarchy/themes/catppuccin-custom/` by copying from stock, then edit
- "Run a script every time I change themes" -> Create `~/.config/nomarchy/hooks/theme-set`
- "Reset waybar to defaults" -> `nomarchy-refresh-waybar`

View File

@@ -1,11 +0,0 @@
[colors.primary]
background = "0x000000"
[colors.cursor]
cursor = "0x000000"
[font]
size = 18.0
[window]
opacity = 1.0

View File

@@ -1,57 +0,0 @@
# File system
if command -v eza &> /dev/null; then
alias ls='eza -lh --group-directories-first --icons=auto'
alias lsa='ls -a'
alias lt='eza --tree --level=2 --long --icons --git'
alias lta='lt -a'
fi
if [[ "$TERM" == "xterm-kitty" ]]; then
alias ff="fzf --preview 'case \$(file --mime-type -b {}) in image/*) kitty icat --clear --transfer-mode=memory --stdin=no --place=\${FZF_PREVIEW_COLUMNS}x\${FZF_PREVIEW_LINES}@0x0 {} ;; *) bat --style=numbers --color=always {} ;; esac'"
else
alias ff="fzf --preview 'bat --style=numbers --color=always {}'"
fi
alias eff='$EDITOR "$(ff)"'
sff() { if [ $# -eq 0 ]; then echo "Usage: sff <destination> (e.g. sff host:/tmp/)"; return 1; fi; local file; file=$(find . -type f -printf '%T@\t%p\n' | sort -rn | cut -f2- | ff) && [ -n "$file" ] && scp "$file" "$1"; }
if command -v zoxide &> /dev/null; then
alias cd="zd"
zd() {
if (( $# == 0 )); then
builtin cd ~ || return
elif [[ -d $1 ]]; then
builtin cd "$1" || return
else
if ! z "$@"; then
echo "Error: Directory not found"
return 1
fi
printf "\U000F17A9 "
pwd
fi
}
fi
open() (
xdg-open "$@" >/dev/null 2>&1 &
)
# Directories
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
# Tools
alias c='opencode'
alias cx='printf "\033[2J\033[3J\033[H" && claude --allow-dangerously-skip-permissions'
alias d='docker'
alias r='rails'
alias t='tmux attach || tmux new -s Work'
n() { if [ "$#" -eq 0 ]; then command nvim . ; else command nvim "$@"; fi; }
# Git
alias g='git'
alias gcm='git commit -m'
alias gcam='git commit -a -m'
alias gcad='git commit -a --amend'

View File

@@ -1,6 +0,0 @@
# Editor used by CLI
export SUDO_EDITOR="$EDITOR"
export BAT_THEME=ansi
# Duplicated from .config/uwsm/env so SSH works too
export PATH=$PATH:$HOME/.local/bin

View File

@@ -1,3 +0,0 @@
# Compression
compress() { tar -czf "${1%/}.tar.gz" "${1%/}"; }
alias decompress="tar -xzf"

View File

@@ -1,59 +0,0 @@
# Write iso file to sd card
iso2sd() {
if (( $# < 1 )); then
echo "Usage: iso2sd <input_file> [output_device]"
echo "Example: iso2sd ~/Downloads/ubuntu-25.04-desktop-amd64.iso /dev/sda"
return 1
fi
local iso="$1"
local drive="$2"
if [[ -z $drive ]]; then
local available_sds=$(lsblk -dpno NAME | grep -E '/dev/sd')
if [[ -z $available_sds ]]; then
echo "No SD drives found and no drive specified"
return 1
fi
drive=$(nomarchy-drive-select "$available_sds")
if [[ -z $drive ]]; then
echo "No drive selected"
return 1
fi
fi
sudo dd bs=4M status=progress oflag=sync if="$iso" of="$drive"
sudo eject "$drive"
}
# Format an entire drive for a single partition using exFAT
format-drive() {
if (( $# != 2 )); then
echo "Usage: format-drive <device> <name>"
echo "Example: format-drive /dev/sda 'My Stuff'"
echo -e "\nAvailable drives:"
lsblk -d -o NAME -n | awk '{print "/dev/"$1}'
else
echo "WARNING: This will completely erase all data on $1 and label it '$2'."
read -rp "Are you sure you want to continue? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
sudo wipefs -a "$1"
sudo dd if=/dev/zero of="$1" bs=1M count=100 status=progress
sudo parted -s "$1" mklabel gpt
sudo parted -s "$1" mkpart primary 1MiB 100%
sudo parted -s "$1" set 1 msftdata on
partition="$([[ $1 == *"nvme"* ]] && echo "${1}p1" || echo "${1}1")"
sudo partprobe "$1" || true
sudo udevadm settle || true
sudo mkfs.exfat -n "$2" "$partition"
echo "Drive $1 formatted as exFAT and labeled '$2'."
fi
fi
}

View File

@@ -1,20 +0,0 @@
# SSH Port Forwarding Functions
fip() {
(( $# < 2 )) && echo "Usage: fip <host> <port1> [port2] ..." && return 1
local host="$1"
shift
for port in "$@"; do
ssh -f -N -L "$port:localhost:$port" "$host" && echo "Forwarding localhost:$port -> $host:$port"
done
}
dip() {
(( $# == 0 )) && echo "Usage: dip <port1> [port2] ..." && return 1
for port in "$@"; do
pkill -f "ssh.*-L $port:localhost:$port" && echo "Stopped forwarding port $port" || echo "No forwarding on port $port"
done
}
lip() {
pgrep -af "ssh.*-L [0-9]+:localhost:[0-9]+" || echo "No active forwards"
}

View File

@@ -1,97 +0,0 @@
# Create a Tmux Dev Layout with editor, ai, and terminal
# Usage: tdl <c|cx|codex|other_ai> [<second_ai>]
tdl() {
[[ -z $1 ]] && { echo "Usage: tdl <c|cx|codex|other_ai> [<second_ai>]"; return 1; }
[[ -z $TMUX ]] && { echo "You must start tmux to use tdl."; return 1; }
local current_dir="${PWD}"
local editor_pane ai_pane ai2_pane
local ai="$1"
local ai2="$2"
# Use TMUX_PANE for the pane we're running in (stable even if active window changes)
editor_pane="$TMUX_PANE"
# Name the current window after the base directory name
tmux rename-window -t "$editor_pane" "$(basename "$current_dir")"
# Split window vertically - top 85%, bottom 15% (target editor pane explicitly)
tmux split-window -v -p 15 -t "$editor_pane" -c "$current_dir"
# Split editor pane horizontally - AI on right 30% (capture new pane ID directly)
ai_pane=$(tmux split-window -h -p 30 -t "$editor_pane" -c "$current_dir" -P -F '#{pane_id}')
# If second AI provided, split the AI pane vertically
if [[ -n $ai2 ]]; then
ai2_pane=$(tmux split-window -v -t "$ai_pane" -c "$current_dir" -P -F '#{pane_id}')
tmux send-keys -t "$ai2_pane" "$ai2" C-m
fi
# Run ai in the right pane
tmux send-keys -t "$ai_pane" "$ai" C-m
# Run nvim in the left pane
tmux send-keys -t "$editor_pane" "$EDITOR ." C-m
# Select the nvim pane for focus
tmux select-pane -t "$editor_pane"
}
# Create multiple tdl windows with one per subdirectory in the current directory
# Usage: tdlm <c|cx|codex|other_ai> [<second_ai>]
tdlm() {
[[ -z $1 ]] && { echo "Usage: tdlm <c|cx|codex|other_ai> [<second_ai>]"; return 1; }
[[ -z $TMUX ]] && { echo "You must start tmux to use tdlm."; return 1; }
local ai="$1"
local ai2="$2"
local base_dir="$PWD"
local first=true
# Rename the session to the current directory name (replace dots/colons which tmux disallows)
tmux rename-session "$(basename "$base_dir" | tr '.:' '--')"
for dir in "$base_dir"/*/; do
[[ -d $dir ]] || continue
local dirpath="${dir%/}"
if $first; then
# Reuse the current window for the first project
tmux send-keys -t "$TMUX_PANE" "cd '$dirpath' && tdl $ai $ai2" C-m
first=false
else
local pane_id=$(tmux new-window -c "$dirpath" -P -F '#{pane_id}')
tmux send-keys -t "$pane_id" "tdl $ai $ai2" C-m
fi
done
}
# Create a multi-pane swarm layout with the same command started in each pane (great for AI)
# Usage: tsl <pane_count> <command>
tsl() {
[[ -z $1 || -z $2 ]] && { echo "Usage: tsl <pane_count> <command>"; return 1; }
[[ -z $TMUX ]] && { echo "You must start tmux to use tsl."; return 1; }
local count="$1"
local cmd="$2"
local current_dir="${PWD}"
local -a panes
tmux rename-window -t "$TMUX_PANE" "$(basename "$current_dir")"
panes+=("$TMUX_PANE")
while (( ${#panes[@]} < count )); do
local new_pane
local split_target="${panes[-1]}"
new_pane=$(tmux split-window -h -t "$split_target" -c "$current_dir" -P -F '#{pane_id}')
panes+=("$new_pane")
tmux select-layout -t "${panes[0]}" tiled
done
for pane in "${panes[@]}"; do
tmux send-keys -t "$pane" "$cmd" C-m
done
tmux select-pane -t "${panes[0]}"
}

View File

@@ -1,53 +0,0 @@
# Transcode a video to a good-balance 1080p that's great for sharing online
transcode-video-1080p() {
ffmpeg -i "$1" -vf scale=1920:1080 -c:v libx264 -preset fast -crf 23 -c:a copy "${1%.*}-1080p.mp4"
}
# Transcode a video to a good-balance 4K that's great for sharing online
transcode-video-4K() {
ffmpeg -i "$1" -c:v libx265 -preset slow -crf 24 -c:a aac -b:a 192k "${1%.*}-optimized.mp4"
}
# Transcode any image to JPG image that's great for shrinking wallpapers
img2jpg() {
img="$1"
shift
magick "$img" "$@" -quality 85 -strip "${img%.*}-converted.jpg"
}
# Transcode any image to a small JPG (max 1080px wide)
img2jpg-small() {
img="$1"
shift
magick "$img" "$@" -resize 1080x\> -quality 85 -strip "${img%.*}-small.jpg"
}
# Transcode any image to a 4K JPG (max 2160px wide)
img2jpg-medium() {
img="$1"
shift
magick "$img" "$@" -resize 2160x\> -quality 85 -strip "${img%.*}-medium.jpg"
}
# Transcode any image to a 6K JPG (max 3160px wide)
img2jpg-large() {
img="$1"
shift
magick "$img" "$@" -resize 3160x\> -quality 85 -strip "${img%.*}-large.jpg"
}
# Transcode any image to compressed-but-lossless PNG
img2png() {
img="$1"
shift
magick "$img" "$@" -strip -define png:compression-filter=5 \
-define png:compression-level=9 \
-define png:compression-strategy=1 \
-define png:exclude-chunk=all \
"${img%.*}-optimized.png"
}

View File

@@ -1,36 +0,0 @@
# Create a new worktree and branch from within current git directory.
ga() {
if [[ -z "$1" ]]; then
echo "Usage: ga [branch name]"
return 1
fi
local branch="$1"
local base="$(basename "$PWD")"
local wt_path="../${base}--${branch}"
git worktree add -b "$branch" "$wt_path"
mise trust "$wt_path"
cd "$wt_path"
}
# Remove worktree and branch from within active worktree directory.
gd() {
if gum confirm "Remove worktree and branch?"; then
local cwd base branch root worktree
cwd="$(pwd)"
worktree="$(basename "$cwd")"
# split on first `--`
root="${worktree%%--*}"
branch="${worktree#*--}"
# Protect against accidentally nuking a non-worktree directory
if [[ "$root" != "$worktree" ]]; then
cd "../$root"
git worktree remove "$cwd" --force || return 1
git branch -D "$branch"
fi
fi
}

View File

@@ -1 +0,0 @@
for f in $HOME/.config/nomarchy/default/bash/fns/*; do source "$f"; done

View File

@@ -1,24 +0,0 @@
if command -v mise &> /dev/null; then
eval "$(mise activate bash)"
fi
if command -v starship &> /dev/null; then
eval "$(starship init bash)"
fi
if command -v zoxide &> /dev/null; then
eval "$(zoxide init bash)"
fi
if command -v try &> /dev/null; then
eval "$(SHELL=/bin/bash command try init ~/Work/tries)"
fi
if command -v fzf &> /dev/null; then
if [[ -f /usr/share/fzf/completion.bash ]]; then
source /usr/share/fzf/completion.bash
fi
if [[ -f /usr/share/fzf/key-bindings.bash ]]; then
source /usr/share/fzf/key-bindings.bash
fi
fi

View File

@@ -1,47 +0,0 @@
set meta-flag on
set input-meta on
set output-meta on
set convert-meta off
set completion-ignore-case on
set completion-prefix-display-length 2
set show-all-if-ambiguous on
set show-all-if-unmodified on
# Arrow keys match what you've typed so far against your command history
"\e[A": history-search-backward
"\e[B": history-search-forward
"\e[C": forward-char
"\e[D": backward-char
# Immediately add a trailing slash when autocompleting symlinks to directories
set mark-symlinked-directories on
# Do not autocomplete hidden files unless the pattern explicitly begins with a dot
set match-hidden-files off
# Show all autocomplete results at once
set page-completions off
# If there are more than 200 possible completions for a word, ask to show them all
set completion-query-items 200
# Show extra file information when completing, like `ls -F` does
set visible-stats on
# Be more intelligent when autocompleting by also looking at the text after
# the cursor. For example, when the current line is "cd ~/src/mozil", and
# the cursor is on the "z", pressing Tab will not autocomplete it to "cd
# ~/src/mozillail", but to "cd ~/src/mozilla". (This is supported by the
# Readline used by Bash 4.)
set skip-completed-text on
# Coloring for Bash 4 tab completions.
set colored-stats on
# Cycle forward and backward through completion candidates (tab/shift+tab)
# (completion listing and display behavior configured above)
TAB: menu-complete
"\e[Z": menu-complete-backward
# On first Tab, complete the common prefix before cycling candidates
set menu-complete-display-prefix on

View File

@@ -1,6 +0,0 @@
source ~/.config/nomarchy/default/bash/envs
source ~/.config/nomarchy/default/bash/shell
source ~/.config/nomarchy/default/bash/aliases
source ~/.config/nomarchy/default/bash/functions
source ~/.config/nomarchy/default/bash/init
[[ $- == *i* ]] && bind -f ~/.config/nomarchy/default/bash/inputrc

View File

@@ -1,13 +0,0 @@
# History control
shopt -s histappend
HISTCONTROL=ignoreboth
HISTSIZE=32768
HISTFILESIZE="${HISTSIZE}"
# Autocompletion
if [[ ! -v BASH_COMPLETION_VERSINFO && -f /usr/share/bash-completion/bash_completion ]]; then
source /usr/share/bash-completion/bash_completion
fi
# Ensure command hashing is off for mise
set +h

View File

@@ -1,21 +0,0 @@
chrome.commands.onCommand.addListener((command) => {
if (command === 'copy-url') {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
const currentTab = tabs[0];
chrome.scripting.executeScript({
target: { tabId: currentTab.id },
func: () => {
navigator.clipboard.writeText(window.location.href);
}
}).then(() => {
chrome.notifications.create({
type: 'basic',
iconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==',
title: ' URL copied to clipboard',
message: ''
});
});
});
}
});

View File

@@ -1 +0,0 @@
../../../../icon.png

View File

@@ -1,19 +0,0 @@
{
"manifest_version": 3,
"name": "Copy URL",
"version": "1.0",
"description": "Copy current URL to clipboard, this extension is installed by Nomarchy",
"permissions": ["activeTab", "scripting", "notifications"],
"icons": {
"16": "icon.png",
"48": "icon.png",
"128": "icon.png"
},
"commands": {
"copy-url": {
"suggested_key": {"default": "Alt+Shift+L"},
"description": "Copy URL"
}
},
"background": {"service_worker": "background.js"}
}

View File

@@ -1,73 +0,0 @@
Name = "nomarchyBackgroundSelector"
NamePretty = "Nomarchy Background Selector"
Cache = false
HideFromProviderlist = true
SearchName = true
local function ShellEscape(s)
return "'" .. s:gsub("'", "'\\''") .. "'"
end
function FormatName(filename)
-- Remove leading number and dash
local name = filename:gsub("^%d+", ""):gsub("^%-", "")
-- Remove extension
name = name:gsub("%.[^%.]+$", "")
-- Replace dashes with spaces
name = name:gsub("-", " ")
-- Capitalize each word
name = name:gsub("%S+", function(word)
return word:sub(1, 1):upper() .. word:sub(2):lower()
end)
return name
end
function GetEntries()
local entries = {}
local home = os.getenv("HOME")
-- Read current theme name
local theme_name_file = io.open(home .. "/.config/nomarchy/current/theme.name", "r")
local theme_name = theme_name_file and theme_name_file:read("*l") or nil
if theme_name_file then
theme_name_file:close()
end
-- Directories to search
local dirs = {
home .. "/.config/nomarchy/current/theme/backgrounds",
}
if theme_name then
table.insert(dirs, home .. "/.config/nomarchy/backgrounds/" .. theme_name)
end
-- Track added files to avoid duplicates
local seen = {}
for _, wallpaper_dir in ipairs(dirs) do
local handle = io.popen(
"find " .. ShellEscape(wallpaper_dir)
.. " -maxdepth 1 -type f \\( -name '*.jpg' -o -name '*.jpeg' -o -name '*.png' -o -name '*.gif' -o -name '*.bmp' -o -name '*.webp' \\) 2>/dev/null | sort"
)
if handle then
for background in handle:lines() do
local filename = background:match("([^/]+)$")
if filename and not seen[filename] then
seen[filename] = true
table.insert(entries, {
Text = FormatName(filename),
Value = background,
Actions = {
activate = "nomarchy-theme-bg-set " .. ShellEscape(background),
},
Preview = background,
PreviewType = "file",
})
end
end
handle:close()
end
end
return entries
end

View File

@@ -1,95 +0,0 @@
--
-- Dynamic Nomarchy Theme Menu for Elephant/Walker
--
Name = "nomarchythemes"
NamePretty = "Nomarchy Themes"
HideFromProviderlist = true
-- Check if file exists using Lua (no subprocess)
local function file_exists(path)
local f = io.open(path, "r")
if f then
f:close()
return true
end
return false
end
-- Get first matching file from directory using ls (single call for fallback)
local function first_image_in_dir(dir)
local handle = io.popen("ls -1 '" .. dir .. "' 2>/dev/null | head -n 1")
if handle then
local file = handle:read("*l")
handle:close()
if file and file ~= "" then
return dir .. "/" .. file
end
end
return nil
end
-- The main function elephant will call
function GetEntries()
local entries = {}
local user_theme_dir = os.getenv("HOME") .. "/.config/nomarchy/themes"
local default_theme_dir = os.getenv("HOME") .. "/.local/share/nomarchy/themes"
local seen_themes = {}
-- Helper function to process themes from a directory
local function process_themes_from_dir(theme_dir)
-- Single find call to get all theme directories
local handle = io.popen("find -L '" .. theme_dir .. "' -mindepth 1 -maxdepth 1 -type d 2>/dev/null")
if not handle then
return
end
for theme_path in handle:lines() do
local theme_name = theme_path:match(".*/(.+)$")
if theme_name and not seen_themes[theme_name] then
seen_themes[theme_name] = true
-- Check for preview images directly (no subprocess)
local preview_path = nil
local preview_png = theme_path .. "/preview.png"
local preview_jpg = theme_path .. "/preview.jpg"
if file_exists(preview_png) then
preview_path = preview_png
elseif file_exists(preview_jpg) then
preview_path = preview_jpg
else
-- Fallback: get first image from backgrounds (one ls call)
preview_path = first_image_in_dir(theme_path .. "/backgrounds")
end
if preview_path and preview_path ~= "" then
local display_name = theme_name:gsub("_", " "):gsub("%-", " ")
display_name = display_name:gsub("(%a)([%w_']*)", function(first, rest)
return first:upper() .. rest:lower()
end)
display_name = display_name .. " "
table.insert(entries, {
Text = display_name,
Preview = preview_path,
PreviewType = "file",
Actions = {
activate = "nomarchy-theme-set " .. theme_name,
},
})
end
end
end
handle:close()
end
-- Process user themes first (they take precedence)
process_themes_from_dir(user_theme_dir)
-- Then process default themes (only if not already seen)
process_themes_from_dir(default_theme_dir)
return entries
end

View File

@@ -1,3 +0,0 @@
window-padding-x = 0
window-padding-y = 0
window-padding-color = "extend-always"

View File

@@ -1,7 +0,0 @@
keyserver hkps://keyserver.ubuntu.com
keyserver hkps://pgp.surfnet.nl
keyserver hkps://keys.mailvelope.com
keyserver hkps://keyring.debian.org
keyserver hkps://pgp.mit.edu
connect-quick-timeout 4

View File

@@ -1,9 +0,0 @@
# App-specific tweaks
source = ~/.config/nomarchy/default/hypr/apps/browser.conf
source = ~/.config/nomarchy/default/hypr/apps/hyprshot.conf
source = ~/.config/nomarchy/default/hypr/apps/localsend.conf
source = ~/.config/nomarchy/default/hypr/apps/retroarch.conf
source = ~/.config/nomarchy/default/hypr/apps/telegram.conf
source = ~/.config/nomarchy/default/hypr/apps/terminals.conf
source = ~/.config/nomarchy/default/hypr/apps/walker.conf
source = ~/.config/nomarchy/default/hypr/apps/webcam-overlay.conf

View File

@@ -1,2 +0,0 @@
windowrulev2 = noscreenshare, class:^(1[p|P]assword)$
windowrulev2 = tag +floating-window, class:^(1[p|P]assword)$

View File

@@ -1,6 +0,0 @@
windowrulev2 = noscreenshare, class:^(Bitwarden)$
windowrulev2 = tag +floating-window, class:^(Bitwarden)$
# Bitwarden Chrome Extension
windowrulev2 = noscreenshare, class:chrome-nngceckbapebfimnlniiiahkandclblb-Default
windowrulev2 = tag +floating-window, class:chrome-nngceckbapebfimnlniiiahkandclblb-Default

View File

@@ -1,16 +0,0 @@
# Browser types
windowrulev2 = tag +chromium-based-browser, class:((google-)?[cC]hrom(e|ium)|[bB]rave-browser|[mM]icrosoft-edge|Vivaldi-stable|helium)
windowrulev2 = tag +firefox-based-browser, class:([fF]irefox|zen|librewolf)
windowrulev2 = tag -default-opacity, tag:chromium-based-browser
windowrulev2 = tag -default-opacity, tag:firefox-based-browser
# Video apps: remove chromium browser tag so they don't get opacity applied
windowrulev2 = tag -chromium-based-browser, class:(chrome-youtube.com__-Default|chrome-app.zoom.us__wc_home-Default)
windowrulev2 = tag -default-opacity, class:(chrome-youtube.com__-Default|chrome-app.zoom.us__wc_home-Default)
# Force chromium-based browsers into a tile to deal with --app bug
windowrulev2 = tile, tag:chromium-based-browser
# Only a subtle opacity change, but not for video sites
windowrulev2 = opacity 1.0 0.97, tag:chromium-based-browser
windowrulev2 = opacity 1.0 0.97, tag:firefox-based-browser

View File

@@ -1,2 +0,0 @@
# Focus floating DaVinci Resolve dialog windows
windowrulev2 = stayfocused, class:.*[Rr]esolve.*, float:1

View File

@@ -1,5 +0,0 @@
windowrule {
name = geforce
class:= GeForceNOW
idle_inhibit = fullscreen
}

View File

@@ -1,2 +0,0 @@
# Remove 1px border around hyprshot screenshots
layerrule = noanim, namespace:selection

View File

@@ -1,4 +0,0 @@
# Float LocalSend and fzf file picker
windowrulev2 = float, class:(Share|localsend)
windowrulev2 = center, class:(Share|localsend)
windowrulev2 = size 1100 700, class:localsend

View File

@@ -1,6 +0,0 @@
windowrule {
name = moonlight
class:= com.moonlight_stream.Moonlight
fullscreen = 1
idle_inhibit = fullscreen
}

View File

@@ -1,10 +0,0 @@
# Picture-in-picture overlays
windowrulev2 = tag +pip, title:(Picture.?in.?[Pp]icture)
windowrulev2 = tag -default-opacity, tag:pip
windowrulev2 = float, tag:pip
windowrulev2 = pin, tag:pip
windowrulev2 = size 600 338, tag:pip
windowrulev2 = keep_aspect_ratio on, tag:pip
windowrulev2 = border_size 0, tag:pip
windowrulev2 = opacity 1 1, tag:pip
windowrulev2 = move (monitor_w-window_w-40) (monitor_h*0.04), tag:pip

View File

@@ -1,2 +0,0 @@
windowrulev2 = tag -default-opacity, class:qemu
windowrulev2 = opacity 1 1, class:qemu

View File

@@ -1,4 +0,0 @@
windowrulev2 = fullscreen, class:com.libretro.RetroArch
windowrulev2 = tag -default-opacity, class:com.libretro.RetroArch
windowrulev2 = opacity 1 1, class:com.libretro.RetroArch
windowrulev2 = idleinhibit, fullscreen, class:com.libretro.RetroArch

View File

@@ -1,8 +0,0 @@
# Float Steam
windowrulev2 = float, class:steam
windowrulev2 = center, class:steam, title:Steam
windowrulev2 = tag -default-opacity, class:steam.*
windowrulev2 = opacity 1 1, class:steam.*
windowrulev2 = size 1100 700, class:steam, title:Steam
windowrulev2 = size 460 800, class:steam, title:Friends List
windowrulev2 = idleinhibit, fullscreen, class:steam

View File

@@ -1,23 +0,0 @@
# Floating windows
windowrulev2 = float, tag:floating-window
windowrulev2 = center, tag:floating-window
windowrulev2 = size 875 600, tag:floating-window
windowrulev2 = tag +floating-window, class:(org.nomarchy.bluetui|org.nomarchy.impala|org.nomarchy.wiremix|org.nomarchy.btop|org.nomarchy.terminal|org.nomarchy.bash|org.gnome.NautilusPreviewer|org.gnome.Evince|com.gabm.satty|Nomarchy|About|TUI.float|imv|mpv)
windowrulev2 = tag +floating-window, class:(xdg-desktop-portal-gtk|sublime_text|DesktopEditors|org.gnome.Nautilus), title:^(Open.*Files?|Open [F|f]older.*|Save.*Files?|Save.*As|Save|All Files|.*wants to [open|save].*|[C|c]hoose.*)
windowrulev2 = float, class:org.gnome.Calculator
# Fullscreen screensaver
windowrulev2 = fullscreen, class:org.nomarchy.screensaver
windowrulev2 = float, class:org.nomarchy.screensaver
windowrulev2 = animation slide, class:org.nomarchy.screensaver
# No transparency on media windows
windowrulev2 = tag -default-opacity, class:^(zoom|vlc|mpv|org.kde.kdenlive|com.obsproject.Studio|com.github.PintaProject.Pinta|imv|org.gnome.NautilusPreviewer)$
windowrulev2 = opacity 1 1, class:^(zoom|vlc|mpv|org.kde.kdenlive|com.obsproject.Studio|com.github.PintaProject.Pinta|imv|org.gnome.NautilusPreviewer)$
# Popped window rounding
windowrulev2 = rounding 8, tag:pop
# Prevent idle while open
windowrulev2 = idleinhibit, always, tag:noidle

View File

@@ -1,2 +0,0 @@
# Prevent Telegram from stealing focus on new messages
windowrulev2 = focusonactivate off, class:org.telegram.desktop

View File

@@ -1,4 +0,0 @@
# Define terminal tag to style them uniformly
windowrulev2 = tag +terminal, class:(Alacritty|kitty|com.mitchellh.ghostty)
windowrulev2 = tag -default-opacity, tag:terminal
windowrulev2 = opacity 0.97 0.9, tag:terminal

View File

@@ -1,2 +0,0 @@
# Application-specific animation
layerrule = noanim, namespace:walker

View File

@@ -1,6 +0,0 @@
# Webcam overlay for screen recording
windowrulev2 = float, title:WebcamOverlay
windowrulev2 = pin, title:WebcamOverlay
windowrulev2 = noinitialfocus, title:WebcamOverlay
windowrulev2 = nodim, title:WebcamOverlay
windowrulev2 = move (monitor_w-window_w-40) (monitor_h-window_h-40), title:WebcamOverlay

View File

@@ -1,17 +0,0 @@
exec-once = uwsm-app -- hypridle
exec-once = uwsm-app -- mako
exec-once = nomarchy-welcome
# exec-once = uwsm-app -- waybar
# fcitx5 is autostarted by NixOS's i18n.inputMethod when
# nomarchy.system.inputMethod.enable = true; no manual exec-once needed.
# swaybg is started as a systemd user service (nomarchy-wallpaper.service)
# so failures surface in logs and the wallpaper survives Hyprland restarts.
exec-once = uwsm-app -- swayosd-server
exec-once = nomarchy-on-boot
# Slow app launch fix -- set systemd vars
exec-once = systemctl --user import-environment $(env | cut -d'=' -f 1)
exec-once = dbus-update-activation-environment --systemd --all
# Network Manager
exec-once = uwsm-app 'nm-applet --indicator'

View File

@@ -1,16 +0,0 @@
# Deprecated bindings file. New installations include everything directly.
bindd = SUPER, RETURN, Terminal, exec, $terminal
bindd = SUPER, F, File manager, exec, $fileManager
bindd = SUPER, B, Web browser, exec, $browser
bindd = SUPER, M, Music player, exec, $music
bindd = SUPER, N, Neovim, exec, $terminal -e nvim
bindd = SUPER, T, Top, exec, $terminal -e btop
bindd = SUPER, D, Lazy Docker, exec, $terminal -e lazydocker
bindd = SUPER, G, Messenger, exec, $messenger
bindd = SUPER, O, Obsidian, exec, obsidian -disable-gpu
bindd = SUPER, SLASH, Password manager, exec, $passwordManager
source = ~/.config/nomarchy/default/hypr/bindings/media.conf
source = ~/.config/nomarchy/default/hypr/bindings/tiling-v2.conf
source = ~/.config/nomarchy/default/hypr/bindings/utilities.conf

View File

@@ -1,5 +0,0 @@
# Copy / Paste
bindd = SUPER, C, Universal copy, sendshortcut, CTRL, Insert,
bindd = SUPER, V, Universal paste, sendshortcut, SHIFT, Insert,
bindd = SUPER, X, Universal cut, sendshortcut, CTRL, X,
bindd = SUPER CTRL, V, Clipboard manager, exec, nomarchy-launch-walker -m clipboard

View File

@@ -1,28 +0,0 @@
# Only display the OSD on the currently focused monitor
$osdclient = swayosd-client --monitor "$(hyprctl monitors -j | jq -r '.[] | select(.focused == true).name')"
# Laptop multimedia keys for volume and LCD brightness (with OSD)
bindeld = ,XF86AudioRaiseVolume, Volume up, exec, $osdclient --output-volume raise
bindeld = ,XF86AudioLowerVolume, Volume down, exec, $osdclient --output-volume lower
bindeld = ,XF86AudioMute, Mute, exec, $osdclient --output-volume mute-toggle
bindeld = ,XF86AudioMicMute, Mute microphone, exec, $osdclient --input-volume mute-toggle
bindeld = ,XF86MonBrightnessUp, Brightness up, exec, nomarchy-brightness-display +5%
bindeld = ,XF86MonBrightnessDown, Brightness down, exec, nomarchy-brightness-display 5%-
bindeld = ,XF86KbdBrightnessUp, Keyboard brightness up, exec, nomarchy-brightness-keyboard up
bindeld = ,XF86KbdBrightnessDown, Keyboard brightness down, exec, nomarchy-brightness-keyboard down
bindld = ,XF86KbdLightOnOff, Keyboard backlight cycle, exec, nomarchy-brightness-keyboard cycle
# Precise 1% multimedia adjustments with Alt modifier
bindeld = ALT, XF86AudioRaiseVolume, Volume up precise, exec, $osdclient --output-volume +1
bindeld = ALT, XF86AudioLowerVolume, Volume down precise, exec, $osdclient --output-volume -1
bindeld = ALT, XF86MonBrightnessUp, Brightness up precise, exec, nomarchy-brightness-display +1%
bindeld = ALT, XF86MonBrightnessDown, Brightness down precise, exec, nomarchy-brightness-display 1%-
# Requires playerctl
bindld = , XF86AudioNext, Next track, exec, $osdclient --playerctl next
bindld = , XF86AudioPause, Pause, exec, $osdclient --playerctl play-pause
bindld = , XF86AudioPlay, Play, exec, $osdclient --playerctl play-pause
bindld = , XF86AudioPrev, Previous track, exec, $osdclient --playerctl previous
# Switch audio output with Super + Mute
bindld = SUPER, XF86AudioMute, Switch audio output, exec, nomarchy-cmd-audio-switch

View File

@@ -1,128 +0,0 @@
# Close windows
bindd = SUPER, W, Close window, killactive,
bindd = CTRL ALT, DELETE, Close all windows, exec, nomarchy-hyprland-window-close-all
# Control tiling
bindd = SUPER, J, Toggle window split, layoutmsg, togglesplit
bindd = SUPER, P, Pseudo window, pseudo, # dwindle
bindd = SUPER, T, Toggle window floating/tiling, togglefloating,
bindd = SUPER, F, Full screen, fullscreen, 0
bindd = SUPER CTRL, F, Tiled full screen, fullscreenstate, 0 2
bindd = SUPER ALT, F, Full width, fullscreen, 1
bindd = SUPER, O, Pop window out (float & pin), exec, nomarchy-hyprland-window-pop
bindd = SUPER, L, Toggle workspace layout, exec, nomarchy-hyprland-workspace-layout-toggle
# Move focus with SUPER + arrow keys
bindd = SUPER, LEFT, Move window focus left, movefocus, l
bindd = SUPER, RIGHT, Move window focus right, movefocus, r
bindd = SUPER, UP, Move window focus up, movefocus, u
bindd = SUPER, DOWN, Move window focus down, movefocus, d
# Switch workspaces with SUPER + [1-9; 0]
bindd = SUPER, code:10, Switch to workspace 1, workspace, 1
bindd = SUPER, code:11, Switch to workspace 2, workspace, 2
bindd = SUPER, code:12, Switch to workspace 3, workspace, 3
bindd = SUPER, code:13, Switch to workspace 4, workspace, 4
bindd = SUPER, code:14, Switch to workspace 5, workspace, 5
bindd = SUPER, code:15, Switch to workspace 6, workspace, 6
bindd = SUPER, code:16, Switch to workspace 7, workspace, 7
bindd = SUPER, code:17, Switch to workspace 8, workspace, 8
bindd = SUPER, code:18, Switch to workspace 9, workspace, 9
bindd = SUPER, code:19, Switch to workspace 10, workspace, 10
# Move active window to a workspace with SUPER + SHIFT + [1-9; 0]
bindd = SUPER SHIFT, code:10, Move window to workspace 1, movetoworkspace, 1
bindd = SUPER SHIFT, code:11, Move window to workspace 2, movetoworkspace, 2
bindd = SUPER SHIFT, code:12, Move window to workspace 3, movetoworkspace, 3
bindd = SUPER SHIFT, code:13, Move window to workspace 4, movetoworkspace, 4
bindd = SUPER SHIFT, code:14, Move window to workspace 5, movetoworkspace, 5
bindd = SUPER SHIFT, code:15, Move window to workspace 6, movetoworkspace, 6
bindd = SUPER SHIFT, code:16, Move window to workspace 7, movetoworkspace, 7
bindd = SUPER SHIFT, code:17, Move window to workspace 8, movetoworkspace, 8
bindd = SUPER SHIFT, code:18, Move window to workspace 9, movetoworkspace, 9
bindd = SUPER SHIFT, code:19, Move window to workspace 10, movetoworkspace, 10
# Move active window silently to a workspace with SUPER + SHIFT + ALT + [1-9; 0]
bindd = SUPER SHIFT ALT, code:10, Move window silently to workspace 1, movetoworkspacesilent, 1
bindd = SUPER SHIFT ALT, code:11, Move window silently to workspace 2, movetoworkspacesilent, 2
bindd = SUPER SHIFT ALT, code:12, Move window silently to workspace 3, movetoworkspacesilent, 3
bindd = SUPER SHIFT ALT, code:13, Move window silently to workspace 4, movetoworkspacesilent, 4
bindd = SUPER SHIFT ALT, code:14, Move window silently to workspace 5, movetoworkspacesilent, 5
bindd = SUPER SHIFT ALT, code:15, Move window silently to workspace 6, movetoworkspacesilent, 6
bindd = SUPER SHIFT ALT, code:16, Move window silently to workspace 7, movetoworkspacesilent, 7
bindd = SUPER SHIFT ALT, code:17, Move window silently to workspace 8, movetoworkspacesilent, 8
bindd = SUPER SHIFT ALT, code:18, Move window silently to workspace 9, movetoworkspacesilent, 9
bindd = SUPER SHIFT ALT, code:19, Move window silently to workspace 10, movetoworkspacesilent, 10
# Control scratchpad
bindd = SUPER, S, Toggle scratchpad, togglespecialworkspace, scratchpad
bindd = SUPER ALT, S, Move window to scratchpad, movetoworkspacesilent, special:scratchpad
# TAB between workspaces
bindd = SUPER, TAB, Next workspace, workspace, e+1
bindd = SUPER SHIFT, TAB, Previous workspace, workspace, e-1
bindd = SUPER CTRL, TAB, Former workspace, workspace, previous
# Move workspaces to other monitors
bindd = SUPER SHIFT ALT, LEFT, Move workspace to left monitor, movecurrentworkspacetomonitor, l
bindd = SUPER SHIFT ALT, RIGHT, Move workspace to right monitor, movecurrentworkspacetomonitor, r
bindd = SUPER SHIFT ALT, UP, Move workspace to up monitor, movecurrentworkspacetomonitor, u
bindd = SUPER SHIFT ALT, DOWN, Move workspace to down monitor, movecurrentworkspacetomonitor, d
# Swap active window with the one next to it with SUPER + SHIFT + arrow keys
bindd = SUPER SHIFT, LEFT, Swap window to the left, swapwindow, l
bindd = SUPER SHIFT, RIGHT, Swap window to the right, swapwindow, r
bindd = SUPER SHIFT, UP, Swap window up, swapwindow, u
bindd = SUPER SHIFT, DOWN, Swap window down, swapwindow, d
# Cycle through applications on active workspace
bindd = ALT, TAB, Cycle to next window, cyclenext
bindd = ALT SHIFT, TAB, Cycle to prev window, cyclenext, prev
bindd = ALT, TAB, Reveal active window on top, bringactivetotop
bindd = ALT SHIFT, TAB, Reveal active window on top, bringactivetotop
# Resize active window
bindd = SUPER, code:20, Expand window left, resizeactive, -100 0 # - key
bindd = SUPER, code:21, Shrink window left, resizeactive, 100 0 # = key
bindd = SUPER SHIFT, code:20, Shrink window up, resizeactive, 0 -100
bindd = SUPER SHIFT, code:21, Expand window down, resizeactive, 0 100
# Scroll through existing workspaces with SUPER + scroll
bindd = SUPER, mouse_down, Scroll active workspace forward, workspace, e+1
bindd = SUPER, mouse_up, Scroll active workspace backward, workspace, e-1
# Move/resize windows with mainMod + LMB/RMB and dragging
bindmd = SUPER, mouse:272, Move window, movewindow
bindmd = SUPER, mouse:273, Resize window, resizewindow
# Toggle groups
bindd = SUPER, G, Toggle window grouping, togglegroup
bindd = SUPER ALT, G, Move active window out of group, moveoutofgroup
# Join groups
bindd = SUPER ALT, LEFT, Move window to group on left, moveintogroup, l
bindd = SUPER ALT, RIGHT, Move window to group on right, moveintogroup, r
bindd = SUPER ALT, UP, Move window to group on top, moveintogroup, u
bindd = SUPER ALT, DOWN, Move window to group on bottom, moveintogroup, d
# Navigate a single set of grouped windows
bindd = SUPER ALT, TAB, Next window in group, changegroupactive, f
bindd = SUPER ALT SHIFT, TAB, Previous window in group, changegroupactive, b
# Window navigation for grouped windows
bindd = SUPER CTRL, LEFT, Move grouped window focus left, changegroupactive, b
bindd = SUPER CTRL, RIGHT, Move grouped window focus right, changegroupactive, f
# Scroll through a set of grouped windows with SUPER + ALT + scroll
bindd = SUPER ALT, mouse_down, Next window in group, changegroupactive, f
bindd = SUPER ALT, mouse_up, Previous window in group, changegroupactive, b
# Activate window in a group by number
bindd = SUPER ALT, code:10, Switch to group window 1, changegroupactive, 1
bindd = SUPER ALT, code:11, Switch to group window 2, changegroupactive, 2
bindd = SUPER ALT, code:12, Switch to group window 3, changegroupactive, 3
bindd = SUPER ALT, code:13, Switch to group window 4, changegroupactive, 4
bindd = SUPER ALT, code:14, Switch to group window 5, changegroupactive, 5
# Cycle monitor scaling
bindd = SUPER, Slash, Cycle monitor scaling, exec, nomarchy-hyprland-monitor-scaling-cycle

View File

@@ -1,62 +0,0 @@
# Menus
bindd = SUPER, SPACE, Launch apps, exec, nomarchy-launch-walker
bindd = SUPER CTRL, E, Emoji picker, exec, nomarchy-menu symbols
bindd = SUPER CTRL, C, Capture menu, exec, nomarchy-menu capture
bindd = SUPER CTRL, O, Toggle menu, exec, nomarchy-menu toggle
bindd = SUPER ALT, SPACE, Toggle top bar, exec, nomarchy-toggle-waybar
bindd = SUPER, ESCAPE, System menu, exec, nomarchy-menu system
bindld = , XF86PowerOff, Power menu, exec, nomarchy-menu system
bindd = SUPER, K, Show key bindings, exec, nomarchy-menu-keybindings
bindd = , XF86Calculator, Calculator, exec, gnome-calculator
# Aesthetics
bindd = SUPER SHIFT, SPACE, Nomarchy menu, exec, nomarchy-menu
bindd = SUPER CTRL, SPACE, Theme background menu, exec, nomarchy-menu background
bindd = SUPER SHIFT CTRL, SPACE, Theme menu, exec, nomarchy-menu theme
bindd = SUPER, BACKSPACE, Toggle window transparency, exec, nomarchy-hyprland-active-window-transparency-toggle
bindd = SUPER SHIFT, BACKSPACE, Toggle window gaps, exec, nomarchy-hyprland-window-gaps-toggle
bindd = SUPER CTRL, BACKSPACE, Toggle single-window square aspect, exec, nomarchy-hyprland-window-single-square-aspect-toggle
# Notifications
bindd = SUPER, COMMA, Dismiss last notification, exec, makoctl dismiss
bindd = SUPER SHIFT, COMMA, Dismiss all notifications, exec, makoctl dismiss --all
bindd = SUPER CTRL, COMMA, Toggle silencing notifications, exec, nomarchy-toggle-notification-silencing
bindd = SUPER ALT, COMMA, Invoke last notification, exec, makoctl invoke
bindd = SUPER SHIFT ALT, COMMA, Restore last notification, exec, makoctl restore
# Toggles
bindd = SUPER CTRL, I, Toggle locking on idle, exec, nomarchy-toggle-idle
bindd = SUPER CTRL, N, Toggle nightlight, exec, nomarchy-toggle-nightlight
# Control Apple Display brightness
bindd = CTRL, F1, Apple Display brightness down, exec, nomarchy-brightness-display-apple -5000
bindd = CTRL, F2, Apple Display brightness up, exec, nomarchy-brightness-display-apple +5000
bindd = SHIFT CTRL, F2, Apple Display full brightness, exec, nomarchy-brightness-display-apple +60000
# Captures
bindd = , PRINT, Screenshot, exec, nomarchy-cmd-screenshot
bindd = ALT, PRINT, Screenrecording, exec, nomarchy-menu screenrecord
bindd = SUPER, PRINT, Color picker, exec, pkill hyprpicker || hyprpicker -a
# File sharing
bindd = SUPER CTRL, S, Share, exec, nomarchy-menu share
# Waybar-less information
bindd = SUPER CTRL ALT, T, Show time, exec, notify-send -u low " $(date +"%A %H:%M · %d %B %Y · Week %V")"
bindd = SUPER CTRL ALT, B, Show battery remaining, exec, notify-send -u low "$(nomarchy-battery-status)"
# Control panels
bindd = SUPER CTRL, A, Audio controls, exec, nomarchy-launch-audio
bindd = SUPER CTRL, B, Bluetooth controls, exec, nomarchy-launch-bluetooth
bindd = SUPER CTRL, W, Wifi controls, exec, nomarchy-launch-wifi
bindd = SUPER CTRL, T, Activity, exec, nomarchy-launch-tui btop
# Dictation
bindd = SUPER CTRL, X, Toggle dictation, exec, voxtype record toggle
# Zoom
bindd = SUPER CTRL, Z, Zoom in, exec, hyprctl keyword cursor:zoom_factor $(hyprctl getoption cursor:zoom_factor -j | jq '.float + 1')
bindd = SUPER CTRL ALT, Z, Reset zoom, exec, hyprctl keyword cursor:zoom_factor 1
# Lock system
bindd = SUPER CTRL, L, Lock system, exec, nomarchy-lock-screen

View File

@@ -1,12 +0,0 @@
# Hyprland Color Configuration (Visual)
# This file contains only color-related settings.
# It's sourced AFTER theme colors are applied, allowing theme-specific overrides.
# These are placeholder values - actual colors come from the active theme
# via ~/.config/nomarchy/current/theme/hyprland.conf
# Border colors (set by theme-loader based on active theme)
# The theme's hyprland.conf will define $activeBorderColor and $inactiveBorderColor
# Group bar colors (set by theme)
# Themes can override group bar colors in their hyprland.conf

View File

@@ -1,29 +0,0 @@
# Cursor size
env = XCURSOR_SIZE,24
env = HYPRCURSOR_SIZE,24
# Force all apps to use Wayland
env = GDK_BACKEND,wayland,x11,*
env = QT_QPA_PLATFORM,wayland;xcb
env = QT_STYLE_OVERRIDE,kvantum
env = SDL_VIDEODRIVER,wayland,x11
env = MOZ_ENABLE_WAYLAND,1
env = ELECTRON_OZONE_PLATFORM_HINT,wayland
env = OZONE_PLATFORM,wayland
env = XDG_SESSION_TYPE,wayland
# Allow better support for screen sharing (Google Meet, Discord, etc)
env = XDG_CURRENT_DESKTOP,Hyprland
env = XDG_SESSION_DESKTOP,Hyprland
xwayland {
force_zero_scaling = true
}
# Use XCompose file
env = XCOMPOSEFILE,~/.XCompose
# Don't show update on first launch
ecosystem {
no_update_news = true
}

View File

@@ -1,21 +0,0 @@
# https://wiki.hyprland.org/Configuring/Variables/#input
input {
kb_layout = us
kb_variant =
kb_model =
kb_options = compose:caps
kb_rules =
follow_mouse = 1
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
touchpad {
natural_scroll = false
}
}
misc {
key_press_enables_dpms = true # key press will trigger wake
mouse_move_enables_dpms = true # mouse move will trigger wake
}

View File

@@ -1,146 +0,0 @@
# Refer to https://wiki.hyprland.org/Configuring/Variables/
# Variables
$activeBorderColor = rgba(33ccffee) rgba(00ff99ee) 45deg
$inactiveBorderColor = rgba(595959aa)
# https://wiki.hyprland.org/Configuring/Variables/#general
general {
gaps_in = 5
gaps_out = 10
border_size = 2
# https://wiki.hyprland.org/Configuring/Variables/#variable-types for info about colors
col.active_border = $activeBorderColor
col.inactive_border = $inactiveBorderColor
# Set to true enable resizing windows by clicking and dragging on borders and gaps
resize_on_border = false
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
allow_tearing = false
layout = dwindle
}
# https://wiki.hyprland.org/Configuring/Variables/#decoration
decoration {
rounding = 0
shadow {
enabled = true
range = 2
render_power = 3
color = rgba(1a1a1aee)
}
# https://wiki.hyprland.org/Configuring/Variables/#blur
blur {
enabled = true
size = 2
passes = 2
special = true
brightness = 0.60
contrast = 0.75
}
}
# https://wiki.hypr.land/Configuring/Variables/#group
group {
col.border_active = $activeBorderColor
col.border_inactive = $inactiveBorderColor
col.border_locked_active = -1
col.border_locked_inactive = -1
groupbar {
font_size = 12
font_family = monospace
font_weight_active = ultraheavy
font_weight_inactive = normal
indicator_height = 0
indicator_gap = 5
height = 22
gaps_in = 5
gaps_out = 0
text_color = rgb(ffffff)
text_color_inactive = rgba(ffffff90)
col.active = rgba(00000040)
col.inactive = rgba(00000020)
gradients = true
gradient_rounding = 0
gradient_round_only_edges = false
}
}
# https://wiki.hyprland.org/Configuring/Variables/#animations
animations {
enabled = yes
# Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
bezier = easeOutQuint,0.23,1,0.32,1
bezier = easeInOutCubic,0.65,0.05,0.36,1
bezier = linear,0,0,1,1
bezier = almostLinear,0.5,0.5,0.75,1.0
bezier = quick,0.15,0,0.1,1
animation = global, 1, 10, default
animation = border, 1, 5.39, easeOutQuint
animation = windows, 1, 4.79, easeOutQuint
animation = windowsIn, 1, 4.1, easeOutQuint, popin 87%
animation = windowsOut, 1, 1.49, linear, popin 87%
animation = fadeIn, 1, 1.73, almostLinear
animation = fadeOut, 1, 1.46, almostLinear
animation = fade, 1, 3.03, quick
animation = layers, 1, 3.81, easeOutQuint
animation = layersIn, 1, 4, easeOutQuint, fade
animation = layersOut, 1, 1.5, linear, fade
animation = fadeLayersIn, 1, 1.79, almostLinear
animation = fadeLayersOut, 1, 1.39, almostLinear
animation = workspaces, 0, 0, ease
animation = specialWorkspace, 1, 4, easeOutQuint, slidevert
}
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
dwindle {
pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
preserve_split = true # You probably want this
force_split = 2 # Always split on the right
}
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
master {
new_status = master
}
# https://wiki.hyprland.org/Configuring/Variables/#misc
misc {
disable_hyprland_logo = true
disable_splash_rendering = true
disable_scale_notification = true
focus_on_activate = true
}
# https://wiki.hypr.land/Configuring/Variables/#cursor
cursor {
hide_on_key_press = true
warp_on_change_workspace = 1
}
# Auto toggle scratchpad on switching workspace from scratchpad
binds {
hide_special_on_workspace_change = true
}
# Style Gum confirm to match terminal theme
env = GUM_CONFIRM_PROMPT_FOREGROUND,6 # Cyan
env = GUM_CONFIRM_SELECTED_FOREGROUND,0 # Black
env = GUM_CONFIRM_SELECTED_BACKGROUND,2 # Green
env = GUM_CONFIRM_UNSELECTED_FOREGROUND,7 # White
env = GUM_CONFIRM_UNSELECTED_BACKGROUND,8 # Dark grey
# Dark grey

View File

@@ -1,16 +0,0 @@
# Application bindings
bindd = SUPER, RETURN, Terminal, exec, uwsm-app -- xdg-terminal-exec --dir="$(nomarchy-cmd-terminal-cwd)"
bindd = SUPER SHIFT, RETURN, Browser, exec, nomarchy-launch-browser
bindd = SUPER SHIFT, F, File manager, exec, uwsm-app -- nautilus --new-window
bindd = SUPER ALT SHIFT, F, File manager (cwd), exec, uwsm-app -- nautilus --new-window "$(nomarchy-cmd-terminal-cwd)"
bindd = SUPER SHIFT, B, Browser, exec, nomarchy-launch-browser
bindd = SUPER SHIFT ALT, B, Browser (private), exec, nomarchy-launch-browser --private
bindd = SUPER SHIFT, N, Editor, exec, nomarchy-launch-editor
# Add extra bindings
# bindd = SUPER SHIFT, A, ChatGPT, exec, nomarchy-launch-webapp "https://chatgpt.com"
# bindd = SUPER SHIFT, R, exec, alacritty -e ssh your-server
# Overwrite existing bindings, like putting Nomarchy Menu on Super + Space
# unbind = SUPER, SPACE
# bindd = SUPER, SPACE, Nomarchy menu, exec, nomarchy-menu

View File

@@ -1,15 +0,0 @@
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
# Hyprland 0.53+ syntax
#windowrulev2 = suppressevent maximize, class:.*
# Tag all windows for default opacity (apps can override with -default-opacity tag)
#windowrulev2 = tag +default-opacity, class:.*
# Fix some dragging issues with XWayland
#windowrulev2 = nofocus, class:^$, title:^$, xwayland:1, float:1, fullscreen:0, pin:0
# App-specific tweaks (may remove default-opacity tag)
source = ~/.config/nomarchy/default/hypr/apps.conf
# Apply default opacity after apps have had a chance to opt out
#windowrulev2 = opacity 0.97 0.9, tag:default-opacity

View File

@@ -1,34 +0,0 @@
anchor=top-right
default-timeout=5000
width=420
outer-margin=20
padding=10,15
border-size=2
max-icon-size=32
font=sans-serif 14px
[app-name=Spotify]
invisible=1
[mode=do-not-disturb]
invisible=true
[mode=do-not-disturb app-name=notify-send]
invisible=false
[urgency=critical]
default-timeout=0
layer=overlay
[summary~="Setup Wi-Fi"]
on-button-left=exec sh -c 'nomarchy-notification-dismiss "Setup Wi-Fi"; nomarchy-launch-wifi'
[summary~="Update System"]
on-button-left=exec sh -c 'nomarchy-notification-dismiss "Update System"; nomarchy-launch-floating-terminal-with-presentation nomarchy-update'
[summary~="Learn Keybindings"]
on-button-left=exec sh -c 'nomarchy-notification-dismiss "Learn Keybindings"; nomarchy-menu-keybindings'
[summary~="Screenshot copied & saved"]
max-icon-size=80
format=<b>%s</b>\n%b

View File

@@ -1,97 +0,0 @@
# Voxtype Configuration
#
# Location: ~/.config/voxtype/config.toml
# All settings can be overridden via CLI flags
#
# State file for external integrations (Waybar, polybar, etc.)
# Use "auto" for default location ($XDG_RUNTIME_DIR/voxtype/state),
# a custom path, or "disabled" to turn off. The daemon writes state
# ("idle", "recording", "transcribing") to this file whenever it changes.
# Required for `voxtype record toggle` and `voxtype status` commands.
state_file = "auto"
[hotkey]
# Hotkey is configured in Hyprland. Default is Super + Ctrl + X
enabled = false
[audio]
# Audio input device ("default" uses system default)
# List devices with: pactl list sources short
device = "default"
# Sample rate in Hz (whisper expects 16000)
sample_rate = 16000
# Maximum recording duration in seconds (safety limit)
max_duration_secs = 60
# [audio.feedback]
# Enable audio feedback sounds (beeps when recording starts/stops)
# enabled = true
#
# Sound theme: "default", "subtle", "mechanical", or path to custom theme directory
# theme = "default"
#
# Volume level (0.0 to 1.0)
# volume = 0.7
[whisper]
# Model to use for transcription
# Options: tiny, tiny.en, base, base.en, small, small.en, medium, medium.en, large-v3, large-v3-turbo
# .en models are English-only but faster and more accurate for English
# large-v3-turbo is faster than large-v3 with minimal accuracy loss (recommended for GPU)
# Or provide absolute path to a custom .bin model file
model = "base.en"
# Language for transcription
# Use "en" for English, "auto" for auto-detection
# See: https://github.com/openai/whisper#available-models-and-languages
language = "en"
# Translate non-English speech to English
translate = false
# Number of CPU threads for inference (omit for auto-detection)
# threads = 4
[output]
# Primary output mode: "type" or "clipboard"
# - type: Simulates keyboard input at cursor position (requires ydotool)
# - clipboard: Copies text to clipboard (requires wl-copy)
mode = "type"
# Fall back to clipboard if typing fails
fallback_to_clipboard = true
# Delay between typed characters in milliseconds
# 0 = fastest possible, increase if characters are dropped
type_delay_ms = 1
# Post-processing command (optional)
# Pipe transcribed text through an external command for cleanup before output.
# The command receives text on stdin and outputs processed text on stdout.
# Useful for LLM-based text cleanup, grammar correction, filler word removal.
# On any failure (timeout, error), falls back to original transcription.
#
# [output.post_process]
# command = "ollama run llama3.2:1b 'Clean up this dictation. Fix grammar, remove filler words. Output only the cleaned text:'"
# timeout_ms = 30000 # 30 second timeout (generous for LLM)
[output.notification]
# Show notification when recording starts (hotkey pressed)
on_recording_start = false
# Show notification when recording stops (transcription beginning)
on_recording_stop = false
# Show notification with transcribed text after transcription completes
on_transcription = false
# [text]
# Text processing options (word replacements, spoken punctuation)
#
# Enable spoken punctuation conversion (e.g., say "period" to get ".")
# spoken_punctuation = false
#
# Custom word replacements (case-insensitive)
# replacements = { "hyperwhisper" = "hyprwhspr" }

View File

@@ -1,3 +0,0 @@
[Service]
Restart=always
RestartSec=2

View File

@@ -1,156 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"></requires>
<object class="GtkWindow" id="Window">
<style>
<class name="window"></class>
</style>
<property name="resizable">true</property>
<property name="title">Walker</property>
<child>
<object class="GtkBox" id="BoxWrapper">
<style>
<class name="box-wrapper"></class>
</style>
<property name="width-request">644</property>
<property name="overflow">hidden</property>
<property name="orientation">horizontal</property>
<property name="valign">center</property>
<property name="halign">center</property>
<child>
<object class="GtkBox" id="Box">
<style>
<class name="box"></class>
</style>
<property name="orientation">vertical</property>
<property name="hexpand-set">true</property>
<property name="hexpand">true</property>
<property name="spacing">10</property>
<child>
<object class="GtkBox" id="SearchContainer">
<style>
<class name="search-container"></class>
</style>
<property name="overflow">hidden</property>
<property name="orientation">horizontal</property>
<property name="halign">fill</property>
<property name="hexpand-set">true</property>
<property name="hexpand">true</property>
<child>
<object class="GtkEntry" id="Input">
<style>
<class name="input"></class>
</style>
<property name="halign">fill</property>
<property name="hexpand-set">true</property>
<property name="hexpand">true</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="ContentContainer">
<style>
<class name="content-container"></class>
</style>
<property name="orientation">horizontal</property>
<property name="spacing">10</property>
<property name="vexpand">true</property>
<property name="vexpand-set">true</property>
<child>
<object class="GtkLabel" id="ElephantHint">
<style>
<class name="elephant-hint"></class>
</style>
<property name="hexpand">true</property>
<property name="height-request">100</property>
<property name="label">Waiting for elephant...</property>
</object>
</child>
<child>
<object class="GtkLabel" id="Placeholder">
<style>
<class name="placeholder"></class>
</style>
<property name="label">No Results</property>
<property name="yalign">0.0</property>
<property name="hexpand">true</property>
</object>
</child>
<child>
<object class="GtkScrolledWindow" id="Scroll">
<style>
<class name="scroll"></class>
</style>
<property name="hexpand">true</property>
<property name="can_focus">false</property>
<property name="overlay-scrolling">true</property>
<property name="max-content-width">600</property>
<property name="max-content-height">300</property>
<property name="min-content-height">0</property>
<property name="propagate-natural-height">true</property>
<property name="propagate-natural-width">true</property>
<property name="hscrollbar-policy">automatic</property>
<property name="vscrollbar-policy">automatic</property>
<child>
<object class="GtkGridView" id="List">
<style>
<class name="list"></class>
</style>
<property name="max_columns">1</property>
<property name="can_focus">false</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="Preview">
<style>
<class name="preview"></class>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="Keybinds">
<property name="hexpand">true</property>
<property name="margin-top">10</property>
<style>
<class name="keybinds"></class>
</style>
<child>
<object class="GtkBox" id="GlobalKeybinds">
<property name="spacing">10</property>
<style>
<class name="global-keybinds"></class>
</style>
</object>
</child>
<child>
<object class="GtkBox" id="ItemKeybinds">
<property name="hexpand">true</property>
<property name="halign">end</property>
<property name="spacing">10</property>
<style>
<class name="item-keybinds"></class>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkLabel" id="Error">
<style>
<class name="error"></class>
</style>
<property name="xalign">0</property>
<property name="visible">false</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -1,117 +0,0 @@
@import "../../../../../../../.config/nomarchy/current/theme/walker.css";
* {
all: unset;
}
* {
font-family: monospace;
font-size: 18px;
color: @text;
}
scrollbar {
opacity: 0;
}
.normal-icons {
-gtk-icon-size: 16px;
}
.large-icons {
-gtk-icon-size: 32px;
}
.box-wrapper {
background: alpha(@base, 0.95);
padding: 20px;
border: 2px solid @border;
}
.preview-box {
}
.box {
}
.search-container {
background: @base;
padding: 10px;
}
.input placeholder {
opacity: 0.5;
}
.input {
}
.input:focus,
.input:active {
box-shadow: none;
outline: none;
}
.content-container {
}
.placeholder {
}
.scroll {
}
.list {
}
child,
child > * {
}
child:hover .item-box {
}
child:selected .item-box {
background-color: @selected-background;
}
child:selected .item-box * {
color: @selected-text;
}
.item-box {
padding-left: 14px;
}
.item-text-box {
all: unset;
padding: 14px 0;
}
.item-text {
}
.item-subtext {
font-size: 0px;
min-height: 0px;
margin: 0px;
padding: 0px;
}
.item-image {
margin-right: 14px;
-gtk-icon-transform: scale(0.9);
}
.current {
font-style: italic;
}
.keybind-hints {
background: @background;
padding: 10px;
margin-top: 10px;
}
.preview {
}

View File

@@ -1,7 +0,0 @@
[Desktop Entry]
Name=Walker
Comment=Walker Service
Exec=walker --gapplication-service
StartupNotify=false
Terminal=false
Type=Application

View File

@@ -1,7 +0,0 @@
#!/usr/bin/env bash
if pgrep -x hypridle >/dev/null; then
echo '{"text": ""}'
else
echo '{"text": "󱫖", "tooltip": "Idle lock disabled", "class": "active"}'
fi

View File

@@ -1,7 +0,0 @@
#!/usr/bin/env bash
if makoctl mode | grep -q 'do-not-disturb'; then
echo '{"text": "󰂛", "tooltip": "Notifications silenced", "class": "active"}'
else
echo '{"text": ""}'
fi

View File

@@ -1,7 +0,0 @@
#!/usr/bin/env bash
if pgrep -f "^gpu-screen-recorder" >/dev/null; then
echo '{"text": "󰻂", "tooltip": "Stop recording", "class": "active"}'
else
echo '{"text": ""}'
fi

View File

@@ -1,18 +0,0 @@
## Use software volume control for all ALSA devices.
## This prevents hardware mixer quirks (like muffled audio on Realtek codecs)
## and provides consistent volume behavior across all hardware.
monitor.alsa.rules = [
{
matches = [
{
device.name = "~alsa_card.*"
}
]
actions = {
update-props = {
api.alsa.soft-mixer = true
}
}
}
]

View File

@@ -1,29 +0,0 @@
include "%L"
# Emoji
<Multi_key> <m> <s> : "😄" # smile
<Multi_key> <m> <c> : "😂" # cry
<Multi_key> <m> <l> : "😍" # love
<Multi_key> <m> <v> : "✌️" # victory
<Multi_key> <m> <h> : "❤️" # heart
<Multi_key> <m> <y> : "👍" # yes
<Multi_key> <m> <n> : "👎" # no
<Multi_key> <m> <f> : "🖕" # fuck
<Multi_key> <m> <w> : "🤞" # wish
<Multi_key> <m> <r> : "🤘" # rock
<Multi_key> <m> <k> : "😘" # kiss
<Multi_key> <m> <e> : "🙄" # eyeroll
<Multi_key> <m> <d> : "🤤" # droll
<Multi_key> <m> <m> : "💰" # money
<Multi_key> <m> <x> : "🎉" # xellebrate
<Multi_key> <m> <1> : "💯" # 100%
<Multi_key> <m> <t> : "🥂" # toast
<Multi_key> <m> <p> : "🙏" # pray
<Multi_key> <m> <i> : "😉" # wink
<Multi_key> <m> <o> : "👌" # OK
<Multi_key> <m> <g> : "👋" # greeting
<Multi_key> <m> <a> : "💪" # arm
<Multi_key> <m> <b> : "🤯" # blowing
# Typography
<Multi_key> <space> <space> : "—"

View File

@@ -1,20 +0,0 @@
# Overwrite parts of the nomarchy-menu with user-specific submenus.
# See $OMARCHY_PATH/bin/nomarchy-menu for functions that can be overwritten.
#
# WARNING: Overwritten functions will obviously not be updated when Nomarchy changes.
#
# Example of minimal system menu:
#
# show_system_menu() {
# case $(menu "System" " Lock\n󰐥 Shutdown") in
# *Lock*) nomarchy-lock-screen ;;
# *Shutdown*) nomarchy-system-shutdown ;;
# *) back_to show_main_menu ;;
# esac
# }
#
# Example of overriding just the about menu action: (Using zsh instead of bash (default))
#
# show_about() {
# exec nomarchy-launch-or-focus-tui "zsh -c 'fastfetch; read -k 1'"
# }

View File

@@ -1,10 +0,0 @@
#!/bin/bash
# This hook is called with the current battery percentage when the low battery
# notification is sent. To put it into use, remove .sample from the name.
SOUND_FILE="/usr/share/sounds/freedesktop/stereo/dialog-warning.oga"
if nomarchy-cmd-present mpv && [[ -f $SOUND_FILE ]]; then
mpv --no-video "$SOUND_FILE" >/dev/null 2>&1
fi

View File

@@ -1,7 +0,0 @@
#!/bin/bash
# This hook is called with the snake-cased name of the font that has just been set.
# To put it into use, remove .sample from the name.
# Example: Show the name of the theme that was just set.
# notify-send -u low "New font" "Your new font is $1"

View File

@@ -1,7 +0,0 @@
#!/bin/bash
# This hook is called after an Nomarchy system update has been performed.
# To put it into use, remove .sample from the name.
# Example: Show notification after the system has been updated.
# notify-send -u low "Update Performed" "Your system is now up to date"

View File

@@ -1,7 +0,0 @@
#!/bin/bash
# This hook is called with the snake-cased name of the theme that has just been set.
# To put it into use, remove .sample from the name.
# Example: Show the name of the theme that was just set.
# notify-send -u low "New theme" "Your new theme is $1"

View File

@@ -1,86 +0,0 @@
# Nomarchy User Template Example: Alacritty
#
# This is a sample template file demonstrating how to create custom themed
# configurations. Templates use placeholder variables that get replaced with
# your current theme's colors when you switch themes.
#
# HOW TO USE:
# 1. Rename this file to: alacritty.toml.tpl (remove the .sample extension)
# 2. Customize it as needed
# 3. Change your theme to apply the template
#
# User templates in ~/.config/nomarchy/themed/ take priority over the built-in
# templates in the Nomarchy default/themed/ directory. This lets you override
# any built-in template or create templates for applications not included
# by default.
#
# AVAILABLE VARIABLES:
# {{ background }} - Main background color (e.g., "#1a1b26")
# {{ foreground }} - Main foreground/text color
# {{ cursor }} - Cursor color
# {{ accent }} - Theme accent color
# {{ selection_background }} - Selection highlight background
# {{ selection_foreground }} - Selection highlight foreground
#
# {{ color0 }} through {{ color15 }} - Standard 16-color terminal palette
# color0-7: Normal colors (black, red, green, yellow, blue, magenta, cyan, white)
# color8-15: Bright variants
#
# VARIABLE MODIFIERS:
# {{ variable_strip }} - Hex color without the # prefix (e.g., "1a1b26")
# {{ variable_rgb }} - Decimal RGB values (e.g., "26,27,38")
#
# Example using modifiers:
# background = "{{ background }}" -> background = "#1a1b26"
# background = "{{ background_strip }}" -> background = "1a1b26"
# background = "rgb({{ background_rgb }})" -> background = "rgb(26,27,38)"
#
# ---------------------------------------------------------------------------
[colors.primary]
background = "{{ background }}"
foreground = "{{ foreground }}"
[colors.cursor]
text = "{{ background }}"
cursor = "{{ cursor }}"
[colors.vi_mode_cursor]
text = "{{ background }}"
cursor = "{{ cursor }}"
[colors.search.matches]
foreground = "{{ background }}"
background = "{{ color3 }}"
[colors.search.focused_match]
foreground = "{{ background }}"
background = "{{ color1 }}"
[colors.footer_bar]
foreground = "{{ background }}"
background = "{{ foreground }}"
[colors.selection]
text = "{{ selection_foreground }}"
background = "{{ selection_background }}"
[colors.normal]
black = "{{ color0 }}"
red = "{{ color1 }}"
green = "{{ color2 }}"
yellow = "{{ color3 }}"
blue = "{{ color4 }}"
magenta = "{{ color5 }}"
cyan = "{{ color6 }}"
white = "{{ color7 }}"
[colors.bright]
black = "{{ color8 }}"
red = "{{ color9 }}"
green = "{{ color10 }}"
yellow = "{{ color11 }}"
blue = "{{ color12 }}"
magenta = "{{ color13 }}"
cyan = "{{ color14 }}"
white = "{{ color15 }}"

View File

@@ -1,32 +0,0 @@
add_newline = true
command_timeout = 200
format = "[$directory$git_branch$git_status]($style)$character"
[character]
error_symbol = "[✗](bold cyan)"
success_symbol = "[](bold cyan)"
[directory]
truncation_length = 2
truncation_symbol = "…/"
repo_root_style = "bold cyan"
repo_root_format = "[$repo_root]($repo_root_style)[$path]($style)[$read_only]($read_only_style) "
[git_branch]
format = "[$branch]($style) "
style = "italic cyan"
[git_status]
format = '[$all_status]($style)'
style = "cyan"
ahead = "⇡${count} "
diverged = "⇕⇡${ahead_count}⇣${behind_count} "
behind = "⇣${count} "
conflicted = " "
up_to_date = " "
untracked = "? "
modified = " "
stashed = ""
staged = ""
renamed = ""
deleted = ""

View File

@@ -1,13 +0,0 @@
# Changes require a restart to take effect.
# Install other terminals via Install > Terminal
export TERMINAL=xdg-terminal-exec
# Use code for VSCode
export EDITOR=nvim
# Use a custom directory for screenshots (remember to make the directory!)
# export OMARCHY_SCREENSHOT_DIR="$HOME/Pictures/Screenshots"
# Use a custom directory for screenrecordings (remember to make the directory!)
# export OMARCHY_SCREENRECORD_DIR="$HOME/Videos/Screencasts"

View File

@@ -1,11 +0,0 @@
# Changes require a restart to take effect.
# Ensure Nomarchy bins are in the path
export OMARCHY_PATH=$HOME/.local/share/nomarchy
export PATH=$OMARCHY_PATH/bin:$PATH:$HOME/.local/bin
# Set default terminal and editor
source ~/.config/uwsm/default
# Activate mise if present on the system
nomarchy-cmd-present mise && eval "$(mise activate bash --shims)"

View File

@@ -1,5 +0,0 @@
# overwrites default wiremix configuration
# defaults: https://github.com/tsowell/wiremix/blob/main/wiremix.toml
[char_sets.default]
default_device = "⮞"

View File

@@ -1,3 +0,0 @@
# Terminal emulator preference order for xdg-terminal-exec
# The first found and valid terminal will be used
Alacritty.desktop

View File

@@ -1,59 +0,0 @@
{ config, pkgs, lib, ... }:
let
configDir = ./config;
# Explicit list of config items to manage
# This replaces dynamic builtins.readDir for clarity and faster evaluation
configItems = {
# Directories
fastfetch = "directory";
fcitx5 = "directory";
fontconfig = "directory";
git = "directory";
imv = "directory";
"nautilus-python" = "directory";
nomarchy = "directory";
"nomarchy-skill" = "directory";
uwsm = "directory";
wiremix = "directory";
# Files
"brave-flags.conf" = "regular";
"chromium-flags.conf" = "regular";
"starship.toml" = "regular";
"xdg-terminals.list" = "regular";
};
# Files/directories handled elsewhere or not intended for ~/.config/
# - nomarchy.ttf: font file, not a config
# - waybar: handled in waybar.nix
# - walker: handled in walker.nix
# - alacritty: handled in alacritty.nix
# - swayosd: handled in swayosd.nix
# Check for user overrides
userConfigDir = config.nomarchy.configOverrides;
# Generate the xdg.configFile attribute set
makeMapping = name: type:
let
source = if userConfigDir != null then "${userConfigDir}/${name}" else "${configDir}/${name}";
in {
inherit name;
value = lib.mkDefault {
inherit source;
recursive = type == "directory";
};
};
configMappings = lib.mapAttrs' (name: type: makeMapping name type) configItems;
in
{
xdg.configFile = configMappings;
home.file.".XCompose" = lib.mkDefault {
source = ./config/nomarchy/default/xcompose;
};
}

View File

@@ -1,14 +0,0 @@
{ ... }:
{
imports = [
./options.nix
./state.nix
./overrides.nix
./fonts.nix
./configs.nix
./security.nix
./bash.nix
./gaming.nix
];
}

View File

@@ -1,7 +0,0 @@
{ lib, ... }:
{
config = {
fonts.fontconfig.enable = lib.mkDefault true;
};
}

Some files were not shown because too many files have changed in this diff Show More