# dotfiles-nixos One flake builds every machine I own. ## Repository Conventions - Follow `docs/technical-writing.md` for comments, user-facing descriptions, commit prose, pull-request prose, and Markdown documentation. - Comments posted to the forge under the operator's account must end with `— Pi`. The sign-off identifies the agent as the author instead of the operator. - Commit messages follow Conventional Commits, defined in `docs/conventional-commits.md`. Use a scope for the changed module or host, such as `fish`, `nvim`, or `neogaia`. - Keep commit messages about the Git history, not the forge workflow. Do not reference issue or pull-request numbers unless the commit itself requires a stable external reference. - Use `gitea-axi` for Gitea issues, pull requests, labels, reviews, comments, and milestones. It resolves this repository from the `origin` remote inside the checkout. ## Dotfiles Conventions ### Desktop - When adding a graphical application, add a `window-rewrite` icon mapping in `modules/desktop/waybar.nix`. The workspace indicator uses this mapping to show an application icon instead of the generic default glyph. Match the mapping on the window class. Run `hyprctl clients -j | jq -r '.[].class' | sort -u` to list classes in the running session. - Set Hyprland session environment variables in `modules/desktop/hyprland/hyprland.nix` with `env = KEY,VALUE`. `home.sessionVariables` do **not** reach the Hyprland session because UWSM does not source `hm-session-vars.sh`. Source cursor values from `config.stylix.cursor`. Set `XCURSOR_*` and `HYPRCURSOR_*` to the same theme for Bibata. - Configure the Steam desktop client as an XWayland application. SDL Wayland selectors do not make the visible client native Wayland. Keep fractional scaling sharp with Hyprland's `xwayland.force_zero_scaling` and Steam's `STEAM_FORCE_DESKTOPUI_SCALING`. ### Firefox - Manage Firefox search engines through `programs.firefox.search` with `force = true`. Hide built-in engines with `.metaData.hidden = true` because omission does not remove them. Use current engine ids, such as `default = "ddg"` instead of `"DuckDuckGo"`. Decode the built `search.json.mozlz4` with `mozlz4a -d ` to check the result. - Avoid Home Manager Firefox extension settings unless the whole profile can use the legacy extension-storage backend. Any non-empty `profiles..extensions.settings..settings` sets `extensions.webextensions.ExtensionStorageIDB.enabled = false` for the whole profile. ### Neovim - Nixvim's flake input follows the root nixpkgs source, but its Home Manager module does not reuse the host's `pkgs` instance. Keep `programs.nixvim.nixpkgs.useGlobalPackages = true`. That setting makes Nixvim use the shared package set without warning that its source default changed. ### AI Tooling - Use produced literals for Herdr key names that include shifted punctuation. For example, use `prefix+<` instead of `prefix+shift+comma`. - Treat `~/.pi/agent/skills` as generated output from Home Manager. Do not edit skills in that directory. A new file created there stays outside the repo. Shared global skills come from the `skills` flake through `modules/agents/skills.nix`. Update the `skills` flake input, then rebuild. - Keep generated `.agents/skills/.gitignore` files from ignoring symlinked skills. Pi skill discovery honors `.gitignore`, `.ignore`, and `.fdignore` inside scanned skill directories. An ignored symlinked skill does not load even when `.agents/skills//SKILL.md` exists. - Write directly to flake-managed Pi extension, prompt, and skill directories only for throwaway development or local experiments. Home Manager activation can overwrite or hide unmanaged files in those directories. Promote finished work into the dotfiles module before treating it as deployed. ## Gotchas ### Architecture - Guest modules are host-agnostic wiring, while host files own deployment-specific service configuration such as served volumes and host paths. For example, `guests/copyparty.nix` should expose options and translate them into guest mounts/service settings, while `hosts/pikachu/default.nix` chooses `/inbox`, `/media`, and their backing paths. - `self.lib.registry.collect { hosts = self.nixosConfigurations; }` reads only top-level host `config.registry` declarations. Registry declarations inside guest interiors live under `config.containers..config.registry`. The collected registry does not include those guest-interior declarations. Publish guest values from host-side code, or extend the collector to recurse into guests. See http://git.alexion.dev/alexion/dotfiles/issues/65. - A NixOS module function argument default such as `registry ? config.registry` does not safely handle an unprovided module argument. The module system still queries `_module.args.registry`. Evaluation fails when that argument is absent. For an optional special-argument fallback, bind module arguments through `@args`. Test `args ? ` inside the module body. ### Build Inputs - `chaotic-nyx` must **not** follow this flake's `nixpkgs`. Chaotic builds its packages against its own pinned `nixpkgs`. Its overlay defaults to `onTopOf = "flake-nixpkgs"`, the cache-friendly path. That setup lets `nyx-cache.chaotic.cx` serve the CachyOS kernel instead of building it from source. Chaotic packages do not see this flake's `unstable` or `stable` overlays. ### Deployment - Remote deploy helpers that run target-side `sudo` over SSH need a TTY. Use `ssh -t` unless the target command cannot prompt for sudo credentials. ### Host Environment - This host has no `python` or `python3` command on its ordinary `PATH`. For one-off Python commands, use Nix explicitly, such as `nix shell nixpkgs#python3 -c python3