Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Perch

Perch provides a structured framework for Nix flakes, offering a stable place to organize, extend, and refine your configurations.

It does so by importing all nix files in a subdirectory of your repository and interpreting them as flake modules which define your flake outputs.

Get started

Add the following to flake.nix to build flake modules from the flake directory into a flake:

{
  inputs = {
    perch.url = "github:haras-unicorn/perch/refs/tags/<perch-version>";
  };

  outputs = { perch, ... } @inputs:
    perch.lib.flake.make {
      inherit inputs;
      root = ./.;
      prefix = "flake";
    };
}

This will interpret all nix files in the ./flake subdirectory as flake modules and produce a flake based off of them.

The next chapter of this book explains in more detail on how to write flake modules.

Modules

Here is a fizzbuzz flake from Perch end-to-end tests:

{{ #include ../test/e2e/fizzbuzz/flake.nix }}

In the example we see a call to perch.lib.flake.make with one fizzbuzz module. The module defines:

  • a default and named package called fizzbuzz by the name of the module for the abovementioned systems like so:

    {
      packages = {
        "systems..." = {
          default = "<<derivation>>";
          fizzbuzz = "<<derivation>>";
        };
      };
    }
    
  • a default and named NixOS module using the beforementioned package called fizzbuzz by the name of the module like so:

    {
      nixosModules = {
        default = "<<module>>";
        fizzbuzz = "<<module>>";
      };
    }
    
  • a NixOS configuration using the beforementioned NixOS module named fizzbuzz-${system} where the system is the abovementioned system

    {
      nixosConfigurations = {
        "fizzbuzz-${system}" = "<<nixos configuration>>";
      };
    }
    

Special arguments

  • root - if using perch.lib.flake.make with root and prefix the root argument will be supplied to special arguments of each module in any context
  • pkgs - when creating modules, packages or configurations Perch automatically creates pkgs for you with the specified systems or all default systems if not provided with the consequence of the pkgs argument being null while evaluating the nixpkgs configuration for those pkgs
  • super - when creating modules, packages or configurations Perch wraps your flake options and config into super attrset with the consequence of super being null in any other context since the prior config and options arguments may be occupied by another NixOS configuration

Import library (flake.lib.import)

Directory-scanning import helpers used very early in Perch’s bootstrap (unit test harness, loading other lib bits from disk, etc.).

Because of that, this module must not reference self.lib (circular “I need me to build me” risk). So it exports plain functions and is documented a bit more “by hand”, but in the same style as the rest of the library docs.


Mental model (shared across functions)

These helpers:

  1. walk a directory tree (builtins.readDir)
  2. treat certain entries as “import leaves”
  3. attach leaf metadata under __import
  4. return results in one of 3 shapes:
    • tree attrset (preserves directory structure)
    • flat list (all leaves)
    • flat attrset (all leaves keyed by generated name)

Leaf metadata (__import)

Each imported/examined leaf has:

  • __import.path: string path examined/imported
  • __import.type: "regular" (a *.nix file), "default" (a default.nix in a dir), "unknown"
  • __import.value: imported value (or null for unknown)
  • __import.name: generated name based on nesting + separator

Filtering

Most entrypoints accept:

  • nameRegex (matches __import.name)
  • pathRegex (matches __import.path)

Leaves failing either filter are excluded.

This can be used to filter via glob patterns using the perch.lib.glob.toRegex function.

Default.nix behavior

By default, directories containing default.nix are treated as a leaf. Set ignoreDefaults = true to force recursion instead.


import.dirToAttrsWithMap

Walk a directory and return a tree-shaped attrset, calling map on each leaf (metadata included).

Type:

{
  map: raw value -> raw value,
  dir: absolute path,
  separator: string,
  nameRegex: null or string,
  pathRegex: null or string,
  ignoreDefaults: boolean,
  ...
} -> attribute set

import.dirToListWithMap

Walk a directory and return a flat list of mapped leaves.

Type:

{
  map: raw value -> raw value,
  dir: absolute path,
  separator: string,
  nameRegex: null or string,
  pathRegex: null or string,
  ignoreDefaults: boolean,
  ...
} -> list of raw value

import.dirToFlatAttrsWithMap

Walk a directory and return a flat attrset keyed by __import.name.

Type:

{
  map: raw value -> raw value,
  dir: absolute path,
  separator: string,
  nameRegex: null or string,
  pathRegex: null or string,
  ignoreDefaults: boolean,
  ...
} -> attribute set

Convenience projections (same scan, different “view”)

These are all just preset map functions over the same core scan:

  • dirToAttrsWithMetadata: tree of metadata (leaves are the { __import = ...; } wrapper)

  • dirToValueAttrs: tree of __import.value

  • dirToPathAttrs: tree of __import.path

  • dirToListWithMetadata: list of metadata wrappers

  • dirToValueList: list of __import.value

  • dirToPathList: list of __import.path

  • dirToFlatAttrsWithMetadata: flat attrset of metadata wrappers (keyed by __import.name)

  • dirToFlatValueAttrs: flat attrset of __import.value

  • dirToFlatPathAttrs: flat attrset of __import.path


Notes / gotchas

  • Generated names depend on separator + nesting; pick a separator that won’t collide with real names if you care about readability.
  • "unknown" leaves exist so tooling can notice non-nix files; most callers map to __import.value (which becomes null) or filter via regex.
  • This does real directory reads + imports: great for aggregation/tooling, not something you want in hot inner loops.

Options

app

The app

Type: raw value

appNixpkgs

Nixpkgs configuration for app

Type: nixpkgs config

check

The check

Type: raw value

checkNixpkgs

Nixpkgs configuration for check

Type: nixpkgs config

defaultApp

Whether to set this as the default app

Type: boolean

Default: false

defaultCheck

Whether to set this as the default check

Type: boolean

Default: false

defaultDevShell

Whether to set this as the default devShell

Type: boolean

Default: false

defaultFormatter

Whether to set this as the default formatter

Type: boolean

Default: false

defaultLegacyPackage

Whether to set this as the default legacyPackage

Type: boolean

Default: false

defaultNixosConfiguration

Whether to set this as the default nixosConfiguration

Type: boolean

Default: false

defaultNixosModule

Whether to set this as the default nixosModule

Type: boolean

Default: false

defaultPackage

Whether to set this as the default package

Type: boolean

Default: false

devShell

The devShell

Type: raw value

devShellNixpkgs

Nixpkgs configuration for devShell

Type: nixpkgs config

docTestsAsChecks

Convert all "perch.lib.docs.function" tests to checks

Type: boolean

Default: false

dummy.attrsOfSubmodule

Dummy option to test attrs of option flattening.

Type: attribute set of (submodule)

Default: { }

dummy.attrsOfSubmodule.<name>.suboption

Dummy suboption to test attrs of option flattening.

Type: string

Default: ""

Example: test test test

dummy.listOfSubmodule

Dummy option to test list of option flattening.

Type: list of (submodule)

Default: { }

dummy.listOfSubmodule.*.suboption

  • Read-only

Dummy suboption to test list of option flattening.

Type: string

Default: ""

dummy.submodule

Dummy option to test direct option flattening.

Type: submodule

Default: { }

dummy.submodule.suboption

Dummy suboption to test direct option flattening.

Type: string

Default:

(x: builtins.trace x x) "hello world :)"

eval.allowedArgs

List of allowed argument names for module evaluation

Type: list of string

Default: [ ]

eval.privateConfig

Private configuration paths not exposed in output flake modules

Type: list of list of string

Default: [ ]

eval.publicConfig

Public configuration paths are exposed in output flake modules

Type: list of list of string

Default: [ ]

flake.apps

Attribute set of all apps in the flake

Type: attribute set of (attribute set)

flake.checks

Attribute set of all checks in the flake

Type: attribute set of (attribute set)

flake.config

Evaluated flake config attrset

Type: raw value

Default: { }

flake.devShells

Attribute set of all devShells in the flake

Type: attribute set of (attribute set)

flake.formatter

Attribute set of all formatter in the flake

Type: attribute set

flake.legacyPackages

Attribute set of all legacyPackages in the flake

Type: attribute set of (attribute set)

flake.lib

Attribute set of all library functions in the flake

Type: nested attribute set of raw value

Default: { }

flake.modules

Modules prepared for use in other flakes

Type: attribute set of module

Default: { }

flake.nixosConfigurations

Attribute set of all nixosConfigurations in the flake

Type: attribute set

flake.nixosModules

Attribute set of all nixosModules in the flake

Type: attribute set

flake.options

Evaluated flake options attrset

Type: raw value

Default: { }

flake.overlays

Attribute set of all overlays in the flake

Type: attribute set of (nixpkgs overlay)

Default: { }

flake.packages

Attribute set of all packages in the flake

Type: attribute set of (attribute set)

flakeTests.args

Additional arguments for "nix flake check"

Type: list of string

Default:

[
  "--override-input"
  "self'"
  (builtins.toString (
    builtins.path {
      path = config.flakeTests.root;
      name = "self-prime";
    }
  ))
]

flakeTests.asApps

Aggregate checks of flakes from a specified path to apps in this flake

Type: boolean

Default: false

flakeTests.asChecks

Aggregate checks of flakes from a specified path to checks in this flake

IMPORTANT: this will require the recursive-nix feature which will most likely fail due to a current regression in nix (nixpkgs issue 14529)

Type: boolean

Default: false

flakeTests.asPackages

Aggregate checks of flakes from a specified path to packages in this flake

Type: boolean

Default: false

flakeTests.commands

Extra commands to run for each flake during flake testing

Type: list of string

Default: [ ]

flakeTests.path

Path to test flakes

Type: absolute path

Default:

lib.path.append config.flakeTests.root config.flakeTests.prefix

flakeTests.prefix

The prefix from the root at which test flakes are located

Type: string

Default: "test"

flakeTests.root

The root of the repository used to get test flakes and to set "self'" input

Type: absolute path

Default:

specialArgs.root

formatter

The formatter

Type: raw value

formatterNixpkgs

Nixpkgs configuration for formatter

Type: nixpkgs config

legacyPackage

The legacyPackage

Type: raw value

legacyPackageNixpkgs

Nixpkgs configuration for legacyPackage

Type: nixpkgs config

nixosConfiguration

The module result for nixosConfiguration

Type: raw value

nixosConfigurationNixpkgs

Nixpkgs configuration for nixosConfiguration

Type: nixpkgs config

nixosModule

Result of the nixosModule

Type: attribute set

overlays

Attribute set of all overlays in the flake

Type: attribute set of (nixpkgs overlay)

Default: { }

package

The package

Type: raw value

packageNixpkgs

Nixpkgs configuration for package

Type: nixpkgs config

packagesAsApps

Convert all packages to apps and put them in flake outputs

Type: boolean

Default: false

packagesAsLegacyPackages

Convert all packages to legacy packages and put them in flake outputs

Type: boolean

Default: false

traceDocTestsInChecks

Whether to trace successful passes of library tests in checks

Type: boolean

Default: false

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