ypares/rigup.nix/nix-module-system

Claude Code and agent skill by ypares/rigup.nix

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Install

npx vskill@latest install ypares/rigup.nix/nix-module-system

SKILL.md

Nix Module System: Dark Corners

Practical knowledge about lib.evalModules that's hard to find in official docs.

Sources:

Module Identity & Deduplication

When the same module is included multiple times (e.g., via imports from different places), evalModules deduplicates by identity:

Path-based modules: Deduplicated by path string

nix
modules = [ ./foo.nix ./foo.nix ]; # Same path → evaluated once

Function/attrset modules: Deduplicated by key attribute

nix
# Without key: each inclusion is separate (can cause "defined multiple times" errors)
modules = [ myModule myModule ]; # Evaluated twice!
# With key: deduplicated
myModule = {
key = "my-unique-module-id";
imports = [ actualModule ];
};
modules = [ myModule myModule ]; # Evaluated once

Use key when you wrap modules dynamically and need deduplication across import chains.

Module Arguments

_module.args vs specialArgs

Both inject arguments into module functions, but differ in timing:

nix
evalModules {
specialArgs = { foo = "available during option declaration"; };
modules = [{
_module.args = { bar = "only available in config, not options"; };
}];
}
specialArgs_module.args
Available in options = { ... }✓✗
Available in config = { ... }✓✓
Can reference config✗✓

Rule of thumb: Use specialArgs for things needed to declare options (like lib), use _module.args for runtime values (like pkgs).

_module.check

Disable "unknown option" errors:

nix
{ _module.check = false; }

Useful when modules set options that might not exist (e.g., optional integrations).

_module.freeformType

Allow arbitrary attributes in config without declaring options:

nix
{
_module.freeformType = lib.types.attrsOf lib.types.anything;
# Now any attribute is allowed without explicit options
whatever.you.want = "works";
}

Priority & Merging

mkDefault / mkForce / mkOverride

Control which definition wins when multiple modules set the same option:

nix
# Priority scale: lower number wins
lib.mkOverride 1000 "default priority" # Same as mkDefault
lib.mkOverride 100 "normal priority" # Default when no mk* used
lib.mkOverride 50 "force priority" # Same as mkForce
# Shorthands
lib.mkDefault x # mkOverride 1000 - easily overridden
lib.mkForce x # mkOverride 50 - overrides most things
mkMerge

Combine multiple config fragments:

nix
config = lib.mkMerge [
{ services.foo.enable = true; }
(lib.mkIf condition { services.foo.port = 8080; })
];
mkIf (it's not just if)

lib.mkIf is not the same as Nix's if:

nix
# Nix if: evaluated immediately, fails if option doesn't exist
config = if condition then { foo = 1; } else { };
# lib.mkIf: deferred, only evaluated if condition is true
config = lib.mkIf condition { foo = 1; };

mkIf prevents "infinite recursion" errors when the condition depends on other config values.

mkBefore / mkAfter / mkOrder

For list-type options, control ordering:

nix
{
environment.systemPackages = lib.mkBefore [ earlyPkg ]; # Prepend
environment.systemPackages = lib.mkAfter [ latePkg ]; # Append
environment.systemPackages = lib.mkOrder 500 [ midPkg ]; # Explicit order
}

Disabling Modules

Remove a module from evaluation:

nix
{
disabledModules = [
"services/web-servers/nginx.nix" # Path relative to modules root
someImportedModule # Direct reference
];
}

Useful for replacing NixOS modules with custom implementations.

Common Errors & Fixes

See references/troubleshooting.md for detailed error explanations.

Quick fixes:

  • "The option ... is defined multiple times" → Add key attribute or use lib.mkForce/lib.mkMerge
  • "infinite recursion encountered" → Use lib.mkIf instead of if, or check for circular dependencies
  • "The option ... does not exist" → Check spelling, or set _module.check = false for optional deps

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
86
Repository forks
4
7-day trend score
22

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 22 Mar 2026, 7 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/ypares/rigup.nix/nix-module-system/badge)](https://verified-skill.com/skills/ypares/rigup.nix/nix-module-system)

Something wrong with this skill or its page? Tell us.