CLI tool
mitchellh/zig-overlay avatar
mitchellh/zig-overlay

zig-overlay: a Nix flake for the Zig compiler and its nightlies

Nix flake for the Zig compiler.

557 stars62 forksNixMIT

At a glance

What is it?
The zig-overlay flake packages the official prebuilt Zig binaries for Nix, with one package per tagged release, one per nightly, a Homebrew bottle set for macOS, an overlay that adds a zigpkgs scope, and a template that sets up a development environment for working on the Zig compiler itself.
Who is it for?
Adopt zig-overlay if you want the Zig compiler available in a Nix shell with a version you can pin exactly, since tracking nightly builds by date is the thing this flake is unusually good at. Do not adopt it if you need Zig built from source, because the readme says plainly that the flake mirrors the official binaries and does not build from source.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Nix, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A packaging flake, and what it deliberately does not do

This repository is a Nix flake packaging the Zig compiler, and the second sentence of the readme is the one that defines the project: the flake mirrors the binaries built officially by Zig and does not build them from source.

That is a significant architectural choice. A Zig source build is a large undertaking, because Zig bootstraps itself and the process needs a working Zig of an earlier stage. Packaging that in Nix is possible but it is a lot of work, and the result is a package that is slow to evaluate and hard to keep current. Mirroring the official binaries sidesteps all of it.

The trade is that you are trusting the upstream artefacts rather than reproducing the build. That is the right trade for most people, and it is what makes the nightly support possible, which is the flake's actual point of existence.

The repository is MIT licensed, the primary language is Nix, and the last push was on 2026-10-20, which is recent enough that the nightly list is being maintained actively. There are no GitHub releases, which is expected for a flake.

The top level of the repository shows the machinery. There is flake.nix and flake.lock, and a default.nix so that the package can be imported directly by non-flakes, which the readme mentions as a supported route. There is sources.json, the file that describes the upstream binaries, and mirrors.json, which presumably lists where to fetch them from. There is a separate brew-sources.json for the Homebrew variant, and shell.nix for the development shell. The templates/ directory holds the compiler-dev template, and there are two scripts at the root, update and update-brew, which are the refresh mechanisms for the two sets of packages.

There is also a .envrc, which is the direnv integration, so that entering the directory loads the Nix environment automatically if you use direnv.

What the flake exposes

The flake outputs are documented in flake.nix and summarised in the readme, and the list is short enough to be worth taking one item at a time.

The default package and app is the latest released version. The app output is what makes nix run work without naming a version.

packages.<version> gives a tagged release, so a specific version can be pinned by name. packages.master gives the latest nightly release. packages.master-<date> gives a nightly release by date, which is the one that matters when you are chasing a specific bug or need to bisect a regression across nightlies.

packages.brew.<version> gives a Homebrew bottle build, and the readme notes this one is macOS only.

There is overlays.default, an overlay that adds zigpkgs to be the packages exposed by this flake. That is the mechanism for a non-flake consumer, or for a flake that wants to consume zig through an overlay rather than as a direct input.

And there is templates.compiler-dev, which sets up a development environment for Zig compiler development.

So there are three ways to consume the package: as a direct flake input with an outputs block, through the overlay for a package set that already exists, or through the default.nix for a project that has not adopted flakes at all. Supporting all three is a small piece of pragmatism that avoids forcing a migration on anyone who just wants a Zig compiler.

The naming scheme is worth noting too, because it is a good example of how a flake makes version selection legible. master-<date> is a nightly identifier, so a lock file that pins a nightly is completely reproducible, and the difference between a stable and a nightly package is visible in the attribute name rather than hidden in a derivation.

Using it from a flake and from a shell

The usage section is the part you will actually need, and it covers the flake input, running a version, and opening a shell in one.

As a flake input, the block is small:

nix
{
  inputs.zig.url = "github:mitchellh/zig-overlay";

  outputs = { self, zig, ... }: {
    ...
  };
}

And the shell commands cover the four cases that matter. Running the latest released version is nix run against the flake with no attribute. Opening a shell with the latest nightly is nix shell against the master attribute. Opening a shell with a specific Zig version is nix shell with the version quoted in the attribute, and the quotes matter because the version string starts with a digit and contains dots, so the shell would otherwise mangle it. And there is an example with a dated nightly, master-2021-02-13, which the comment describes as the oldest version available.

That last detail is a useful one to know, because it tells you the dated nightly history has a floor. The readme's own explanation, in the section on missing nightlies, says that historical dates beyond a certain point do not exist because they predate this overlay, or the original overlays it derives from.

The date in that example is 2021, and the readme's thanks section says the author has been compiling nightly release information since 2021. So the archive goes back about five years, which is a substantial history for a compiler that was young for much of that period.

The Homebrew bottles and the reason they exist

The brew package set is the most interesting thing in this repository, because it solves a problem that is not obvious until you hit it.

The brew package set provides Zig builds from Homebrew's official binary bottles. These are built from source by Homebrew with macOS-specific patches applied. The derivations are fully self-contained, with all dylib dependencies, LLVM, LLD and zstd, bundled and patched so no Homebrew installation is required at runtime.

