API Reference
Obtaining import-tree
Section titled “Obtaining import-tree”As a flake input:
inputs.import-tree.url = "github:vic/import-tree";As a plain import:
let import-tree = import ./path-to/import-tree;The resulting value is a callable attrset — the primary import-tree object.
Core: Calling import-tree
Section titled “Core: Calling import-tree”import-tree <path | [paths]>
Section titled “import-tree <path | [paths]>”Takes a path or a (nested) list of paths. Returns a Nix module with imports set to all discovered files.
import-tree ./modulesimport-tree [ ./modules ./extra ]import-tree [ ./a [ ./b ] ] # nested lists are flattenedOther import-tree objects can appear in the list as if they were paths.
Anything with an outPath attribute (like flake inputs) is treated as a path:
import-tree [ { outPath = ./modules; } ]Non-path values (like attrsets) are passed through the filter and included if they pass.
Filtering
Section titled “Filtering”.filter <fn>
Section titled “.filter <fn>”fn : string -> bool — only include paths where fn returns true.
import-tree.filter (lib.hasInfix ".mod.") ./modulesMultiple .filter calls compose with AND.
.filterNot <fn>
Section titled “.filterNot <fn>”Inverse of .filter — exclude paths where fn returns true.
import-tree.filterNot (lib.hasInfix "experimental") ./modules.match <regex>
Section titled “.match <regex>”Include only paths matching the regex. Uses builtins.match (tests full string).
import-tree.match ".*/[a-z]+_[a-z]+\.nix" ./modulesMultiple .match calls compose with AND.
.matchNot <regex>
Section titled “.matchNot <regex>”Exclude paths matching the regex.
import-tree.matchNot ".*/test_.*\.nix" ./modules.initFilter <fn>
Section titled “.initFilter <fn>”Replaces the default filter (.nix suffix, no /_ infix). Use for non-Nix files or custom ignore conventions.
import-tree.initFilter (lib.hasSuffix ".md") ./docsimport-tree.initFilter (p: lib.hasSuffix ".nix" p && !lib.hasInfix "/skip/" p)Also applies to non-path items in import lists.
Transformation
Section titled “Transformation”.map <fn>
Section titled “.map <fn>”fn : path -> a — transform each discovered path.
import-tree.map lib.traceVal ./modules # trace each pathimport-tree.map (p: { imports = [ p ]; }) # wrap in moduleimport-tree.map import # actually importMultiple .map calls compose (first map runs first).
Path Accumulation
Section titled “Path Accumulation”.addPath <path>
Section titled “.addPath <path>”Prepend a path to the internal path list. Can be called multiple times:
(import-tree.addPath ./vendor).addPath ./modules# discovers files in both directoriesExtension
Section titled “Extension”.addAPI <attrset>
Section titled “.addAPI <attrset>”Extend the import-tree object with new methods. Each value is a function receiving self (the current import-tree):
import-tree.addAPI { maximal = self: self.addPath ./all-modules; feature = self: name: self.filter (lib.hasInfix name);}Methods are late-bound — you can reference methods added in later .addAPI calls.
Output
Section titled “Output”.withLib <lib>
Section titled “.withLib <lib>”Required before .leafs or .pipeTo when used outside module evaluation. Provides lib.filesystem.listFilesRecursive.
import-tree.withLib pkgs.lib.leafs
Section titled “.leafs”Returns a configured import-tree that produces file lists instead of modules:
(import-tree.withLib lib).leafs ./modules# => [ ./modules/a.nix ./modules/b.nix ].files
Section titled “.files”Shorthand for .leafs.result:
(import-tree.addPath ./modules).withLib lib |>.files.pipeTo <fn>
Section titled “.pipeTo <fn>”Like .leafs but pipes the result list through fn:
(import-tree.withLib lib).pipeTo builtins.length ./modules# => 3.result
Section titled “.result”Evaluate with an empty path list. Equivalent to calling with []:
(import-tree.addPath ./modules).resultReturns a fresh import-tree with empty state — no paths, filters, maps, or API extensions.
configured-tree.new # back to a clean slate