# Agent Guidelines for NixOS/nix-darwin Dotfiles This repository contains NixOS, nix-darwin, and Home Manager configurations written in the Nix language. This document provides essential information for AI coding agents working in this codebase. ## Identity You are a sysadmin that manages server configurations and deployments in NixOS/nix-darwin using the Nix language. ## Build, Test, and Deployment Commands ### Building Configurations **Linux (NixOS):** ```bash # Build configuration nixos-rebuild build --flake . --show-trace just build # Apply configuration sudo nixos-rebuild switch --flake . --builders '' --max-jobs 1 --cores 32 just install cores='32' # Test configuration (no activation) sudo nixos-rebuild test --fast --flake . ``` **macOS (nix-darwin):** ```bash # Build configuration nix run nix-darwin -- build --flake . --show-trace just build # Apply configuration nix run nix-darwin -- switch --flake . just install ``` **Home Manager:** ```bash nix --extra-experimental-features "nix-command flakes" run home-manager/master -- switch --flake . --show-trace just home ``` ### Deployment to Remote Machines ```bash # Deploy to specific machine (uses deploy-rs) deploy -s .#ryu # Desktop (x86_64-linux) deploy -s .#tako # Server (x86_64-linux) deploy -s .#tsuba # Raspberry Pi (aarch64-linux) deploy -s .#kuro # MacBook M4 Pro (aarch64-darwin) deploy -s .#shiro # Mac Mini M4 (aarch64-darwin) ``` ### Validation and Checking ```bash # Check flake for errors nix flake check # Check deployment configuration nix flake check --show-trace # Validate specific output nix eval .#nixosConfigurations.ryu.config.system.build.toplevel ``` ### Formatting ```bash # Format Nix files with alejandra alejandra fmt .nix # Format all files in directory alejandra fmt . ``` ## Directory Structure ``` . ├── flake.nix # Main flake entry point ├── overlays.nix # Package overlays ├── deploy.nix # deploy-rs configuration ├── sops.nix # Secrets management ├── stylix.nix # Styling configuration ├── nixos/ # NixOS configurations │ ├── default.nix # NixOS builder │ ├── ryu/ # Desktop machine config │ ├── tako/ # Server config │ └── tsuba/ # Raspberry Pi config ├── darwin/ # macOS configurations │ ├── default.nix # Darwin builder │ ├── kuro/ # MacBook config │ └── shiro/ # Mac Mini config ├── home/ # Home Manager modules │ ├── default.nix │ ├── programs/ # Program configurations │ ├── services/ # Service configurations │ ├── apps/ # Application configs │ └── accounts/ # Account configs ├── modules/ # Custom NixOS/Darwin/Home modules │ ├── default.nix │ ├── nixos/ # NixOS-specific modules │ ├── darwin/ # Darwin-specific modules │ └── home/ # Home Manager modules ├── builders/ # Machine builder definitions ├── packages/ # Custom packages ├── scripts/ # Helper scripts ├── secrets/ # SOPS secrets (encrypted) └── patches/ # Package patches ``` ## Code Style Guidelines ### Nix Language Conventions **File Structure:** ```nix { inputs, config, pkgs, lib, device, ... }: { # Configuration here } ``` **Imports:** - List all parameter imports at the top - Order: `inputs`, `config`, `pkgs`, `lib`, `device`, custom params, `...` - Use set destructuring for clarity **Formatting:** - Use `alejandra` formatter (maintained in the repo) - 2-space indentation - Keep lines under 100 characters when reasonable - Use trailing commas in lists and attribute sets **Naming Conventions:** - Files: lowercase with hyphens (e.g., `my-module.nix`) - Attributes: camelCase (e.g., `enableMyFeature`) - Functions: camelCase (e.g., `mkDevice`) - Constants: UPPER_SNAKE_CASE (e.g., `API_KEY`) - Device names: lowercase (e.g., `ryu`, `tako`, `kuro`) **Let Expressions:** ```nix with lib; let cfg = config.programs.myProgram; myHelper = x: y: x + y; in { options = { ... }; config = mkIf cfg.enable { ... }; } ``` **Options:** ```nix options = { programs.myProgram = { enable = mkEnableOption "my program"; package = mkPackageOption pkgs "myProgram" {}; settings = mkOption { type = types.attrs; default = {}; description = "Configuration settings"; }; }; }; ``` **Conditionals:** - Use `mkIf` for config options - Use `lib.optionalAttrs` for attribute sets - Use `lib.optionals` for lists - Prefer inline `if-then-else` for simple expressions **String Interpolation:** ```nix # Good "${pkgs.package}/bin/command" "${config.home.homeDirectory}/.config" # Avoid unnecessary interpolation "simple string" # not "${''simple string''}" ``` **Comments:** ```nix # Single-line comments for brief explanations # Use above the line being explained /* Multi-line comments for longer explanations or documentation blocks */ ``` ### Module Patterns **Simple Package Module:** ```nix {pkgs, ...}: { home.packages = [pkgs.myPackage]; } ``` **Program Configuration Module:** ```nix { config, pkgs, lib, ... }: with lib; let cfg = config.programs.myProgram; in { options.programs.myProgram = { enable = mkEnableOption "myProgram"; }; config = mkIf cfg.enable { home.packages = [pkgs.myProgram]; }; } ``` **Service Module:** ```nix { config, lib, ... }: { services.myService = { enable = true; settings = { # Configuration here }; }; } ``` ### Device-Specific Logic ```nix # Check device properties home.packages = lib.optionals device.isLinux [ pkgs.linuxPackage ] ++ lib.optionals device.isDarwin [ pkgs.macPackage ]; # Or use conditionals sessionVariables = { BROWSER = if device.isDarwin then "open" else "xdg-open"; }; ``` ## Important Rules 1. **NEVER create new markdown files** unless explicitly requested 2. **DO NOT add helper scripts or shell scripts** - use Nix expressions 3. **DO NOT add example snippets or sample code files** 4. **All configurations must use Nix expressions** when possible 5. **Follow existing naming conventions** and directory structure 6. **Ensure new files match the structure** of existing similar files ## Secrets Management - Secrets are managed with SOPS (Secrets OPerationS) - Encrypted secrets in `secrets/` directory - Configuration in `.sops.yaml` - Access secrets via `config.sops.secrets."path/to/secret".path` ## Common Patterns ### Adding a New Program ```bash # Use the justfile recipe just add program myprogram # This creates home/programs/myprogram.nix and adds import ``` ### Creating a Module 1. Determine location: `modules/nixos/`, `modules/darwin/`, or `modules/home/` 2. Create file with proper structure 3. Add to `modules/default.nix` imports 4. Use the module in appropriate device configuration ### Device Configuration Devices are defined in `flake.nix` using `mkDevice`: ```nix ryu = mkDevice { name = "ryu"; system = "x86_64-linux"; user = "servius"; isNix = true; monitors = { ... }; }; ``` Properties available: - `device.isLinux`, `device.isDarwin` - `device.isServer`, `device.hasGui` - `device.isDesktopLinux` - `device.name`, `device.user`, `device.home` ## Error Handling - Use `mkIf` to conditionally enable configurations - Check for required options before using them - Validate paths and files exist when referencing external resources - Handle both Linux and macOS cases when adding cross-platform features ## Testing Changes 1. Build the configuration first: `just build` or `nixos-rebuild build --flake .` 2. Check for errors with `--show-trace` flag 3. Test on non-production systems first 4. Use `sudo nixos-rebuild test` for temporary activation on Linux ## Version Information - Nix Version: 2.32+ - Flakes: Enabled (required) - Formatter: alejandra - State Version: 23.11+ (varies by machine)