API Methods
imp.filter
Filter paths by predicate. Multiple filters compose with AND.
Example
imp.filter (lib.hasInfix "/services/") ./modules
imp.filterNot (lib.hasInfix "/deprecated/") ./modules
Arguments
predicate : Function that receives a path string and returns boolean.
imp.filterNot
Exclude paths matching predicate. Opposite of filter.
Example
imp.filterNot (lib.hasInfix "/deprecated/") ./modules
Arguments
predicate : Function that receives a path string and returns boolean.
imp.match
Filter paths by regex. Uses builtins.match.
Example
imp.match ".*[/]services[/].*" ./nix
Arguments
regex : Regular expression string.
imp.matchNot
Exclude paths matching regex. Opposite of match.
Example
imp.matchNot ".*[/]test[/].*" ./src
Arguments
regex : Regular expression string.
imp.initFilter
Replace the default filter. By default, imp finds .nix files
and excludes paths containing underscore prefixes.
Example
# Import markdown files instead of nix files
imp.initFilter (lib.hasSuffix ".md") ./docs
Arguments
predicate : Function that receives a path string and returns boolean.
imp.map
Transform each matched path. Composes with multiple calls.
Example
imp.map import ./packages
Arguments
f : Transformation function applied to each path or value.
imp.mapTree
Transform values when building a tree with .tree. Composes with multiple calls.
Example
(imp.withLib lib)
.mapTree (drv: drv // { meta.priority = 5; })
.tree ./packages
Arguments
f : Transformation function applied to each tree value.
imp.withLib
Provide nixpkgs lib. Required before using .leafs, .files, .tree, or .configTree.
Example
imp.withLib pkgs.lib
imp.withLib inputs.nixpkgs.lib
Arguments
lib : The nixpkgs lib attribute set.
imp.addPath
Add additional paths to search.
Example
(imp.withLib lib)
.addPath ./modules
.addPath ./vendor
.leafs
Arguments
path : Path to add to the search.
imp.addAPI
Extend imp with custom methods. Methods receive self for chaining.
Example
let
myImp = imp.addAPI {
services = self: self.filter (lib.hasInfix "/services/");
packages = self: self.filter (lib.hasInfix "/packages/");
};
in
myImp.services ./nix
Arguments
api : Attribute set of name = self: ... methods.
imp.pipeTo
Apply a function to the final file list.
Example
(imp.withLib lib).pipeTo builtins.length ./modules
Arguments
f : Function to apply to the file list.
imp.leafs
Get the list of matched files. Requires .withLib.
Example
(imp.withLib lib).leafs ./modules
imp.tree
Build a nested attrset from directory structure. Requires .withLib.
Directory names become attribute names. Files are imported and their values placed at the corresponding path.
Example
(imp.withLib lib).tree ./outputs
# { packages.hello = <imported>; apps.run = <imported>; }
Arguments
path : Root directory to build tree from.
imp.treeWith
Convenience function combining .withLib, .mapTree, and .tree.
Example
# These are equivalent:
((imp.withLib lib).mapTree (f: f args)).tree ./outputs
imp.treeWith lib (f: f args) ./outputs
Arguments
lib : The nixpkgs lib attribute set.
f : Transformation function for tree values.
path : Root directory to build tree from.
imp.configTree
Build a module where directory structure maps to NixOS option paths. Each file receives module args and returns config values.
Example
{ inputs, lib, ... }: {
imports = [ ((inputs.imp.withLib lib).configTree ./config) ];
}
# File ./config/programs/git.nix sets config.programs.git
Arguments
path : Root directory containing config files.
imp.configTreeWith
Like .configTree but passes extra arguments to each file.
Example
(imp.withLib lib).configTreeWith { myArg = "value"; } ./config
Arguments
extraArgs : Additional arguments passed to each config file.
path : Root directory containing config files.
imp.mergeConfigTrees
Merge multiple config trees into a single module.
Example
# Later trees override earlier (default)
(imp.withLib lib).mergeConfigTrees [ ./base ./overrides ]
# With mkMerge semantics
(imp.withLib lib).mergeConfigTrees { strategy = "merge"; } [ ./base ./local ]
Arguments
options (optional)
: Attribute set with strategy ("override" or "merge") and extraArgs.
paths : List of directories to merge.
imp.new
Returns a fresh imp instance with empty state, preserving custom API extensions.
Example
let
customImp = imp.addAPI { myMethod = self: self.filter predicate; };
fresh = customImp.new;
in
fresh.myMethod ./src
imp.imports
Build a modules list from mixed items. Handles paths, registry nodes, and modules.
For registry nodes or paths that import to attrsets with __module,
extracts just the __module. For functions that are "registry wrappers"
(take inputs arg and return attrsets with __module), wraps them to
extract __module from the result.
This allows registry modules to declare __inputs and __overlays
without polluting the module system.
Example
modules = imp.imports [
registry.hosts.server
registry.modules.nixos.base
./local-module.nix
inputs.home-manager.nixosModules.home-manager
{ services.openssh.enable = true; }
];
Arguments
items : List of paths, registry nodes, or module values.
imp.analyze
Namespace for dependency analysis and visualization.
Example
graph = (imp.withLib lib).analyze.registry { registry = myRegistry; }
html = (imp.withLib lib).analyze.toHtml graph
json = (imp.withLib lib).analyze.toJson graph
imp.fragments
Collect fragments from a .d directory. Requires .withLib.
Follows the .d convention where fragments are sorted by filename
and composed together. Files are processed in order (00-base before 10-extra).
Returns an attrset with multiple access methods:
.list- raw list of fragment contents.asString- fragments concatenated with newlines (for shell scripts).asList- fragments flattened (for lists of packages).asAttrs- fragments merged (for attrsets)
Note: For known flake output directories (packages.d, devShells.d, etc.),
tree.nix auto-merges fragments. Use imp.fragments for other .d dirs
like shellHook.d or shell-packages.d.
Example
let
imp = inputs.imp.withLib lib;
# Shell scripts concatenated
shellHookFragments = imp.fragments ./shellHook.d;
# Package lists merged
shellPkgFragments = imp.fragmentsWith { inherit pkgs self'; } ./shell-packages.d;
in
pkgs.mkShell {
packages = shellPkgFragments.asList;
shellHook = shellHookFragments.asString;
}
Arguments
dir
: Directory ending in .d containing fragments (.nix or .sh files).
imp.fragmentsWith
Collect fragments with arguments passed to each .nix file.
Like fragments, but calls each .nix fragment as a function with the
provided arguments. Shell (.sh) files are still read as strings.
Example
# Each file in shell-packages.d/ is called with { pkgs, self' }
# and should return a list like [ pkgs.ast-grep self'.packages.lint ]
shellPkgs = (imp.withLib lib).fragmentsWith { inherit pkgs self'; } ./shell-packages.d;
packages = shellPkgs.asList;
Arguments
args : Attrset of arguments to pass to each fragment function.
dir : Directory containing fragments.
Registry
imp.buildRegistry
Build registry from a directory. Each directory gets __path plus child entries.
Arguments
root : Root directory path to scan.
imp.flattenRegistry
Flatten registry to dot-notation paths.
flattenRegistry registry
# => { home.alice = <path>; modules.nixos.base = <path>; }
registry
: Function argument
imp.lookup
Lookup a dotted path in the registry.
lookup "home.alice" registry # => <path>
path
: Function argument
registry
: Function argument
imp.makeResolver
Create resolver function: name -> path.
resolve = makeResolver registry;
resolve "home.alice" # => <path>
registry
: Function argument
imp.toPath
Extract path from registry value. Works for paths and __path nodes.
x
: Function argument
imp.isRegistryNode
Check if a value is a registry node (has __path).
x
: Function argument
Format Flake
imp.formatValue
Format a value as Nix source code.
Arguments
depth : Indentation depth level.
value : Value to format (string, bool, int, null, list, or attrset).
imp.formatInput
Format a single input definition (at depth 1).
Arguments
name : Input name.
def : Input definition attrset.
imp.formatInputs
Format multiple inputs as a block.
Example
formatInputs { treefmt-nix = { url = "github:numtide/treefmt-nix"; }; }
# => "treefmt-nix.url = \"github:numtide/treefmt-nix\";"
Arguments
inputs : Attrset of input definitions.
imp.formatFlake
Generate complete flake.nix content.
Example
formatFlake {
description = "My flake";
coreInputs = { nixpkgs.url = "github:nixos/nixpkgs"; };
collectedInputs = { treefmt-nix.url = "github:numtide/treefmt-nix"; };
}
Arguments
description : Flake description string (optional).
coreInputs : Core flake inputs attrset (optional).
collectedInputs : Collected inputs from __inputs declarations (optional).
outputsFile : Path to outputs file (default: "./outputs.nix").
header : Header comment for generated file (optional).
Analyze
imp.analyzeConfigTree
Analyze a single configTree, returning nodes and edges.
The path should be a directory. We scan it for .nix files and
read each one to check for registry references.
Note: We only collect refs from files directly in this directory, not from subdirectories (those are handled as separate nodes).
Arguments
path : Directory path to analyze.
id : Identifier for this config tree node.
imp.analyzeMerge
Analyze a mergeConfigTrees call.
Arguments
id : Identifier for this merged tree.
sources : List of { id, path } for each source tree.
strategy
: Merge strategy ("merge" or "override").
imp.analyzeRegistry
Analyze an entire registry, discovering all modules and their relationships.
This walks the registry structure, finds all configTrees, and analyzes each one for cross-references. Optionally also scans an outputs directory to include flake outputs (like nixosConfigurations) as sink nodes.
Example
analyzeRegistry { registry = myRegistry; }
# => { nodes = [...]; edges = [...]; }
# With outputs directory
analyzeRegistry { registry = myRegistry; outputsSrc = ./outputs; }
Arguments
registry : Registry attrset to analyze.
outputsSrc
: Optional path to outputs directory (e.g., imp.src). Files here that
reference registry paths will be included as output nodes.
imp.scanDir
Scan a directory and build a list of all .nix files with their logical paths.
Example
scanDir ./nix
# => [ { path = /abs/path.nix; segments = ["programs" "git"]; } ... ]
Arguments
root : Root directory to scan.
Visualize
imp.toJson
Convert graph to a JSON-serializable structure with full paths.
Arguments
graph : Graph with nodes and edges from analyze functions.
imp.toJsonMinimal
Convert graph to JSON without paths (avoids store path issues with special chars).
Arguments
graph : Graph with nodes and edges from analyze functions.
Export Sinks
imp.collectExports
Scan directories for __exports declarations and collect them.
Recursively scans .nix files for __exports attribute declarations
and collects them, tracking source paths. Returns an attrset mapping
sink keys to lists of export records.
Only attrsets with __exports are collected. For functions that need
to declare exports, use the __functor pattern:
{
__exports."nixos.role.desktop" = {
value = { services.pipewire.enable = true; };
strategy = "merge";
};
__functor = _: { inputs, ... }: { __module = ...; };
}
Example
imp.collectExports ./registry
# => {
# "nixos.role.desktop" = [
# {
# source = "/path/to/audio.nix";
# value = { services.pipewire.enable = true; };
# strategy = "merge";
# }
# ];
# }
Arguments
pathOrPaths : Directory/file path, or list of paths, to scan for __exports declarations.
imp.buildExportSinks
Build export sinks from collected exports.
Takes collected exports and merges them according to their strategies, producing a nested attrset of sinks. Each sink contains merged values and metadata about contributors.
Example
buildExportSinks {
lib = nixpkgs.lib;
collected = imp.collectExports ./registry;
sinkDefaults = {
"nixos.*" = "merge";
"hm.*" = "merge";
};
}
# => {
# nixos.role.desktop = {
# __module = { ... };
# __meta = { contributors = [...]; strategy = "merge"; };
# };
# }
Arguments
lib : nixpkgs lib for merge operations.
collected : Output from collectExports.
sinkDefaults : Optional attrset mapping glob patterns to default strategies.
enableDebug : Include __meta with contributor info (default: true).
Standalone Utilities
imp.collectInputs
Scan directories for __inputs declarations and collect them.
Recursively scans .nix files for __inputs attribute declarations
and merges them into a single attrset. Detects conflicts when the
same input name has different definitions in different files.
Only attrsets with __inputs are collected. For files that need to
be functions (e.g., to receive inputs at runtime), use the __functor
pattern so __inputs is accessible without calling the function:
{
__inputs.foo.url = "github:foo/bar";
__functor = _: { inputs, ... }: inputs.foo.lib.something;
}
Accepts either a single path or a list of paths. When given multiple paths, all are scanned and merged with conflict detection.
Example
# Single path
imp.collectInputs ./outputs
# => { treefmt-nix = { url = "github:numtide/treefmt-nix"; }; }
# Multiple paths
imp.collectInputs [ ./outputs ./registry ]
# => { treefmt-nix = { ... }; nur = { ... }; }
Arguments
pathOrPaths : Directory/file path, or list of paths, to scan for __inputs declarations.
imp.collectAndFormatFlake
Convenience function combining collectInputs and formatFlake.
Scans a directory for __inputs declarations and generates
complete flake.nix content in one step.
Example
imp.collectAndFormatFlake {
src = ./outputs;
coreInputs = { nixpkgs.url = "github:nixos/nixpkgs"; };
description = "My flake";
}
# => "{ description = \"My flake\"; inputs = { ... }; ... }"
Arguments
src : Directory to scan for __inputs declarations.
coreInputs : Core flake inputs attrset (optional).
description : Flake description string (optional).
outputsFile : Path to outputs file (default: "./outputs.nix").
header : Header comment for generated file (optional).