Dauliac/nix-lib
{ "createdAt": "2026-01-29T02:25:23Z", "defaultBranch": "main", "description": null, "fullName": "Dauliac/nix-lib", "homepage": null, "language": "Nix", "name": "nix-lib", "pushedAt": "2026-07-16T14:22:48Z", "stargazersCount": 14, "topics": [], "updatedAt": "2026-07-16T21:55:26Z", "url": "https://github.com/Dauliac/nix-lib"}nix-lib
Section titled “nix-lib”A Nix library framework implementing the Lib Modules Pattern - where library functions are defined as module options with built-in types, tests, and documentation.
The Problem
Section titled “The Problem”Writing Nix libraries typically means:
- Functions scattered across files with no consistent structure
- Tests living separately (or not existing at all)
- Types and documentation as afterthoughts
- No standard way to compose libraries
The Solution: Lib Modules Pattern
Section titled “The Solution: Lib Modules Pattern”Define functions as config values that bundle everything together:
nix-lib.lib.double = { type = lib.types.functionTo lib.types.int; fn = x: x * 2; description = "Double a number"; tests."doubles 5" = { args.x = 5; expected = 10; };};This gives you:
- Type safety - explicit Nix types for your functions
- Built-in testing - tests live with the code (nix-unit integration)
- Documentation - descriptions in one place
- Composition - use the NixOS module system to combine libraries
- Nested propagation - libs from nested modules (home-manager in NixOS) are accessible in parent scope
Consumer Inputs
Section titled “Consumer Inputs”nix-lib is designed to be lightweight. Consumers only fetch:
- flake-parts — the module system framework
- nixpkgs-lib — lib-only subset of nixpkgs (~few MB, NOT the full ~500MB checkout)
Full nixpkgs is never fetched from nix-lib. Consumers provide their own for pkgs.
# Deduplicate nixpkgs-lib with your own nixpkgs:nix-lib.inputs.nixpkgs-lib.follows = "nixpkgs";Quick Start
Section titled “Quick Start”Using mkFlake (Recommended)
Section titled “Using mkFlake (Recommended)”nlib.lib.mkFlake is the main entry point. It evaluates lib modules and optionally integrates with flake-parts:
{ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; flake-parts.url = "github:hercules-ci/flake-parts"; nlib.url = "github:Dauliac/nlib"; nlib.inputs.nixpkgs-lib.follows = "nixpkgs"; };
outputs = inputs: inputs.nlib.lib.mkFlake { inherit inputs; modules = [ ./libs/math.nix ]; flake-parts = inputs.flake-parts; # Optional: enables flake-parts integration } { systems = [ "x86_64-linux" "aarch64-linux" ];
perSystem = { lib, pkgs, ... }: { # lib.math.* available in OPTIONS phase! packages.default = pkgs.writeText "result" "double 5 = ${toString (lib.math.double 5)}"; }; };}Lib Module Format
Section titled “Lib Module Format”{ lib, config, ... }: { lib.math.double = { fn = x: x * 2; description = "Double a number"; tests."doubles 5" = { args.x = 5; expected = 10; }; };
# Self-referencing via config lib.math.quadruple = { fn = x: config.lib.math.double.fn (config.lib.math.double.fn x); description = "Quadruple using double"; };}Standalone Mode (no flake-parts)
Section titled “Standalone Mode (no flake-parts)”{ outputs = inputs: inputs.nlib.lib.mkFlake { inherit inputs; modules = [ ./libs/math.nix ]; } { packages.x86_64-linux.default = ...; };}Importing External Libs
Section titled “Importing External Libs”inputs.nlib.lib.mkFlake { inherit inputs; modules = [ ./libs/math.nix # Your lib modules { inherit soonix; } # External: soonix.lib -> lib.soonix.* { custom = otherLib; } # Renamed: otherLib.lib -> lib.custom.* ]; flake-parts = inputs.flake-parts;} { ... }Using flake-parts Module (Alternative)
Section titled “Using flake-parts Module (Alternative)”Two import tiers are available:
{ inputs = { nlib.url = "github:Dauliac/nlib"; nlib.inputs.nixpkgs-lib.follows = "nixpkgs"; nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; flake-parts.url = "github:hercules-ci/flake-parts"; };
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } { # Full: libs + docs package + per-system support (lazy pkgs) imports = [ inputs.nlib.flakeModules.default ];
# Or pure: zero pkgs dependency, no docs, no per-system # imports = [ inputs.nlib.flakeModules.pure ];
nix-lib.lib.double = { type = lib.types.functionTo lib.types.int; fn = x: x * 2; description = "Double a number"; tests."doubles 5" = { args.x = 5; expected = 10; }; }; };}| Module | pkgs needed | Includes |
|---|---|---|
flakeModules.default | only when building docs | Everything: libs, docs, per-system, adapters |
flakeModules.pure | never | Libs, adapters, test generation (no docs, no per-system) |
See examples/ and tests/scenarios/ for complete working examples.
Lib Modules Architecture
Section titled “Lib Modules Architecture”┌──────────────────────────────────────────────────────────┐│ nlib.lib.mkFlake ││ ┌────────────────────────────────────────────────────┐ ││ │ 1. Evaluate lib modules (BEFORE flake-parts) │ ││ │ → produces lib.* │ ││ └──────────────────────┬─────────────────────────────┘ ││ │ inject into lib ││ ▼ ││ ┌────────────────────────────────────────────────────┐ ││ │ 2. flake-parts.lib.mkFlake (if provided) │ ││ │ specialArgs.lib = nixpkgs.lib // evaluatedLibs │ ││ │ → lib.* available in OPTIONS phase! │ ││ └──────────────────────┬─────────────────────────────┘ ││ │ ││ ▼ ││ ┌────────────────────────────────────────────────────┐ ││ │ 3. NixOS/home-manager adapters │ ││ │ → config.lib.* │ ││ └────────────────────────────────────────────────────┘ │└──────────────────────────────────────────────────────────┘mkFlake Options
Section titled “mkFlake Options”| Option | Type | Description |
|---|---|---|
inputs | attrset | Flake inputs (required) |
modules | list | Lib modules to evaluate |
flake-parts | input | Optional: flake-parts input for integration |
Lib Module Format
Section titled “Lib Module Format”Lib modules are NixOS-style modules that define lib.*:
{ lib, config, ... }: { lib.<namespace>.<name> = { fn = ...; # Required: the function description = "..."; # Optional: documentation tests = { ... }; # Optional: test cases type = ...; # Optional: type signature visible = true; # Optional: public/private };}Importing External Libs (soonix-style)
Section titled “Importing External Libs (soonix-style)”For libs that follow the soonix pattern (input.lib = { pkgs }: { ... }), use nix-lib.imports in perSystem:
perSystem = { pkgs, config, ... }: { nix-lib.imports = [ { inherit soonix; } # soonix.lib { inherit pkgs; } -> config.lib.soonix.* { inherit anotherLib; } # -> config.lib.anotherLib.* { custom = someLib; } # -> config.lib.custom.* ];
# Now available: devShells.default = pkgs.mkShell { shellHook = config.lib.soonix.mkShellHook { ... }; };};For pure libs (no pkgs needed), use nix-lib.imports at flake level:
nix-lib.imports = [ { inherit pureLib; } # pureLib.lib.* -> flake.lib.pureLib.*];API Reference
Section titled “API Reference”Defining Libraries
Section titled “Defining Libraries”Define libs at nix-lib.lib.<name> (supports nested namespaces like nix-lib.lib.utils.helper):
nix-lib.lib.myFunc = { type = lib.types.functionTo lib.types.int; # Required: function signature fn = x: x * 2; # Required: implementation description = "What it does"; # Required: documentation tests."test name" = { # Optional: test cases args.x = 5; expected = 10; }; visible = true; # Optional: public (true) or private (false)};Lib Flow
Section titled “Lib Flow”flowchart TB subgraph Input["Define (nix-lib.lib.*)"] D1["nix-lib.lib.myFunc = {<br/>type, fn, description, tests}"] end
subgraph Process["nix-lib Processing"] P1["Extract fn → config.lib.*"] P2["Extract tests → flake.tests"] P3["Store metadata → nix-lib._libsMeta"] end
subgraph Output["Outputs"] O1["config.lib.myFunc<br/>(use in module)"] O2["flake.lib.namespace.myFunc<br/>(flake export)"] O3["flake.tests.test_myFunc_*<br/>(nix-unit tests)"] end
D1 --> P1 D1 --> P2 D1 --> P3 P1 --> O1 P1 --> O2 P2 --> O3flowchart TB subgraph Define["Define (nix-lib.lib.*)"] D1[type + fn + description + tests] end
subgraph Use["Use (config.lib.*)"] U1[NixOS config.lib.foo] U2[home-manager config.lib.bar] U3[nixvim config.lib.baz] end
subgraph Propagate["Nested Propagation"] P1[NixOS config.lib.home.*] P2[NixOS config.lib.home.vim.*] end
subgraph Export["Flake Export (flake.lib.*)"] E1[flake.lib.nixos.*] E2[flake.lib.home.*] E3[flake.lib.vim.*] end
D1 --> U1 D1 --> U2 D1 --> U3 U2 --> P1 U3 --> P2 U1 --> E1 U2 --> E2 U3 --> E3Lib Output Layers
Section titled “Lib Output Layers”Libs defined in different module systems are available at different paths:
Flake-Level Libs (pure, no pkgs)
Section titled “Flake-Level Libs (pure, no pkgs)”| Defined in | Module to import | Access within module | Flake output |
|---|---|---|---|
flake-parts nix-lib.lib.* | flakeModules.default | config.lib.flake.<name> | flake.lib.flake.<name> |
perSystem nix-lib.lib.* | flakeModules.default | config.lib.<name> | legacyPackages.<system>.nix-lib.<name> |
System Configuration Libs
Section titled “System Configuration Libs”| Defined in | Module to import | Access within module | Flake output |
|---|---|---|---|
NixOS nix-lib.lib.* | nixosModules.default | config.lib.<name> | flake.lib.nixos.<name> |
home-manager nix-lib.lib.* | homeModules.default | config.lib.<name> | flake.lib.home.<name> |
nix-darwin nix-lib.lib.* | darwinModules.default | config.lib.<name> | flake.lib.darwin.<name> |
nixvim nix-lib.lib.* | nixvimModules.default | config.lib.<name> | flake.lib.vim.<name> |
system-manager nix-lib.lib.* | systemManagerModules.default | config.lib.<name> | flake.lib.system.<name> |
Nested Module Propagation
Section titled “Nested Module Propagation”When a parent module imports a nested module system, the nested libs are automatically accessible in the parent scope under a namespace prefix.
flowchart LR subgraph NixOS N[config.lib.*] end
subgraph home-manager H[nix-lib.lib.*] end
subgraph nixvim V[nix-lib.lib.*] end
H -->|home.*| N V -->|vim.*| H V -->|home.vim.*| NNested Libs Access Table
Section titled “Nested Libs Access Table”| Parent module | Nested module | Libs defined in nested | Access in parent |
|---|---|---|---|
| NixOS | home-manager | nix-lib.lib.foo | config.lib.home.foo |
| NixOS | home-manager → nixvim | nix-lib.lib.bar | config.lib.home.vim.bar |
| nix-darwin | home-manager | nix-lib.lib.foo | config.lib.home.foo |
| nix-darwin | home-manager → nixvim | nix-lib.lib.bar | config.lib.home.vim.bar |
| home-manager | nixvim | nix-lib.lib.bar | config.lib.vim.bar |
Namespace Prefixes
Section titled “Namespace Prefixes”| Module system | Namespace prefix |
|---|---|
| home-manager | home |
| nixvim | vim |
| nix-darwin | darwin |
| system-manager | system |
Flake Outputs Summary
Section titled “Flake Outputs Summary”All libs are collected and exported at the flake level under flake.lib.<namespace>:
| Namespace | Source | Description |
|---|---|---|
flake.lib.flake.* | nix-lib.lib.* in flake-parts | Pure flake-level libs |
flake.lib.nix-lib.* | nix-lib internals | mkAdapter, backends utilities |
flake.lib.nixos.* | nixosConfigurations.*.config.lib.* | NixOS configuration libs |
flake.lib.home.* | homeConfigurations.*.config.lib.* | Standalone home-manager libs |
flake.lib.darwin.* | darwinConfigurations.*.config.lib.* | nix-darwin libs |
flake.lib.vim.* | nixvimConfigurations.*.config.lib.* | Standalone nixvim libs |
flake.lib.system.* | systemConfigs.*.config.lib.* | system-manager libs |
flake.lib.wrappers.* | wrapperConfigurations.*.config.lib.* | nix-wrapper-modules libs |
Per-system libs are available at legacyPackages.<system>.lib.<namespace>.*.
Available Modules
Section titled “Available Modules”Import the adapter for your module system. Libs are automatically available at config.lib.*:
| Module | Import path | Description |
|---|---|---|
flakeModules.default | inputs.nix-lib.flakeModules.default | Full experience (docs, per-system) |
flakeModules.pure | inputs.nix-lib.flakeModules.pure | Pure lib only (zero pkgs) |
nixosModules.default | nix-lib.nixosModules.default | |
homeModules.default | nix-lib.homeModules.default | |
darwinModules.default | nix-lib.darwinModules.default | |
nixvimModules.default | nix-lib.nixvimModules.default | |
systemManagerModules.default | nix-lib.systemManagerModules.default | |
wrapperModules.default | nix-lib.wrapperModules.default |
Test Formats
Section titled “Test Formats”Simple expected value
Section titled “Simple expected value”tests."test name" = { args.x = 5; # Argument passed to fn expected = 10; # Expected return value};Multiple arguments
Section titled “Multiple arguments”tests."test name" = { args.x = { a = 2; b = 3; }; # For fn = { a, b }: a + b expected = 5;};Multiple assertions
Section titled “Multiple assertions”tests."test name" = { args.x = 5; assertions = [ { name = "is positive"; check = result: result > 0; } { name = "is even"; check = result: lib.mod result 2 == 0; } { name = "equals 10"; expected = 10; } ];};Wrapper Module Systems
Section titled “Wrapper Module Systems”nix-lib supports wrapper-based module systems that create wrapped executables:
- nix-wrapper-modules - Module system for wrapped packages with DAG-based flag ordering
- Lassulus/wrappers - Library for creating wrapped executables via module evaluation
Both use lib.evalModules internally, making them compatible with nix-lib’s adapter system.
Basic Usage
Section titled “Basic Usage”{ inputs = { nix-lib.url = "github:Dauliac/nix-lib"; nix-wrapper-modules.url = "github:BirdeeHub/nix-wrapper-modules"; # Or: wrappers.url = "github:Lassulus/wrappers"; };
outputs = { nixpkgs, nix-lib, nix-wrapper-modules, ... }: nix-lib.inputs.flake-parts.lib.mkFlake { inherit inputs; } { imports = [ nix-lib.flakeModules.default ];
# Define wrapper configurations flake.wrapperConfigurations.myApp = nixpkgs.lib.evalModules { modules = [ # nix-lib adapter for wrappers nix-lib.wrapperModules.default
# Your wrapper libs { nix-lib.enable = true; nix-lib.lib.mkFlags = { type = lib.types.functionTo lib.types.attrs; fn = name: flags: { drv.flags.${name} = flags; }; description = "Generate wrapper flags"; }; } ]; }; };}With nix-wrapper-modules
Section titled “With nix-wrapper-modules”# Use BirdeeHub's wrapper definitionsflake.wrapperConfigurations.alacritty = inputs.nix-wrapper-modules.wrappers.alacritty.wrap { inherit pkgs; modules = [ nix-lib.wrapperModules.default { nix-lib.enable = true; nix-lib.lib.terminalHelper = { type = lib.types.functionTo lib.types.attrs; fn = shell: { settings.terminal.shell.program = shell; }; description = "Set terminal shell"; }; } ]; # Use the helper settings = config.lib.terminalHelper "${pkgs.zsh}/bin/zsh"; };With Lassulus/wrappers
Section titled “With Lassulus/wrappers”# Use Lassulus's wrapper modulesflake.wrapperConfigurations.mpv = inputs.wrappers.wrapperModules.mpv.apply { inherit pkgs; modules = [ nix-lib.wrapperModules.default { nix-lib.enable = true; nix-lib.lib.addScript = { type = lib.types.functionTo lib.types.attrs; fn = script: { scripts = [ script ]; }; description = "Add mpv script"; }; } ]; };Accessing Wrapper Libs
Section titled “Accessing Wrapper Libs”Libs defined in wrapper configurations are collected at:
| Location | Path |
|---|---|
| Within wrapper module | config.lib.<name> |
| Flake output | flake.lib.wrappers.<name> |
Custom Module Systems
Section titled “Custom Module Systems”mkAdapter is generic and works with any NixOS-style module system:
# Create adapter for your custom module systemflake.myModules.default = inputs.nix-lib.lib.mkAdapter { name = "my-module-system"; namespace = "my";};
# Use in your module system{ lib, config, ... }: { imports = [ myModules.default ];
nix-lib.enable = true; nix-lib.lib.myHelper = { type = lib.types.functionTo lib.types.attrs; fn = x: { result = x; }; description = "Custom helper"; };
# Available at: config.lib.myHelper}Requirements
Section titled “Requirements”- Module system must support NixOS-style modules (
config,lib,optionsargs) - No domain-specific options required - mkAdapter only sets
nix-lib.*andlib.*
Custom Collectors
Section titled “Custom Collectors”Collectors aggregate libs from flake outputs into flake.lib.<namespace>. Define custom collectors via nix-lib.collectorDefs:
# In your flake-parts modulenix-lib.collectorDefs.wrappers = { pathType = "flat"; # "flat" or "perSystem" configPath = [ "wrapperConfigurations" ]; # Path in flake outputs namespace = "wrappers"; # Output at flake.lib.wrappers.* description = "nix-wrapper-modules libs";};Path Types
Section titled “Path Types”| Type | Description | Collection Path |
|---|---|---|
flat | Direct configuration set | flake.<configPath>.<name>.config.nix-lib._fns |
perSystem | Per-system in legacyPackages | flake.legacyPackages.<system>.<configPath> |
Disabling Built-in Collectors
Section titled “Disabling Built-in Collectors”nix-lib.collectorDefs.nixos.enable = false; # Disable NixOS collectionOverriding Namespaces
Section titled “Overriding Namespaces”nix-lib.collectorDefs.nixos.namespace = "os"; # flake.lib.os.* instead of flake.lib.nixos.*Testing
Section titled “Testing”nix-lib supports multiple testing frameworks through a pluggable backend system. Tests defined in nix-lib.lib.*.tests are automatically converted to the selected backend format.
Supported Testing Frameworks
Section titled “Supported Testing Frameworks”| Backend | Framework | Description |
|---|---|---|
nix-unit | nix-unit | Default. Catches eval errors, uses Nix C++ API, in nixpkgs |
nixtest | nixtest | Pure Nix, no nixpkgs dependency, lightweight |
nix-tests | nix-tests | Rust CLI, parallel execution, helpers API |
runTests | lib.debug.runTests | Built-in nixpkgs testing function |
nixt | nixt | TypeScript-based, describe/it blocks |
namaka | namaka | Snapshot testing with review workflow |
Configuring the Backend
Section titled “Configuring the Backend”nix-lib.testing = { backend = "nix-unit"; # or "nixtest", "nix-tests", "runTests", "nixt", "namaka" reporter = "junit"; outputPath = "test-results.xml";};Running Tests
Section titled “Running Tests”Run all tests (format + 46 unit tests):
nix flake checkRun a single test scenario (standalone subflake):
cd tests/scenarios/nix-unitnix run .#testTest Architecture
Section titled “Test Architecture”flowchart TB subgraph Define["Define Libraries"] L1["nix-lib.lib.double = {<br/>fn, type, tests...}"] L2["nix-lib.lib.add = {<br/>fn, type, tests...}"] end
subgraph BDD["BDD Tests (tests/bdd/)"] B1["collectors.nix"] B2["adapters.nix"] B3["libDef.nix"] end
subgraph PerSystem["perSystem.nix-unit.tests"] PS["System-specific tests"] end
subgraph Generate["Auto-Generated"] G1["test_double_doubles_5"] G2["test_add_adds_positives"] end
subgraph Merge["flake.tests"] M["All tests merged"] end
subgraph Run["nix run .#test"] R["nix-unit --flake .#tests<br/>🎉 97/97 successful"] end
L1 --> G1 L2 --> G2 G1 --> M G2 --> M B1 --> M B2 --> M B3 --> M PS --> M M --> RTests are organized in three layers:
| Layer | Location | Purpose |
|---|---|---|
| Unit tests | nix-lib.lib.*.tests | Function behavior (defined with libs) |
| BDD tests | tests/bdd/*.nix | Structure validation (namespaces, adapters) |
| perSystem tests | perSystem.nix-unit.tests | System-specific lib checks |
| E2E scenarios | tests/scenarios/*/ | End-to-end integration per backend |
All tests are merged into flake.tests and run as eval-time checks via nix flake check.
Writing Tests
Section titled “Writing Tests”Tests are defined alongside lib definitions:
nix-lib.lib.add = { type = lib.types.functionTo lib.types.int; fn = { a, b }: a + b; description = "Add two numbers"; tests = { "adds positives" = { args.x = { a = 2; b = 3; }; expected = 5; }; "adds negatives" = { args.x = { a = -1; b = -2; }; expected = -3; }; };};For BDD-style structure tests, create modules in tests/bdd/:
{ lib, config, ... }:{ # System-agnostic tests flake.tests = { "test_myFeature_works" = { expr = lib.hasAttr "myAttr" config.flake.lib; expected = true; }; };
# System-specific tests perSystem = { config, ... }: { nix-unit.tests = { "test_perSystem_lib_exists" = { expr = config.legacyPackages.lib != { }; expected = true; }; }; };}Note: nix-unit requires test names to start with test.
Documentation Generator
Section titled “Documentation Generator”nix-lib includes a built-in documentation generator that produces a markdown API reference from your lib metadata. It renders types, function arguments, descriptions, implementation bodies, and test cases.
Generating Docs
Section titled “Generating Docs”nix build .#nix-lib-docscat result/docs.mdConfiguration
Section titled “Configuration”Configure via nix-lib.docs.* in your perSystem:
| Option | Type | Default | Description |
|---|---|---|---|
src | path | null | null | Source root for fn body extraction (set to self to enable) |
showIndex | bool | true | Include a function index at the top |
showTitle | bool | true | Include the title and lib count header |
enableOutput | bool | true | Export docs as packages.nix-lib-docs |
Example
Section titled “Example”perSystem = { config, ... }: { nix-lib.docs = { src = self; # Enable tree-sitter fn body extraction showIndex = true; showTitle = true; };};What Gets Rendered
Section titled “What Gets Rendered”For each lib function, the generated docs.md includes:
- Function arguments — set-pattern (
{ a, b, c ? default }) or curried (x → y → z), rendered in fenced code blocks - Type — human-readable type signature
- Description — from the lib definition
- Source file — link to the source
- Implementation body — collapsible section with the function body (requires
srcto be set, uses tree-sitter-nix) - Test cases — collapsible table with input/expected columns
- Namespace headings — libs are grouped hierarchically by source (see below)
Doc Namespacing
Section titled “Doc Namespacing”Libs in the generated docs are automatically namespaced by where they are defined. The doc generator prefixes each lib name with its source module system, then organizes them into a hierarchical heading structure.
| Defined in | Doc namespace prefix | Example in docs |
|---|---|---|
Flake-level nix-lib.lib.* | flake. | flake.math.double |
NixOS nix-lib.lib.* | nixos. | nixos.mkService |
home-manager nix-lib.lib.* | home. | home.mkShell |
nix-darwin nix-lib.lib.* | darwin. | darwin.mkApp |
nixvim nix-lib.lib.* | vim. | vim.mkPlugin |
system-manager nix-lib.lib.* | system. | system.mkUnit |
nix-wrapper-modules nix-lib.lib.* | wrappers. | wrappers.mkFlags |
perSystem nix-lib.lib.* | (none) | myHelper |
Nested namespaces create hierarchical headings in the output. For example, libs defined as nix-lib.lib.math.double and nix-lib.lib.math.add at the flake level produce:
### flake#### math##### `double`##### `add`Body Extraction
Section titled “Body Extraction”When nix-lib.docs.src is set, the generator uses tree-sitter-nix to parse your source files and extract function implementation bodies. Without it, docs are generated in pure Nix (faster, but no implementation bodies).
Migrating from v1 to v2
Section titled “Migrating from v1 to v2”v2.0.0 is a breaking change. The library API (nix-lib.lib.*, adapters, module options) is unchanged, but flake inputs, imports, and some outputs changed.
1. Update your flake input
Section titled “1. Update your flake input”inputs = { nix-lib.url = "github:Dauliac/nix-lib"; nix-lib.url = "github:Dauliac/nix-lib/v2.0.0"; nix-lib.inputs.nixpkgs-lib.follows = "nixpkgs";};The nixpkgs-lib.follows deduplicates nix-lib’s lightweight lib-only input with your full nixpkgs.
2. Choose your import tier
Section titled “2. Choose your import tier”v2 offers two flake-parts modules:
# Full (same as v1, includes docs + per-system libs):imports = [ inputs.nix-lib.flakeModules.default ];
# Pure (new — zero pkgs dependency, no docs, no per-system):imports = [ inputs.nix-lib.flakeModules.pure ];3. Top-level API moved to lib.*
Section titled “3. Top-level API moved to lib.*”nix-lib.mkFlake { ... }nix-lib.lib.mkFlake { ... }
nix-lib.mkAdapter { name = "nixos"; }nix-lib.lib.mkAdapter { name = "nixos"; }
nix-lib.mkLib { ... }nix-lib.lib.mkLib { ... }4. NixOS example: use option paths, not imports
Section titled “4. NixOS example: use option paths, not imports”# v1 (broken — infinite recursion):{ config, ... }: { imports = [ (config.lib.mkSystemdService "foo") ];}
# v2 (correct — use specific option paths):{ config, ... }: { systemd.services.foo = config.lib.mkSystemdService "foo";}Lib functions should return option-level values, not top-level config fragments.
5. Removed: nix-let-fn-linter
Section titled “5. Removed: nix-let-fn-linter”The nix-let-fn-linter package and linterMeta output were removed. If you referenced them, delete those references.
6. Removed inputs (consumers no longer fetch these)
Section titled “6. Removed inputs (consumers no longer fetch these)”These were dev-only and are now isolated in a partition:
systems, import-tree, treefmt-nix, nix-unit, devour-flake, get-flake, flake-file
If you used follows for any of these, remove them.
Summary of breaking changes
Section titled “Summary of breaking changes”| v1 | v2 |
|---|---|
| 9 consumer inputs | 2 (flake-parts + nixpkgs-lib) |
nix-lib.mkFlake | nix-lib.lib.mkFlake |
flakeModules.default only | + flakeModules.pure |
config.lib.* in imports | config.lib.* in option paths only |
linterMeta output | removed |
nix-let-fn-linter package | removed |
See Also
Section titled “See Also”examples/- Working examples for each module systemexamples/docs.nix- Documentation generator configuration and optionstests/scenarios/- Backend compatibility test subflakes (nix-unit, nix-tests, standalone, mkFlake)tests/bdd/- BDD tests for structure validationCONTRIBUTING.md- Development and testing guide