Skip to content

sivchari/dendrite

Repository files navigation

dendrite

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.

Install

go install github.com/sivchari/dendrite/cmd/dendrite@latest

Or 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/

Usage

1. Define tools in dendrite.yaml

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:
      - rg

2. Lock dependencies

dendrite lock -f dendrite.yaml

This fetches SHA256 hashes via nix-prefetch-url and writes dendrite.lock.yaml.

3. Generate Nix files

dendrite generate -f dendrite.yaml -o packages/

This creates packages/<repo>/default.nix for each tool.

One-step

dendrite generate -f dendrite.yaml -o packages/ --lock

YAML Schema

tools:
  - 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.

Placeholders

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)

Non-GitHub sources

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:
      - gcloud

Custom version prefix

Some tools use non-standard version prefixes:

tools:
  - name: golang/go@go1.26.0
    asset: go{version}.{os}-{arch}.tar.gz
    version_prefix: "go"
    bins:
      - go

Multiple binaries

When a single release contains multiple binaries:

tools:
  - name: golang/tools@v0.42.0
    asset: golang-tools-{version}-{os}-{arch}.tar.gz
    bins:
      - goimports
      - gopls

Generated Output

For 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.

CLI Reference

dendrite lock

Flag Default Description
-f dendrite.yaml Path to config file

dendrite generate

Flag Default Description
-f dendrite.yaml Path to config file
-o packages/ Output directory
--lock false Run lock before generate

Requirements

  • Go 1.22+
  • Nix (nix-prefetch-url and nix hash convert)

License

MIT

About

Generate Nix default.nix from YAML configuration

Resources

License

Stars

6 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors