Homebrew, rebuilt in Zig

The same bottles from formulae.brew.sh, installed by one 1.3 MB static binary. No Ruby, no runtime, no sudo. About five times faster per package.

What it does

A package manager without the interpreter

Homebrew formulae are Ruby programs run by a bundled Ruby. metalbrew reads the prebuilt JSON index instead and pours bottles directly, so there is nothing to boot before work starts.

FIG. 002 — commandsmetalbrew 0.2.1
metalbrew update          # cache the formula index
metalbrew search wget     # match formula names
metalbrew info wget       # version, deps, description
metalbrew deps wget       # runtime deps in install order
metalbrew install wget    # fetch, verify, relocate, link
metalbrew upgrade         # everything, or name one
metalbrew uninstall wget  # unlink and remove
Install path

Four steps per bottle

  1. 1

    Fetch

    Download the bottle from GHCR, straight from the index entry.

  2. 2

    Verify

    Check the SHA-256 against the index before anything is unpacked.

  3. 3

    Relocate

    Rewrite Homebrew placeholders to your prefix and fix install names.

  4. 4

    Link

    Symlink binaries into <prefix>/bin and write a receipt.

Benchmarks

Same work, less waiting

FIG. 003 — install time, cold cache, macOS arm64median of 3 runs

tokei: Homebrew 3.65 s, metalbrew 0.67 s; micro: Homebrew 4.00 s, metalbrew 0.80 s; gdu: Homebrew 4.53 s, metalbrew 1.00 s; neofetch: Homebrew 1.46 s, metalbrew 0.19 s; duf: Homebrew 4.25 s, metalbrew 0.70 s; procs: Homebrew 5.30 s, metalbrew 0.94 s

Homebrewmetalbrew
5.4×

Mean speedup across six single-bottle installs: 3.87 s with Homebrew, 0.72 s with metalbrew. Cold cache, median of three runs, macOS arm64.

The gap is manager overhead: Homebrew starts Ruby and runs post-install hooks for every package. On large dependency trees the downloads dominate and the two converge.

Reproduce it with ./bench/bench.sh from the repository.

Details

Small on purpose

One static binary

About 1.3 MB, no dynamic dependencies. Starts in milliseconds.

No sudo by default

Only .pkg casks need root, and only with --allow-sudo.

Homebrew's bottles

Nothing is rebuilt. You get the binaries Homebrew CI already published.

Quarantine kept

Apps keep com.apple.quarantine, so Gatekeeper still checks them.

Ports and adapters

Fetchers, catalogs and receipts are swappable interfaces in plain Zig.

MIT licensed

Read it, fork it, vendor it. Zig 0.16 builds it from source.

FAQ

Questions

Does it replace Homebrew?

It can sit next to it. metalbrew uses its own prefix, so an existing /opt/homebrew stays untouched. Use it alone if you only need bottles and casks.

Which Macs does it run on?

Apple Silicon (macOS arm64). Intel Macs and Linux are not supported.

What if a formula has no bottle?

metalbrew does not build from source. Formulae without an arm64 bottle report that and stop.

Where do files go?

~/.metalbrew by default. Set METALBREW_PREFIX to change it and add <prefix>/bin to your PATH.

Why Zig?

No runtime and no garbage collector, cross-compilation built in, and a binary small enough to curl in one request.

Get started in seconds

Or build it: git clone git@github.com:4thel00z/metalbrew.git && make install