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/adr/0007-nix-flake-packaging.md
alexion 1af090caa3 docs: add nix flake packaging spec and ADR
Replace the stale Bun-only project-scaffold spec with a Nix-aware
packaging spec, and record the flake-parts + bun2nix + pinned-Bun
decision as ADR 0007.
2026-07-25 20:25:19 -04:00

67 lines
4.5 KiB
Markdown

# ADR 0007 — Nix Flake Packaging
**Status**: Accepted
## Context
The repository was scaffolded as a Bun workspaces monorepo before the project moved to Nix.
The developer wants to install the `kitchen` CLI declaratively and develop in a reproducible shell.
Bun is a first-class citizen for development and native-binary compilation, but it is the least turnkey JavaScript toolchain to build reproducibly under Nix.
Nix builds are sandboxed with no network, while `bun install` fetches from npm.
The design commits `core` to the remark/unified ecosystem (see ADR 0002) plus chalk in the CLI, so a real dependency closure must be vendored rather than wished away.
Runtime alternatives were weighed and rejected.
Switching to pnpm or npm on Node would unwind a Bun-shaped spec set and lose the self-contained single binary that satisfies the "no Node.js on target" goal.
Deno keeps the single binary but adds an npm-publishing step (`dnt`) for `core`, half of which is a library destined for an Obsidian plugin.
Three axes had to be decided: the flake's structure, how Bun dependencies are vendored in the sandbox, and how the Bun version is managed.
Flake structure — three options:
**Plain flake** with a hand-rolled per-system helper.
**flake-utils** with `eachDefaultSystem`.
**flake-parts** with the module system.
Dependency vendoring — two viable options:
**Manual fixed-output derivation** running `bun install` inside one FOD.
**bun2nix** generating per-package fixed-output derivations from the lockfile.
## Decision
Package the repository as a **flake-parts** flake that builds the Bun-compiled `kitchen` binary as an installable package, with dependencies vendored via **bun2nix**, and the **Bun version pinned** and shared between the dev shell and the build.
- Outputs: a default package (the compiled binary), an app, a dev shell, and a checks set running the Bun tests and biome (the latter via treefmt-nix).
- Systems: `x86_64-linux` only initially, extensible through the flake-parts systems list.
- nixpkgs tracks `nixpkgs-unstable`.
## Rationale
flake-parts is chosen over the alternatives because the flake already has four per-system output categories and will compose tooling as modules — treefmt-nix for lint now, git-hooks later.
The module system pays for itself at the second integration, and the outputs it organises are real, not speculative.
flake-utils is rejected as the least future-proof: it is effectively in maintenance and handles system-independent outputs awkwardly.
Plain flake is the fallback for maximum transparency, but it leaves the per-system plumbing hand-maintained.
bun2nix is chosen over a manual fixed-output derivation because its per-package derivations are content-addressed fetches rather than a byte-reproduced install.
That is more robust across Bun versions and avoids the per-platform hash multiplication a single install-FOD incurs.
It has first-class workspace support, which matters because this is a monorepo, and a postinstall hook that keeps the generated expression in sync with the lockfile automatically.
It is maintained under nix-community, which answers the bus-factor concern.
The manual FOD's only advantage — zero third-party inputs — is not worth its more fragile, hand-maintained, per-platform hash story.
Pinning Bun is a correctness constraint, not hygiene.
Native compilation has produced empty binaries inside the Nix sandbox on specific Bun point releases, so the version that develops must be the version that compiles, and both must avoid known-bad releases.
## Consequences
- bun2nix is a flake input, and a generated vendoring expression is checked in and kept current by a postinstall hook on lockfile changes.
- The dev shell and the build derivation share one pinned Bun version; bumping Bun is a deliberate, single-point change that must be validated against the sandbox compilation behaviour.
- `nix build`, `nix run`, `nix develop`, and `nix flake check` are the supported entry points; `nix flake check` runs the Bun test tiers and biome and is CI-callable.
- The compiled binary embeds its dependencies, so the installed CLI has no Node.js or Bun runtime requirement; the vendored closure is build-time only.
- Adding a target platform is a systems-list addition, each carrying its own per-platform vendoring and compilation.
- Biome runs as a reproducible check via treefmt-nix; a future pre-commit integration can be added as another flake-parts module.
- The packaging decision is documented here; the Bun monorepo layout it wraps is unchanged.