feat(modules): export NixOS modules by reading their directory #1287
Open
lytedev
wants to merge 10 commits from
propose/module-directory-scanner into main
pull from: propose/module-directory-scanner
merge into: lytedev:main
lytedev:main
lytedev:propose/collie-voice
lytedev:propose/education-account
lytedev:propose/element-x-personal-releases
lytedev:propose/special-args-cleanup
lytedev:propose/limine-fallback
lytedev:propose/household-kiosk
lytedev:propose/xwayland-ei-display-from-client
lytedev:propose/steamdeck-mouse-steps-aside-for-games
lytedev:propose/assistant-watch
lytedev:propose/lpcamm-watch
lytedev:propose/agents-where-information-lives
lytedev:propose/tuwunel-1.9.2
lytedev:propose/pin-flake-registry
lytedev:propose/headscale-0-29-3
lytedev:propose/canary-freshness-per-repo
lytedev:propose/boot-guard-efivars-fix
lytedev:propose/deck-dock-panel-under-niri
lytedev:propose/admindevice-ssh-anything
lytedev:propose/kdeconnect-announce
lytedev:steamdeck-mgba
lytedev:propose/doorbell-no-internet
lytedev:propose/ha-list-tasks
lytedev:propose/ha-music-not-found
lytedev:propose/bc250-40cu-measured
lytedev:propose/multiboot-foxtrot-dragon
lytedev:propose/pitft-stmpe-drive
lytedev:propose/foxtrot-multiboot-prep
lytedev:propose/pitft-no-smartd
lytedev:propose/kexec-luks-reboot
lytedev:propose/foxtrot-multiboot
lytedev:propose/model-eval
lytedev:propose/foxtrot-vm-seats
lytedev:iamb-sender
lytedev:propose/calendar-alarms
lytedev:pinephone-niri
lytedev:push-tsntxvxynzps
lytedev:propose/spoof-reject-cleanups
lytedev:propose/finance-pipeline
lytedev:steamframe-plan
lytedev:pinephone-buildable
lytedev:deck-pose-wip
lytedev:aerc-open-html
lytedev:local-auth-unification
lytedev:iamb-dotfiles
lytedev:esphome-music-panel
lytedev:wifi-system-profile
lytedev:gauge-history
lytedev:validate-gate-fix2
lytedev:validate-slot-no-hugepages
lytedev:pinephone-reenable
lytedev:cyberdeck-research
lytedev:git-anon-ratelimit
lytedev:headscale-basedomain
lytedev:ssd-fast-tier
lytedev:hold-impermanence-flip
lytedev:gate-dummy-eval
lytedev:zen-browser
lytedev:initrd-remote-unlock
lytedev:beefcake-rpool-backup
lytedev:sec-sso-plan
lytedev:sec-mail
lytedev:flab-lid-wake
lytedev:hearth-k8s
lytedev:zulip
lytedev:router-guest-vlan
lytedev:headscale-extra-records
lytedev:beefcake-advertise-lan
lytedev:push-qrvuuqmxtznv
lytedev:voxtype-per-host-model
lytedev:cleanup
lytedev:push-kanidm-opt-in
lytedev:push-voxtype-flake-fix
lytedev:push-uvqqknxvqlvy
lytedev:push-qrqsxkmlrevert
lytedev:fix-kanidm-uid-attr-map
lytedev:nix-on-droid
lytedev:self-hosted-dns
lytedev:fix-runner-tmpfs-revert
lytedev:beefcake-email
lytedev:beefcake-immich
lytedev:firefox-nightly-devedition
lytedev:fix-bun-baseline
lytedev:flab-stuff
lytedev:printer-sftp
lytedev:dragon-vr-monado
lytedev:clever-vr-game-clamshell-mode-detection
lytedev:wireguard-mesh
lytedev:rescue-beefcake-unpushed-nix
No reviewers
Labels
No labels
bug
enhancement
question
scary
upstream
Milestone
Clear milestone
No items
No milestone
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set
Reference
lytedev/nix!1287
Loading…
Reference in a new issue
No description provided.
Delete branch "propose/module-directory-scanner"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Stacked on #1286 (its commits are included here); review the last four commits one by one, since each message carries the rationale and testing.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Asr2hJ2uNCVY7UH8yPE4Vh
steam.nix sets nothing (`lib.mkIf … { }`) and nothing imports it. nixosModules.remote-disk-key-entry-on-boot is imported by no host. nixosModules.nix-config is flake.nix's nixConfig attrset, not a module, and nothing reads it; default-module.nix reads nixConfig from flake.nix directly. None of them fits a directory where every file is a module, which the next commits build. History keeps the initrd SSH unlock module if a host ever wants it again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Asr2hJ2uNCVY7UH8yPE4Vhdefault-module, dns-zones, niri and greeter were each curried with the whole flake inputs set, but their headers disagreed: `inputs:`, `flakeInputs:`, or a destructuring pattern of the inputs they used. They now all take `{ inputs }:`. As a module, that header would ask the module system for an `inputs` module argument, which this flake no longer provides now that specialArgs is gone, so the next commit can recognise a curried module from builtins.functionArgs without guessing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Asr2hJ2uNCVY7UH8yPE4Vhlib/modules/nixos/default.nix listed every module by hand, so adding a module meant editing two files, and the list was free to drift from the directory (it had: see the previous commits). It now exports every top-level .nix file in the directory under its file name, via lib/modules/import-modules-from-directory.nix: - A file whose header is exactly `{ inputs }:` is applied to the flake inputs with lib.modules.importApply, which records the file for error messages, plus an explicit key. - Every other file is exported as its path, so the module system names it in errors and deduplicates it by path. Previously each export was `import ./x.nix`, an anonymous function. - default.nix and anything in a subdirectory are not exported, which is where helpers live. `default` stays an alias of default-module, since lib/host.nix and the outside world know it by that name. The idea is from https://ysun.co/special/, whose importApplyWithArgs also probes non-pattern lambdas (`args: …`) by calling them. That is left out here: a probe cannot tell `args: { … }` (a module) from `args: { … }: …` (curried) without calling it with something, and the exact-header rule makes the probe unnecessary. The post also says importApply needs an explicit key to deduplicate. That holds for the pinned nixpkgs: importApply wraps the module in `{ _file; imports = [ m ]; }`, collectModules keys the inner module as `<parent key>:anon-1`, and the two parents of a double import have different keys. The curried-module-imported-twice-is-merged-once check fails with the key removed. Its fixture option carries a description on purpose: two declarations of a bare `types.str` option merge without error, which hid the duplicate on the first attempt. importApply's extra nesting, and shell-defaults-and-applications now importing shell-config itself, change the order in which list options merge, so most hosts' toplevel drvs change (system-path, dbus and polkit restart triggers, man-paths, ...). Tested that this is order only: for all 30 nixosConfigurations, with lyte.flakeStorePath and system.configurationRevision pinned, I compared the full derivation closure before and after this series. Each derivation was reduced to its name and the sorted tokens of its env and args, with store hashes stripped, plus the closure's content-addressed inputSrcs. All 30 are identical. The same comparison does tell main and the series below apart for beefcake (it catches the removed duplicate group members), so it is not blind to small changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Asr2hJ2uNCVY7UH8yPE4VhView command line instructions
Manual merge helper
Use this merge commit message when completing the merge manually.
Checkout
From your project repository, check out a new branch and test the changes.