Config Trees
Config trees are option attrsets derrived from directory structure. The file path is the option path: programs/git.nix sets programs.git. That's it.
home/
programs/
git.nix # -> programs.git = { ... }
zsh.nix # -> programs.zsh = { ... }
services/
gpg-agent.nix # -> services.gpg-agent = { ... }
Each file returns just that option's value:
# home/programs/git.nix
{
enable = true;
userName = "Alice";
}
Want to know if git is configured? Check if programs/git.nix exists. The directory becomes a table of contents.
Usage
{ inputs, lib, ... }:
{
imports = [ ((inputs.imp.withLib lib).configTree ./home) ];
}
With registry (when using the flake-parts module):
{ imp, ... }:
{
imports = [ (imp.configTree ./.) ];
}
Files can be functions
When you need access to module arguments like pkgs or config:
# programs/git.nix
{ pkgs, ... }:
{
enable = true;
package = pkgs.gitFull;
}
Config tree files receive standard module arguments (config, lib, pkgs, etc.) plus any extras you pass.
Extra arguments
imp.configTreeWith { secrets = ./secrets; } ./config
Files then receive secrets alongside standard module args.
Building attribute trees
Config trees are for NixOS/Home Manager modules. For non-module uses (packages, apps, arbitrary attrsets), use .tree or .treeWith:
let packages = (imp.withLib lib).tree ./packages; in
packages.hello # -> imported from ./packages/hello.nix
When files export functions needing arguments:
# packages/hello.nix
{ pkgs }: pkgs.hello
# Build with treeWith
imp.treeWith lib (f: f { inherit pkgs; }) ./packages
# => { hello = <derivation>; }
Transformation patterns
The second argument to treeWith is applied to every imported value. Common uses:
# Call each file with arguments
imp.treeWith lib (f: f { inherit pkgs lib; }) ./outputs
# Add metadata to all derivations
imp.treeWith lib (drv: drv // { meta.priority = 5; }) ./packages
# Wrap each module with common imports
imp.treeWith lib (mod: { imports = [ mod commonModule ]; }) ./modules
For multiple transformations, chain .mapTree:
(imp.withLib lib)
.mapTree (f: f { inherit pkgs; })
.mapTree (drv: drv.overrideAttrs (old: { meta.license = lib.licenses.mit; }))
.tree ./packages