jinx compiles all of nixpkgs from Nix to TypeScript

The author, writing as fzakaria, has released jinx, a transpiler that takes a .nix file and produces a .ts file that evaluates to the same value, with the same thunks, derivation strings and drvPaths. He then compiled all of nixpkgs with it: every attribute, package, module, stdenv and lib function, 231,777 attributes in total. The compiled tree is kept at fzakaria/jinx-nixpkgs, one commit per nixpkgs revision.

The argument behind it: the Nix language is a small lazy functional language with a derivation primitive, and the author says you could design another in a weekend. What you cannot design in a weekend is nixpkgs, which he describes as twenty years of fixes, cross-compilation workarounds and stdenv phases, and which as of October 2026 has 140,000-plus packages that build. Because that library is written in Nix, anyone exploring the store model from a new language, evaluator or editor must start from zero packages. The author calls this the graveyard where Nix reimplementations and forks go to die. Transforming the whole tree into something another ecosystem already speaks avoids that. He picked TypeScript for its tooling, its near-universal browser support and a type system flexible enough to express the shape of a derivation and the oddities of lazy evaluation. He calls himself a frontend impaired "noob".

The output is readable. Each .nix file becomes one .ts module of the same name in a mirrored tree: a lambda is an arrow function, a let is a block of consts, an attribute set is an object literal, import is require. Wherever Nix would allocate a thunk, the emitted code wraps the expression in nix.thunk(() => ...). Evaluation writes nothing to /nix/store; jinx instantiate writes the .drv closure and nix-store --realise builds the derivation. For hello, jinx eval and nix-instantiate --eval --strict print the same drv and out paths.

To check faithfulness, the author evaluated every attribute of nixpkgs' own CI configuration, ci/eval/outpaths.nix, with both jinx and nix-eval-jobs and compared all the drvPaths. The comparison used nixpkgs revision 6510408d on x86_64-linux, aarch64-linux and aarch64-darwin. The result he states is zero differences or failing on one side. A footnote explains that 2,714 attributes fail on both sides, because Nix itself refuses to evaluate them (unsupported platform, broken or insecure).

Speed is the cost. Evaluating nixpkgs in TypeScript is about 3-5x slower than Nix. A first evaluation that has to compile every module it reaches is given as 3x to 10x in speed, and memory is about 2x-4x because thunks are expensive for the garbage collector. The author's summary is that jinx is roughly five times slower than a C++ interpreter that has had twenty years of tuning, which he calls a fine place to start for a brand new compiler on a JavaScript engine. The full benchmark table sits on a separate page. He stresses that the point is not to make Nix faster but to make nixpkgs accessible to the TypeScript ecosystem.

He lists what that unlocks. Profiling: node --cpu-prof on firefox.drvPath, folded through source maps so each frame is a line of nixpkgs. Editor support: language server completion and type checking for every attribute, with source maps back to the original .nix file. Debugging: set a breakpoint on a .nix line and step into stdenv.mkDerivation in VS Code or Chrome DevTools. Exploration: query nixpkgs from a REPL or script with loadNixpkgs, for example listing licences whose SPDX id starts with GPL, instead of dumping the tree to JSON and piping it through jq. Testing: a lib function or package definition is a function in a module, so it can be unit tested with node:test, such as asserting hello's drvPath. Authoring: the compiled form is exact but miserable to write by hand, so there is a nicer hand-written form that interoperates with nixpkgs, where a TypeScript package can call stdenv.mkDerivation and depend on anything in pkgs. Browser: you can evaluate nixpkgs in a tab, which fetches compiled modules from GitHub as needed.

jinx has no dependencies, no native code and no daemon, and runs on Node 24 or in a browser. The source is at github.com/fzakaria/jinx. The author also states plainly that an AI co-authored a lot of the software with him, and says he is annoyed at having to keep disclosing it. He closes with: Nixpkgs is a TypeScript program now.

Key facts

  • jinx compiles Nix to TypeScript and was run over all of nixpkgs: 231,777 attributes in total.
  • Checked against nix-eval-jobs on nixpkgs revision 6510408d across x86_64-linux, aarch64-linux and aarch64-darwin; the author reports zero differences or failing on one side, with 2,714 attributes failing on both sides because Nix refuses to evaluate them.
  • Evaluation is about 3-5x slower than Nix; a first evaluation that compiles every module is given as 3x to 10x, with memory about 2x-4x.
  • The payoff is tooling: source-mapped profiling and debugging, editor completion, REPL queries, node:test unit tests, and evaluation in a browser tab.
  • It runs on Node 24 or in a browser with no dependencies, no native code and no daemon; the author discloses that an AI co-authored a lot of the code.

Why it matters

Nixpkgs, with 140,000-plus buildable packages as of October 2026, is described by the author as the real asset of the Nix world, and it is written in Nix. That has kept anyone who wants a new language, evaluator or editor experience tied to the Nix language or starting from zero packages. jinx tries a different route: translate the whole tree into TypeScript while producing identical drvPaths, so the store does not know the difference. The author's claim is not that this is faster, but that it opens nixpkgs to a large ecosystem of existing tooling.

Who it affects

Nix and nixpkgs users who want better profiling, debugging, completion or testing for package definitions. People who want to explore the store model with a different language or evaluator without giving up nixpkgs. TypeScript developers who want to query or extend nixpkgs from familiar tools. The source does not describe any adoption or community reaction.

How to use it

The source is at github.com/fzakaria/jinx and the compiled nixpkgs tree is at github.com/fzakaria/jinx-nixpkgs. jinx runs on Node 24 or in a browser, and the post links a playground where you can evaluate hello with no Nix installed. Commands shown include jinx compile for a .nix file, jinx eval, and jinx instantiate, which writes the .drv closure so that nix-store --realise can build it. From a script, loadNixpkgs gives you a pkgs object you can inspect, and hand-written TypeScript packages can call stdenv.mkDerivation.

How solid is it

The faithfulness claim comes from the author's own comparison of every attribute in ci/eval/outpaths.nix against nix-eval-jobs on three platforms, using nixpkgs revision 6510408d. It is a single-author report; the speed table is on a separate benchmark page and its per-attribute numbers are not in the post. The 2,714 attributes that fail on both sides are cases Nix itself refuses to evaluate.

Risks and caveats

It is slower: about 3-5x for evaluation, and 3x to 10x with memory about 2x-4x on a first evaluation that must compile every module. It does not replace Nix for building, since builds still go through nix-store --realise. The compiled form is exact down to every thunk and is miserable to write by hand. The author says an AI co-authored a lot of the code, without saying which tool or how much.

“The point is not to make Nix faster, it is to make Nixpkgs accessible to the TypeScript ecosystem.”

— fzakaria, author of jinx