| name | nix-module-options |
| description | Query NixOS and Home Manager module options programmatically using flake evaluation. Use this skill when the user asks to check if a module exists, explore available options, get option documentation, or verify what options are available in upstream NixOS/Home Manager (not custom user modules). Activates for queries like "does home manager have a module for X", "what options does service Y have", "check nixos options for Z", or "explore available options". |
| allowed-tools | Bash, Read |
Nix Module Options Explorer
Expert guidance for programmatically querying NixOS and Home Manager module options using flake evaluation.
Core Capability
This skill provides optimized Nix expressions to query module options from your flake-parts configuration, reusing pre-evaluated values for performance.
Key Benefits
- Offline queries - No need for web searches or option search sites
- Upstream purity - Queries pure Home Manager/NixOS modules (excludes user custom modules)
- Performance - Reuses pre-evaluated
pkgsfrom flake debug - System-agnostic - Uses
currentSystemfor portability - Complete documentation - Returns type, description, default, examples via
optionAttrSetToDocList
Home Manager Module Options
Check if option exists
nix eval --impure --expr '
let
flake = builtins.getFlake (builtins.toString ./.);
args = flake.currentSystem.allModuleArgs;
hmLib = args.pkgs.lib.extend (self: super: {
hm = import "${flake.inputs.home-manager}/modules/lib" { lib = self; };
});
in
(hmLib.evalModules {
modules = import "${flake.inputs.home-manager}/modules/modules.nix" {
lib = hmLib;
pkgs = args.pkgs;
check = false;
};
}).options.OPTION.PATH or null
' --json | jq 'if . == null then "NOT FOUND" else "EXISTS" end'
Get full option documentation
nix eval --impure --expr '
let
flake = builtins.getFlake (builtins.toString ./.);
args = flake.currentSystem.allModuleArgs;
hmLib = args.pkgs.lib.extend (self: super: {
hm = import "${flake.inputs.home-manager}/modules/lib" { lib = self; };
});
in
args.pkgs.lib.optionAttrSetToDocList (
hmLib.evalModules {
modules = import "${flake.inputs.home-manager}/modules/modules.nix" {
lib = hmLib;
pkgs = args.pkgs;
check = false;
};
}
).options.OPTION.PATH
' --json | jq
List all options in a category
nix eval --impure --expr '
let
flake = builtins.getFlake (builtins.toString ./.);
args = flake.currentSystem.allModuleArgs;
hmLib = args.pkgs.lib.extend (self: super: {
hm = import "${flake.inputs.home-manager}/modules/lib" { lib = self; };
});
opts = (hmLib.evalModules {
modules = import "${flake.inputs.home-manager}/modules/modules.nix" {
lib = hmLib;
pkgs = args.pkgs;
check = false;
};
}).options;
in
builtins.attrNames opts.CATEGORY
' --json | jq -r '.[]'
NixOS Module Options
Check if option exists
nix eval --impure --expr '
let
flake = builtins.getFlake (builtins.toString ./.);
args = flake.currentSystem.allModuleArgs;
in
(args.pkgs.lib.evalModules {
modules = import "${flake.inputs.nixpkgs}/nixos/modules/module-list.nix" ++ [
{ nixpkgs.hostPlatform = args.system; }
];
}).options.OPTION.PATH or null
' --json | jq 'if . == null then "NOT FOUND" else "EXISTS" end'
Get full option documentation
nix eval --impure --expr '
let
flake = builtins.getFlake (builtins.toString ./.);
args = flake.currentSystem.allModuleArgs;
in
args.pkgs.lib.optionAttrSetToDocList (
args.pkgs.lib.evalModules {
modules = import "${flake.inputs.nixpkgs}/nixos/modules/module-list.nix" ++ [
{ nixpkgs.hostPlatform = args.system; }
];
}
).options.OPTION.PATH
' --json | jq
List all options in a category
nix eval --impure --expr '
let
flake = builtins.getFlake (builtins.toString ./.);
args = flake.currentSystem.allModuleArgs;
opts = (args.pkgs.lib.evalModules {
modules = import "${flake.inputs.nixpkgs}/nixos/modules/module-list.nix" ++ [
{ nixpkgs.hostPlatform = args.system; }
];
}).options;
in
builtins.attrNames opts.CATEGORY
' --json | jq -r '.[]'
Common Option Categories
Home Manager top-level:
programs.*- User programs (git, vim, zsh, etc.)services.*- User services (gpg-agent, syncthing, etc.)home.*- Home directory settingsxdg.*- XDG directory configurationaccounts.*- Email, calendar accountssystemd.*- User systemd unitsgtk.*,qt.*- Desktop themingwayland.*- Wayland compositors
NixOS top-level:
services.*- System services (nginx, postgresql, etc.)programs.*- System-wide programshardware.*- Hardware configurationboot.*- Boot loader and kernelnetworking.*- Network configurationenvironment.*- System environmentsystemd.*- System unitsusers.*- User managementvirtualisation.*- Containers, VMssecurity.*- Security settings
Option Documentation Fields
lib.optionAttrSetToDocList returns structured documentation:
- name - Full option path (e.g.,
programs.git.enable) - description - What the option does (markdown formatted)
- type - Expected value type (e.g.,
boolean,string,list of string) - default - Default value if not set
- example - Usage examples
- declarations - Source file where option is defined
- visible - Whether option appears in documentation
- readOnly - Whether option can be modified
- internal - Whether option is internal-only
Usage Patterns
Quick existence check
When user asks "does home manager have a duf module?":
nix eval --impure --expr '...' | jq 'if . == null then "NOT FOUND" else "EXISTS" end'
Get option details
When user asks "what options does programs.git have?":
nix eval --impure --expr '...' | jq 'map(select(.visible == true)) | map({name, type, description})'
List available options
When user asks "what programs are available in home manager?":
nix eval --impure --expr '... builtins.attrNames opts.programs' | jq -r '.[]'
Technical Details
Why use currentSystem.allModuleArgs?
- Pre-evaluated -
pkgsalready instantiated by flake-parts - System-aware -
args.systemprovides current system automatically - Overlay-aware - Includes your overlays (though doesn't affect options)
- Faster - Reuses existing evaluation instead of re-accessing inputs
Purity Guarantees
These expressions query upstream modules only:
- Imports directly from
${flake.inputs.home-manager}/modules/modules.nix - Imports directly from
${flake.inputs.nixpkgs}/nixos/modules/module-list.nix - Does NOT include user's custom modules from
.claude/orhome/ - Does NOT evaluate user's actual
homeConfigurationsornixosConfigurations
To query user's actual config (including custom modules):
nix eval --impure --expr '
(builtins.getFlake (builtins.toString ./.))
.homeConfigurations.USERNAME.options.OPTION.PATH
'
Best Practices
- Use
jqfor filtering - Pipe tojqfor readable output - Filter visible options - Use
select(.visible == true)to hide internal options - Cache results - For repeated queries, consider adding to flake outputs
- Check existence first - Use
or nullpattern before getting full docs - Reference declarations - Use
.declarationsfield to find upstream source
Troubleshooting
"path does not exist" error
The flake path must exist. This skill uses builtins.getFlake (builtins.toString ./.) which refers to the current project directory. Ensure you're running commands from within your flake repository.
"attribute does not exist" error
The option path is wrong. Check:
- Correct category (e.g.,
programsvsservices) - Correct nesting (e.g.,
programs.git.enablenotprograms.git) - Option exists in upstream (not a custom module)
Evaluation too slow
Consider adding frequently-used queries as flake outputs for caching.
Wrong module system
Ensure you're using the right command:
- Home Manager queries use
hmLib.evalModuleswith HM modules - NixOS queries use
pkgs.lib.evalModuleswith NixOS modules
Version History
- v1.0 (2025-10-28) - Initial skill creation with optimized flake-parts evaluation