# zigmod and the case for a package manager outside the Zig build

> zigmod is a third-party package manager for Zig that keeps a zig.mod manifest and a zigmod.lock file. It is written in Zig, released as sequential r-tags, and its documentation lives in docs/ rather than in the README.

**nektro/zigmod** — 📦 A package manager for the Zig programming language.

- Repository: https://github.com/nektro/zigmod
- Stars: 949 · Forks: 38
- Language: Zig
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/nektro-zigmod

## A manifest and a lock file, kept outside the build script

zigmod is a package manager for the Zig programming language, and it is not part of the language distribution. The repository has no homepage of its own beyond a documentation site at nektro.github.io/zigmod, and the README points to a docs directory for the real reference.

The dependency model is visible in the top level of the repository. There is a zig.mod file, which is the manifest, a zigmod.lock file, which records the resolved state, and a deps.zig file. Beside them sit build.zig and build.zig.zon, the build files for zigmod itself, and a src directory holding the implementation. The important structural point is that the manifest and the lock file are separate from the build script, so a Zig project's dependency list is expressed as data rather than as build code.

The lock file is what makes the arrangement defensible. A manifest says what you want, a lock file says what you got, and the two together let a project pin the exact set of packages and versions it resolved to. For a language whose ecosystem is young, that kind of pinning is the difference between a build that reproduces and one that drifts.

The primary language is Zig, the licence field on the repository says MIT, and the repository is not archived. The last push was on 2026-10-18.

## Building the tool itself with zig build -j1

The README's build instructions are three lines, and the single job flag is the detail worth noticing.

```bash
$ git clone https://github.com/nektro/zigmod
$ cd zigmod
$ zig build -j1
```

The -j1 flag restricts the build to a single job. The README does not explain why, and it is not a typo you should drop, since the flag is what the project asks for. In a repository with a deps.zig file and a set of shell scripts for building every supported Zig version, a parallel build is the kind of thing that surfaces ordering problems in a build graph, and serialising it is the conservative choice for a tool whose own releases are cut from this code.

The other build path in the repository is the shell script family. build_all_zig.sh sits next to build_release.sh, make_release.sh, release_num.sh, changelog.sh and update_explain.sh, and there is a shell.nix file for a Nix environment. Two more scripts, test_repo.sh and test_repo_all.sh, exist for exercising the tool against repositories.

The distribution route is the same as most Zig tooling: binaries come from the GitHub releases page, and the README links that page under Download. There is no separate install channel documented, and no package manager recipe for the tool itself.

## Releases are numbered r104, r105, r106

The release naming is unusual and immediately legible once you know it. The recent tags are r106 on 2026-10-18, r105 on 2026-09-04 and r104 on 2026-06-10, and there is no semantic version in the tag itself.

That scheme has a practical implication. A tool whose releases are sequential revision numbers has no built-in statement of compatibility, so the relationship between a zigmod build and the Zig version it was built for has to be established from elsewhere. In this repository, the answer lives in the README's Build With section, which names Zig 0.17.0, and in the zig.mod and zigmod.lock files that the README points to for build details.

There is a second version signal, and the two do not agree. The README carries a badge for Zig 0.14, while the Build With line names Zig 0.17.0. One of them is stale. A reader cannot tell from the README which is current, and the release scripts in the repository (release_num.sh, make_release.sh, build_release.sh) suggest the build matrix is managed by script rather than by hand, so the badge is probably not updated by that process.

Practically, treat the release date as the thing to correlate against your own Zig version, and expect to read zig.mod and zigmod.lock to see what a given release was built with. The gaps between the three tags are uneven, and nothing in the README states a support policy for old revisions.

## Docs live in docs/, including a tutorial-style getting started guide

The README is short, and that is by design rather than an oversight. It gives the description, the download link, the build commands and then hands off. The real documentation is in the docs directory, and there is also a published site at nektro.github.io/zigmod.

One entry in the README is worth calling out because documentation shape tells you what the project considers important. The README says there is a tutorial-style getting started guide that goes over various use cases that Zigmod provides and caters to, and points to docs/tutorial.md. A tutorial that is framed around use cases rather than command reference suggests the project expects to be adopted by people who have a goal, such as adding a dependency to a build, rather than by people who want to read a specification.

The docs directory is one of the larger parts of the repository, and there is a __snapshots__ directory at the top level next to src, which is the shape of a project that tests its output as text.

What the README does not contain is worth noting too. There is no documented configuration format, no list of registry sources, no offline or vendoring mode, and no migration notes. If you are evaluating the tool, docs/tutorial.md and the docs site are where that information has to come from, and the README alone will not tell you how dependencies are fetched or how a version is selected.

