| name | nixos-test-changes |
| description | Incremental NixOS/home-manager flake testing - only evaluate changed modules for 6-7x faster feedback. USE WHEN user says 'test my changes', 'quick test', 'incremental test', 'check what changed', 'test nixos config', or working on NixOS/home-manager configurations and needs fast validation. |
NixOS Incremental Testing
Fast, granular testing for NixOS flakes - only evaluate what changed.
When to Activate This Skill
- User is working on NixOS or home-manager configuration changes
- User says "test my changes", "quick test", "incremental test"
- User asks "what changed" or "what needs testing"
- User wants faster feedback than full
task test (~9s vs ~60s)
- User is in a NixOS configuration repository with
test-changes app
Core Workflow
Quick Test (Recommended)
For fast iteration during development:
vim hosts/homes/jq@desktop/default.nix
task inc
task test
Detailed Analysis
To see what's affected before testing:
task test-changes
nix run .#test-changes -- analyze main
nix run .#test-changes -- test --eval-only
Key Commands
task inc
task test-changes
nix run .#test-changes -- analyze
nix run .#test-changes -- analyze main
nix run .#test-changes -- test --eval-only
nix run .#test-changes -- test --dry-run
nix run .#test-changes -- compare
nix run .#test-changes -- build nixosConfigurations.desktop
nix run .#test-changes -- build --eval-only homeConfigurations.jq@desktop
File-to-Output Mapping
The tool automatically maps changed files to specific flake outputs:
| Changed File Pattern | Affected Output | Test Speed |
|---|
hosts/nixos/desktop/* | nixosConfigurations.desktop only | ~10s |
hosts/homes/jq@desktop/* | homeConfigurations.jq@desktop only | ~9s |
hosts/homes/jq@qb/* | homeConfigurations.jq@qb only | ~9s |
modules/nixos/* | ALL configs (full test required) | ~60s |
modules/home/* | ALL configs (full test required) | ~60s |
flake.nix, flake.lock | ALL configs (full test required) | ~60s |
overlays/*, pkgs/* | ALL configs (full test required) | ~60s |
Common Patterns
Pattern 1: Development Workflow (Host-Specific)
When changing a single host's configuration:
vim hosts/homes/jq@desktop/default.nix
task inc
task test
Speedup: 6.7x faster (9s vs 60s)
Pattern 2: Feature Branch Testing
Test all changes on your branch before PR:
nix run .#test-changes -- analyze main
nix run .#test-changes -- test main --eval-only
task test
Pattern 3: Module Changes (No Speedup)
When changing shared modules, full test is required:
vim modules/home/programs/git/default.nix
task test-changes
task test
Pattern 4: Dry-Run Preview
See what would be tested without running:
nix run .#test-changes -- test --dry-run
Performance Benchmarks
| Scenario | Full Test | Incremental | Speedup |
|---|
| Single home config | ~60s | ~9s | 6.7x |
| Single NixOS host | ~60s | ~10s | 6x |
| Two hosts | ~60s | ~18s | 3.3x |
| Shared module | ~60s | ~60s | 1x (must test all) |
Flags
--eval-only / -e - Only evaluate, don't build (faster, recommended)
--dry-run / -n - Show commands without executing
analyze [base] - Detect changes (base defaults to HEAD)
test [base] - Run incremental test
compare [base] - Benchmark incremental vs full
build <outputs> - Build specific outputs
Environment Variables
DRY_RUN=true nix run .#test-changes -- test
EVAL_ONLY=true nix run .#test-changes -- test
Examples
vim hosts/homes/jq@desktop/default.nix
task inc
vim hosts/nixos/desktop/hardware.nix
vim hosts/nixos/qb/profiles.nix
nix run .#test-changes -- analyze
nix run .#test-changes -- test --eval-only
git checkout -b feature/new-module
nix run .#test-changes -- analyze main
nix run .#test-changes -- test main
nix run .#test-changes -- build --eval-only \
nixosConfigurations.desktop \
homeConfigurations.jq@desktop
nix run .#test-changes -- test origin/main --eval-only
When NOT to Use
- Changing shared modules - Use
task test directly (no speedup possible)
- Before final commit - Always run full
task test before pushing
- Building actual outputs - Use
task nixos or task home-manager for activation
- CI/CD final validation - Use full test suite for merge validation
Integration with Existing Workflow
The incremental testing complements, doesn't replace, full testing:
task inc
task inc
task inc
task test
git commit -m "..."
task apply
Troubleshooting
"No changes detected"
- You have no uncommitted changes
- Solution: Make changes or specify different base with
analyze main
"No outputs affected by changes"
- Changed files don't map to any flake outputs (e.g., README, scripts)
- Solution: This is fine, no testing needed for those files
"FULL_CHECK required"
- Changed files affect shared modules/overlays/packages
- Solution: Run
task test for full validation
Test fails but full test passes
- Rare edge case with dependency detection
- Solution: Always run full
task test before committing
Key Principles
- Use incremental for iteration - 6-7x faster feedback during development
- Always full test before push - Ensure everything still works together
- Understand the mapping - Host-specific = fast, shared = full test
- Trust the detection - Tool accurately maps files to outputs
- Eval-only is enough - Build only needed for final activation
Supplementary Resources
For implementation details: read apps/test-changes/README.md
For app source: read apps/test-changes/test-changes.sh
For Taskfile integration: read Taskfile.yml