Skip to content
nixcafePublic

About

Nix flake framework with auto-discovery, namespace support, and a rich module system — build flakes from your project structure

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

purr

A lean Nix flake framework — auto-discovery, namespaces, and module composition.
purr.nixcafe.org

FlakeHub License


What is purr?

purr turns your project directory structure into a fully wired Nix flake — no boilerplate, no manual wiring. Drop files into conventional directories and purr discovers everything: modules, packages, shells, checks, apps, overlays, templates, NixOS/darwin systems, home-manager homes, and a shared lib.

Compared to other flake auto-discovery tools, purr stays minimal — a single dependency (nixpkgs-lib, ~2 MB) and a small, focused API surface.

# flake.nix — that's it. No manual wiring needed.
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    purr.url = "https://flakehub.com/f/nixcafe/purr/0.1.*.tar.gz";
  };

  outputs = inputs:
    inputs.purr.lib.mkFlake {
      inherit inputs;
      src = ./.;
    };
}

Put your code in the right directories, and purr wires your entire flake:

.
├── flake.nix
├── modules/              → nixosModules, darwinModules, homeModules
├── packages/             → packages.<system>.* (also registered into pkgs.*)
├── legacyPackages/       → legacyPackages.<system>.*
├── shells/               → devShells.<system>.*
├── checks/               → checks.<system>.*
├── apps/                 → apps.<system>.*
├── overlays/             → overlays.*
├── templates/            → templates.*
├── formatters/           → formatter.<system>
├── hydraJobs/            → hydraJobs.* (CI jobs, opt-in)
├── lib/                  → lib.<namespace>.* (shared across all modules)
├── systems/              → nixosConfigurations, darwinConfigurations
└── homes/                → homeConfigurations

Quick Start

Scaffold a new purr project in seconds:

# Standalone (mkFlake)
nix flake init -t github:nixcafe/purr

# With flake-parts
nix flake init -t github:nixcafe/purr#flake-parts

Usage

purr offers two integration modes — pick the one that fits your workflow.

Standalone (mkFlake)

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    purr.url = "github:nixcafe/purr";
  };

  outputs = inputs:
    inputs.purr.lib.mkFlake {
      inherit inputs;
      src = ./.;
      namespace = "myproject";
      outputsBuilder = { pkgs, ... }: {
        formatter = pkgs.nixfmt;
      };
    };
}

flake-parts module

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    flake-parts.url = "github:hercules-ci/flake-parts";
    purr.url = "github:nixcafe/purr";
  };

  outputs = inputs:
    inputs.flake-parts.lib.mkFlake { inherit inputs; } {
      imports = [ inputs.purr.flakeModules.default ];
      purr = {
        enable = true;
        src = ./.;
        namespace = "myproject";
      };
    };
}

Core Concepts

Automatic Module Discovery

Drop modules into modules/ — purr discovers them by subdirectory convention:

modules/
├── nixos/services/openssh/default.nix  → nixosModules.services.openssh
├── darwin/system/defaults/default.nix  → darwinModules.system.defaults
├── home/programs/git/default.nix       → homeModules.programs.git
└── shared/users/default.nix            → merged into nixos + darwin

Customize the mapping with moduleTypes:

moduleTypes = {
  nixos = ["nixos" "shared" "container"];
};

Namespace Support

purr injects a namespace parameter into every module, scoping options under config.<namespace>.* — no more global option collisions:

{ config, lib, namespace, ... }:
let
  cfg = config.${namespace}.my-module;
in
{
  options.${namespace}.my-module.enable = lib.mkEnableOption "my module";
  config = lib.mkIf cfg.enable { /* ... */ };
}

Custom Lib (lib.<namespace>.*)

Create a lib/ directory to share functions across all modules, packages, shells, and checks:

# lib/default.nix
{ lib, inputs, namespace }:
{
  keys = import ./keys.nix { inherit lib inputs namespace; };
  utils = import ./utils.nix { inherit lib inputs namespace; };
}

