This repository has been archived on 2026-07-29. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
kitchen-md/.claude/tasks/0001-flake-build.md
alexion 8fd2e53c53 build: package the kitchen CLI as a Nix flake
Add a flake-parts flake whose default package Bun-compiles the kitchen
CLI into a self-contained native binary, built in the sandbox with
dependencies vendored by bun2nix.

Bun is pinned via a dedicated nixpkgs-bun input (Bun 1.3.13) that
bun2nix follows, so nixpkgs can track unstable without moving the
compile toolchain onto a release that emits empty binaries.

bun2nix is both a flake input and an npm devDependency, and a
postinstall hook keeps the checked-in bun.nix in sync with the lockfile.
2026-07-25 22:28:10 -04:00

3.9 KiB

spec
spec
nix-flake-packaging

What to build

The tracer bullet for packaging the repository as a Nix flake: a flake-parts flake whose default package Bun-compiles the kitchen CLI into a self-contained native binary, built reproducibly in the sandbox with vendored dependencies.

This is the whole risk seam — a Nix build is sandboxed with no network, while bun install fetches from npm, so the dependency closure must be vendored before anything compiles. Bun dependencies are vendored via bun2nix (a flake input) reading the workspace lockfile into a checked-in generated expression, kept in sync with the lockfile by a postinstall hook so a dependency change needs no separate manual regeneration. A single pinned Bun version is shared by the build derivation (and later the dev shell), avoiding point releases known to produce empty binaries under sandboxed native compilation.

Once this compiles, the remaining outputs (nix run, nix develop, checks) hang off the working flake in the next slice.

Acceptance criteria

  • The flake is structured with flake-parts, with x86_64-linux in the systems list and nixpkgs tracking nixpkgs-unstable.
  • bun2nix is a flake input, and its generated vendoring expression is checked in and regenerated by a postinstall hook on lockfile changes.
  • A single Bun version is pinned in one place and consumed by the build derivation.
  • nix build produces a runnable kitchen binary reproducibly with no network access during the build.
  • The compiled binary embeds its dependencies and runs on a machine with no Node.js or Bun runtime present.
  • The default package is consumable as a flake input from another configuration.

Implementation Notes

The tracer bullet builds and all six criteria were verified end-to-end against a real nix build, not just by inspection.

The Bun pin

bun2nix compiles the binary with the bun from its own nixpkgs, baked into its setup hook at bun2nix build time. So pinning Bun means controlling the nixpkgs that bun2nix follows, not overlaying bun in this flake's package set. The pin is a dedicated nixpkgs-bun input fixed to one revision (Bun 1.3.13), with bun2nix.inputs.nixpkgs.follows = "nixpkgs-bun". That revision is the one bun2nix 2.1.2 itself locks, so the compile toolchain matches what bun2nix was tested against. nixpkgs still tracks nixpkgs-unstable for everything else, and updating it cannot move Bun. The dev shell in task 0002 consumes the same nixpkgs-bun, keeping "develop with the version that compiles" true from one place.

Vendoring and the postinstall hook

bun2nix is both a flake input (native builder) and an npm devDependency, so the postinstall: bun2nix -o bun.nix hook regenerates the checked-in bun.nix on any bun install even outside the Nix dev shell. The build passes dontRunLifecycleScripts = true so that same postinstall does not fire redundantly inside the sandbox.

Verification performed

nix build produced a 101 MB native ELF that runs to exit 0 under env -i (empty environment, no Node or Bun, ldd shows only glibc), confirming the embedded-runtime and no-network claims — the compile derivation is a normal sandboxed derivation with networking disabled. A throwaway consumer flake built the package through inputs.kitchen.packages.x86_64-linux.default, confirming criterion 6.

Deviations from the plan

  • The nix-community cachix nixConfig block that the bun2nix templates ship was dropped, because the spec lists "any binary cache or substituter setup" as out of scope. Consequence: a first build with a cold store compiles bun2nix from source. A developer who wants the prebuilt bun2nix can add the substituter to their own Nix configuration.
  • packages/bin/src/index.ts is still the placeholder entry point. The CLI's behaviour belongs to the core-parser and cli-view specs, so the compiled binary is a no-op that exits 0 — enough to prove the packaging seam.