Compare commits

..

2 Commits

Author SHA1 Message Date
09b9d432c2 build: package the kitchen CLI as a Nix flake (task 0001)
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 20:54:05 -04:00
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
11 changed files with 517 additions and 65 deletions

View File

@@ -0,0 +1,66 @@
# 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.

View File

@@ -0,0 +1,82 @@
## 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.

View File

@@ -1,63 +0,0 @@
## Problem Statement
The `kitchen-md` repository is a fresh git init with no files.
Before any implementation can begin, the project needs a complete structural scaffold: a monorepo layout, two packages, TypeScript configuration, and a testing infrastructure organised by tier.
## Solution
A Bun-workspaces monorepo containing two packages (`@kitchen-md/core` and `@kitchen-md/bin`), a shared TypeScript base configuration, and per-package test scaffolding organised into unit, integration, and smoke tiers.
Synthetic test fixtures are shared at the workspace root so both packages can reference the same canonical recipe files.
## User Stories
1. As a developer, I want a Bun workspace root so that I can manage both packages with a single toolchain and no additional runtime.
2. As a developer, I want `@kitchen-md/core` isolated as its own package so that it can be consumed by a future Obsidian plugin without bundling the CLI.
3. As a developer, I want `@kitchen-md/bin` isolated as its own package so that the CLI binary can be compiled and distributed independently of the library.
4. As a developer, I want a shared TypeScript base configuration at the workspace root so that both packages inherit consistent compiler settings without duplication.
5. As a developer, I want unit test files co-located with their source module so that the test for a module is always findable next to the module itself.
6. As a developer, I want integration test files co-located with the code they exercise so that cross-module test coverage is discoverable alongside the relevant source.
7. As a developer, I want smoke tests in `@kitchen-md/bin` that invoke the CLI directly so that end-to-end user-story coverage is separated from unit-level coverage.
8. As a developer, I want synthetic recipe fixture files at the workspace root so that both packages can reference the same canonical test inputs without duplication.
## Implementation Decisions
- Bun is the single toolchain for the entire project: package manager, runtime, test runner, and native binary compiler (`bun --compile`).
No Node.js runtime is required on target machines.
- The workspace root `package.json` declares Bun workspaces pointing to `packages/core` and `packages/bin`.
- `@kitchen-md/core` lives in `packages/core/` and is structured as a publishable library with a single entry point.
- `@kitchen-md/bin` lives in `packages/bin/`, declares `@kitchen-md/core` as a workspace dependency, and declares a `bin` entry named `kitchen` pointing at the CLI entry point.
- A `tsconfig.json` at the workspace root defines shared compiler settings (strict mode, ESNext target and module, bundler module resolution, Bun types).
Each package's `tsconfig.json` extends the root config.
- A `fixtures/` directory at the workspace root holds synthetic `.md` recipe files.
The primary fixture covers every annotation type (ingredient, cookware, timer) and all format features.
Additional fixture files are acceptable for regression cases or edge cases that cannot fit cleanly into the primary file.
## Testing Decisions
- Tests assert external behaviour only — given an input, assert the output — never implementation internals.
- **Unit tests**: co-located with the source file they test, named `{module}_test.ts`.
All test data is inline raw strings within the test file; no filesystem access.
Both packages have unit tests.
- **Integration tests**: co-located with the source they exercise, naming is flexible.
Integration tests read from the shared `fixtures/` directory.
Both packages have integration tests where they cross file boundaries.
- **Smoke tests**: present only in `@kitchen-md/bin`.
Each smoke test invokes the CLI directly (via subprocess or equivalent) and asserts its output against expected results.
Smoke tests use the shared `fixtures/` directory as input.
Smoke test coverage maps directly to the CLI user stories in the recipe format spec.
- The Bun test runner discovers test files via `*_test.ts` and `*.test.ts` patterns; all test files must match one of these patterns to be picked up automatically.
## Out of Scope
- Parser implementation (covered by the recipe format spec).
- CLI command design and subcommand structure.
- Aisle mapping file format.
- Shopping list generator.
- Publishing either package to a registry.
- CI/CD configuration.
## Further Notes
- The `$` sigil for cookware and the choice of Bun over other runtimes are decisions from the recipe format spec; this scaffold spec assumes them and does not re-litigate them.
- The binary is named `kitchen` (the `bin` key in `@kitchen-md/bin`'s `package.json`), not `kitchen-md` or `kmd`.
- Smoke tests differ from integration tests in degree, not kind: they test the CLI as a black box from the outside rather than testing module interactions from the inside.

View File

@@ -0,0 +1,53 @@
---
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
- [x] The flake is structured with flake-parts, with `x86_64-linux` in the systems list and nixpkgs tracking `nixpkgs-unstable`.
- [x] bun2nix is a flake input, and its generated vendoring expression is checked in and regenerated by a postinstall hook on lockfile changes.
- [x] A single Bun version is pinned in one place and consumed by the build derivation.
- [x] `nix build` produces a runnable `kitchen` binary reproducibly with no network access during the build.
- [x] The compiled binary embeds its dependencies and runs on a machine with no Node.js or Bun runtime present.
- [x] 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.

4
.gitignore vendored
View File

@@ -3,6 +3,10 @@ node_modules/
# compiled CLI binary
packages/bin/kitchen
# nix build result symlinks
result
result-*
# local environment overrides
.env
.env.local

View File

@@ -7,6 +7,7 @@
"devDependencies": {
"@biomejs/biome": "^2.5.3",
"bun-types": "latest",
"bun2nix": "^2.1.2",
},
},
"packages/bin": {
@@ -51,6 +52,12 @@
"bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
"bun2nix": ["bun2nix@2.1.2", "", { "dependencies": { "sade": "^1.8.1" }, "bin": { "bun2nix": "index.ts" } }, "sha512-0wx6Ar5ccrz4aSD5prbShwymjDEXFh7Bucxs+YrpAMa67TnVB95Hv8FV3oaQEbtOx6QGgIAyOmap6Y3WCRqetg=="],
"mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
"sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="],
"undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="],
}
}

