Skip to content

pix

Explore Nix internals through readable Python.

Nix's core algorithms — store path hashing, NAR serialization, derivation parsing, the daemon wire protocol — are buried in C++ across dozens of source files. pix re-derives each one in straightforward Python so you can read, modify, and single-step through the logic.

Every module produces output identical to the real nix CLI, verified by the test suite. The code is the documentation; these pages are the commentary.

What's inside Nix

When you run nix build, a lot happens under the hood. pix breaks it into pieces you can understand one at a time:

Concept What Nix does pix module Docs
Base32 Custom encoding for store path hashes — not RFC 4648 base32.py How it differs
Hash compression XOR-folds SHA-256 (32 B) down to 160 bits (20 B) hash.py In store path computation
NAR Deterministic archive format — no timestamps, no uid, just content nar.py Wire format spec
Store paths /nix/store/<hash>-<name> computed from a fingerprint string store_path.py Full algorithm
Derivations .drv files in ATerm format; hashDerivationModulo breaks circular deps derivation.py Format + hashing
Daemon protocol Unix socket with uint64-LE framing, stderr log stream, operation opcodes daemon.py Protocol spec

pixpkgs — building on pix

Once you understand the internals, pixpkgs shows how to build a nixpkgs-like package set on top of them, mapping Nix patterns to Python idioms:

Nix pattern Python idiom pixpkgs module
mkDerivation drv() function → Package dataclass drv.py
callPackage inspect.signature + getattr package_set.py
String interpolation (${pkg}) __str__ returning output path drv.py
pkg.override Re-call drv() with merged kwargs drv.py
nix-store --realize realize() → daemon add_text_to_store + build_paths realize.py

See the pixpkgs API reference for details.

Overlays and the bootstrap

The deepest rabbit hole in Nix: how does nixpkgs build GCC when building GCC requires GCC? The answer is overlays composed via a fixed-point — and it maps surprisingly well to Python's self and method override. We explore four different Python implementations, each revealing different failure modes:

Experiment Pattern final prev
A Class inheritance self (MRO) self._prev (manual)
B __getattr__ chain _final ref _prev link
C Lazy fixed-point LazyAttrSet proxy prev dict
D Class decorator self (MRO) self._prev (auto)

The full analysis — including an infinite recursion trap in class inheritance, the real nixpkgs 7-stage bootstrap, and a comparison of tradeoffs — is in Overlays & Bootstrap.

Reading order

The modules build on each other. Start from the bottom:

pix (Nix internals):
  1. base32.py        ← simplest: just an encoding
  2. hash.py          ← one function: XOR-fold
  3. nar.py           ← serialization format, uses hash
  4. store_path.py    ← the core algorithm, uses base32 + hash
  5. derivation.py    ← parsing + the hashDerivationModulo trick
  6. daemon.py        ← standalone: wire protocol over Unix socket

pixpkgs (package set layer, uses pix):
  7. drv.py           ← drv() + Package: the mkDerivation equivalent
  8. package_set.py   ← PackageSet.call(): the callPackage equivalent
  9. realize.py       ← write .drv to store + build via daemon

Each pix file is self-contained and under 150 lines. You can read the entire codebase in one sitting.

Try it yourself

nix develop

# See that pix computes the exact same hash as nix
python -m pix hash-path ./pix/base32.py --base32
nix hash path ./pix/base32.py --type sha256 --base32
# same output

# Compute a store path, then verify via the daemon
python -m pix store-path ./pix --name pix-source
python -m pix add-text hello.txt "hello world"
python -m pix drv-show /nix/store/...-hello.drv

Verify

pytest tests/ pixpkgs/tests/ -v   # 41 tests, all comparing against real nix

How to use these docs

  • Internals — Start here. Explains how Nix works with diagrams, hex dumps, and protocol traces.
  • API Reference — Function signatures and usage examples for each module.
  • CLI Reference — The python -m pix commands for quick experimentation.