Claude Code Plugins

Community-maintained marketplace

Feedback

nix-patterns

@aitchwhy/dotfiles
3
0

Nix patterns for DOTFILES MANAGEMENT ONLY (nix-darwin + home-manager)

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name nix-patterns
description Nix patterns for DOTFILES MANAGEMENT ONLY (nix-darwin + home-manager)
scope ~/dotfiles
NOT_FOR development, orchestration, containers, builds
allowed-tools Read, Write, Edit, Bash, Grep
token-budget 700

SCOPE RESTRICTION

This skill applies to dotfiles management only:

  • nix-darwin (macOS system config)
  • home-manager (user dotfiles)
  • Flake structure for reproducibility

NOT for development. Use devops-patterns skill for:

  • Docker Compose (orchestration)
  • Multi-stage Dockerfile (builds)
  • Pulumi ESC (configuration)

Architecture

~/dotfiles/
├── flake.nix           # Entry point using flake-parts.lib.mkFlake
├── flake.lock          # Locked dependencies
├── flake/
│   ├── darwin.nix      # darwinConfigurations
│   ├── devshells.nix   # Development shells + pre-commit hooks
│   └── checks.nix      # Custom validation checks
├── modules/
│   ├── darwin/         # nix-darwin system modules
│   └── home/           # Home Manager modules
└── lib/
    └── ports.nix       # Centralized port allocation

Flake Template (flake-parts)

{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    flake-parts.url = "github:hercules-ci/flake-parts";
    nix-darwin = {
      url = "github:LnL7/nix-darwin";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    git-hooks-nix = {
      url = "github:cachix/git-hooks.nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = inputs@{ flake-parts, ... }:
    flake-parts.lib.mkFlake { inherit inputs; } {
      imports = [
        inputs.git-hooks-nix.flakeModule
        ./flake/darwin.nix
        ./flake/devshells.nix
      ];

      systems = [ "aarch64-darwin" "x86_64-linux" ];

      perSystem = { pkgs, ... }: {
        formatter = pkgs.nixfmt-rfc-style;
      };
    };
}

Darwin Configuration (flake/darwin.nix)

{ self, inputs, withSystem, ... }:
{
  flake.darwinConfigurations.hostname = withSystem "aarch64-darwin" (
    ctx@{ pkgs, ... }:
    inputs.nix-darwin.lib.darwinSystem {
      specialArgs = { inherit inputs self; };
      modules = [
        ../modules/darwin
        inputs.home-manager.darwinModules.home-manager
        {
          home-manager = {
            useGlobalPkgs = true;
            useUserPackages = true;
            extraSpecialArgs = { inherit inputs self; };
            users.username = import ../users/username.nix;
          };
        }
      ];
    }
  );
}

Development Shell (flake/devshells.nix)

{ inputs, ... }:
{
  perSystem = { config, pkgs, system, ... }: {
    pre-commit.settings.hooks = {
      nixfmt-rfc-style.enable = true;
      deadnix.enable = true;
      statix.enable = true;
    };

    devShells.default = pkgs.mkShell {
      shellHook = ''
        ${config.pre-commit.installationScript}
        echo "Dev Shell (${system})"
      '';

      packages = with pkgs; [
        nixd
        nixfmt-rfc-style
        just
        git
      ];
    };
  };
}

Home Manager Module Pattern

{ config, lib, pkgs, ... }:
let
  inherit (lib) mkEnableOption mkIf;
  cfg = config.modules.home.apps.example;
in
{
  options.modules.home.apps.example = {
    enable = mkEnableOption "Example app configuration";
  };

  config = mkIf cfg.enable {
    home.packages = with pkgs; [ example-package ];
    home.file.".config/example/config.toml".source = ./config.toml;
  };
}

macOS System Preferences

{ config, lib, pkgs, ... }:
{
  system.defaults = {
    NSGlobalDomain = {
      AppleShowAllExtensions = true;
      InitialKeyRepeat = 15;
      KeyRepeat = 2;
    };
    dock = { autohide = true; orientation = "left"; };
    finder = { AppleShowAllFiles = true; ShowPathbar = true; };
  };

  nix.settings.experimental-features = ["nix-command" "flakes"];
}

Key Concepts

perSystem

Replaces forAllSystems helper:

perSystem = { pkgs, system, config, ... }: {
  packages.default = pkgs.hello;
  devShells.default = pkgs.mkShell {
    shellHook = config.pre-commit.installationScript;
  };
};

withSystem

Access per-system context from flake-level outputs:

{ withSystem, ... }:
{
  flake.darwinConfigurations.foo = withSystem "aarch64-darwin" (
    ctx@{ pkgs, ... }: ...
  );
}

self Reference

Pass self via specialArgs:

{ self, inputs, ... }:
{
  flake.darwinConfigurations.foo = inputs.nix-darwin.lib.darwinSystem {
    specialArgs = { inherit inputs self; };
    modules = [ ... ];
  };
}

Version Policy (December 2025)

  • nixpkgs: nixos-unstable
  • stateVersion: 26.05 (bleeding edge)
  • Node.js: Current (25.x) not LTS
  • Python: 3.14+ only
  • PostgreSQL: 18+ only

Anti-Patterns

Anti-Pattern Correct Pattern
forAllSystems helper Use flake-parts systems + perSystem
nixpkgs.legacyPackages.\${system} Use perSystem.pkgs
with lib; Use inherit (lib) ...
Manual multi-system devShells Use perSystem.devShells.default
Inline pre-commit scripts Use git-hooks-nix.flakeModule

Commands

darwin-rebuild switch --flake .#hostname  # Apply changes
nix develop           # Enter dev shell
nix flake check       # Validate flake
nix fmt               # Format with nixfmt-rfc-style
nix flake update      # Update inputs

See Also

  • secrets-management - sops-nix patterns for dotfiles
  • devops-patterns - Docker-first development (NOT Nix)