terlar/nix-config/nix-coding
Claude Code and agent skill by terlar/nix-config
- community
Checking that the SKILL.md file is still in the repository.
Use when writing, editing, or reviewing Nix code — including NixOS modules, Home Manager configuration, packages, and overlays. Covers Nix coding style, module system patterns, common lib functions, and tooling (nixfmt, deadnix, statix). For flake-parts-specific patterns use the flake-parts skill instead.
Install
npx vskill@latest install terlar/nix-config/nix-codingSKILL.md
Style
- Prefer functional programming style; apply eta reduction where it improves
clarity (e.g., map f xs not map (x: f x) xs).
- Use
lib.pipeto express sequential transformations instead of nested calls:
``nix lib.pipe value [ lib.flatten (map toString) (lib.concatStringsSep " ") ] ``
- Prefer
libfunctions over builtins when an equivalent exists
(e.g., lib.attrNames over builtins.attrNames).
- Use
let inherit (x) a b c; into reduce repetition when pulling multiple
names from the same attrset.
- Always bind
cfg = config.<module-path>;at the top of a module'slet
block and reference it throughout.
Module decomposition
Split large modules across files by concern:
interface.nix— options declarations only, noconfigdefault.nix—importslist + top-level wiring, minimal logic- Backend/feature files — each contributes only
configfor their concern
default.nix acts as an orchestration point with zero business logic:
Module system patterns
Key functions:
| Function | Purpose | |
|---|---|---|
mkEnableOption "desc" | Standard boolean option, default false | |
mkOption { type; default; description; } | Declare a typed option | |
mkIf condition config | Conditional config block | |
mkMerge [ cfg1 cfg2 ] | Merge multiple config blocks | |
mkDefault value | Set a value at low priority (overridable) | |
mkOverride priority value | Set priority explicitly (100 = default) | |
mkForce value | Set at priority 50 (overrides mkDefault) | |
mkBefore [ … ] | Prepend to a list (priority 500) | |
mkAfter [ … ] | Append to a list (priority 1500) | |
mkOrder n [ … ] | Insert at explicit list priority |
Overriding mkEnableOption defaults
Override just the default field without rewriting the whole option:
Conditional config with mkIf + mkDefault
Gate a value with mkIf, use mkDefault inside so users can still override:
mkMerge list of mkIf blocks
Prefer a flat list of conditional blocks over deeply nested if-else:
apply — normalise at definition time
Use apply to canonicalise a value whenever the option is set:
Advanced option types
| Type | When to use | |
|---|---|---|
types.lazyAttrsOf t | Attrsets of submodules — avoids evaluating all values upfront | |
types.functionTo t | Expose a configurable strategy/transform function as an option | |
types.deferredModule | Store a module for deferred/separate evaluation | |
types.submoduleWith { modules; specialArgs; shorthandOnlyDefinesConfig; } | Submodule with extra args or shorthand support |
_module.args — inject shared libraries
Inject a shared library at the module root so all submodules receive it as a regular function argument without needing import paths:
_module.freeformType — escape hatch for unknown fields
Allow arbitrary fields while still validating known options:
Internal options
Mark computed/implementation-detail options with internal = true to hide them from documentation:
specialArgs — pass parent config into submodules
Pass a parent's config into child submodules via specialArgs:
For submodules:
Look up unfamiliar lib functions with @nixpkgs-lib — browse lib/attrsets.nix, lib/lists.nix, lib/strings.nix, lib/modules.nix, lib/trivial.nix, etc.
Common lib idioms
Tooling
Tools are not guaranteed to be installed. Use , (comma) to run them without installing — , nixfmt, , deadnix, , statix etc.
nixfmt
nixfmt is the official, opinionated Nix formatter — no configuration. Always run it on new or modified .nix files before committing.
Key formatting rules nixfmt enforces:
- 2-space indentation
- Spaces around
=in bindings - Function arguments on separate lines when they don't fit on one line
- Trailing newline
- No trailing whitespace
deadnix
deadnix removes unused bindings and function arguments.
statix
statix is a linter that catches Nix antipatterns.
Common patterns statix flags: unnecessary with, rec when not needed, builtins.* when a lib equivalent exists, map (x: f x) instead of map f.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingmodules/home/profiles/user/terje/programs/opencode/skills/nix-coding/SKILL.md
Popularity
- Repository stars
- 104
- Repository forks
- 5
- 7-day trend score
- 23
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
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
[](https://verified-skill.com/skills/terlar/nix-config/nix-coding)