fzakaria выпустил jinx: nixpkgs скомпилирован из Nix в TypeScript

Разработчик под ником fzakaria выпустил jinx, инструмент, который компилирует код на языке Nix в TypeScript. Он берёт файл .nix и выдаёт файл .ts, вычисляющийся в то же значение: с теми же отложенными вычислениями (thunks), теми же строками деривации и теми же drvPath. Затем автор скомпилировал этим инструментом весь nixpkgs, каждый пакет, модуль и функции stdenv и lib, всего 231 777 атрибутов. Скомпилированное дерево лежит в репозитории fzakaria/jinx-nixpkgs, по одному коммиту на ревизию nixpkgs.

Исходная мысль автора: по-настоящему ценна не сама Nix, а модель хранилища (store), она даёт воспроизводимость и герметичность. Сам язык, по его словам, маленький ленивый функциональный язык с примитивом деривации, и другой такой можно придумать за выходные. А вот nixpkgs за выходные не напишешь: это двадцать лет исправлений, обходные пути для кросс-компиляции, фазы stdenv, патчи configure-скриптов. По состоянию на октябрь 2026 года там более 140 000 собираемых пакетов. Для тех, кто хочет попробовать другой язык, вычислитель или редактор, это ловушка: приходится начинать с нуля пакетов, и именно там, пишет автор, умирают реимплементации и форки Nix. Если же перевести nixpkgs в то, что уже понимает другая экосистема, можно исследовать модель хранилища, не отказываясь от наработанного. Автор выбрал TypeScript: у него богатый инструментарий, поддержка почти во всех браузерах и гибкая система типов, способная описать форму деривации и странности ленивых вычислений. Себя он называет «noob» во фронтенде.

Как это устроено: каждый .nix-файл становится одноимённым .ts-модулем в дереве, повторяющем исходное. Лямбда превращается в стрелочную функцию, let, в блок const, множество атрибутов, в объектный литерал, import, в require. Поскольку Nix ленив, везде, где Nix создал бы thunk, в код добавляется обёртка nix.thunk(() => ...). Вычисление в jinx ничего не пишет в /nix/store; команда jinx instantiate записывает замыкание .drv, а nix-store --realise собирает деривацию. На примере пакета hello команды jinx eval и nix-instantiate --eval --strict выдают одинаковые пути .drv и out.

Проверка верности: автор вычислил все атрибуты CI-конфигурации самого nixpkgs, ci/eval/outpaths.nix, и через jinx, и через nix-eval-jobs и сравнил все drvPath. На ревизии nixpkgs 6510408d, на платформах x86_64-linux, aarch64-linux и aarch64-darwin результат, ноль расхождений либо сбой на одной из сторон. Ещё 2 714 атрибутов падают с обеих сторон: Nix сам отказывается их вычислять (неподдерживаемая платформа, сломанный или небезопасный пакет).

Зачем это нужно, если вычисление nixpkgs на TypeScript примерно в 3-5 раз медленнее? Автор подчёркивает: цель не ускорить Nix, а открыть nixpkgs для экосистемы TypeScript. Он перечисляет возможности: профилировать вычисление через node --cpu-prof с картами исходников, так что каждый кадр указывает на строку nixpkgs; получить автодополнение и проверку типов для каждого атрибута nixpkgs через языковой сервер; ставить точки останова на строках .nix в VS Code или Chrome DevTools и заходить внутрь stdenv.mkDerivation; задавать nixpkgs вопросы в REPL или скрипте (в примере, перебор лицензий lib.licenses, у которых spdxId начинается с GPL); писать модульные тесты Nix на node:test (например, проверять drvPath пакета hello); писать пакеты прямо на TypeScript, вызывая stdenv.mkDerivation и опираясь на любые пакеты из pkgs; наконец, запускать вычисление во вкладке браузера, которая подгружает скомпилированные модули с GitHub по мере надобности.

Про скорость автор пишет откровенно: медленно, но не слишком. По его описанию, для первого вычисления, которое компилирует каждый затронутый модуль, речь идёт о 3-10-кратной разнице по скорости и примерно 2-4-кратной по памяти, потому что thunks дороги для сборщика мусора. Полную таблицу замеров он вынес на отдельную страницу бенчмарка. Итоговая оценка: примерно в пять раз медленнее C++-интерпретатора, который двадцать лет шлифовали, для нового компилятора на JavaScript-движке это нормальное начало.

Попробовать можно уже сейчас: исходники лежат в github.com/fzakaria/jinx, у инструмента нет зависимостей, нативного кода и демона, он запускается на Node 24 или в браузере. В конце автор прямо заявляет, что значительную часть кода ему помогал писать ИИ, и просит не искать в этом моральной вины. Заканчивается пост словами: nixpkgs теперь, программа на TypeScript.

