bin/utils/nomarchy-docs-scripts walks features/scripts/utils, core/system/scripts, and themes/engine/scripts; emits a populated SCRIPTS.md with three tables: - Scripts (136): location, top callers, status (kept / unused?). - Missing references: tokens grepped from code with no script file (75 rows tagged missing). - Menu items: every case arm in nomarchy-menu's show_*_menu functions, mapped to its target command and tagged. Status histogram: 158 kept, 75 missing, 45 unused?. Phase B opens per-batch PRs that refine missing → port-from-omarchy / delete-dead / stub-with-notify, and unused? → kept / delete-dead. Roadmap and AGENT.md updated to point at the generator and explain the Phase B workflow. Now-column row replaced with the Phase B handoff. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
13 KiB
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) andnixosModules.home(apps + desktop), plus threenixosConfigurations(installerIso,installerIsoGraphical,default) and standalonehomeConfigurations. - Downstream users get the distro by importing
nomarchy.nixosModules.systemandnomarchy.nixosModules.homefrom their own/etc/nixos/flake.nix. The Nomarchy installer generates that flake for them; an existing-NixOS user can hand-write it (seedocs/MIGRATION.md). - A bash/
gumTUI installer lives ininstaller/install.sh(~1100 lines). It auto-detects hardware viainstaller/hardware-db.sh(DMI +lspci+BAT*sysfs), prompts for the rest, and generatesflake.nix,system.nix,home.nix, andhardware-selection.nixinto/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:
README.md— public face.docs/STRUCTURE.md— directory layout and module logic.docs/OPTIONS.md— everynomarchy.*option a downstream flake can set.docs/ROADMAP.md— what's planned. This is your work queue.docs/SCRIPTS.md— the script & menu audit table (Pillar 3 of the roadmap).docs/MIGRATION.md— how an existing NixOS install becomes Nomarchy.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/<name>/default.nix(+ optionalconfig/), import it fromfeatures/default.nix. - A new system service →
core/system/<name>.nix, import fromcore/default.nix. - A new toggle → add to
core/system/options.nixorcore/home/options.nix, wire it into the relevant module, document it indocs/OPTIONS.md.
3. Guardrails (non-negotiable unless the user overrides)
These are inherited from the established Nomarchy conventions. Violating them is a bug.
- Declarative-first. No imperative state in
core/. Mutable state goes in~/.config/nomarchy/state.jsonor in NixOS / home-manager options. - Downstream-flake friendly. Every behavior toggle is a
nomarchy.*option documented indocs/OPTIONS.md. Adding a feature without a corresponding option is a bug. - 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.
lib.mkDefaulteverywhere user might override. If a downstreamsystem.nixwould reasonably want to change something Nomarchy sets, set it withlib.mkDefault. If it must not be overridden, uselib.mkForceand explain why in a comment.- Reuse before invent. ~155
nomarchy-*scripts already exist acrosscore/system/scripts/,features/scripts/utils/,themes/engine/scripts/. Grep before writing a new one. - 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.
- No backwards-compat shims. If you remove a thing, remove it everywhere. No re-exports, no
// removedmarkers.
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.mdso 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 and is regenerated by:
./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-<batch> 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:
- Understand the current state first.
git statusandgit log -5so you know what's just landed and what's in flight.- Read the relevant files. Don't infer.
- 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.
- Reuse existing options and scripts. Grep
core/system/options.nix,core/home/options.nix, and the three script directories before adding anything. - Touch the docs in the same change. New option → row in
docs/OPTIONS.md. New script → row indocs/SCRIPTS.md. Roadmap item shipped → move it to the Shipped section at the bottom ofdocs/ROADMAP.md. - Verify the change evaluates (cheap, do this before declaring done):
For installer changes, also do a dry-run end-to-end:
nix --extra-experimental-features 'nix-command flakes' flake check --no-build bash -n installer/install.sh # if you touched itFor waybar / Hyprland visual changes, the only reliable check is booting the live ISO withsudo /etc/install.sh --dry-run # in the live ISO or VMnomarchy-test-live-iso. If you can't boot it, say so rather than claiming success. - Commit narrowly. One concept per commit. The commit subject is
<type>: <imperative summary>(feat:,fix:,docs:,chore:). The body explains the why. - Push only when the user asks. Local commits are free; pushing publishes.
6. Patterns worth knowing
Adding a new option
# 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:
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:
- Drop the file in
features/scripts/utils/orcore/system/scripts/. chmod +xit (it'll be wrapped with the right deps automatically).- Reference the right
categoryDepsgroup infeatures/scripts/default.nixif it needs new tools. - Test that
which <script>resolves after a rebuild.
Heredocs in installer/install.sh
The system-config generator uses unquoted heredocs (<< EOF) so $VAR expands. The home-config generator now also uses unquoted heredocs — any literal $ or backtick in the body must be escaped (see installer/install.sh:1043-1131). If you forget and the install fails with a "unbound variable" or unexpected command output, that's why.
7. Things to never do without explicit user OK
git push --force,git reset --hard,git clean -f,rm -rfoutside obvious sandbox dirs.- Touch
flake.lockunless the user asked to update inputs. - Bump
nixpkgsmajor version (e.g.25.11→26.05) — that's a release decision. - Add a new flake input. They're load-bearing across all three host configurations.
- Skip pre-commit hooks (
--no-verify). - Ship a feature without a
nomarchy.*option to gate it. - Ship a removal without updating callers (grep first).
- Mock the database / external services in tests — use the real thing.
8. Where to put your own notes
- Long-lived docs →
docs/. - Working notes / per-session plans →
~/.claude/plans/. Don't commit them. - Memory about the user, this project, or process preferences → your harness's memory directory at
/home/bernardo/.claude/projects/-home-bernardo-Projects-nomarchy/memory/. Each entry gets a frontmatter file plus a one-line index entry inMEMORY.md.
9. The shape of a good handoff
Before you stop, leave the next agent (or future you) something to land on:
- The roadmap is up to date — items you shipped are in Shipped.
git statusis clean (or has one obvious WIP commit on awave/...branch).- If you discovered new scope, you logged it as a roadmap row, not a verbal heads-up.
- Any plan file you wrote in
~/.claude/plans/is named after the task, not the date. - The user's last message has been answered concisely.
That's it. The roadmap tells you what; this file tells you how. Go pick a Now item.