Example of using a library: clap
We are going to use a library to add a very common feature when creating command-line tools: parsing arguments.
At https://zigistry.dev/ You can search for libraries of all kinds. From there, I have chosen one that seemed intuitive for this purpose.
It is called clap: https://github.com/Hejsil/zig-clap.
The description of the library as of May 2026 is the following:
Summary of the clap repository
“A simple and easy to use command line argument parser library for Zig.”
Features
- Short arguments -a
- Chaining -abc where a and b do not take values.
- Multiple specifications are tallied (e.g. -v -v).
- Long arguments --long
- Supports both passing values using spacing and = (-a 100, -a=100)
- Short args also support passing values with no spacing or = (-a100)
- This all works with chaining (-ba 100, -ba=100, -ba100)
- Supports options that can be specified multiple times (-e 1 -e 2 -e 3)
- Print help message from parameter specification.
- Parse help message to parameter specification.
Installation instructions from repository
Developers tend to either use
- The latest tagged release of Zig
- The latest build of Zigs master branch
Depending on which developer you are, you need to run different zig fetch commands:
|
# Version of zig-clap that works with a tagged release of Zig # Replace `<REPLACE ME>` with the version of zig-clap that you want to use # See: https://github.com/Hejsil/zig-clap/releases zig fetch --save https://github.com/Hejsil/zig-clap/archive/refs/tags/<REPLACE ME>.tar.gz # Version of zig-clap that works with latest build of Zigs master branch zig fetch --save git+https://github.com/Hejsil/zig-clap |
Then in your build.zig:
|
const clap = b.dependency("clap", .{}); exe.root_module.addImport("clap", clap.module("clap")); |
Once we have read the library description, we are going to create our program, which we will call argdemo:
mkdir argdemo;
cd argdemo;
zig init --minimal
Zig will create a minimal configuration. Immediately after that, we modify the build.zig.zon and build.zig files.
As we saw in the library README.md, we run:
zig fetch --save=clap https://github.com/Hejsil/zig-clap/archive/refs/heads/master.zip
This command will download the library and modify the build.zig.zon file.
Configuration files and the program
build.zig.zon
|
.{ .name = .argdemo, .version = "0.0.1", .dependencies = .{ .clap = .{ .url = "git+https://github.com/…", .hash = "...", }, }, .minimum_zig_version = "0.16.0", .paths = .{ "build.zig", "build.zig.zon", "src", }, .fingerprint = <here Zig generates a fingerprint>, } |
zig fetch will record the library as a dependency, but we still need to set the .paths for the files.
build.zig
|
const std = @import("std"); pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); const exe = b.addExecutable(.{ .name = "argdemo", .root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, }), }); exe.root_module.addImport("clap", b.dependency("clap", .{ .target = target, .optimize = optimize, }).module("clap")); b.installArtifact(exe); const run_step = b.step("run", "Run the app"); const run_cmd = b.addRunArtifact(exe); if (b.args) |args| { run_cmd.addArgs(args); } run_step.dependOn(&run_cmd.step); run_cmd.step.dependOn(b.getInstallStep()); } |
After modifying these files, we create the program's source code file, src/main.zig:
src/main.zig
|
const std = @import("std"); const print = std.debug.print; const clap = @import("clap"); pub fn main(init: std.process.Init) !void { const io = init.io; const allocator = init.gpa; // Parameter specification: short, long, value type, and help text. // `str` is zig-clap's built-in parser for []const u8. const params = comptime clap.parseParamsComptime( \\-h, --help Display this help and exit. \\-n, --name <str> Your name (required). \\-a, --age <i64> Your age (18..120, default 33). \\ ); var diag = clap.Diagnostic{}; var res = clap.parse(clap.Help, ¶ms, clap.parsers.default, init.minimal.args, .{ .diagnostic = &diag, .allocator = allocator, }) catch |err| { try diag.reportToFile(io, .stderr(), err); return err; }; defer res.deinit(); // --help prints usage and exits. if (res.args.help != 0) { try clap.helpToFile(io, .stdout(), clap.Help, ¶ms, .{}); return; } // --name is required in this demo: bail out if missing. const s_name = res.args.name orelse { print("error: --name is required\n", .{}); std.process.exit(1); }; // --age is optional; apply default and validate the range. const n_age: i64 = res.args.age orelse 33; if (n_age < 18) { print("error: age too low (must be >= 18)\n", .{}); std.process.exit(1); } if (n_age > 120) { print("error: age too high (must be <= 120)\n", .{}); std.process.exit(1); } print("Hello: {s}, your age: {d}\n", .{ s_name, n_age }); } |
Using the library is straightforward if we follow the instructions on the repository page itself. We import the library in the same way we usually do with std.
We copy the code exactly as explained in the repository for basic use of clap:
|
// Parameter specification: short, long, value type, and help text. // `str` is zig-clap's built-in parser for []const u8. const params = comptime clap.parseParamsComptime( \\-h, --help Display this help and exit. \\-n, --name <str> Your name (required). \\-a, --age <i64> Your age (18..120, default 33). \\ ); var diag = clap.Diagnostic{}; var res = clap.parse(clap.Help, ¶ms, clap.parsers.default, init.minimal.args, .{ .diagnostic = &diag, .allocator = allocator, }) catch |err| { try diag.reportToFile(io, .stderr(), err); return err; }; defer res.deinit(); |
When we run the program, we get:
|
$ zig build && zig-out/bin/argdemo --help |
|
-h, --help Print help information -a, --age <usize> Your age as a number. Only accepted between 18 and 120. Default: 33 -n, --name <str> Your name |