That last point is the reason this exists as a separate output. A Homebrew bottle is normally a relocatable archive that depends on other Homebrew packages being present. Packaging it in Nix requires either reproducing the whole dependency graph or vendoring the libraries in, and this flake does the latter. The result is a Zig package on macOS that behaves like the official one but does not care whether Homebrew exists on the machine.

The stated reason to prefer the Homebrew build is compatibility. These can be useful because in some situations Homebrew backports more patches to their bottles than the official Zig releases to keep compatibility with newer macOS versions.

That is a real and specific problem. Zig ships official macOS binaries built against a particular SDK, and when Apple releases a new macOS version, an older binary can fail to run or misbehave. Homebrew, which rebuilds continuously against the current toolchain, can ship a patched binary that works. So the two paths solve the problem from opposite ends, one by being current and the other by being what upstream published.

The commands are correspondingly simple, and the version numbers here are the current ones:

sh
# use the Homebrew-built Zig 0.16.0
$ nix shell 'github:mitchellh/zig-overlay#brew."0.16.0"'

And through the overlay, the attribute is zigpkgs.brew."0.16.0". Brew packages are only available on macOS, on aarch64-darwin and x86_64-darwin, which is expected since the whole point is the macOS dylib patching.

Working on the Zig compiler itself

The template output is the part of this flake aimed at contributors to Zig rather than users of it, and it is a small but genuinely useful thing to have.

If you are looking to contribute to the Zig compiler, the readme gives the steps. Clone zig and go into that directory, then run nix flake init with the template from this flake, and then there are two options. Start a shell with nix develop, which forces bash, or if you have direnv installed, use direnv allow to start the shell environment in your active shell, whether that is fish, zsh or something else.

sh
# clone zig and go into that directory
$ git clone https://github.com/ziglang/zig.git
$ cd zig
# setup the template
$ nix flake init -t 'github:mitchellh/zig-overlay#compiler-dev'
# Two options:
# (1) start a shell, this forces bash
$ nix develop
# (2) If you have direnv installed, you can start the shell environment
# in your active shell (fish, zsh, etc.):
$ direnv allow

The direnv option is the nicer one, and the reason the .envrc file exists in this repository. With direnv, entering the directory loads the development shell into whatever shell you already use, so you are not dropped into bash and losing your prompt and your plugins. The readme is honest that the nix develop route forces bash.

The point of a template like this is that the dependency set for building Zig is not trivial, and getting it exactly right by hand is a day of work for a new contributor. Having the flake author, who has to solve this problem anyway for their own use, encode it as a template means a contributor starts with a working environment.

That is the same philosophy as the rest of the repository. The nightly archive, the Homebrew bottles, the overlay, the default.nix fallback and the compiler-dev template are all about removing friction from a particular workflow rather than adding capability.

Editorial conclusion

Adopt zig-overlay if you want the Zig compiler available in a Nix shell with a version you can pin exactly, since tracking nightly builds by date is the thing this flake is unusually good at. Do not adopt it if you need Zig built from source, because the readme says plainly that the flake mirrors the official binaries and does not build from source. Before you commit, read the section on missing nightlies, since the history has gaps and the reason is not always a bug in the overlay, and check whether the Homebrew bottle set is relevant to you, because it exists for a specific macOS compatibility reason.

Frequently asked questions

What is the zig-overlay Nix flake?

It is a Nix flake packaging the Zig compiler. The flake mirrors the binaries built officially by Zig and does not build them from source. It is MIT licensed, its primary language is Nix, and it exposes a default package, tagged releases, nightly builds, Homebrew bottles, an overlay and a compiler development template.

How do I get a specific version of Zig with the flake?

Use nix shell with the version in the attribute, quoted, for example nix shell 'github:mitchellh/zig-overlay#"0.14.0"'. For a nightly, use the master attribute for the latest or a master-<date> attribute for a specific one, and nix run with no attribute gives you the latest released version.

What are the Homebrew bottles in the zig-overlay for?

The brew package set provides Zig builds from Homebrew's official binary bottles, which Homebrew builds from source with macOS-specific patches applied. The derivations bundle all dylib dependencies, LLVM, LLD and zstd, so no Homebrew installation is needed at run time. They are useful because Homebrew backports more patches to keep compatibility with newer macOS versions than the official Zig releases do.

Why is a nightly build sometimes missing from the overlay?

Two reasons. The Zig download JSON used to generate the overlay only shows the latest master release and does not keep historical records, so a day can be missed if the overlay was not running. And the official Zig CI only generates a master release if the CI runs full green, so during periods when the compiler's master branch is broken no nightly is built at all.

How do I set up a development environment for working on the Zig compiler?

Clone the zig repository, then run nix flake init -t 'github:mitchellh/zig-overlay#compiler-dev' in it. Afterwards you can start a shell with nix develop, which forces bash, or use direnv allow if you have direnv installed, which loads the environment into your existing shell instead.

Official sources

  1. Issues
  2. License: MIT
  3. mitchellh/zig-overlay on GitHub
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mitchellh-zig-overlay.svg)](https://hysenlabs.com/projects/mitchellh-zig-overlay)

Was this useful?