Zig packages
Publish a Zig package and get the exact hash zig fetch will compute, check a package before publishing, use any Zaryn repository as a dependency, and fix build.zig.zon errors. Every step explained.
Search for a command to run…
Publish a Zig package and get the exact hash zig fetch will compute, check a package before publishing, use any Zaryn repository as a dependency, and fix build.zig.zon errors. Every step explained.
Zig doesn't have a central package registry. A dependency is simply a web address of an archive plus its hash, written in your project's build.zig.zon. zig build downloads the archive, computes its hash, and stops if it doesn't match.
That design is safe, but it leaves you to host the archive somewhere and work out the hash. Zaryn does both:
zig fetch does it, so you can paste them straight into build.zig.zon.build.zig.zon the way zig does and tells you, in plain words, what zig would refuse (a missing fingerprint, a name that isn't allowed, files left out of the package)..zip files and git+https repositories), and the Zig compiler itself, can come through Zaryn; zev mirror zig does it for a whole project: see Mirrors.A folder with a build.zig (how to build it) and a build.zig.zon (what it is). zig init creates both. A build.zig.zon looks like this:
.{ .name = .greet, // the package name: letters, digits and _ .version = "0.1.0", // raise it for every release .fingerprint = 0x3610a6865d7ac0a2, // made by zig init; never change it .minimum_zig_version = "0.15.1", // oldest Zig that builds it .dependencies = .{}, // other packages it uses .paths = .{ "build.zig", "build.zig.zon", "src" }, // what belongs to the package}.name starts with a dot (.greet, not "greet") since Zig 0.14..fingerprint is your package's permanent ID. If you copy someone's package to start your own, Zaryn's check tells you the new value to use..paths lists the files and folders that are part of the package. Everything else in the archive (notes, test data, pictures) is left out and doesn't change the hash.From the folder above your package (here the package is in greet/):
tar czf greet-0.1.0.tar.gz greetThis makes one compressed file of the folder. .tar.xz, .tar.zst and plain .tar work too.
On Packages, choose Zig, then Check a package before publishing and pick the file. Or from a terminal:
curl --data-binary @greet-0.1.0.tar.gz -H "Authorization: Bearer $ZARYN_TOKEN" \ https://api.zaryn.xyz/v1/packages/zig/-/checkYou get the hash, how many files are in the package, and every problem zig would stop at, for example:
invalid fingerprint 0x1234 for the name .greet: if this is a new or forked package, use 0x3610a6865d7ac0a2Nothing is stored.
Create a token on Packages (Create a publish token), then:
curl -T greet-0.1.0.tar.gz -H "Authorization: Bearer $ZARYN_TOKEN" \ https://api.zaryn.xyz/v1/packages/zig/-T uploads the file.build.zig.zon, so there's nothing else to type.?owner=<organization> to the address.Zaryn answers with everything someone needs to use it:
{ "name": "greet", "version": "0.1.0", "hash": "greet-0.1.0-osB6XSsBAACcv0dHgf4SJ_AaruNKCheoTxH_lgjFjt-i", "url": "https://api.zaryn.xyz/v1/packages/zig/greet/greet-0.1.0.tar.gz", "zon_entry": ".greet = .{ .url = \"…\", .hash = \"…\" },"}A published version can't be replaced: for a fix, raise .version and publish again.
In the other project's folder:
zig fetch --save https://api.zaryn.xyz/v1/packages/zig/greet/greet-0.1.0.tar.gzzig fetch --save downloads the package, checks it, and adds it to build.zig.zon with its hash. The package's page on Zaryn shows the same entry, ready to copy, if you'd rather paste it yourself.
Then use it in build.zig:
const greet = b.dependency("greet", .{});exe.root_module.addImport("greet", greet.module("lib"));"lib" is the module name the package's own build.zig gives with b.addModule("lib", …); the package's README should say which names it offers.
Every commit of a repository can be downloaded as a .tar.gz:
https://api.zaryn.xyz/v1/repos/<owner>/<repo>/branches/<branch>/archive/<commit>.tar.gzThe same commit always gives the same bytes, so its hash never changes. The simplest way to get the address and hash is to ask Zaryn:
curl https://api.zaryn.xyz/v1/repos/<owner>/<repo>/branches/main/zig-package/HEADThe answer pins the newest commit (never "HEAD", which moves) and includes a ready zig fetch --save … line and .dependencies entry, plus anything in that commit's build.zig.zon zig would refuse. On the repository's page, a repository with a build.zig.zon also has a zig tab next to the clone commands that shows the same. The repository must be public for zig fetch to download it, since zig can't send a token.
Packages can be made private on their page (Premium). Because zig fetch can't send a token, download a private package with curl, unpack it inside your project, and point to the folder:
curl -LO -H "Authorization: Bearer $ZARYN_TOKEN" \ https://api.zaryn.xyz/v1/packages/zig/greet/greet-0.1.0.tar.gzmkdir -p deps && tar xzf greet-0.1.0.tar.gz -C deps.dependencies = .{ .greet = .{ .path = "deps/greet" },},| You see | What it means | Fix |
|---|---|---|
| "missing top-level 'fingerprint' field; suggested value: 0x…" | build.zig.zon has no fingerprint | add .fingerprint = 0x… with the suggested value |
| "invalid fingerprint … use 0x…" | the fingerprint doesn't belong to this name (often a copied package) | use the value given |
| "'name' must be an enum literal" | .name = "greet" is the old style | write .name = .greet |
| "missing top-level 'paths' field" | zig needs to know which files belong to the package | add .paths = .{ "build.zig", "build.zig.zon", "src" } |
| "there is no build.zig.zon at the top of the archive" | the archive holds a folder of folders, or no manifest | pack the package folder itself |
| "this package name belongs to someone else" | another account published that name | rename .name (and make a new fingerprint) |
zig says hash mismatch | the archive at that address changed since the hash was written | for Zaryn addresses this can't happen; for other sites, see Mirrors |
zig doesn't hash the archive file; it hashes what's inside. It unpacks the archive, keeps only the files under .paths, hashes each file together with its path, and combines those hashes in name order. The result is written as name-version- followed by 44 characters that also encode the fingerprint and the package's size. That's why re-packing the same files with a different tool, or adding a notes file outside .paths, gives the same hash. Zaryn uses the same rules (checked against zig fetch on real packages), so the hash it shows is the hash zig will compute.