## test_repo.sh, snapshots and licenses.txt: how correctness is checked

The repository carries its own test scaffolding, and it points at something a package manager has to get right before anything else: a project that declares dependencies and then gets the right code.

test_repo.sh and test_repo_all.sh are the two entry points, and the split between them suggests one script exercises a single repository and the other sweeps a set of them. The __snapshots__ directory alongside them is the giveaway: expected outputs are stored as text fixtures and compared. For a dependency resolver, snapshot tests are the sensible approach, because the interesting question is rarely whether an error message is pretty, it is whether the resolved set and the lock file content are exactly the same as last time.

The licenses.txt file at the top level is a related concern handled with the same seriousness. A tool that pulls third-party code into your build has to record what licences those dependencies carry, and keeping that list in the repository is how a project makes that auditable. The MIT licence applies to zigmod itself.

The limitation of this approach is that a package manager's hard cases are the ones outside a test corpus. A registry that is unreachable, a package whose tag has moved, a transitive dependency that has changed its own dependencies: these are the failures that decide whether a resolver is usable in a team, and a snapshot suite does not cover them unless the corpus contains such cases. The README says nothing about how offline builds, registry outages or moving tags are handled.

## Against vendoring dependencies by hand

The realistic alternative is not another package manager but no package manager. In a Zig project you can pin dependencies directly in your own repository, as a submodule or as copied source, and let build.zig refer to those local paths. The difference in approach is straightforward.

Vendoring by hand puts the dependency source in the repository you own. Fetching happens at a known time, usually by a person, and the build afterwards is a local compile. Nothing is resolved during the build, so a registry being slow or unreachable cannot break a release build, and a reviewer can see exactly which version of a dependency the project uses by looking at the tree. The cost is duplication: every project that wants the same dependency carries its own copy, and updating means doing it in every repository.

A registry-based approach like zigmod reverses that trade. The manifest names a dependency and a version, the lock file records the resolved result, and the fetch happens as part of the normal build flow. Duplication disappears, updates become a one-line change plus a lock file refresh, and several projects can share one resolved set.

The deciding factor is where your pain is. If the dependency count is small and stable, hand-pinning wins on build reliability and needs no extra tool. If you have several dependencies, or several people, or a CI pipeline that must reproduce last week's build exactly, then the manifest and lock file earn their keep, and the cost is that your build now depends on something you do not control.

## Conclusion

zigmod suits Zig developers who want a registry style manifest and lock file outside the language's own build files, and who want a package manager that is itself written in Zig, so its source is readable to them. It does not suit a project that prefers to pin dependencies directly in its own repository, and it does not suit a team that needs a stable toolchain contract, because the releases are sequential r-tags and the README's version badge and its build requirement name different Zig versions. Before adopting it, read docs/tutorial.md to see whether the workflow matches yours, run the repository's own test_repo.sh against a scratch project to check the resolution behaves the way your build expects, and confirm the Zig version you compile it with matches the one your build.zig requires.

## FAQ

### How do I build zigmod from source?

Clone the repository, change into the directory and run `zig build -j1`. The single job flag is what the README specifies. Prebuilt binaries are published on the GitHub releases page.

### Which Zig version does zigmod use?

The README's Build With section names Zig 0.17.0, while the badge in the README shows Zig 0.14, so the two signals disagree. The `zig.mod` and `zigmod.lock` files are the reference the README points to for build details.

### Where are zigmod's dependencies declared?

In a `zig.mod` manifest with a `zigmod.lock` file recording the resolved state, plus a `deps.zig` file, all at the top level of a project, separate from `build.zig` and `build.zig.zon`.

### How are zigmod releases versioned?

With sequential revision tags rather than semantic versions. The recent releases are r106 on 2026-10-18, r105 on 2026-09-04 and r104 on 2026-06-10.

### How do I get started with zigmod?

The README points to a tutorial-style getting started guide at `docs/tutorial.md` that covers the use cases zigmod provides, and to the documentation site at nektro.github.io/zigmod. The README itself only covers the build.

## Sources

- [Issues](https://github.com/nektro/zigmod/issues)
- [License: MIT](https://github.com/nektro/zigmod/blob/master/LICENSE)
- [nektro/zigmod on GitHub](https://github.com/nektro/zigmod)
- [README](https://github.com/nektro/zigmod/blob/master/README.md)
- [Releases](https://github.com/nektro/zigmod/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/nektro-zigmod
