## Problem Statement The repository was scaffolded as a Bun workspaces monorepo before the developer adopted Nix. There is no declarative, reproducible way to build, run, or install the `kitchen` CLI, and no reproducible development environment. A contributor must install the right Bun version and tooling by hand, and the "no Node.js runtime on target machines" promise is trusted rather than enforced. The developer wants to install the CLI declaratively — as a flake input in a system or home configuration — and to enter a fully specified dev shell with a single command. ## Solution Package the whole repository as a Nix flake, structured with flake-parts, exposing the `kitchen` CLI as an installable package plus a development shell, a runnable app, and a set of checks. Bun dependencies are vendored reproducibly with bun2nix so the sandboxed build needs no network. Bun itself is pinned so the version used to develop is the version used to compile. The flake is the single declarative entry point: build it, run it, install it, or develop in it. ## User Stories 1. As the developer, I want to install the `kitchen` CLI declaratively via a flake input, so that it lands in my system or home configuration reproducibly without manual build steps. 2. As the developer, I want `nix build` to produce the compiled `kitchen` binary, so that the artifact is built the same way on any machine. 3. As the developer, I want `nix run` to execute the CLI without a prior install, so that I can try it ad hoc. 4. As a contributor, I want `nix develop` to drop me into a shell with the exact Bun and tooling the project expects, so that I do not have to install or match versions by hand. 5. As a contributor using direnv, I want the dev shell to load automatically on entering the directory, so that the environment is present without a manual command. 6. As the developer, I want `nix flake check` to run the test suites and the linter, so that a single command verifies the project reproducibly and can gate CI later. 7. As the developer, I want the compiled binary to embed its dependencies, so that no Node.js or Bun runtime is required on the target machine. 8. As a maintainer, I want dependency vendoring to stay in sync with the lockfile automatically, so that adding or removing a dependency does not require a separate manual regeneration step I might forget. 9. As a maintainer, I want the Bun version pinned and shared between the dev shell and the build, so that a Bun release that breaks sandboxed compilation cannot silently diverge dev from build. ## Implementation Decisions - **Flake structure: flake-parts.** Per-system outputs (package, dev shell, app, checks) are declared through flake-parts' `perSystem` module, and system-independent configuration sits at the top level. This keeps per-system and top-level outputs separate and lets tooling integrations compose as modules. - **Outputs.** The flake exposes a default package building the `kitchen` binary, a default app pointing at that binary, a default dev shell, and a checks set aggregating tests and lint. `nix build`, `nix run`, `nix develop`, and `nix flake check` are the supported entry points. - **Dependency vendoring: bun2nix.** Bun workspace dependencies are vendored via bun2nix, which reads the lockfile and produces a generated Nix expression the build consumes. A postinstall hook regenerates that expression on any dependency change, keeping it in sync with the lockfile without a manual step. bun2nix is added as a flake input. - **Binary build via Bun's native compiler.** The package derivation compiles the CLI to a self-contained native binary that embeds its dependencies, so the runtime closure on the target has no Node.js or Bun. The vendored dependencies are consumed at build time only. - **Bun pinned.** A single pinned Bun version is shared by the dev shell and the build derivation. The pin avoids Bun releases known to break native compilation inside the Nix sandbox, where specific point releases have produced empty binaries. - **Systems: `x86_64-linux` only** for now, declared in the flake-parts systems list. Additional targets are a one-line addition when a real target appears; vendoring and compilation are per-platform, so each added system carries its own build. - **nixpkgs tracks `nixpkgs-unstable`**, to follow a recent Bun. - **Lint as a check: treefmt-nix.** Biome runs as a `nix flake check` through the treefmt-nix flake-parts module, so lint verification is reproducible and shares one configuration with the existing biome setup. - **direnv auto-load.** A direnv configuration using `use flake` loads the dev shell automatically for direnv users. - **The monorepo it packages is unchanged.** The existing Bun workspaces layout (`@kitchen-md/core` and `@kitchen-md/bin`) and the `kitchen` binary target are the inputs to the flake; the flake wraps them without restructuring the packages. ## Testing Decisions - The flake's verification surface is its outputs, exercised as commands rather than unit tests. The highest seam is `nix flake check`: it composes the package build, the Bun test suites, and the biome lint into one reproducible gate. - **Build seam.** `nix build` must produce a runnable `kitchen` binary; a minimal check invokes the built binary (for example `--help`) and asserts a zero exit, mirroring the existing smoke-test approach in `@kitchen-md/bin` but against the Nix artifact. - **Dev-shell seam.** Entering the dev shell must expose the pinned Bun and biome; this is verified by the presence and versions of those tools in the shell. - **Application behaviour is not re-tested here.** The parser and CLI behaviour are covered by their own specs' unit, integration, and smoke tiers, which run under the Bun test runner and are invoked by `nix flake check`. This spec's tests concern packaging and environment reproducibility only. - Prior art: the existing smoke tests in `@kitchen-md/bin` invoke the CLI as a black box; the build-seam check reuses that black-box style against the Nix-built binary. ## Out of Scope - The parser and CLI implementation and their behaviour, covered by the core-parser and cli-view specs. - Publishing either package to a registry, and the future Obsidian plugin's own repository and packaging. - CI/CD wiring; `nix flake check` is designed to be CI-callable, but the CI configuration itself is separate. - Multi-system and cross-compilation beyond `x86_64-linux`, and any binary cache or substituter setup. - A NixOS or home-manager module wrapping the package; the package output is directly consumable without one. - git-hooks integration; treefmt-nix covers the lint check, and pre-commit hooks can be added later as another flake-parts module. ## Further Notes - Because Bun's native compiler bundles dependencies into the binary, the vendoring problem is confined to build time; nothing about the dependency closure reaches consumers of the installed CLI. - The Bun-version pin is a correctness constraint, not just hygiene: native compilation has produced empty binaries in the sandbox on specific Bun point releases, so the dev shell and build must never drift apart on Bun version. - The decision to package with a flake, vendor via bun2nix, and pin Bun is recorded in ADR 0007. - This spec replaces the removed project-scaffold spec's role for anything Nix-related; the underlying Bun monorepo layout that spec documented is retained in the codebase.