skip to content

Add gen to a Flake

You can bring gen into a flake in two ways. Take one library’s .lib when you need one feature. Import the hub’s flake-parts module when you want a gen module tree built into nixosConfigurations.

{
inputs.gen-graph.url = "github:sini/gen-graph";
outputs = { gen-graph, ... }:
let
graph = gen-graph.lib;
in
{
# use graph.reachableFrom, graph.roots, ... directly
};
}

A flake that reads inputs.gen-<name>.lib does not need the hub. Without flakes, import ./gen-graph { } on a checkout returns the same library, with its dependencies read from its own flake.lock. Getting Started is a complete example.

From an Aspect to a NixOS System fills in gen-modules/ and builds the systems.

inputs.gen.flakeModules.default declares these options under gen:

optiondefaultwhat it sets
treenullA directory of gen modules. They are merged by gen’s own module system, gen-merge, and never by nixpkgs.
modules[ ]More gen modules, added to the tree.
specialArgs{ }Extra module arguments for the tree, merged over the gen libraries the hub passes in.
aspectCnfnoneThe mkAspectSchema argument: which aspect keys are classes, such as nixos, and which are channels. Required. Without it the build fails with an error.
nodeRegistryPathnoneThe attribute path, in the composed values, of the registry holding the systems to build, for example [ "hosts" ] or [ "fleet" "hosts" ]. Required. A missing path fails with an error listing the top-level keys. A wrong path fails with an error naming the segment it could not find and the keys present beside it.
extraModules.<node>{ }NixOS modules added to one node’s system. A node with no nixos content fails with an error. Key this from your own node list, never from nixosConfigurations.
nixpkgsinputs.nixpkgsThe nixpkgs whose lib.nixosSystem builds each system. null removes the default nixos terminal.
terminals{ }One terminal per class: the function that turns a node’s modules into a built artifact. A default nixos terminal is added unless you supply one.
inject{ genValues = …; }Values passed to your flake-parts modules as module arguments.
injectPerSystemfalseAlso pass inject to every perSystem module.

Two read-only values let you look at the result: gen.composed (the composed values) and gen.realized (every built artifact, keyed by class and node). flake.nixosConfigurations is gen.realized.nixos.

Name one registry in nodeRegistryPath. To build systems from several registries, declare an option in your tree that merges them with mkMerge, and name that option’s path.

Modules in gen.tree receive the gen libraries they build with: genMerge, genSchema, genAspects, genTypes and genPrelude. Add others through gen.specialArgs.

Your ordinary flake-parts modules receive the composed values as genValues:

{ genValues, ... }:
{
flake.hostNames = builtins.attrNames genValues.hosts;
}

To get library arguments in your flake-parts modules too, import inputs.gen.flakeModules.genLibs. It adds genAlgebra, genSchema, genAspects, genScope, genGraph, genSelect, genBind and genDispatch.

inputs.gen.lib.mkGenLibs { } returns every gen library under a short name: graph, merge, schema, aspects, program and the rest. Each value is the same as inputs.gen-<name>.lib.

let gen = inputs.gen.lib.mkGenLibs { }; in
gen.graph.reachableFrom g "web"

A terminal can build flake outputs as well as NixOS systems. gen-bind’s crossing.mkOutputsTerminal takes an evaluate function. The hub’s lib.flakePartsEvaluate is that function for flake-parts:

genBind.crossing.mkOutputsTerminal (inputs.gen.lib.flakePartsEvaluate {
inherit (inputs.flake-parts.lib) evalFlakeModule;
inherit inputs self;
systems = [ "x86_64-linux" ];
})
palette
dark
light
↑↓ select↵ apply esc close

Palettes adapted from Catppuccin (Macchiato) (MIT), Tokyo Night (Apache-2.0), gruvbox (MIT), Catppuccin (Latte) (MIT), Rosé Pine (Dawn) (MIT).