An independent implementation of the Nix expression language in Zig — bit-for-bit compatible with Nix 2.34.7.
ZIX evaluates Nix expressions and produces store paths, .drv files and
derivation attributes that are identical to what real nix produces.
Every result is verified against real Nix 2.34.7 in CI.
- 🎯 Compatibility is a testable property. A 165-expression battery runs
every case in both
zixand realnixand requires identical output — language, builtins, and derivation store paths. - ⚡ Fast. A 50 000-element
foldl'evaluates in ~80 ms; a lazy evaluator with memoized thunks and cycle detection. - 🔍 Small and readable. ~9 500 lines of Zig, zero runtime dependencies, no generated code.
- 🧩 Faithful to the original. Algorithms are modeled directly on Nix's
own
parser.y,lexer.l,derivations.cc,store-dir-config.cc,archive.ccandhash.cc.
- The whole language: literals, strings + interpolation, indented strings,
paths, operators (
+ - * / // ++ == != < > <= >= && || -> ! ?), attrsets (inherit, dynamic attributes, nesting),let/rec/with/assert/if, lambdas with formals/defaults/@-patterns, lists,<nixpkgs>lookup,import,scopedImport. - All 107 Nix 2.34.7 builtins, including
derivation/derivationStrict,fetchurl,fetchTarball,fetchzip,fetchGit,fetchTree,fromTOML,toXML,hashString(md5/sha1/sha256/sha512), regex (match/split, POSIX classes, capture groups), JSON,placeholder,__structuredAttrs,tryEval,genericClosureand more. - Derivations: input-addressed, fixed-output (flat + recursive),
multi-output, content-addressed/floating —
.drvfiles and store paths byte-identical to Nix. zix build: realises derivations (and their inputs) in a writable store, verifies fixed-output hashes, registers outputs in a JSON store database, and supports sandboxed builds via bubblewrap (network isolation, read-only store, restricted writes).zix gc: garbage-collects unreachable store objects.- Pure/impure evaluation exactly like
nix eval/nix eval --impure.
Requirements: Zig 0.16.0 — or nix develop
for a ready-made environment.
$ zig build # builds zig-out/bin/zix (ReleaseSafe by default)
$ zig build test # 27 unit tests
$ zig build verify # nix-vs-zix comparison battery (165 cases, needs `nix`)
$ zig build lang # golden language tests
$ zig build fuzz # structured fuzzing vs nixA static, dependency-free binary is just a target flag away:
$ zig build -Dtarget=x86_64-linux-musl$ zix eval -E '1 + 2 * 3'
7
$ zix eval -E 'builtins.map (x: x * x) [1 2 3 4]'
[ 1 4 9 16 ]
$ zix eval --read-only -E '(builtins.derivation { name = "t"; system = "x86_64-linux"; builder = "/bin/sh"; }).drvPath' --raw
/nix/store/k79611g7bg62d41fh6bvm7xpf1dl2x91-testdrv.drv # identical to real nix| Command | Purpose |
|---|---|
| `zix eval [-E EXPR | FILE]` |
zix eval --impure |
Allow paths, currentSystem, environment (like nix eval --impure) |
zix eval --json |
Print the result as JSON |
zix eval -A path |
Select an attribute path from the result |
zix eval --arg name value / --argstr |
Pass arguments (file targets) |
zix eval --read-only |
Compute store paths without writing |
zix parse FILE |
Lex + parse only |
zix build [--sandbox] [--dry-run] TARGET |
Realise a derivation (file, expression, or .drv) |
zix gc [--delete] |
Garbage-collect unreachable store objects |
--store-dir DIR |
Use a custom store (e.g. /tmp/zs) |
-I path, NIX_PATH |
Search path for <nixpkgs> |
--extra-experimental-features extra-builtins,pipe-operators |
Enable ZIX extensions |
$ zix build --store-dir /tmp/zs examples/hello.nix
$ zix build --store-dir /tmp/zs --sandbox --dry-run x.drvZIX targets Nix 2.34.7 and verifies the following properties in CI:
- All 165 battery expressions produce identical output (values, errors, and
derivation store paths) in
zixand realnix. builtins.toFile, input-addressed, fixed-output (flat + recursive) and reference-carrying derivations produce byte-identical store paths.- The full
import <nixpkgs> {}bootstrap evaluates (pkgs.system,pkgs.hello.name = "hello-2.12.3").
Documented deviations (all opt-in or cosmetic):
nixVersionreports2.34.7(the compatibility target).- ZIX ships a few extra builtins (
bitNot,toUpper,toLower,take,drop,reverseList,mapAttrs') and pipe operators (|>,<|), hidden behind--extra-experimental-featuresby default — mirroring how Nix gates its own experimental features. fetchGit/fetchTreehash the full repository (including.git), while Nix uses git's tree hash — store paths for sources differ; language and derivation behaviour are unaffected.
| Module | Contents |
|---|---|
src/lexer.zig |
Tokenization faithful to lexer.l: paths, URIs, strings, interpolation |
src/parser.zig |
Recursive-descent parser faithful to parser.y: full grammar, precedence, stripIndentation |
src/eval.zig |
Lazy evaluator: memoized thunks, rec/let/with, scoping, deep equality, concatenation |
src/value.zig |
Values: int/float/bool/null, strings with derivation context, lists, attrsets, lambdas, thunks |
src/builtins.zig |
All 107 primops |
src/drv.zig |
.drv ATerm serialization and hashDerivationModulo |
src/store.zig |
Store path computation, NAR serialization, store database |
src/nixhash.zig |
SHA-256, md5, sha1, sha512, base16, Nix base32 |
src/build.zig |
Realisation: planning, builder execution, sandboxing |
src/fsutil.zig |
Portable filesystem helpers |
Deeper write-ups: architecture, store format.
The detailed phased plan lives in ROADMAP.md. Short version:
- ✅ Phases 0–5 of the core (language, builtins, derivations, build, sandbox, gc, fuzzing, docs) — done and CI-green on 3 OSes.
- 🔜 Beyond 1.0: flakes, binary-cache substitution, a full nixpkgs
zix build (import <nixpkgs> {}).helloend-to-end.
ZIX is a small project that depends on its contributors. Whether you are into language implementation, Zig, Nix, or just think this is fun — there is a place for you.
- CONTRIBUTING.md — guidelines, testing workflow, concrete tasks.
- CODE_OF_CONDUCT.md — be kind.
- SECURITY.md — how to report vulnerabilities.
- CHANGELOG.md — what changed.
- Issues and PRs are welcome — small, focused changes with tests move fastest.
Why (and why not) rewrite Nix in Zig — a full analysis of the trade-offs, in
docs/analysis-notes.md.
MIT — see LICENSE. Copyright (c) 2026 Magnus Lislevatn.