How to parse command-line arguments in Zig

A recipe on how to parse command-line arguments in Zig. It covers using std.process.argsWithAllocator with an ArenaAllocator for memory safety.

This recipe was written using Zig version 0.15.2. If this recipe is outdated, please let me know on X (@sepyke) or Bluesky (@pyk.sh).

I’m learning how to build a CLI tool that works like cargo new, and today I figured out how to parse command-line arguments. The standard, cross-platform way to do this in Zig is with std.process.argsWithAllocator.

It’s called WithAllocator because on some platforms (like Windows), Zig needs to allocate memory to store the arguments after parsing them from a raw string. The best practice is to use an ArenaAllocator because you only need the arguments at the start of the program, and an arena can free all the memory at once when you’re done.

You have to remember to call deinit() on the iterator when you’re finished with it, otherwise you’ll have a memory leak. The easiest way to make sure that happens is to use defer.

Here is a simple example:

Zig
const std = @import("std");

pub fn main() !void {
    // 1. Get an allocator. Arena is perfect for this.
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();
    const allocator = arena.allocator();

    // 2. Call argsWithAllocator to get the iterator.
    var args = try std.process.argsWithAllocator(allocator);

    // 3. IMPORTANT: Defer deinit() to free the iterator's internal memory.
    defer args.deinit();

    // 4. Loop through the arguments.
    // The first argument is typically the path to the executable.
    std.debug.print("--- Program Arguments ---\n", .{});
    var i: usize = 0;
    while (args.next()) |arg| {
        // 'arg' is a null-terminated slice: [:0]const u8
        std.debug.print("Arg {d}: {s}\n", .{ i, arg });
        i += 1;
    }
    std.debug.print("-------------------------\n", .{});
}

If you run this code with zig run main.zig -- arg1 "hello world", the output will be:

Plain Text
--- Program Arguments ---
Arg 0: /path/to/your/executable
Arg 1: arg1
Arg 2: hello world
-------------------------