Project layout
yen reads one module. A module is a path, a function or an attrset with three keys: imports, _module.args
and yen. yen does not know what inputs or lib are. You give them as args, and they flow down the
imports tree to every file below.
- default.nix
- flake.nix
Directorymodules/
- aspects.nix
- fleet.nix
- host.nix
- query.nix
modules/ is the fleet. Every file there is a module: put each kind, feature or host in its own file,
and move files freely. File order never changes a result.
Two entry points
Section titled “Two entry points”{ description = "yen: flake and no-flake entry points";
outputs = inputs: inputs.yen.lib.mkFlake { imports = [ (inputs.import-tree ./modules) ]; _module.args = { inherit inputs; inherit (inputs.nixpkgs) lib; }; };
inputs = { yen.url = "github:vic/yen"; import-tree.url = "github:denful/import-tree"; nixpkgs.url = "https://nixos.org/channels/nixos-25.05/nixexprs.tar.xz"; };}# Without flakes: every query of the fleet. Pin the sources with npins, niv or fetchTarball.{ yen ? builtins.fetchTarball "https://github.com/vic/yen/archive/main.tar.gz", nixpkgs ? builtins.fetchTarball "https://nixos.org/channels/nixos-25.05/nixexprs.tar.xz", import-tree ? import ( builtins.fetchTarball "https://github.com/denful/import-tree/archive/main.tar.gz" ),}:(import yen).lib.eval { imports = [ (import-tree ./modules) ]; _module.args = { inputs = { inherit nixpkgs; }; lib = import "${nixpkgs}/lib"; };}mkFlake gives the flake outputs. eval gives every query, flake included. Both read the same modules/.
# Queries on the command line:# nix eval --impure --file query.nix errors# nix eval --impure --json --file query.nix agentimport ./default.nix { }nix eval --impure --file query.nix errors # [ ] when the fleet is validnix eval --impure --file query.nix graph.scopes # every scopenix build -f query.nix flake.nixosConfigurations.laptop.config.system.build.toplevelNixOS without the nixpkgs flake
Section titled “NixOS without the nixpkgs flake”nixpkgs.lib.nixosSystem exists only on the nixpkgs flake. nixos/lib/eval-config.nix works with a flake input
and with a plain path, so one host file serves both entry points:
# eval-config.nix works with a flake input and with a plain nixpkgs path.{ yen, lib, inputs, ...}:{ yen.kinds.host = { fields.system = lib.types.str; sinks.nixos.out = { host, nixos, ... }: { nixosConfigurations.${host.name} = import "${inputs.nixpkgs}/nixos/lib/eval-config.nix" { inherit (host) system; modules = nixos; }; }; };
yen.host.laptop.system = "x86_64-linux";}