78
bun.nix Normal file
View File

@@ -0,0 +1,78 @@
# Autogenerated by `bun2nix`, editing manually is not recommended
#
# Set of Bun packages to install
#
# Consume this with `fetchBunDeps` (recommended)
# or `pkgs.callPackage` if you wish to handle
# it manually.
{
copyPathToStore,
fetchFromGitHub,
fetchgit,
fetchurl,
...
}:
{
"@biomejs/biome@2.5.3" = fetchurl {
url = "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.3.tgz";
hash = "sha512-MrJswFdei9EfDwwUy2tQrPDpK0AO+RmMFvBoaaJ6ayBc3sUbHdCE+XG5N8vp+5So41ZupZJQm0roHFFhMGVD7A==";
};
"@biomejs/cli-darwin-arm64@2.5.3" = fetchurl {
url = "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.3.tgz";
hash = "sha512-QhYP9muVQ0nUO5zztFuPbEwi4+94sJWVjaZds9aMi1l/KNZBiUjdiSUrGHsTaMGDXrYl+r4AS2sUKfgH3w+V3g==";
};
"@biomejs/cli-darwin-x64@2.5.3" = fetchurl {
url = "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.3.tgz";
hash = "sha512-NC1Ss13UaW7QZX+y8j44bF7AP0jSJdBl6iRhe0MAkvaSqZy+mWg3GaXsrb+eSoHoGDBtaXWEbMVV0iVN2cZ7cQ==";
};
"@biomejs/cli-linux-arm64-musl@2.5.3" = fetchurl {
url = "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.3.tgz";
hash = "sha512-fccix0w6xp6csCXgxeC0dU/3ecgRQal0y+cv2SP9ajNlhe7Yrk2Ug7UDe2j9AT9ZDYitkXpvUKgZjjuoYeP4Vg==";
};
"@biomejs/cli-linux-arm64@2.5.3" = fetchurl {
url = "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.3.tgz";
hash = "sha512-ksx1KWeyYW18ILL04msF/J4ZBtBDN33znYK8Z/aNv/vlBVxL9/g3mGP+omgHJKy4+KWbK87vcmmpmurfNjSgiA==";
};
"@biomejs/cli-linux-x64-musl@2.5.3" = fetchurl {
url = "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.3.tgz";
hash = "sha512-O/yU9YKRUiHhmcjF2f38PSjseVk3G4VLWYc0G2HWpzdBVREV6G8IGWIVEFf7MFPfWIzNUIvPsEjeAZQIOgnLcQ==";
};
"@biomejs/cli-linux-x64@2.5.3" = fetchurl {
url = "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.3.tgz";
hash = "sha512-yMkJtilsgvILDcVkh187aVLTb64xYsrxYajx5kym+r1ULkO5HUOfu9AYKLGQbOVLwJtT2utNw7hhFNg+17mUYA==";
};
"@biomejs/cli-win32-arm64@2.5.3" = fetchurl {
url = "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.3.tgz";
hash = "sha512-cX5z+GYwRcqEok0AH3KSfQGgqYd0Nomfp6Fbe1uiTtELE38hdH2k842wQ9wLNaF/JJ7r4rjJQ4VR+ce+fRmQbw==";
};
"@biomejs/cli-win32-x64@2.5.3" = fetchurl {
url = "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.3.tgz";
hash = "sha512-ExSaJWi4/u6+GXCszlSKpWSjKNbDseAYqqkCznsCsZ/4uidZ/BEqsCc5/3ctlq6dfIubdIIRSVLC/PG9xPl70Q==";
};
"@kitchen-md/bin" = copyPathToStore ./packages/bin;
"@kitchen-md/core" = copyPathToStore ./packages/core;
"@types/node@26.1.1" = fetchurl {
url = "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz";
hash = "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==";
};
"bun-types@1.3.14" = fetchurl {
url = "https://registry.npmjs.org/bun-types/-/bun-types-1.3.14.tgz";
hash = "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ==";
};
"bun2nix@2.1.2" = fetchurl {
url = "https://registry.npmjs.org/bun2nix/-/bun2nix-2.1.2.tgz";
hash = "sha512-0wx6Ar5ccrz4aSD5prbShwymjDEXFh7Bucxs+YrpAMa67TnVB95Hv8FV3oaQEbtOx6QGgIAyOmap6Y3WCRqetg==";
};
"mri@1.2.0" = fetchurl {
url = "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz";
hash = "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==";
};
"sade@1.8.1" = fetchurl {
url = "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz";
hash = "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==";
};
"undici-types@8.3.0" = fetchurl {
url = "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz";
hash = "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==";
};
}

