AgentSkillsCN

nix-module

依据本仓库的约定,创建或更新 Nix 模块。

SKILL.md
--- frontmatter
name: nix-module
description: Create or update a nix module with this repo's conventions

Nix Module Conventions (options.michal)

Quick start

  • Modules live under modules/ or services/ and are imported by modules/default.nix or services/default.nix.
  • Custom options always live under options.michal.* with a config mirror under config.michal.*.
  • Use cfg = config.michal.<path> and gate changes with lib.mkIf cfg.enable when the option supports enable.
  • Prefer lib.mkEnableOption + lib.mkOption, and lib.types for type definitions.
  • Keep indentation at 2 spaces, use relative imports, and avoid non-obvious comments.

Module skeleton

nix
{
  config,
  lib,
  pkgs,
  ...
}: let
  cfg = config.michal.<namespace>.<feature>;
in {
  options.michal.<namespace>.<feature> = {
    enable = lib.mkEnableOption "<feature description>";

    # Additional options
    port = lib.mkOption {
      type = lib.types.ints.u16;
      description = "...";
    };
  };

  config = lib.mkIf cfg.enable {
    # NixOS settings
  };
}

Layout and imports

  • modules/default.nix imports the core module set. Add new modules there unless they belong to a sub-tree with its own default.nix.
  • Subtrees use a default.nix that only collects imports (example: modules/network/default.nix).
  • services/default.nix defines helper options and exposes _module.args for shared helpers.
  • Relative imports only, no absolute paths.

Option naming and structure

  • Namespace roots used today:
    • michal.programs.* for apps/features (e.g., michal.programs.tailscale).
    • michal.services.* for services (e.g., michal.services.home-assistant).
    • michal.network.* for network features.
    • michal.browsers.* for browser modules.
    • michal.environment.*, michal.theme, michal.graphical as global knobs.
  • When a module supports toggling, it should define enable = mkEnableOption ....
  • Keep the options tree mirrored in config (cfg = config.michal.<path>).

Common patterns

  • mkIf cfg.enable to gate config blocks.
  • mkOption with lib.types and explicit description for public options.
  • Use small helper generators for repeating option sets:
    • Browsers: modules/gui-packages/browser/options.nix exports mkBrowserOptions.
    • Services: services/default.nix exports myServiceOptions via _module.args.
  • Use config.michal.* values in config blocks, not options directly.
  • All new modules should be imported from default and enabled.
  • Consider which hosts should have the module enabled

Special args and module arguments

  • Host config passes username, hostname, inputs, self, lib via specialArgs in hosts/default.nix.
  • If your module needs these, add them to the argument list in the module signature and use them directly.
  • services/default.nix exposes myServiceOptions via _module.args for services.

File placement expectations

  • GUI/app options under modules/gui-packages/.
  • Service modules under services/ and imported by services/default.nix.
  • Hyprland-related modules under modules/hyprland/.
  • Submodules should be named with kebab-case; default.nix is the entry point for a folder.

Type conventions and gotchas

  • Use lib.types.ints.u16 for ports (see services).
  • Use lib.types.float for fractional thresholds (see modules/battery.nix).
  • Prefer lib.types.attrsOf or lib.types.listOf for collections.
  • If an option can be a scalar or list, use lib.types.either + lib.toList (example: Hyprland keybinds).
  • Ensure option descriptions are clear and avoid commas when the option is used in comma-sensitive contexts (see Hyprland keybinds assertions).

Examples to follow

  • Minimal enable toggle: modules/network/cloudflare-warp.nix.
  • Service with shared options: services/service_proxy.nix + services/default.nix.
  • Generator-based options: modules/gui-packages/browser/options.nix.
  • Complex structured options: modules/hyprland/keybinds.nix.

Docs generation

  • Options docs are generated by generate-docs.nix and expect options.michal.* to be well-typed.
  • If you add new modules, consider adding them to generate-docs.nix so options show up in docs.

Expectations for agent edits

  • Match existing indentation and style (2 spaces, with lib; blocks are common).
  • Keep comments minimal and focused on non-obvious behavior.
  • Avoid introducing new top-level option roots unless explicitly requested.