This is a Nix Home Manager configuration project using flakes for user environment management. The project follows a modular approach to keep configurations simple, maintainable, and reusable.
- Use
nixfmtfor Nix code formatting (runnixfmt .before commits) - 2-space indentation for all Nix files
- Follow nixpkgs conventions for package expressions
- Attribute sets should have consistent formatting with closing braces aligned
- One attribute per line for readability in complex expressions
- Use
recsparingly - preferlet...infor clarity
.
├── flake.nix # Main flake configuration
├── home.nix # Base home configuration
├── modules/ # Feature-specific modules
│ ├── shell.nix # Shell configuration (zsh, bash, etc.)
│ ├── editor.nix # Editor configurations
│ ├── dev.nix # Development tools
│ ├── desktop.nix # Desktop environment configs
│ └── secrets.nix # Agenix secrets configuration
├── programs/ # Program-specific configurations
│ ├── git.nix # Git configuration
│ ├── tmux.nix # Tmux configuration
│ └── ...
├── services/ # Service configurations
│ ├── syncthing.nix # Syncthing service
│ └── ...
└── secrets/ # Encrypted secrets
├── secrets.nix # Defines who can decrypt secrets
└── *.age # Encrypted secret files
- Always verify Home Manager options exist using:
mcp__nixos__home_manager_info - Search for options with:
mcp__nixos__home_manager_search - Check option prefixes with:
mcp__nixos__home_manager_options_by_prefix - For package availability, use:
mcp__nixos__nixos_search
- Test build:
home-manager build --flake .#jason - Apply changes:
home-manager switch --flake .#jason - Check flake:
nix flake check - Update inputs:
nix flake update - Dry Run Tip: Always use
home-manager buildfor a dry run beforeswitch
- Format all Nix files:
nixfmt . - Verify formatting before commits
- Use
nix-instantiate --parseto check for syntax errors
- Each module should be self-contained and focused on a single concern
- Use
mkEnableOptionfor optional features - Provide sensible defaults
- Document options clearly
- Example module structure:
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.myprogram;
in {
options.programs.myprogram = {
enable = mkEnableOption "myprogram";
settings = mkOption {
type = types.attrs;
default = {};
description = "Configuration for myprogram";
};
};
config = mkIf cfg.enable {
home.packages = [ pkgs.myprogram ];
# ... additional configuration
};
}- Keep it simple but modular - Each module should do one thing well
- Always verify before implementing - Use MCP tools to check option availability
- Ask for clarification - When uncertain, always ask. Asking is success!
- Read entire files - Always read complete files before making edits
- Test incrementally - Build and test after each significant change
- Document decisions - Add comments for non-obvious configuration choices
- Use Catppuccin for all theming - Catppuccin provides a unified theming solution
- Global enable with
catppuccin.enable = truefor all supported packages - Choose from four flavors: latte (light), frappe, macchiato, mocha (dark)
- Automatically themes all supported applications
- Avoid manual color configurations when Catppuccin can handle it
- vimjoyer's flake-starter-config: https://github.com/vimjoyer/flake-starter-config
- Excellent modular structure and organization
- Clean separation of concerns
- Note: We're keeping home-manager separate for now (not integrated with NixOS)
- Mitchell Hashimoto's nixos-config: https://github.com/mitchellh/nixos-config/blob/main/users/mitchellh/home-manager.nix
- Professional developer setup with thoughtful choices
- Good examples of program configurations
- Well-documented approach to personal tooling
- Catppuccin examples: https://github.com/catppuccin/nix
- Home Manager community configs: Search GitHub for real-world examples
- Formatter:
nixfmt(from https://github.com/NixOS/nixfmt) - Language Server:
nilornixdfor LSP support - REPL:
nix replfor testing expressions - Flake utilities:
nix flake show- Display flake outputsnix flake metadata- Show flake informationnix flake check- Validate flake
- Home Manager CLI:
home-manager generations- List all generationshome-manager rollback- Rollback to previous generationhome-manager news- Show news about changes
- NixOS MCP: Always verify options and configurations
- Context7 MCP: Use for library documentation lookups
- Brave Search: Use for web searches and finding examples
- Version lookups: Use
mcp__nixos__nixhub_package_versionsfor specific package versions
- Check if program exists:
mcp__nixos__nixos_search "program-name" - Find Home Manager options:
mcp__nixos__home_manager_search "program-name" - Create module in
programs/directory - Import in
home.nix - Test with
home-manager build
- Create secret:
echo "secret-value" | agenix -e secrets/secret-name.age - Add to
modules/secrets.nix - Reference with
config.age.secrets.secret-name.path - Never log or print secret values
- See
AGENIX_GUIDE.mdfor detailed examples
- Catppuccin is already included in
flake.nixinputs - Configure in
modules/theme.nix:{ config, lib, pkgs, ... }: { # Global enable for all supported packages catppuccin.enable = true; # Set the flavor (latte, frappe, macchiato, mocha) catppuccin.flavor = "mocha"; }
- Catppuccin will automatically theme all supported applications
- Check Catppuccin nix docs for package-specific overrides
- Use
home-manager newsto see recent changes - Check logs with
journalctl --user - Validate option types match expected values
- Use
nix replto test expressions
We use agenix for managing encrypted secrets. Secrets are encrypted with age using SSH public keys and stored in the repository. They're decrypted at home-manager switch time using your SSH private key.
- Secrets definition:
secrets/secrets.nix- defines recipients (who can decrypt) - Secrets configuration:
modules/secrets.nix- configures agenix module - Encrypted secrets:
secrets/*.age- safe to commit - Decrypted location:
~/.config/agenix/- never commit! - Guide: See
AGENIX_GUIDE.mdfor detailed usage
# Encrypt a new secret
agenix -e secrets/my-secret.age
# Edit existing secret
agenix -e secrets/my-secret.age
# Re-encrypt all secrets (after adding new recipients)
agenix -r- Add recipient to
secrets/secrets.nix - Define secret in
modules/secrets.nix:age.secrets.my-secret = { file = ../secrets/my-secret.age; };
- Use in configuration:
someOption = config.age.secrets.my-secret.path;
- Never include
/resultsymlinks in commits - Format code before committing
- Use descriptive commit messages following conventional commits
- Test configuration before pushing
- Never commit secrets or API keys
- We use
agenixfor secret management (see Secrets Management section) - Review all external flake inputs
- Keep flake inputs updated for security patches
- Encrypted secrets (*.age files) are safe to commit
- Never commit decrypted secrets or the agenix runtime directories
- Use
nixpkgs.config.allowUnfreejudiciously - Minimize use of IFD (Import From Derivation)
- Prefer binary caches when available
- Use
nix.gcsettings to manage disk usage
- Syntax error? Run
nix-instantiate --parse file.nix - Option not found? Verify with MCP tools
- Build fails? Check
home-manager newsfor breaking changes - Unexpected behavior? Review recent commits
- Performance issues? Profile with
nix-store --optimise
- Dry Run Best Practice: Always use dry run only on home-manager rebuilds to verify changes before applying