# Agent Instructions for Nomarchy You're an AI coding agent picking up the Nomarchy project. This document gives you everything you need to be useful from the first turn: what Nomarchy is, how it's organized, what the rules are, and how to actually pick up the next piece of work. If anything below conflicts with what the user just said, the user wins. If anything below conflicts with the existing code, read the code — these notes can rot. --- ## 1. What Nomarchy is Nomarchy is a NixOS-based distribution that ships the Omarchy Hyprland desktop on a strictly declarative, flake-based foundation. It targets power users who want the polish of Omarchy without giving up reproducibility. Concretely: - A flake at the repo root exposes `nixosModules.system` (foundational OS modules) and `nixosModules.home` (apps + desktop), plus three `nixosConfigurations` (`installerIso`, `installerIsoGraphical`, `default`) and standalone `homeConfigurations`. - Downstream users get the distro by importing `nomarchy.nixosModules.system` and `nomarchy.nixosModules.home` from their own `/etc/nixos/flake.nix`. The Nomarchy installer generates that flake for them; an existing-NixOS user can hand-write it (see `docs/MIGRATION.md`). - A bash/`gum` TUI installer lives in `installer/install.sh` (~1100 lines). It auto-detects hardware via `installer/hardware-db.sh` (DMI + `lspci` + `BAT*` sysfs), prompts for the rest, and generates `flake.nix`, `system.nix`, `home.nix`, and `hardware-selection.nix` into `/mnt/etc/nixos/`. - The desktop is Hyprland + waybar + walker + a curated theming engine (`themes/`) with 22 palettes wired through Stylix. Read in this order to come up to speed: 1. `README.md` — public face. 2. `docs/STRUCTURE.md` — directory layout and module logic. 3. `docs/OPTIONS.md` — every `nomarchy.*` option a downstream flake can set. 4. `docs/ROADMAP.md` — what's planned. **This is your work queue.** 5. `docs/SCRIPTS.md` — the script & menu audit table (Pillar 3 of the roadmap). 6. `docs/MIGRATION.md` — how an existing NixOS install becomes Nomarchy. 7. `docs/creating-themes.md` — when palette work comes up. --- ## 2. How the repo is organized ``` core/ Foundational OS + user defaults. Don't put apps here. system/ NixOS modules, all imported via core/default.nix. options.nix nomarchy.system.* options live here. hardware.nix nomarchy.hardware.* options + module wiring. network.nix NetworkManager, DNS, networkmanagerapplet. impermanence.nix Erase-Your-Darlings root wipe. scripts/ Low-level system scripts (battery, brightness, hardware). home/ Home Manager modules. options.nix Most home-side nomarchy.* options. behavior.nix nomarchy.behavior.* (deploy-default-config toggles). overrides.nix File-based overrides from ~/.config/nomarchy/overrides/. config/ Plain dotfiles symlinked into ~/.config. features/ Apps and desktop components. Add new apps here. apps/ One subdir per app (alacritty, btop, kitty, vscode.nix, …). desktop/ hyprland, waybar, idle.nix, nightlight.nix, … scripts/ User-PATH scripts, battery-monitor user service. utils/ ~68 nomarchy-* user scripts. default.nix Packages them as nomarchy-system-scripts derivation. themes/ Theme engine + 22 palettes. engine/ Loader, Stylix glue, switcher, scripts (font, theme, wallpaper). palettes/ One subdir per palette (summer-night, tokyo-night, …). hosts/ ISO host configs (installerIso, installerIsoGraphical/live-iso). installer/ The bash/gum TUI + disko configs + hardware-db.sh. lib/ Shared Nix helpers (state schema, color resolution, paths). docs/ All long-form documentation. README.md stays at repo root. bin/ Convenience wrappers for testing (nomarchy-test-installer, …). ``` When you add a new feature: - A new app → `features/apps//default.nix` (+ optional `config/`), import it from `features/default.nix`. - A new system service → `core/system/.nix`, import from `core/default.nix`. - A new toggle → add to `core/system/options.nix` or `core/home/options.nix`, wire it into the relevant module, document it in `docs/OPTIONS.md`. --- ## 3. Guardrails (non-negotiable unless the user overrides) These are inherited from the established Nomarchy conventions. Violating them is a bug. 1. **Declarative-first.** No imperative state in `core/`. Mutable state goes in `~/.config/nomarchy/state.json` or in NixOS / home-manager options. 2. **Downstream-flake friendly.** Every behavior toggle is a `nomarchy.*` option documented in `docs/OPTIONS.md`. Adding a feature without a corresponding option is a bug. 3. **Opt-in by default.** New features default off (or default to existing behavior). The installer can flip defaults *for the user being installed*, but the option must read sensibly when set by hand. 4. **`lib.mkDefault` everywhere user might override.** If a downstream `system.nix` would reasonably want to change something Nomarchy sets, set it with `lib.mkDefault`. If it must not be overridden, use `lib.mkForce` and explain why in a comment. 5. **Reuse before invent.** ~155 `nomarchy-*` scripts already exist across `core/system/scripts/`, `features/scripts/utils/`, `themes/engine/scripts/`. Grep before writing a new one. 6. **No comments that narrate.** Don't write comments explaining *what* the code does. Only write a comment when the *why* is non-obvious — a hidden constraint, a subtle invariant, a workaround. 7. **No backwards-compat shims.** If you remove a thing, remove it everywhere. No re-exports, no `// removed` markers. 8. **Docs ride with the change.** Every change ships in the same commit as its doc updates — no follow-up "docs catch-up" PRs. The mapping is in §5.4 below; if a change touches something in that table and the matching doc didn't move with it, the change is incomplete. --- ## 4. How to find work to do The roadmap (`docs/ROADMAP.md`) is the source of truth. It has three columns and seven pillars. **Default rule:** prefer items in the **Now** column. Pick whichever matches the user's current ask, or the smallest one if no ask is in flight. If the user asked for something not in the roadmap: - Do the work. - After it ships, propose a one-line addition to `docs/ROADMAP.md` so future you doesn't re-discover it. If the user asks "what's next?", reply with the Now column items in 2–3 sentences and let them pick. ### The script & menu audit (Pillar 3) This is the **largest single open work item**. Phase A (inventory) hasn't run yet; `docs/SCRIPTS.md` is just scaffolding. The user explicitly flagged this pillar as important. Phase A shipped. The inventory lives at [`docs/SCRIPTS.md`](SCRIPTS.md) and is regenerated by: ```bash ./bin/utils/nomarchy-docs-scripts --out docs/SCRIPTS.md ``` It tags every row with one of `kept` / `unused?` / `missing`. Phase B is the per-batch porting/removal: pick ~10 rows tagged `missing` or `unused?`, decide one of `port-from-omarchy` / `delete-dead` / `stub-with-notify`, and ship as one PR per batch on a `wave/audit-` branch. Each PR description should reference the rows it closes; reviewers spot-check that every caller of a removed/renamed script is updated. --- ## 5. Workflow per change Steps you should follow for any non-trivial change: 1. **Understand the current state first.** - `git status` and `git log -5` so you know what's just landed and what's in flight. - Read the relevant files. Don't infer. 2. **Plan if it's non-trivial.** Tasks with three or more steps benefit from a TaskCreate list. Tasks that touch the architecture benefit from plan mode. 3. **Reuse existing options and scripts.** Grep `core/system/options.nix`, `core/home/options.nix`, and the three script directories before adding anything. 4. **Touch the docs in the same change.** Use this table — if your change matches a row, the doc edit ships in the same commit. No exceptions, no follow-ups. | If you change… | Update in the same commit | | --- | --- | | A `nomarchy.*` option (added, removed, renamed, default flipped, type changed, description changed) | `docs/OPTIONS.md` (matching row) **and** any other row that mentions it (e.g. `formFactor` is referenced from `laptop.enable`'s row) | | A `nomarchy-*` script (added, removed, renamed) | `docs/SCRIPTS.md` — the pre-commit hook regenerates it; verify it's staged. If `core.hooksPath` isn't set, run `./bin/utils/nomarchy-docs-scripts --out docs/SCRIPTS.md` manually. | | A keybinding (`bindd =` / `bindeld =`) under `core/home/config/.../hypr/` | `docs/KEYBINDINGS.md` — regenerate via `./bin/utils/nomarchy-docs-keybindings --out docs/KEYBINDINGS.md`; spot-check the README highlights still hold | | A directory was added/removed/renamed under `core/`, `features/`, `themes/`, `hosts/`, `installer/`, `lib/`, `bin/`, or `docs/` | `docs/STRUCTURE.md` (tree + module logic prose) **and** §2 of this file (`docs/AGENT.md`) if the change is structural enough to affect new-agent onboarding | | A feature module's behavior changed in a way an existing user would notice (a default flipped, a service started/stopped, a key remapped) | `README.md` if it's user-visible at the marketing level; otherwise just `docs/OPTIONS.md` | | An installer prompt added/removed/reordered, or generated-file shape changed | `docs/MIGRATION.md` if it affects hand-written `flake.nix` setups; `installer/install.sh` heredoc comments if a generated file's shape changed | | A theme palette added/removed, or the theming engine's contract changed | `docs/creating-themes.md` and the palette count in `README.md` | | A roadmap item shipped | Move the entry to the **Shipped** section at the bottom of `docs/ROADMAP.md`. Don't delete — that's our changelog. | | A roadmap item discovered (new scope) | Add a one-line row to **Now**, **Next**, or **Later** in `docs/ROADMAP.md`. Don't tell the user verbally and forget. | | A workflow / convention / guardrail you'd want a future agent to follow | `docs/AGENT.md` (this file). | | A new flake input, output, or major architectural decision | `docs/STRUCTURE.md` and `docs/AGENT.md` §1. | Before declaring done, do one explicit pass: did the change cross any row above? If yes, is the matching doc edit staged? If you can't answer "yes" to both, you're not done. 5. **Verify the change evaluates** (cheap, do this before declaring done): ```bash nix --extra-experimental-features 'nix-command flakes' flake check --no-build bash -n installer/install.sh # if you touched it ``` First clone? Enable the repo's pre-commit hook so `docs/SCRIPTS.md` regenerates whenever you add/modify/remove a `nomarchy-*` script: ```bash git config core.hooksPath .githooks ``` For installer changes, also do a dry-run end-to-end: ```bash sudo /etc/install.sh --dry-run # in the live ISO or VM ``` For waybar / Hyprland visual changes, the only reliable check is booting the live ISO with `nomarchy-test-live-iso`. If you can't boot it, **say so** rather than claiming success. 6. **Commit narrowly.** One concept per commit. The commit subject is `: ` (`feat:`, `fix:`, `docs:`, `chore:`). The body explains the why. 7. **Push only when the user asks.** Local commits are free; pushing publishes. --- ## 6. Patterns worth knowing ### Adding a new option ```nix # core/system/options.nix (or core/home/options.nix for home-side) mything.enable = lib.mkEnableOption '' Concise description that reads well in `nix eval`. Mention any pre-conditions (groups, kernel modules, hardware needed). ''; ``` Then wire it inside a `config = lib.mkIf cfg.mything.enable { ... }` block and document it in `docs/OPTIONS.md`. ### Filtering modules conditionally We do this for waybar (drop `battery` on desktop) in `features/desktop/waybar/default.nix:25-39`. Pattern: ```nix let rawSettings = builtins.fromJSON (builtins.readFile configFile); laptopOnly = [ "battery" "custom/battery" ]; filterModules = mods: if config.nomarchy.formFactor == "laptop" then mods else builtins.filter (m: !(builtins.elem m laptopOnly)) mods; settings = rawSettings // { modules-right = filterModules (rawSettings.modules-right or []); modules-center = filterModules (rawSettings.modules-center or []); modules-left = filterModules (rawSettings.modules-left or []); }; in { ... } ``` ### Form-factor (laptop vs desktop) `nomarchy.system.formFactor` and `nomarchy.formFactor` are the two halves of the same flag (system + home). Default `"laptop"`. The installer auto-detects via `compgen -G "/sys/class/power_supply/BAT*"` and writes the explicit value into both generated files. Use this option to gate any laptop-only UI / service. ### State (`state.json`) Theme, font, wallpaper, and a few feature toggles live in `~/.config/nomarchy/state.json` so they can change without a rebuild. Schema is in `lib/state-schema.nix`. The Home Manager evaluator reads it via `lib/default.nix`. **Don't add new state without justifying it** — most "state" should be a NixOS option instead. ### Scripts derivation User-PATH scripts ship via `nomarchy-system-scripts` (`core/system/scripts-derivation.nix`) plus the per-category dependencies declared in `features/scripts/default.nix:categoryDeps`. When you add a script: 1. Drop the file in `features/scripts/utils/` or `core/system/scripts/`. 2. `chmod +x` it (it'll be wrapped with the right deps automatically). 3. Reference the right `categoryDeps` group in `features/scripts/default.nix` if it needs new tools. 4. Test that `which