The Big Sprinkles 'Rewrite'

2026-04-03

# Motivation

I've always had a nagging feeling that sprinkles, despite my love for it, was just really fucking ugly. I understand why this route was taken, it is far more logically consistent than mine (e.g the attrSet passed to outputs is the return value of the sprinkle), but it just feels terrible to use. So, taking inspiration from the UX of flakes and trimming all the fat I could, I came up with this.


# Comparison

# Before

{ sprinkles ? null }:
let
  sources = {
    sprinkles = <sprinkles>;
    nixpkgs = <nixpkgs>;
  };

  inputs = sources: {
    sprinkles = if sprinkles == null
      then import sources.sprinkles
      else sprinkles;

    pkgs = import sources.nixpkgs {};
  };
in
(inputs sources).sprinkles.new {
  inherit inputs sources;
  outputs = self: {
    default = self.inputs.pkgs.hello;
  };
}

# After

{ sprinkles ? <sprinkles> } @ overrides:
(import sprinkles).new {
  inherit overrides;
  sources = { nixpkgs = <nixpkgs>; };
  inputs = {nixpkgs}: { pkgs = import nixpkgs {}; };
  outputs = {pkgs}: pkgs.hello;
}

# Documented Changes

Theres a chance I've missed some changes since I didn't record an indev changelog, but these are all the major changes.

  1. sprinkles is now imported in the sprinkle's top level parameters.
  2. Overrides are now performed using the top level parameters of a sprinkle.
  3. There is no longer a let-in block to define sources and inputs.
  4. inputs now expects an attrSet which can contain sources, inputs or any attr of sources.
  5. inputs can be self-referential.
  6. sprinkles.new is now called using the one passed via the top level parameters, rather than from inputs.
  7. outputs now expects an attrSet which can contain sources, inputs, outputs, or any attr of inputs.
  8. outputs now no longer needs to return an attrSet.
  9. Sprinkles no longer return an attrSet with sources, inputs, outputs, and override. Instead, they return the attrs of outputs.