# Doloro's Dotfiles NixOS dotfiles managed via **flake-parts** + **den** (custom flake framework). Multi-host: desktop, laptop, WSL, RPi5 server. ## Architecture ``` dotfiles/ ├── flake.nix # Entry point: `outputs = inputs.flake-parts.lib.mkFlake { inherit inputs; } (inputs.import-tree ./config);` ├── .sops.yaml # Age-encrypted secrets (6 keys: desktop/laptop user+system, rpi5) ├── config/ │ ├── dendritic.nix # Root config import │ ├── inputs.nix # Flake input definitions │ ├── namespace.nix # Namespace setup │ ├── defaults.nix # Default values │ ├── hosts/ │ │ ├── computers.nix # desktop (x86_64), laptop (aarch64), wsl (aarch64), doloro-bootable │ │ ├── servers.nix # rpi5 (aarch64) │ │ └── aspects/ # Host-specific configurations │ │ ├── doloro-shared.nix # Common to all doloro hosts (nixvim, tmux, git, ssh, hyfetch) │ │ ├── doloro-desktop/ # Desktop-specific (disko, hardware, home, host) │ │ ├── doloro-laptop/ # Laptop-specific (disko, hardware, home, host, power-management) │ │ ├── doloro-wsl/ # WSL-specific (home, host) │ │ ├── doloro-bootable/ # Bootable USB (home, host) │ │ └── servers/rpi5.nix # Raspberry Pi 5 │ └── modules/ # Reusable configuration modules │ ├── ai/ # AI tools (pi-coding-agent, OpenMeteo) │ ├── gaming/ # Steam, gamemode, gamepad │ ├── hyprland/ # Window manager │ ├── niri/ # Alternative WM │ ├── nixvim/ # Neovim config │ ├── power-management/ # TLP, auto-cpufreq, battery targets │ ├── secrets/ # SOPS-managed secrets │ ├── services/ # Caddy, DDNS, Home Assistant, Traefik, RTMP │ └── ... ``` ## Hosts | Host | Arch | Type | Key Modules | | ------ | ------ | ------ | ------------- | | `desktop` | x86_64 | NixOS + HM | Hyprland, gaming, disko, full stack | | `laptop` | aarch64 | NixOS + HM | Power management, Hyprland | | `wsl` | aarch64 | NixOS | WSL setup | | `doloro-bootable` | x86_64 | NixOS | Bootable USB recovery | | `rpi5` | aarch64 | NixOS | Server, no GUI | ## Key Tools & Stack - **Window Manager**: Hyprland (primary), Niri (alternative) - **Editor**: Nixvim (Neovim) — Gruvbox Material, LSP (rust-analyzer, nixd, tsserver), Treesitter, Lualine, Telescope, LazyGit - **Shell**: Fish - **AI**: Pi Coding Agent v0.81.1 (LiteLLM via `scuggo` proxy) - Models: meow (litellm), claude-opus-4-8, gpt-5.5, gpt-5.4-mini (recap/title) - Skills: pi-lens, pi-lean-ctx, pi-vitals, pi-spark, pi-caveman, pi-pretty, pi-context-engineering - **Terminal**: Kitty - **Browser**: Zen Browser, Helium - **Music**: Spicetify (Spotify) - **Aurora**: Stylix (themes), NixOS-Hardware - **Container**: Podman - **Flatpak**: nix-flatpak - **Secrets**: SOPS + Age (6 keys for desktop/laptop user+system, rpi5) - **Nerd Fonts**: Custom patched (Doloro1978/nix-nerd-fonts-patcher) ## Conventions 1. **Never edit `flake.nix` directly** — run `nix run .#write-flake` to regenerate 2. **Secrets** live in `config/modules/secrets/` — encrypted via SOPS age keys in `.sops.yaml` 3. **Modules** are modular: split by concern (ai, gaming, hyprland, power-management, services) 4. **Hosts** split into `computers.nix` and `servers.nix` — each host gets `aspect` references 5. **Shared config** lives in `doloro-shared.nix` — imported by all doloro hosts 6. **Disko** handles disk layouts for desktop/laptop 7. **Power management** is laptop-specific: TLP, auto-cpufreq, battery AC targets, Intel GPU, TDP 8. **CachyOS kernel** available as module for desktop ## Common Operations ```bash # Apply configuration sudo nixos-rebuild switch --flake .#desktop # Home Manager (doloro user) home-manager switch --flake .#doloro-desktop # Update flake inputs nix flake update # Write regenerated flake.nix nix run .#write-flake # Encrypt a secret nix run .#sops-encrypt # Enter development shell nix develop ``` ## Validating Config Changes Standard validation sequence before relying on any edit to a `.nix` module (used for opencode, ai, and other module changes): 1. **Parse check** (fast, catches syntax/brace errors): ```bash nix-instantiate --parse config/modules/ai/ai.nix >/dev/null && echo "PARSE OK" ``` 2. **Hash verification** for any downloaded file pinned via `pkgs.fetchurl` — compute the sha256 locally and confirm it matches the `sha256` in the module: ```bash nix hash file token-tracker.tsx # or: sha256sum token-tracker.tsx ``` 3. **Flake evaluation** — full `nix flake check` may fail on unrelated pre-existing issues (e.g. `` not on NIX_PATH in pure mode). Distinguish pre-existing failures from edit-induced ones before touching the code. `nix flake show --impure` lists the configuration names (`nixosConfigurations: desktop, doloro-bootable, laptop, rpi5, wsl`). 4. **Runtime output check** — the generated config is a home-manager symlink into `/nix/store`. After a rebuild, confirm the live files actually contain the change: ```bash readlink -f ~/.config/opencode/opencode.json # → /nix/store/...-opencode.json rg -n "my-change" "$(readlink -f ~/.config/opencode/opencode.json)" ``` Also verify supporting files that the change depends on (plugins dir, extra packages, etc.): ```bash ls -la ~/.config/opencode/plugins/ && readlink -f ~/.config/opencode/plugins/*.tsx ``` 5. **Cache check** for npm-resolved opencode plugins — confirm opencode actually downloaded the package into its plugin cache: ```bash ls ~/.cache/opencode/packages/ | rg "plugin-name" ``` If the package is absent or an old version, the plugin won't load regardless of config. 6. **Log check** — search opencode's log for plugin-load errors, filtering out your own tool-call noise: ```bash rg -i "plugin" ~/.local/share/opencode/log/opencode.log | rg -v "evaluated permission" | tail -30 ``` 7. **Config is loaded once at startup** — a running opencode session keeps the config it loaded at launch. After changing any config file, restart opencode (and run a home-manager rebuild first) before expecting the change to take effect. ## Important Notes - `allowUnfree = true` globally for proprietary packages (Steam, Spotify, etc.) - Multiple cachix substitutes configured for speed (hyprland, nix-community, niri, raspberrypi, cuda) - Pi coding agent uses `scuggo` LiteLLM proxy at `https://9f5db439.fwds.scug.io` - API key via env var `$SCUG_IO_API_KEY` - WSL host uses `nixos-wsl` flake input - RPi5 uses `nixos-raspberrypi` and `raspberry-pi-nix` ## File Rules - `.gitignore`: exclude `nix/result`, `result`, `nvim`, `tmux/plugins`, `modules/quickshell/quickshell/.qmlls.ini` - `.new` file exists (empty) — likely a marker - `.claude/` directory present (Claude Code config)