Would you accept a PR adding a flake.nix exposing the allium CLI and the allium-lsp server as Nix packages, plus a dev shell?
Why
I want to pin allium and allium-lsp in a devenv.sh setup. The LSP matters because LSP-to-MCP bridges (e.g. mcp-language-server) let AI agents consume Allium's diagnostics, hovers, and cross-references as structured data instead of parsing CLI stdout — far more useful for spec-shaped languages with cross-references between rules and entities than for general code.
Today, Nix users have to either build from source by hand or vendor a custom derivation. A first-party flake gives a single reproducible install path tied to the repo's release tags.
What it would look like for consumers
Ad-hoc usage:
# Run the CLI without installing
nix run github:juxt/allium-tools -- check spec.allium
# Drop into a shell with allium + allium-lsp on $PATH
nix shell github:juxt/allium-tools
# Install into a user profile
nix profile install github:juxt/allium-tools
Pinned in a downstream flake:
{
inputs.allium-tools.url = "github:juxt/allium-tools/v3.2.3";
outputs = { self, nixpkgs, allium-tools, ... }: {
# ...
devShell = nixpkgs.legacyPackages.x86_64-linux.mkShell {
packages = [
allium-tools.packages.x86_64-linux.allium
allium-tools.packages.x86_64-linux.allium-lsp
];
};
};
}
Inside a devenv.nix (my actual use case):
{ pkgs, inputs, ... }: {
packages = [
inputs.allium-tools.packages.${pkgs.system}.allium
inputs.allium-tools.packages.${pkgs.system}.allium-lsp
];
# Editor or MCP-LSP bridge can now spawn `allium-lsp` directly,
# no Node runtime needed in the project's devenv.
}
For contributors to allium-tools itself:
git clone https://github.com/juxt/allium-tools && cd allium-tools
nix develop # rustc + wasm-pack + Node 20 + npm + pre-commit, ready to go
cargo test
npm run build
Why this is mostly cheap
Looked at the build inputs first. The CLI is the easy half:
crates/allium is pure Rust (serde, regex-lite, serde_json), no build.rs, no FFI, no system libs. rustPlatform.buildRustPackage against the existing Cargo.lock is enough.
- CI already cross-compiles to
x86_64-linux, aarch64-linux, x86_64-darwin, aarch64-darwin (release-artifacts.yml) — same set as flake-utils.lib.defaultSystems.
- No existing
flake.nix / shell.nix / .envrc to conflict with.
The LSP is the real engineering work: it requires wasm-pack to produce packages/allium-parser-wasm/, then buildNpmPackage over the npm workspace consuming that artifact. Tractable, but the wasm-pack ↔ wasm-bindgen-cli version pinning is a known sharp edge in nixpkgs.
The change is purely additive — no edits to Cargo.toml, package.json, scripts, or workflows.
Proposed scope
Split across two PRs to keep review manageable:
PR 1 — CLI + dev shell:
packages.allium / packages.default — CLI from crates/allium.
apps.default — wires nix run to the CLI.
devShells.default — rustc stable + wasm32-unknown-unknown + wasm-pack + Node 20 + npm + pre-commit, matching what .github/workflows/ci.yml installs.
PR 2 — LSP:
packages.allium-parser-wasm — wasm-pack output as a Nix derivation.
packages.allium-lsp — buildNpmPackage consuming the WASM derivation.
VS Code extension .vsix packaging is out of scope; VS Code installs .vsix directly.
Blast radius
Net-new files only: flake.nix, flake.lock. No existing files modified. cargo build, npm run build, CI, release pipeline, pre-commit, and Homebrew distribution are all untouched. Reversible with git rm.
Questions before I start
- Preference on
flake-parts vs flat flake-utils? I'll default to flake-parts if you don't mind.
- Toolchain source: plain nixpkgs
rustc (matches CI's dtolnay/rust-toolchain@stable), or pin via rust-overlay / fenix? I'd lean nixpkgs to avoid an extra flake input.
Happy to send the PRs if there's interest.
Would you accept a PR adding a
flake.nixexposing thealliumCLI and theallium-lspserver as Nix packages, plus a dev shell?Why
I want to pin
alliumandallium-lspin a devenv.sh setup. The LSP matters because LSP-to-MCP bridges (e.g.mcp-language-server) let AI agents consume Allium's diagnostics, hovers, and cross-references as structured data instead of parsing CLI stdout — far more useful for spec-shaped languages with cross-references between rules and entities than for general code.Today, Nix users have to either build from source by hand or vendor a custom derivation. A first-party flake gives a single reproducible install path tied to the repo's release tags.
What it would look like for consumers
Ad-hoc usage:
Pinned in a downstream flake:
Inside a
devenv.nix(my actual use case):For contributors to
allium-toolsitself:Why this is mostly cheap
Looked at the build inputs first. The CLI is the easy half:
crates/alliumis pure Rust (serde,regex-lite,serde_json), nobuild.rs, no FFI, no system libs.rustPlatform.buildRustPackageagainst the existingCargo.lockis enough.x86_64-linux,aarch64-linux,x86_64-darwin,aarch64-darwin(release-artifacts.yml) — same set asflake-utils.lib.defaultSystems.flake.nix/shell.nix/.envrcto conflict with.The LSP is the real engineering work: it requires
wasm-packto producepackages/allium-parser-wasm/, thenbuildNpmPackageover the npm workspace consuming that artifact. Tractable, but the wasm-pack ↔ wasm-bindgen-cli version pinning is a known sharp edge in nixpkgs.The change is purely additive — no edits to
Cargo.toml,package.json, scripts, or workflows.Proposed scope
Split across two PRs to keep review manageable:
PR 1 — CLI + dev shell:
packages.allium/packages.default— CLI fromcrates/allium.apps.default— wiresnix runto the CLI.devShells.default— rustc stable +wasm32-unknown-unknown+wasm-pack+ Node 20 + npm +pre-commit, matching what.github/workflows/ci.ymlinstalls.PR 2 — LSP:
packages.allium-parser-wasm— wasm-pack output as a Nix derivation.packages.allium-lsp—buildNpmPackageconsuming the WASM derivation.VS Code extension
.vsixpackaging is out of scope; VS Code installs.vsixdirectly.Blast radius
Net-new files only:
flake.nix,flake.lock. No existing files modified.cargo build,npm run build, CI, release pipeline, pre-commit, and Homebrew distribution are all untouched. Reversible withgit rm.Questions before I start
flake-partsvs flatflake-utils? I'll default toflake-partsif you don't mind.rustc(matches CI'sdtolnay/rust-toolchain@stable), or pin viarust-overlay/fenix? I'd lean nixpkgs to avoid an extra flake input.Happy to send the PRs if there's interest.