Back to list
khaneliman

writing-nix

by khaneliman

Nix configuration for my systems supporting macOS, NixOS, and WSL.

303🍴 14📅 Jan 23, 2026

SKILL.md


name: writing-nix description: Writes idiomatic, performant, and maintainable Nix code. Covers best practices, anti-patterns to avoid (like with), module system design, and performance optimization.

Writing Nix

Core Principles

  1. Declarative over Imperative: Describe what, not how.
  2. Explicit over Implicit: Avoid magic scoping or hidden dependencies.
  3. Hermetic: No side effects, no network access during build (except fixed-output derivations).

Critical Anti-Patterns

1. The with Statement

NEVER use with. It breaks static analysis, tools (LSP), and readability.

# BAD
meta = with lib; { license = licenses.mit; };

# GOOD
meta = { license = lib.licenses.mit; };

2. Recursive Attributes (rec)

Avoid rec when let-in suffices. rec can cause infinite recursion and expensive evaluation.

# BAD
rec {
  version = "1.0";
  name = "pkg-${version}";
}

# GOOD
let
  version = "1.0";
in {
  inherit version;
  name = "pkg-${version}";
}

Module System

Standard Pattern

All modules must follow this structure:

{ config, lib, pkgs, ... }:
let
  cfg = config.khanelinix.path.to.module;
  inherit (lib) mkIf mkEnableOption mkOption types;
in {
  options.khanelinix.path.to.module = {
    enable = mkEnableOption "module description";
    # Other options...
  };

  config = mkIf cfg.enable {
    # Configuration implementation
  };
}

Option Design

  • Namespacing: Always prefix with khanelinix..
  • Types: Use strict types (types.bool, types.str, types.listOf types.package).
  • Defaults: Use mkDefault for overridable values.

Performance Optimization

Evaluation

  • Laziness: Nix is lazy. Don't force evaluation of unused attributes.
  • Imports: Avoid importing large files if only a small part is needed.
  • Regex: Avoid expensive regex operations in hot loops.

Build

  • Closure Size: Split outputs (dev, doc, lib) to reduce runtime dependencies.
  • Filters: Use lib.cleanSource or nix-filter to avoid rebuilding on irrelevant file changes (e.g., README updates).

Idiomatic Functions

Destructuring

Always destructure arguments in function headers.

# BAD
args: stdenv.mkDerivation { name = args.pname; ... }

# GOOD
{ stdenv, pname, version, ... }: stdenv.mkDerivation {
  inherit pname version;
  ...
}

Overrides

  • override: Change function arguments (inputs).
  • overrideAttrs: Change derivation attributes (steps, build inputs).

Formatting

  • Use nixfmt (or treefmt).
  • camelCase for variables.
  • kebab-case for attributes/files.

See Also

Score

Total Score

65/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

+5
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

+5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon