zv is a blazing-fast, cross-platform, simple-to-use compiler toolchain manager for Zig, written in Rust. zv aims to be a fast and dependable manager for Zig and ZLS, both system-wide and project-specific, with either inline syntax zig +<version> or by using a .zigversion file in your project root. A version can be a semver, master, or latest for the latest stable. These values are fetched from the cached Ziglang download index available at Zig official index.
With zv binaries, you can now build with the master branch without changing your default system Zig version:
Caching is built-in, so you never have to wait any longer than strictly necessary.
You can also specify a version number, e.g., zig +0.16.0. With zv, you also have the option of pinning per-project Zig versions using a .zigversion file, which takes the same format as + would for inline Zig commands. You can have a project with these contents:
# file .zigversion
0.16.0
which will always use version 0.16.0 when you run any zig command inside it. How cool is that?
It also doubles as a project template starter, providing multiple variants of a Zig project, from a barebones template with a very trimmed-down build.zig and main.zig file, or the standard Zig project template. Find out more with zv init --help.
zv uses randomized ranked community mirrors for downloads (can be overridden to use ziglang.org with -f), as that's the official recommendation, with minisign and shasum verification done before any toolchain is installed. Future versions should bring in an optimization to rank the mirrors based on speed so that faster mirrors are selected more often without user intervention.
Installation
There are two primary paths: fetch a prebuilt binary or build from source. Either way, finish with zv sync — that's all you need. zv setup is a legacy fallback covered at the end.
Option 1 — Prebuilt binary (Recommended)
Linux/macOS:
|
Windows (PowerShell):
irm https://github.com/weezy20/zv/releases/latest/download/install.ps1 | iex
If you get an execution policy error on Windows:
powershell -ExecutionPolicy Bypass -Command "irm https://github.com/weezy20/zv/releases/latest/download/install.ps1 | iex"
The script downloads the release binary, places it at ~/.local/share/zv/bin/zv, and creates a symlink at ~/.local/bin/zv (Linux/macOS) or installs to %USERPROFILE%\.zv\bin\zv.exe (Windows). Then finish with:
Option 2 — Build from source
# Clone and build
# Sync using the freshly built binary
Or via cargo install:
HomeBrew / NPM / Bun:
# or
zv setup — legacy PATH configuration (last resort)
On Linux, zv setup is a no-op — run zv sync instead.
On macOS (non-XDG layout) or Windows, if zv sync warns that your PATH isn't configured, run zv setup. It will make the following changes to your system:
- Creates a shell environment file at
$ZV_DIR/env - Appends a
source $ZV_DIR/envline to your shell RC file (e.g.~/.bashrc,~/.zshrc,~/.zprofile)
To preview these changes without applying them:
Updating zv
Simple update (Recommended):
This command checks for new releases on GitHub and updates zv in place. It works whether you're running from ZV_DIR/bin/zv or from an external location (like cargo install).
Options:
If you have the repo cloned or are using a cargo-installed binary:
# Build new version and update the binary in ZV_DIR/bin
# Or if you installed from crates.io, install it and sync
# or if you already have ZV_DIR/bin in path
Usage
All zv data follows the XDG Base Directory Specification on Linux/macOS:
Default locations (Linux/macOS):
- Data (binaries, versions):
$HOME/.local/share/zv - Config (
zv.toml):$HOME/.config/zv - Cache (index, mirrors, downloads):
$HOME/.cache/zv - Public bin (symlinks):
$HOME/.local/bin
Default locations (Windows):
- All data:
%USERPROFILE%\.zv
You can override the data directory by setting the ZV_DIR environment variable (falls back to pre-XDG self-contained layout).
Use zv for project creation:
| # Create a zig project with build.zig.zon:
| | # Note: this requires an active zig version >= 0.12.0 where build.zig.zon support was introduced
Note:
zv initwill use thebuild.zigthat's present in templates/build.zig which is checked to work against minimum zig version specified in templates/.zigversion. If you want to use a different zig version, set it as active zig and usezv init -zorzig initdirectly.
Use zv as your Zig compiler toolchain manager:
# Version selection - basic usage
# pass in -f or --force-ziglang to download using `ziglang.org` instead of community mirrors (default & recommended)
| | |
# Per-project Zig config
# Management commands
| | | | |
ZLS (Zig Language Server) provisioning
zv can automatically provision a ZLS build compatible with your active Zig version.
|
You can also provision ZLS inline when installing or switching Zig versions:
minisign verification is done using jedisct1/rust-minisign-verify — a small minisign library in pure Rust.
It also supports NO_COLOR for non-TTY environments.
I hope you enjoy using it! ♥
Customizing ZV behaviour:
Environment Variables for customizing zv
| Variable | Description | Default / Notes |
|---|---|---|
ZV_LOG |
Sets the log level (same as RUST_LOG). If set, logging follows the specified level. |
Inherits RUST_LOG behavior |
ZV_DIR |
Overrides the data directory for zv. When set, all paths (data, config, cache) live under this directory. |
Linux/macOS: $XDG_DATA_HOME/zv (default $HOME/.local/share/zv). Windows: %USERPROFILE%\.zv |
ZV_INDEX_TTL_DAYS |
Number of days between automatic index syncs. | 21 days — Using master or latest in inline mode use a shorter cache duration of just 1 day unlike use which will always fetch master & latest from network, so practically, you never have to worry about setting this variable yourself. |
ZV_MIRRORS_TTL_DAYS |
Number of days before refreshing the mirrors list. Broken mirrors degrade automatically. Use zv sync to force refresh. |
21 days — mirrors and index can be resynced immediately with zv sync. master relies on latest builds & so does latest and some community mirrors may not have it available; zv will retry other mirrors in that case. |
ZV_MAX_RETRIES |
Maximum number of retry attempts for downloads when a download fails. | 3 retries — If a download fails, zv will retry up to this many times before giving up. |
NO_COLOR |
If set, disables color output in all zv commands. | No color output; useful for non-TTY environments or scripts. |
ZV_FETCH_TIMEOUT_SECS |
Request timeout to use for network operations requiring fetching index/mirrors list from ziglang.org. |
Default 4 seconds for most operations. |
Tips:
-
If you prefer some mirrors to others, you can put it as
rank = 1on your preferred mirrors (Default is rank 1 for all mirrors) or lower the rank of mirrors that you don't want.rankis a range from 1..255, lower is better and more preferred when doing random selection. The mirrors file is generated at$XDG_CACHE_HOME/zv/mirrors.toml(default~/.cache/zv/mirrors.toml) -
Currently
zv use masterwill only install the master as present in zig-index. This means that older master installations still remain under the masters folder and can be selected viazv use master@<older master version>which can be obtained viazv ls. Note, installing older master versions like this may work now (zv v0.6.0 onwards):zv i <pre-release version>orzv use <pre-release version>if some mirror has the build, it'll be fetched.
Upgrading from v0.9.x? See docs/migrating-to-xdg.md for breaking changes and migration instructions.