# Command-Line Arguments

> Reading argv and the environment through std.process.

```zig
const std = @import("std");
const expect = std.testing.expect;
const expectEqualStrings = std.testing.expectEqualStrings;

test "iterate arguments" {
    const gpa = std.testing.allocator;
    // A real program iterates `init.minimal.args` (see the page). Here we
    // parse a fixed command line with the same iterator, so the test stays
    // deterministic in the browser sandbox, which has no argv of its own.
    var it = try std.process.Args.IteratorGeneral(.{}).init(gpa, "app --name zig -v");
    defer it.deinit();

    try expectEqualStrings("app", it.next().?); // argv[0] is the program name
    try expectEqualStrings("--name", it.next().?);
    try expectEqualStrings("zig", it.next().?);
    try expectEqualStrings("-v", it.next().?);
    try expect(it.next() == null); // exhausted
}

test "a minimal flag parser" {
    const gpa = std.testing.allocator;
    var it = try std.process.Args.IteratorGeneral(.{}).init(gpa, "app --verbose --out result.txt");
    defer it.deinit();

    _ = it.next(); // skip argv[0]
    var verbose = false;
    var out: []const u8 = "a.out";
    while (it.next()) |arg| {
        if (std.mem.eql(u8, arg, "--verbose")) {
            verbose = true;
        } else if (std.mem.eql(u8, arg, "--out")) {
            // A flag that takes a value pulls the next token itself.
            out = it.next() orelse return error.MissingValue;
        }
    }
    try expect(verbose);
    try expectEqualStrings("result.txt", out);
}

test "environment variables" {
    const gpa = std.testing.allocator;
    // `init.environ_map` is exactly this type, filled from the real
    // environment. Building one by hand keeps the test self-contained.
    var env = std.process.Environ.Map.init(gpa);
    defer env.deinit();
    try env.put("EDITOR", "vim");

    try expectEqualStrings("vim", env.get("EDITOR").?);
    try expect(env.get("MISSING") == null);
    try expect(env.contains("EDITOR"));
}
```

*Runnable: compiled to WebAssembly and executed by CI against Zig master. (`03-standard-library.command-line`)*

## Where the real arguments come from

Your `main` receives a `std.process.Init` (the same value that carries `io`,
`gpa`, and the arena). Its `minimal.args` field is a `std.process.Args`, and
`iterate` turns it into an iterator whose `next` yields each argument as a
`[:0]const u8`:

```zig
pub fn main(init: std.process.Init) !void {
    var it = init.minimal.args.iterate();
    defer it.deinit();

    _ = it.next(); // argv[0]: the program's own path
    while (it.next()) |arg| {
        // ... handle arg ...
    }
}
```

The snippet above uses `Args.IteratorGeneral`, which parses a fixed string
with the identical `next` shape. That is what lets it run in your browser: the
WASI sandbox has no argv of its own, so a real iterator would come back empty.
The parsing logic you write is the same either way.

## Parsing is yours to write

There is no `argparse` in the standard library. For a small tool the loop in
the snippet, match a flag, and pull the next token when it takes a value, is
usually all you need. The first argument is always the program path, so skip it
before parsing. Reach for a package (see the Build System section) only when
you want subcommands, help text, and typed conversion.

## Environment variables

`init.environ_map` is a `std.process.Environ.Map` built from the real
environment. It behaves like the other maps in this section: `get` returns an
optional, `contains` a bool. Because absence is normal for an environment
variable, `get` returning `null` is the case you handle, not an error.

## Spawning other programs

The reverse direction, running a subprocess, is `std.process.Child`. Like
everything that touches the outside world it takes an `Io`, and it lets you
wire up the child's stdin, stdout, and stderr or capture its output. It needs a
real OS process, so it is not something the browser sandbox can demonstrate.