Ключевые факты

  • jinx, транспилятор: файл .nix превращается в .ts-модуль с теми же thunks, строками деривации и drvPath; каждый thunk явно обёрнут в nix.thunk(() => ...).
  • Автор скомпилировал весь nixpkgs, 231 777 атрибутов; дерево хранится в fzakaria/jinx-nixpkgs, по коммиту на ревизию.
  • Проверка на ревизии 6510408d (x86_64-linux, aarch64-linux, aarch64-darwin): все drvPath из ci/eval/outpaths.nix совпали с результатом nix-eval-jobs либо сбой на одной из сторон; 2 714 атрибутов падают у обоих.
  • Вычисление примерно в 3-5 раз медленнее Nix; для первого вычисления с компиляцией модулей автор называет 3-10x по скорости и ~2-4x по памяти. Цель, не ускорить Nix, а открыть nixpkgs для экосистемы TypeScript (редактор, отладчик, профайлер, браузер).
  • Работает на Node 24 или в браузере, без зависимостей, нативного кода и демона; автор сообщает, что значительную часть кода написал вместе с ИИ.

Почему это важно

Главная проблема любого, кто хочет придумать новый язык или вычислитель поверх модели хранилища Nix, отсутствие пакетов: nixpkgs написан на Nix, и его двадцатилетний багаж (более 140 000 собираемых пакетов на октябрь 2026) нельзя воспроизвести заново. jinx показывает путь обхода: перевести сам nixpkgs в язык, который знает другая экосистема, сохранив точные пути деривации. По утверждению автора, при этом хранилище «не видит разницы». Это заявка на то, что nixpkgs можно использовать как библиотеку в обычных JavaScript- и TypeScript-инструментах.

Кому это важно

Пользователям Nix и авторам пакетов, которым нужны автодополнение, отладка по строкам .nix и профилирование вычислений привычными средствами VS Code, Chrome DevTools и node --cpu-prof. Тем, кто делает альтернативные вычислители, языки и редакторы вокруг модели хранилища: им не нужно начинать с нуля пакетов. А также TypeScript-разработчикам, которым любопытно писать деривации на знакомом языке и запускать вычисление nixpkgs прямо в браузерной вкладке.

Как это применить

Исходники лежат в github.com/fzakaria/jinx, скомпилированный nixpkgs, в github.com/fzakaria/jinx-nixpkgs; для запуска нужен Node 24 либо браузер, а у проекта нет зависимостей, нативного кода и демона. Команда jinx compile превращает .nix в .ts, jinx eval вычисляет значение, jinx instantiate записывает замыкание .drv, а сборка по-прежнему идёт через nix-store --realise. Из TypeScript можно загрузить дерево через loadNixpkgs, писать тесты на node:test и описывать пакеты вручную через pkgs.stdenv.mkDerivation. Автор также даёт онлайн-песочницу, где hello вычисляется в браузере без установленного Nix.

Можно ли доверять

Все утверждения, слова самого автора в личном блоге; независимых оценок в тексте нет. Сильная сторона: проверка воспроизводима по задуманной схеме, сравнение всех drvPath из CI-конфигурации nixpkgs с nix-eval-jobs на трёх платформах и одной ревизии, а код и скомпилированное дерево открыты. Однако результат «ноль расхождений либо сбой на одной из сторон» относится к конкретной ревизии 6510408d, а 2 714 атрибутов, которые не вычисляет даже сам Nix, из сравнения выпадают. Автор честно раскрывает и использование ИИ при написании кода, не уточняя, каким именно и в каком объёме. Про принятие в сообществе Nix и планы влить это в nixpkgs в тексте ничего нет.

Риски и подводные камни

Скорость: вычисление примерно в 3-5 раз медленнее Nix, а первый прогон с компиляцией модулей по описанию автора ещё тяжелее, 3-10x по скорости и ~2-4x по памяти, поскольку thunks дороги для сборщика мусора. Сгенерированный код точен до каждого thunk, поэтому, по словам автора, писать его вручную мучительно; для ручной работы предусмотрена отдельная, более удобная форма. jinx не заменяет Nix: сборка пакетов по-прежнему идёт через nix-store --realise. Ревизий nixpkgs много, и скомпилированное дерево привязано к ним коммитами; проверенная совместимость заявлена только для описанной ревизии. Кроме того, это пока личный проект одного автора.

«Nixpkgs теперь, программа на TypeScript. Идите, поставьте точку останова в stdenv.»

— fzakaria, автор jinx