CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Repository Overview
This is a comprehensive NixOS and home-manager monorepo for managing personal infrastructure, system configurations, and custom tools. The repository uses Nix flakes as the primary interface for building and deploying configurations across multiple machines.
Architecture
Core Structure
The repository follows a modular architecture centered around flake.nix:
/lib: Core library functions includingmkHost,mkHome, andmkSystemManagerfor generating NixOS, home-manager, and system-manager configurationsglobals.nix: Global configuration including machine definitions (network, SSH, syncthing), DNS zones, and VPN settings/systems: NixOS system configurations, organized by hostname with a shared/systems/commondirectory containing base, desktop, hardware, programs, services, and users modules/home: Home-manager configurations with/home/commoncontaining desktop, dev, services, and shell modules/pkgs: Custom Nix packages that are exposed via overlays/tools: Source code for custom tools (battery-monitor, emacs configuration)/modules: Custom NixOS modules (wireguard-client, wireguard-server, govanityurl, gosmee)/overlays: Nix overlays for additions, modifications, and unstable packages/keyboards: Hardware keyboard configurations (ZMK for Corne, QMK for Moonlander, Kanata software remapper)/imperative: Idempotent configuration scripts for non-NixOS managed systems, organized by hostname (e.g.,/imperative/nagoya/apply.sh). These scripts are meant to be run repeatedly to maintain system state on hosts that cannot use NixOS.
Host Configuration Pattern
Each host has a dedicated directory in /systems/<hostname> containing:
boot.nix: Boot configuration (bootloader, initrd, kernel modules)hardware.nix: Hardware-specific settings (hardware imports, filesystem mounts)extra.nix(optional): Additional host-specific configurationhome.nix(optional): Host-specific home-manager configuration
System Types
- Unstable systems (kyushu, aomi, sakhalin, foobar): Use
nixpkgs(nixos-unstable) - Stable systems (athena, demeter, aix, aion, rhea, kerkouane): Use
nixpkgs-25_05with specific hardware types like “rpi4” for Raspberry Pi 4
Package Management
Custom packages are defined in /pkgs/default.nix and exposed through the additions overlay. They are built using standard Nix packaging functions (pkgs.callPackage). The repository provides packages for both x86_64-linux and aarch64-linux architectures.
Secrets Management
Secrets are managed using agenix:
secrets.nixdefines which secrets are encrypted for which hosts and users- Yubikeys are used for age encryption
- Host SSH keys are used for system-level secret decryption
Common Commands
Everything should happen using make (and Makefile accross the repository). You can use make help to figure out what it does.
IMPORTANT: Never use home-manager switch or nixos-rebuild commands directly. Always use make switch or the appropriate make targets.
Building and Deploying Systems
# Build and switch the current system
make switch
# Build and activate on next boot
make boot
# Test build without switching
make dry-build
# Build a specific remote host
make host/<hostname>/build
# Deploy to a remote host (boot)
make host/<hostname>/boot
# Deploy to a remote host (switch)
make host/<hostname>/switch
Building Packages
# Build a single package
nix build .#<package-name>
# Install a package to your profile
nix profile install .#<package-name>
# List all available packages
nix flake show
Home Manager
# Update home-manager configuration
home-manager switch --flake .#<username>@<hostname>
Development
# Enter development shell
nix develop
# Format Nix files
make fmt
# Run pre-commit checks
make pre-commit
# Install git hooks
make install-hooks
Maintenance
# Clean old system generations (older than 15 days) and build results
make clean
# Update flake inputs
nix flake update
Pre-commit Hooks
The repository uses pre-commit hooks configured in flake.nix for:
- Go formatting (gofmt)
- Nix formatting (nixfmt-rfc-style) and linting (deadnix)
- Python linting (flake8, ruff)
- Shell script checking (shellcheck)
These run automatically via git hooks if installed with make install-hooks.
Key Patterns
Adding a New Host
- Create
/systems/<hostname>directory withboot.nixandhardware.nix - Add host entry in
flake.nixnixosConfigurations usinglibx.mkHost - Add machine metadata to
globals.nix(network IPs, SSH keys, syncthing ID if applicable) - If using secrets, update
secrets.nixwith host SSH key
Adding a New Package
- Create package directory in
/pkgs/<package-name>withdefault.nix - Add entry to
/pkgs/default.nixusingpkgs.callPackage - Package will be available via
nix build .#<package-name>
Modifying Desktop Environment
Desktop configurations are in /systems/common/desktop and /home/common/desktop. The desktop type (“sway” or “niri”) is specified when calling mkHost in flake.nix and conditionally imports desktop modules.
Testing
For Go-based tools, run tests from the tool directory:
cd tools/<tool-name>
go test ./...
Keyboard Firmware
# Build Moonlander QMK firmware in folder keyboards/moonlander of the git repository
make keyboards/moonlander/build
# Build eyelash_corne ZMK firmware in folder keyboards/eyelash_corne of the git repository
make keyboards/eyelash_corne/build
# Generate keymap SVGs for visualization
make keyboards/draw # Generate SVGs for all keyboards
make keyboards/moonlander/draw # Generate SVG for Moonlander only
make keyboards/eyelash_corne/draw # Generate SVG for Eyelash Corne only
Deployment Safety
IMPORTANT: Always ask for user confirmation before deploying to remote hosts.
When making configuration changes that require deployment:
- Show the changes first - Use
git diffor explain what will be deployed - Ask for explicit approval - Never run
nixos-rebuild switchormake host/<hostname>/switchwithout asking the user first - Suggest dry-run builds - Offer to run
make host/<hostname>/buildornixos-rebuild buildto test first - Confirm the target host - Make sure the user wants to deploy to that specific machine
Examples of what to ask:
- “Would you like me to deploy these changes to rhea?”
- “Should I run a dry-build first to verify the configuration?”
- “These changes will affect
. Do you want to proceed with the deployment?”
Never deploy automatically - even if it seems like the logical next step. Remote deployments can have significant impact on running services.
Special Notes
- The repository uses XDG base directories for Nix configuration (enabled via
use-xdg-base-directories = true) - Custom binary caches are configured: vdemeester.cachix.org, chapeau-rouge.cachix.org, nixos-raspberrypi.cachix.org
- The
globals.nixfile contains sensitive network topology information and should be consulted when working with networking or machine-specific configurations - Some hosts use specific NixOS versions: stable hosts use 25.05, unstable hosts use nixos-unstable