Generate Nix default.nix files from a simple YAML configuration.
dendrite lets you manage CLI tool installations via Nix without writing Nix code. Define your tools in YAML, and dendrite generates default.nix files that can be imported from a flake.nix.
go install github.com/sivchari/dendrite/cmd/dendrite@latestOr run it directly with Nix:
nix run github:sivchari/dendrite -- generate -f dendrite.yaml -o packages/For local development from this repository:
nix run . -- generate -f dendrite.yaml -o packages/tools:
- name: aquaproj/aqua@v2.39.0
asset: aqua_{os}_{arch}.tar.gz
- name: cli/cli@v2.87.0
asset: gh_{version}_{os}_{arch}.zip
bins:
- gh
# Use a platform map when a release uses explicit asset names.
- name: cli/cli@v2.87.0
asset:
darwin/arm64: gh_{version}_macOS_arm64.zip
linux/amd64: gh_{version}_linux_amd64.tar.gz
linux/arm64: gh_{version}_linux_arm64.tar.gz
bins:
- gh
- name: BurntSushi/ripgrep@14.1.0
asset: ripgrep-{version}-{arch}-{os}.tar.gz
bins:
- rgdendrite lock -f dendrite.yamlThis fetches SHA256 hashes via nix-prefetch-url and writes dendrite.lock.yaml.
dendrite generate -f dendrite.yaml -o packages/This creates packages/<repo>/default.nix for each tool.
dendrite generate -f dendrite.yaml -o packages/ --locktools:
- name: <owner>/<repo>@<version> # required
asset: <pattern> # required, unless url is set
url: <url_pattern> # for non-GitHub sources, mutually exclusive with asset
bins: # optional (defaults to [repo name])
- <binary_name>
version_prefix: "v" # optional (default: "v", set to "go" for golang/go, "" for no prefix)asset and url can be either a single pattern or a platform map.
Single patterns are expanded to dendrite's default platforms. Use a platform map when you need to target a different platform set or exact asset names.
For patterns with {os} or {arch}, dendrite tries multiple OS/arch name combinations and common archive extensions, then uses the first URL that succeeds.
| Placeholder | Description |
|---|---|
{version} |
Version with prefix stripped (configurable via version_prefix) |
{os} |
OS name (darwin, macOS, linux, Linux) |
{arch} |
Architecture (arm64, aarch64, amd64, x86_64) |
Use url instead of asset for tools hosted outside GitHub Releases:
tools:
- name: google/cloud-sdk@v529.0.0
url: https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-{version}-darwin-arm.tar.gz
bins:
- gcloudSome tools use non-standard version prefixes:
tools:
- name: golang/go@go1.26.0
asset: go{version}.{os}-{arch}.tar.gz
version_prefix: "go"
bins:
- goWhen a single release contains multiple binaries:
tools:
- name: golang/tools@v0.42.0
asset: golang-tools-{version}-{os}-{arch}.tar.gz
bins:
- goimports
- goplsFor cli/cli@v2.87.0 with a .zip asset, dendrite generates a package that selects the source from stdenv.hostPlatform.system:
# Code generated by dendrite; DO NOT EDIT.
{
lib,
stdenv,
fetchurl,
unzip,
}:
let
platform = stdenv.hostPlatform.system;
sources = {
"aarch64-darwin" = {
url = "https://github.com/cli/cli/releases/download/v2.87.0/gh_2.87.0_macOS_arm64.zip";
sha256 = "sha256-sebjq3ZIkqM6H+Rkwjm+OT5rvUIggEaS+RnEyAWx278=";
extract = ''tmpdir=$(mktemp -d) && unzip -o $src -d $tmpdir && find $tmpdir -type f \( -name gh \) -exec cp {} $out/bin/ \;'';
needsUnzip = true;
};
"x86_64-linux" = {
url = "https://github.com/cli/cli/releases/download/v2.87.0/gh_2.87.0_linux_amd64.tar.gz";
sha256 = "sha256-...";
extract = ''tmpdir=$(mktemp -d) && tar -xzf $src -C $tmpdir && find $tmpdir -type f \( -name gh \) -exec cp {} $out/bin/ \;'';
needsUnzip = false;
};
"aarch64-linux" = {
url = "https://github.com/cli/cli/releases/download/v2.87.0/gh_2.87.0_linux_arm64.tar.gz";
sha256 = "sha256-...";
extract = ''tmpdir=$(mktemp -d) && tar -xzf $src -C $tmpdir && find $tmpdir -type f \( -name gh \) -exec cp {} $out/bin/ \;'';
needsUnzip = false;
};
};
platformSrc = sources.${platform} or (throw "dendrite: unsupported platform ${platform} for cli");
in
stdenv.mkDerivation rec {
pname = "cli";
version = "2.87.0";
src = fetchurl { inherit (platformSrc) url sha256; };
dontUnpack = true;
dontStrip = true;
nativeBuildInputs = lib.optionals (platformSrc.needsUnzip or false) [ unzip ];
installPhase = ''
mkdir -p $out/bin
${platformSrc.extract}
chmod +x $out/bin/gh
'';
}These files are designed to be imported from a flake.nix as package modules.
| Flag | Default | Description |
|---|---|---|
-f |
dendrite.yaml |
Path to config file |
| Flag | Default | Description |
|---|---|---|
-f |
dendrite.yaml |
Path to config file |
-o |
packages/ |
Output directory |
--lock |
false |
Run lock before generate |
- Go 1.22+
- Nix (
nix-prefetch-urlandnix hash convert)
MIT