Installation, Tooling and First Program
2.1 Installing Zig
Download a release tarball/zip from ziglang.org/download. Extract it and add it to your PATH. It's a single self-contained directory with no dependencies.
Package managers: brew install zig, winget install zig.zig, scoop install zig, snap, distro packages (may lag behind).
Version managers: zigup, zvm, anyzig (picks the version from build.zig.zon's minimum_zig_version).
Verify: zig version, zig env.
2.2 The zig Command
zig run file.zig Compile and run zig build-exe file.zig Build an executable zig build-lib / zig build-obj Build a library or object file zig test file.zig Run tests in a file Run the build script (build.zig) zig build run / zig build test Common build steps
Create a new project (build.zig, build.zig.zon, src/) zig fetch --save <url> Add a dependency zig cc / zig c++ Drop-in C/C++ compiler (Clang-based) zig translate-c header.h Translate C code to Zig zig ast-check file.zig Quick syntax and semantic check List supported targets
Open the standard library docs in a browser Print environment info
zig objcopy, zig ar, zig ranlib, zig dlltool, zig lib
2.3 Editor Setup
ZLS (Zig Language Server): install the build that matches your Zig version. It provides completion, go-to-definition, diagnostics, and inlay hints.
VS Code: the official "Zig Language" extension (it can manage Zig and ZLS installs). Also Neovim (nvim-lspconfig), Helix (built-in), Emacs (zig-mode), Sublime, JetBrains (ZigBrains).
Enable format-on-save with zig fmt. Turn on zls build-on-save for full semantic errors.
2.4 Hello, World
std.debug.print writes to stderr, is unbuffered, and can't fail (errors are ignored). It's perfect for learning and debugging.
The .{...} syntax is an anonymous struct/tuple literal holding the format arguments.
// hello.zig
const std = @import("std");
pub fn main() void {
std.debug.print("Hello, {s}!\n", .{"World"});
}zig run hello.zig
zig build-exe hello.zig && ./hello
zig build-exe -O ReleaseSmall hello.zig # optimized, small binary2.5 Writing to stdout (Zig 0.15 I/O)
!void means main can return an error (Zig prints it with an error return trace).
const std = @import("std");
pub fn main() !void {
var buf: [1024]u8 = undefined;
var stdout_writer = std.fs.File.stdout().writer(&buf); // buffered writer
const stdout = &stdout_writer.interface; // *std.Io.Writer
try stdout.print("Hello, {s}! {d}\n", .{ "stdout", 42 });
try stdout.flush(); // don't forget to flush!
}2.6 Creating a Project
Output goes to zig-out/bin. The cache lives in .zig-cache/ (local) and a global cache.
mkdir myapp && cd myapp
zig init # creates build.zig, build.zig.zon, src/main.zig, src/root.zig
zig build run # build + run
zig build test # run tests
zig build -Doptimize=ReleaseFast