Library
artifacts.make
Build a system-indexed set of “artifacts” from flake modules.
This evaluates each module for one or more target systems (based on its nixpkgsConfig settings, or a default set), then extracts the requested "config" value into an output shaped like "result.<system>.<module> = <value>".
This is useful for producing flake outputs like per-system packages/apps/checks from a shared module collection, while still supporting a clean per-system "default".
Type:
{
# Name of the config field to extract as the artifact value
# (supports top-level or "config.<name>").
config: string,
# Config flag name that marks an artifact as the per-system default.
defaultConfig: string,
# Attrset of flake modules to evaluate
# and extract artifacts from (keyed by module name).
flakeModules: attribute set of module,
# Path to a nixpkgs input,
# used to instantiate "pkgs" for each target system.
nixpkgs: absolute path,
# Name of the config field that describes nixpkgs settings for a module
# (especially the target "system"/systems).
# If a module doesn’t specify it, default systems are used.
nixpkgsConfig: string,
# Extra args used during module evaluation
# (passed through like "specialArgs").
specialArgs: attribute set,
...
} -> attribute set
attrset.flatten
Flatten an attrset recursively using a key separator.
Type:
{
# The attrset to flatten
attrs: attribute set,
# Final attrset key separator
separator: string,
# Recurse into attrsets depending on this predicate
while: raw value -> boolean,
...
} -> attribute set
attrset.isDictionary
Returns true for an attrset that is "safe" to peek into (not a derivation ,an option type or a functor).
Type: attribute set -> boolean
attrset.keepAttrByPath
Keep only the nested attribute specified by a path, returning a minimal attrset (or empty if missing).
Type: list of string -> attribute set -> attribute set
attrset.keepAttrsByPath
Keep only the nested attributes specified by a list of paths, merging the kept results into one attrset.
Type: list of list of string -> attribute set -> attribute set
attrset.removeAttrByPath
Remove a nested attribute specified by a path from an attrset.
Type: list of string -> attribute set -> attribute set
attrset.removeAttrsByPath
Remove multiple nested attributes specified by a list of paths from an attrset.
Type: list of list of string -> attribute set -> attribute set
configurations.make
Build NixOS configurations from flake modules, across one or more target systems.
For each module that provides "config", this evaluates a "lib.nixosSystem" using the module’s "nixpkgsConfig" (or default systems) and returns an attrset of configurations keyed like: "<module>-<system>".
This is useful when you want a module-driven way to generate "nixosConfigurations" (including per-system defaults) without manually writing one "nixosSystem" per host/system combo.
Type:
{
# Name of the config field that contains the NixOS module
# (or module-like value) to feed into "lib.nixosSystem".
config: string,
# Config flag name that marks a configuration as the default
# for its system (emits "default-<system>").
defaultConfig: string,
# Attrset of flake modules to turn into NixOS configurations
# (keyed by module name).
flakeModules: attribute set of module,
# Path to a nixpkgs input used indirectly via "lib.nixosSystem"
# (for system-specific evaluation).
nixpkgs: absolute path,
# Name of the config field that defines nixpkgs settings per module
# (especially the target "system"/systems).
# If absent, default systems are used.
nixpkgsConfig: string,
# Extra args passed through to "lib.nixosSystem" and
# module evaluation (like "specialArgs").
specialArgs: attribute set,
...
} -> attribute set
debug.trace
Trace a JSON-renderable view of a value (functions replaced with a placeholder) and return the original value.
Type: raw value -> raw value
debug.traceString
Create a JSON-renderable view of a value;
Type: raw value -> string
docs.function
Attach documentation (and optional runtime assertions) to a function.
Type:
{
# Whether the function argument/result will be asserted
asserted: (boolean or one of "argument", "result"),
# Function description
description: string,
# Unit test attrset or function for this function
tests: ((attribute set of (boolean or ({
# Test failure message
message: string,
# Whether te test passes or not
success: boolean,
...
}) or ({
# Actual value to be equated with expected
actual: raw value,
# Expected value to be equated against actual
expected: raw value,
# Test failure message
message: string,
...
}))) or (opaque function -> attribute set of (boolean or ({
# Test failure message
message: string,
# Whether te test passes or not
success: boolean,
...
}) or ({
# Actual value to be equated with expected
actual: raw value,
# Expected value to be equated against actual
expected: raw value,
# Test failure message
message: string,
...
}))) or ({
# Function to test
target: opaque function,
...
} -> attribute set of (boolean or ({
# Test failure message
message: string,
# Whether te test passes or not
success: boolean,
...
}) or ({
# Actual value to be equated with expected
actual: raw value,
# Expected value to be equated against actual
expected: raw value,
# Test failure message
message: string,
...
}))) or ({
# Pkgs constructed from nixpkgs if available.
# If pkgs are required and not available for this test run
# this testing function wont be ran.
pkgs: raw value,
# Function to test
target: opaque function,
...
} -> attribute set of (boolean or ({
# Test failure message
message: string,
# Whether te test passes or not
success: boolean,
...
}) or ({
# Actual value to be equated with expected
actual: raw value,
# Expected value to be equated against actual
expected: raw value,
# Test failure message
message: string,
...
})))),
# Function type
type: optionType,
...
} -> opaque function -> opaque function
docs.libFunctionsMarkdown
Render docs for a library attrset as markdown.
Hides ""_module.*"" options and strips "declarations".
Type:
{
# The library attrset to document.
lib: raw value,
# A "pkgs" set providing "nixosOptionsDoc".
pkgs: raw value,
# Special args passed to "evalModules".
specialArgs: attribute set,
...
} -> string
docs.libToOptions
Render a flake library to options ready to be rendered to markdown.
Type: attribute set -> attribute set
docs.moduleOptionsMarkdown
Render module options docs as markdown.
It also hides "_module.*" options and strips "declarations".
Type:
{
# Modules to evaluate and document.
modules: list of module,
# A "pkgs" set providing "nixosOptionsDoc".
pkgs: raw value,
# Special args passed to "lib.evalModules".
specialArgs: attribute set,
...
} -> string
eval.filter
Filters an attrset of modules based on a predicate that runs during module evaluation.
Type:
attribute set -> (raw value -> raw value -> boolean) -> attribute set -> attribute set
eval.flake
Evaluate a list of input modules and an attrset of flake modules.
This occurs in two stages:
Stage 1: evaluate to discover policy (allowed args + which config paths are public/private).
Stage 2: re-evaluate with arg filtering and config path filtering applied, and produce "flake.modules" suitable for consumption by other flakes (including a generated "default" module).
Type:
attribute set -> list of module -> attribute set of module -> raw value
eval.flakeEvalModule
Internal module that defines the options used by "flake.lib.eval.flake" to control what is considered public/private config, and which ""_module.args" are allowed through during evaluation. Exposed as a function only to satisfy module/type expectations during evaluation.
Type: attribute set -> attribute set
eval.preEval
Safely evaluate a list of modules patching up any args they might need with null if not available in "specialArgs".
Type: attribute set -> module -> list of module -> raw value
factory.artifactModule
Factory for building a module that generates per-system artifacts and exposes them in "flake.<configs>".
You provide "config" plus how to interpret "nixpkgsConfig", and it produces a module that:
1. lets modules define a "config" value and nixpkgs settings for it
2. collects the evaluated results into "flake.<configs>"" (typically keyed by system, with optional per-system defaults)
3. offers mapping hooks to tweak the resulting artifacts and the exposed options/config shape
Type:
{
# Option type for "flake.<configs>".
artifactType: raw value,
# Name of the field to extract as the artifact value.
config: string,
# Plural name used under "flake.<configs>".
configs: string,
# All flake modules to evaluate artifacts from.
flakeModules: attribute set of module,
# Hook to post-process the computed artifacts.
mapArtifacts: raw value -> raw value,
# Hook to post-process final "config" (gets artifacts, then base config).
mapConfig: raw value -> raw value -> raw value,
# Hook to post-process generated "options".
mapOptions: raw value -> raw value,
# nixpkgs input/path used to instantiate "pkgs" per system.
nixpkgs: absolute path,
# Name of the config field that carries nixpkgs/system settings.
nixpkgsConfig: string,
# Extra args for evaluation (extended with "super.*").
specialArgs: attribute set,
# Exposed as "super.config".
superConfig: raw value,
# Exposed as "super.options".
superOptions: raw value,
...
} -> module
factory.configurationModule
Factory for building a module that produces NixOS configurations and exposes them in "flake.<configs>".
You provide "<config>" plus "<nixpkgsConfig>", and it produces a module that:
1. lets modules define the NixOS module/configuration for "config" (and optionally mark a default)
2. evaluates them into real "nixosSystem" results across the intended systems
3. publishes the final set under "flake.<configs>", with hooks for reshaping options/config and post-processing the result
Type:
{
# Name of the field that provides the NixOS module/configuration to build.
config: string,
# Plural name used under "flake.<configs>".
configs: string,
# Option type for "flake.<configs>".
configurationType: raw value,
# All flake modules to evaluate into NixOS configurations.
flakeModules: attribute set of module,
# Hook to post-process final "config".
mapConfig: raw value -> raw value -> raw value,
# Hook to post-process the computed configurations.
mapConfigurations: raw value -> raw value,
# Hook to post-process generated "options".
mapOptions: raw value -> raw value,
# nixpkgs input/path used for system-specific evaluation.
nixpkgs: absolute path,
# Name of the config field that carries nixpkgs/system settings.
nixpkgsConfig: string,
# Extra args for evaluation (extended with "super.*").
specialArgs: attribute set,
# Exposed as "super.config".
superConfig: raw value,
# Exposed as "super.options".
superOptions: raw value,
...
} -> module
factory.submoduleModule
Factory for building a module that collects and exposes submodules in "flake.<configs>".
You tell it which "config" you’re defining, and it produces a module that:
1. lets individual modules declare "config" (and optionally mark themselves as the default)
2. aggregates all of them into "flake.<configs>"" for the whole flake
3. supports light customization hooks ("mapSubmodules"/"mapOptions"/"mapConfig") so you can shape the API without rewriting the plumbing
Type:
{
# Singular name of the thing being collected (e.g. "overlay").
config: string,
# Plural name used under "flake.<configs>".
configs: string,
# All flake modules to scan/collect submodules from.
flakeModules: attribute set of module,
# Hook to post-process final "config"
# (gets submodules, then base config).
mapConfig: raw value -> raw value -> raw value,
# Hook to post-process generated "options".
mapOptions: raw value -> raw value,
# Hook to post-process the collected submodules set.
mapSubmodules: raw value -> raw value,
# Extra args for evaluation
# (extended with "super.config"/"super.options").
specialArgs: attribute set,
# Option type for "flake.<configs>".
submoduleType: raw value,
# Parent config exposed to submodules as "super.config".
superConfig: raw value,
# Parent options exposed to submodules as "super.options".
superOptions: raw value,
...
} -> module
flake.make
Build a flake output attrset from flake modules.
It can:
1. load modules from a directory on disk (via "root" + "prefix")
2. take explicit modules you pass in ("selfModules", "inputModules")
3. optionally include "modules.default" from your flake inputs
4. (optionally) do a small bootstrapping step ("libPrefix") so "self.lib" can be provided by modules themselves
Type:
{
# Whether to automatically include "modules.default" from each flake input
# (excluding "self"), when that input provides it.
#
# Disable this if you want full manual control over
# which input modules participate.
includeInputModulesFromInputs: boolean,
# Extra input modules to include during evaluation.
inputModules: list,
# Flake inputs attrset
# (typically the "inputs" from your "outputs = { ... }:" function).
#
# Used as "specialArgs" during evaluation,
# and also scanned for "modules.default" when enabled.
inputs: attribute set,
# Optional bootstrapping mode for flakes
# that define their own "self.lib" via modules.
#
# When set, Perch first evaluates only modules whose names start with "libPrefix"
# to obtain "config.flake.lib", then re-evaluates the full module se
# with that "self.lib" injected into "specialArgs".
#
# This is useful when options/config evaluation
# depends on something from "self.lib" to avoid infinite recursion.
libPrefix: null or string,
# Subdirectory (relative to "root") to scan for modules.
# Only used when both "root" and "prefix" are non-null.
prefix: null or string,
# Root path for discovering modules on disk.
#
# When combined with "prefix", imports modules
# from "root/prefix".
root: null or absolute path,
# Modules belonging to this flake.
#
# When a list is passed the modules are named
# "module-0", "module-1", etc.
#
# Each module is patched to have a key corresponding to its name.
selfModules: (list) or (attribute set),
# Separator used when generating names for modules
# discovered on disk (via "root/prefix").
#
# These names become keys in the flat module attrset
# (for example: "foo-bar-baz").
separator: string,
...
} -> attribute set
format.optionsToArgsString
Converts evaluated options to a human-friendly string useful for function arguments
Type: raw value -> raw value
glob.toRegex
Convert a glob pattern to a fully-anchored regular expression string.
Type: string -> string
module.patch
Patch a module (or module path) by rewriting its function args declaration/values and mapping its resulting attrset, recursively applying the same patch to any imported modules.
Type: raw value -> raw value -> raw value -> raw value -> raw value
options.flatten
Flatten an evaluated NixOS-style options tree into a sorted list. Also descends into submodule option types (including listOf submodule) and removes any `_module` options.
Type: raw value -> list
options.toMarkdown
Render an evaluated options tree into a simple markdown document excluding any "_module" options.
For each option it produces a heading with the option path, its description, type and default if provided.
Type:
{
# Evaluated options tree to render.
options: raw value,
# Transform options with a mapper function.
transformOptions: raw value -> raw value,
...
} -> string
packages.asApps
Convert packages to apps
Type:
attribute set of attribute set of package -> attribute set of attribute set of raw value
string.capitalize
Capitalize the first character of a string (leaving the rest unchanged).
Type: string -> string
string.indent
Indent (or dedent via negative) a multi-line string by a number of spaces.
Type: signed integer -> string -> string
string.toTitle
Convert a string into a simple title.
Type: string -> string
string.wordSplit
Split a string into words on casing boundaries (camelCase / PascalCase) and delimiters (whitespace / dashes / underscores).
Type: string -> list of string
submodules.make
Create a ready-to-use attrset of submodules from a set of flake modules.
You pick which config field you want to expose (via "config"), and this function returns only the modules that provide it, plus a sensible "default" module.
This is useful for turning a large flake module collection into a small, clean “module API” other code can consume.
Type:
{
# Which config field to extract from each module
# (e.g. "nixosModule", "homeManagerModule", etc.).
config: string,
# Config flag name used to choose the default module;
# if none is marked, a default is generated.
defaultConfig: string,
# Candidate flake modules to turn into submodules (keyed by name).
flakeModules: attribute set of module,
# Extra args used during evaluation (like "specialArgs" in "lib.evalModules").
specialArgs: attribute set,
...
} -> attribute set of module
test.flake
Evaluate flake tests in a directory and returns an attrset in the form expected for flake outputs.
Type:
{
# Additional arguments for "nix flake check"
args: list of string,
# Extra commands to run for each flake during flake testing
commands: list of string,
# Path to the directory containing test flakes
path: absolute path,
# Creates packages suitable for flake checks.
#
# IMPORTANT: this will require the recursive-nix feature
# which will most likely fail due to a current regression
# in nix (https://github.com/NixOS/nix/issues/14529)
recursive: boolean,
...
} -> attribute set of attribute set of package
test.unit
Evaluate unit tests for a flake library attrset.
Type:
{
# Library with tests to evaluate
lib: nested attribute set of raw value,
# Pkgs constructed via nixpkgs.
# If provided, runs only tests that require pkgs.
# If not provided, runs only tests that do not require pkgs.
pkgs: raw value,
...
} -> {
# Message to display
message: string,
# Whether all tests passed
success: boolean,
...
}
trivial.importIfPath
If given a path/string, import it and attach {_file,key}; otherwise pass through the module and still attach those when possible.
Type: raw value -> raw value
trivial.isFunctor
Return true if a value is a functor attrset (has a functional __functor field).
Type: raw value -> boolean
trivial.mapAttrsetImports
If an attrset has an imports list, map a function over the imported modules (importing paths/strings first).
Type: (raw value -> raw value) -> raw value -> raw value
trivial.mapFunctionArgs
Wrap a function to rewrite its argument declaration and argument value before calling it.
Type:
(raw value -> raw value -> raw value) -> raw value -> raw value -> raw value
trivial.mapFunctionResult
Wrap a function so its result is transformed by a mapper while preserving declared function arguments.
Type: (raw value -> raw value -> raw value) -> raw value -> raw value
trivial.toFunctor
Convert a function to a functor attrset (or pass through an existing functor), throwing on other values.
Type: raw value -> raw value