163
flake.lock generated Normal file
View File

@@ -0,0 +1,163 @@
{
"nodes": {
"bun2nix": {
"inputs": {
"flake-parts": "flake-parts",
"nixpkgs": [
"nixpkgs-bun"
],
"systems": [
"systems"
],
"treefmt-nix": "treefmt-nix"
},
"locked": {
"lastModified": 1784665499,
"narHash": "sha256-9BMxlTxCCDAeoNLtb1a/st7udtTIJep+wpUzquA29VU=",
"owner": "nix-community",
"repo": "bun2nix",
"rev": "0f2a1f0b6f42cebe3b149bf62d38754c5e0e9729",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "2.1.2",
"repo": "bun2nix",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"bun2nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1782949081,
"narHash": "sha256-vp6Y/Grm98ESt6ceOkWiHWyZRDV3J1RID4w+6NWK9yA=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "17c9d6cdfc60c64f4ee8d306f9bc0b4ccb51481e",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_2": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1782949081,
"narHash": "sha256-vp6Y/Grm98ESt6ceOkWiHWyZRDV3J1RID4w+6NWK9yA=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "17c9d6cdfc60c64f4ee8d306f9bc0b4ccb51481e",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1784872115,
"narHash": "sha256-THPEF2po0fsoH8gNtp+Ae0XFDJH3N/ol7xO3v6VMTJU=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "335f0738cb2fa9708f3f428e39d2eae975d1338d",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-bun": {
"locked": {
"lastModified": 1784497964,
"narHash": "sha256-vlHUuqAcbcH2RKmHbPiuQzbv1pnzzavXnI62RD0bqCU=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "241313f4e8e508cb9b13278c2b0fa25b9ca27163",
"type": "github"
},
"original": {
"owner": "nixos",
"repo": "nixpkgs",
"rev": "241313f4e8e508cb9b13278c2b0fa25b9ca27163",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1782614948,
"narHash": "sha256-ePjCwr1sNm9NYUqywL7QfK3JnlS015msC+eBu2zKlp8=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "db3f255737b94216eb71cce308e2912cf6bc2d7c",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
}
},
"root": {
"inputs": {
"bun2nix": "bun2nix",
"flake-parts": "flake-parts_2",
"nixpkgs": "nixpkgs",
"nixpkgs-bun": "nixpkgs-bun",
"systems": "systems"
}
},
"systems": {
"locked": {
"lastModified": 1680978846,
"narHash": "sha256-Gtqg8b/v49BFDpDetjclCYXm8mAnTrUzR0JnE2nv5aw=",
"owner": "nix-systems",
"repo": "x86_64-linux",
"rev": "2ecfcac5e15790ba6ce360ceccddb15ad16d08a8",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "x86_64-linux",
"type": "github"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"bun2nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1784369104,
"narHash": "sha256-47cxbcZODibHv3rELFQ9vZly0vUNkND/atn/U7HLeb0=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "df3c0640565d04a0261253cdd89fce78ec50168a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

41
flake.nix Normal file
View File

@@ -0,0 +1,41 @@
{
description = "kitchen the KitchenMD CLI, packaged as a Nix flake";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
# Provides the single pinned Bun used to compile the binary, held apart
# from `nixpkgs` so a `nixpkgs` update cannot drag Bun to a release that
# emits empty binaries under sandboxed native compilation.
nixpkgs-bun.url = "github:nixos/nixpkgs/241313f4e8e508cb9b13278c2b0fa25b9ca27163";
flake-parts.url = "github:hercules-ci/flake-parts";
systems.url = "github:nix-systems/x86_64-linux";
bun2nix = {
url = "github:nix-community/bun2nix?ref=2.1.2";
# Compile against the pinned Bun rather than `nixpkgs`'s.
inputs.nixpkgs.follows = "nixpkgs-bun";
inputs.systems.follows = "systems";
};
};
outputs =
inputs:
inputs.flake-parts.lib.mkFlake { inherit inputs; } {
systems = import inputs.systems;
perSystem =
{ system, ... }:
let
pkgs = import inputs.nixpkgs {
inherit system;
overlays = [ inputs.bun2nix.overlays.default ];
};
in
{
packages.default = pkgs.callPackage ./package.nix { };
};
};
}

View File

@@ -9,10 +9,12 @@
"scripts": {
"test": "bun test",
"lint": "biome check .",
"format": "biome check --write ."
"format": "biome check --write .",
"postinstall": "bun2nix -o bun.nix"
},
"devDependencies": {
"@biomejs/biome": "^2.5.3",
"bun-types": "latest"
"bun-types": "latest",
"bun2nix": "^2.1.2"
}
}

19
package.nix Normal file
View File

@@ -0,0 +1,19 @@
# The `kitchen` CLI compiled to a self-contained native binary.
{ lib, bun2nix }:
bun2nix.mkDerivation {
pname = "kitchen";
version = (lib.importJSON ./packages/bin/package.json).version;
src = ./.;
module = "packages/bin/src/index.ts";
bunDeps = bun2nix.fetchBunDeps {
bunNix = ./bun.nix;
};
# No vendored dependency needs install-time lifecycle scripts, and running
# them would fire this repo's own `postinstall` (bun2nix) inside the sandbox,
# where it is redundant.
dontRunLifecycleScripts = true;
}