Access anywhere with lib.<namespace>.keys, lib.<namespace>.utils, etc.

Packages

Modules under packages/ become per-system packages (packages.<system>.<name>) and are auto-registered into pkgs, so any module can reference them as pkgs.<name> — no imports or overlays to wire:

# packages/hello/default.nix
{ lib, ... }: { /* ... */ }
# checks/lint/default.nix
{ pkgs, ... }: pkgs.hello   # the discovered package

Each package is wrapped like a callPackage package (.override / .overrideAttrs work) and added to pkgs through an overlay built on the package-set fixpoint, so packages may depend on each other:

# packages/wrapper/default.nix — `hello` resolves from `pkgs`
{ hello, ... }: hello.override { /* ... */ }

One-way dependencies resolve lazily; mutual cycles are an error, as with any nixpkgs overlay. Disable registration with packagesToPkgs = false (packages stay available as packages.<system>.<name>). Registration applies to both mkFlake and the flake-parts module.

Systems & Homes

purr auto-discovers NixOS/darwin systems and home-manager homes using <arch>-<format>/<name>:

systems/
├── x86_64-linux/server/default.nix    → nixosConfigurations.server
└── aarch64-darwin/macbook/default.nix → darwinConfigurations.macbook

homes/
└── x86_64-linux/alice@server/default.nix  → homeConfigurations."alice@server"

Each host can carry host meta — a meta.nix next to its default.nix, or hosts.<name>.meta in the flake config. Declaring images in the meta makes the host an image-only recipe (e.g. installer ISOs): it is excluded from nixosConfigurations/darwinConfigurations unless you also set deployable = true. Its images are exposed as a top-level images.<host>.<format> output:

# systems/x86_64-linux/installer/meta.nix
{
  images = [ "iso" ];
}

The merged meta (auto-generated keys + your custom keys) is injected into the host's modules as purr.meta.

Homes named <user>@<host> auto-link to matching hosts. No extra wiring needed.

# systems/x86_64-linux/server/default.nix
{ config, pkgs, lib, purr, ... }:
{
  networking.hostName = purr.meta.name;  # "server"
  # ...auto-injects home-manager config for alice@server automatically
}

Namespace Bridge

Forward home-manager config from any NixOS module via the namespace bridge — set purr.users.<name>.homeConfig on a host with linked homes:

{ config, pkgs, lib, ... }:
{
  purr.users.alice.homeConfig = {
    home.packages = [ pkgs.cowsay ];
    programs.git.userName = "Alice";
  };
}

Why purr?

purr Other frameworks
Dependencies 1 (nixpkgs-lib, ~2 MB) 3+ (flake-parts, flake-utils, ...)
API surface Single mkFlake call or one flake-parts module Multiple nested imports
Option namespace Built-in namespace injection Manual config.<name>. prefixing
Systems & homes Auto-discovered, auto-linked Manual wiring
Custom lib lib.<namespace>.* propagated everywhere Manual import passthrough

Testing

Tests live under tests/ and are auto-discovered — drop a test-*.nix into tests/unit/ (1:1 with a lib/ module) or tests/integration/ (real-project runs against tests/integration/project) and it is picked up automatically.

nix flake check                       # CI gate: pre-commit + purr-tests
nix build .#checks.x86_64-linux.purr-tests && cat result   # full per-test report
tests/run-tests.sh                    # run directly, live per-test output
nix develop --command purr-test       # same, from the dev shell

The purr-tests check writes the full report into its result; if a test fails the build fails and nix log shows the failing cases. Unit tests run hermetically with nixpkgs-lib; integration tests mock nixosSystem / homeManagerConfiguration to evaluate the generated configs through the real lib.evalModules without pulling a full nixpkgs.

Documentation

Full documentation at purr.nixcafe.org — flake-parts integration, full API reference, directory layout guide, and more.

License

CC0 1.0 Universal

About

Nix flake framework with auto-discovery, namespace support, and a rich module system — build flakes from your project structure

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

Generated from nixcafe-develop/nix