Files
Nomarchy/docs/AGENT.md
Bernardo Magri 133ef9ddfc docs: add AGENT.md briefing for AI agents continuing the roadmap
Self-contained handbook so a fresh agent (or future-me) can land
useful work on the first turn: vision, repo layout, guardrails,
how to find work, the per-change workflow, common patterns, and
hard-don't-do rules. Points at ROADMAP.md / SCRIPTS.md as the
durable work queue.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-25 21:39:38 +01:00

13 KiB
Raw Blame History

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/<name>/default.nix (+ optional config/), import it from features/default.nix.
  • A new system service → core/system/<name>.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.

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 23 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.

To pick it up:

  1. Run the three generator commands at the top of docs/SCRIPTS.md.
  2. Populate the Scripts table with one row per nomarchy-* file (location, callers, status unknown for now).
  3. Populate the Menu items table by walking each show_*_menu function in features/scripts/utils/nomarchy-menu.
  4. Tag every row with one of: kept / port-from-omarchy / delete-dead / stub-with-notify / unknown. Triage live, but leave anything ambiguous as unknown.
  5. Land it as one PR (the inventory PR). Don't start porting in the same change.

Then Phase B is per-script: one PR per ~10 scripts, branch named wave/audit-<batch>. Each PR closes specific rows in docs/SCRIPTS.md.


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. New option → row in docs/OPTIONS.md. New script → row in docs/SCRIPTS.md. Roadmap item shipped → move it to the Shipped section at the bottom of docs/ROADMAP.md.
  5. Verify the change evaluates (cheap, do this before declaring done):
    nix --extra-experimental-features 'nix-command flakes' flake check --no-build
    bash -n installer/install.sh   # if you touched it
    
    For installer changes, also do a dry-run end-to-end:
    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 <type>: <imperative summary> (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

# 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:

  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 <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 -rf outside obvious sandbox dirs.
  • Touch flake.lock unless the user asked to update inputs.
  • Bump nixpkgs major version (e.g. 25.1126.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 docsdocs/.
  • 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 in MEMORY.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 status is clean (or has one obvious WIP commit on a wave/... 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.