Examples ​
This page provides comprehensive examples demonstrating args.zig features.
Basic Example ​
A simple CLI with flags, options, and positional arguments:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parser = try args.ArgumentParser.init(allocator, .{
.name = "greet",
.version = "1.0.0",
.description = "A friendly greeting application",
});
defer parser.deinit();
// Boolean flag
try parser.addFlag("verbose", .{
.short = 'v',
.help = "Enable verbose output",
});
// String option with default
try parser.addOption("name", .{
.short = 'n',
.help = "Name to greet",
.default = "World",
});
// Required positional argument
try parser.addPositional("message", .{
.help = "Greeting message",
.required = true,
});
var result = try parser.parseProcess(init);
defer result.deinit();
const verbose = result.getBool("verbose") orelse false;
const name = result.getString("name") orelse "World";
const message = result.getString("message").?;
if (verbose) {
std.debug.print("[VERBOSE] Preparing greeting...\n", .{});
}
std.debug.print("{s}, {s}!\n", .{ message, name });
}Usage:
greet "Hello" # Output: Hello, World!
greet -n Alice "Hi" # Output: Hi, Alice!
greet -v --name Bob "Hey" # [VERBOSE] Preparing... / Hey, Bob!Subcommands Example ​
Git-style subcommands with their own arguments:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parser = try args.ArgumentParser.init(allocator, .{
.name = "mycli",
.version = "2.0.0",
.description = "A CLI with subcommands",
});
defer parser.deinit();
// Global flag
try parser.addFlag("verbose", .{ .short = 'v' });
// Add 'init' subcommand
try parser.addSubcommand(.{
.name = "init",
.help = "Initialize a new project",
.aliases = &[_][]const u8{"i"},
.args = &[_]args.ArgSpec{
.{ .name = "name", .positional = true, .required = true, .help = "Project name" },
.{ .name = "template", .short = 't', .long = "template", .default = "basic" },
},
});
// Add 'build' subcommand
try parser.addSubcommand(.{
.name = "build",
.help = "Build the project",
.aliases = &[_][]const u8{"b"},
.args = &[_]args.ArgSpec{
.{ .name = "release", .short = 'r', .long = "release", .action = .store_true },
.{ .name = "target", .long = "target", .default = "native" },
},
});
var result = try parser.parseProcess(init);
defer result.deinit();
const verbose = result.getBool("verbose") orelse false;
if (result.subcommand) |cmd| {
const sub = result.subcommand_args.?;
if (std.mem.eql(u8, cmd, "init")) {
const name = sub.getString("name").?;
const template = sub.getString("template") orelse "basic";
std.debug.print("Initializing '{s}' with template '{s}'\n", .{ name, template });
} else if (std.mem.eql(u8, cmd, "build")) {
const release = sub.getBool("release") orelse false;
const target = sub.getString("target") orelse "native";
const mode = if (release) "release" else "debug";
std.debug.print("Building in {s} mode for {s}\n", .{ mode, target });
}
if (verbose) std.debug.print("(verbose mode)\n", .{});
} else {
try parser.printHelp();
}
}Usage:
mycli init myproject # Initialize 'myproject' with template 'basic'
mycli i myapp -t advanced # Initialize 'myapp' with template 'advanced'
mycli build --release # Building in release mode for native
mycli -v build --target aarch64 # Building in debug mode for aarch64 (verbose mode)Environment Variables Example ​
Using environment variables as fallback values:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parser = try args.ArgumentParser.init(allocator, .{
.name = "server",
.description = "A server with environment variable configuration",
});
defer parser.deinit();
// Options with environment variable fallback
try parser.addOption("host", .{
.short = 'H',
.help = "Server hostname",
.env_var = "SERVER_HOST",
.default = "0.0.0.0",
});
try parser.addOption("port", .{
.short = 'p',
.help = "Server port",
.value_type = .int,
.env_var = "SERVER_PORT",
.default = "8080",
});
try parser.addOption("secret", .{
.help = "Secret key (required)",
.env_var = "SERVER_SECRET",
.required = true,
});
var result = try parser.parseProcess(init);
defer result.deinit();
const host = result.getString("host").?;
const port = result.getInt("port").?;
const secret = result.getString("secret").?;
std.debug.print("Starting server on {s}:{d}\n", .{ host, port });
std.debug.print("Secret: {s}...\n", .{secret[0..@min(4, secret.len)]});
}Usage:
# Using environment variables
export SERVER_SECRET="my-secret-key"
export SERVER_PORT="3000"
server --host 127.0.0.1
# Using command line (overrides env vars)
server --secret "cli-secret" --port 9000Configuration Modes Example ​
examples/config_modes.zig demonstrates non-breaking parser behavior flags:
case_sensitive = falsefor case-insensitive long optionsallow_short_clusters = falseto treat-abcas a positional valueallow_interspersed = falseto stop option parsing after first positionalparsing_mode = .permissiveto collect unknown options inremaining
Run it with:
zig build run-config_modesNegated Flags Example ​
examples/negated_flags.zig demonstrates long-flag negation via --no-<name>:
--no-cachetogglescachetofalsefor astore_trueflag--no-colortogglescolortotruefor astore_falseflag
Run it with:
zig build run-negated_flagsPositional Validation Example ​
examples/positional_validation.zig demonstrates:
- Positional
choicesvalidation - Explicit inverse flag helper
addFalseFlag - Non-breaking strict parse behavior with clear constraints
Run it with:
zig build run-positional_validationSelect/All Example ​
examples/select_all.zig demonstrates CMD-style targeting helpers:
addSelectOptionfor--select <value>addAllFlagfor--alladdSelectOrAllfor one-call mutually exclusive setupparseCsvListfor parsing comma-separated selection values
Run it with:
zig build run-select_allQuestion Flow Example ​
examples/question_flow.zig demonstrates a production-ready interactive flow:
- Use parsed
--select/--allif present - Prompt for a choice when arguments are missing
- Validate answers with retries, prefix matching, and suggestions
Run it with:
zig build run-question_flowInclude/Exclude Example ​
examples/include_exclude.zig demonstrates reusable filter helpers:
addIncludeExcludefor CLI schema setupresolveIncludeExcludefor parsed CSV list resolution
Run it with:
zig build run-include_excludeInclude/Exclude Strict Example ​
examples/include_exclude_strict.zig demonstrates strict filter workflows:
- Choice normalization (
gr=>groupswhen unique) - Duplicate suppression for repeated values
- Optional
allkeyword handling with exclusions - Conflict detection between include and exclude values
Run it with:
zig build run-include_exclude_strictFile Support Example ​
examples/file_support.zig demonstrates path/file/directory helpers:
addPathOptionfor generic pathsaddFileOptionWithExtensionsfor reusable extension validationaddDirectoryOptionfor directory-oriented options
Run it with:
zig build run-file_supportData Input Validation Example ​
examples/data_input_validation.zig demonstrates typed input validator helpers:
addEmailOptionaddUrlOptionaddIpv4OptionaddIpOptionaddIpv6OptionaddHostNameOptionaddPortOptionaddEndpointOptionaddKeyValueOptionaddUuidOptionaddIsoDateOptionandaddIsoDateTimeOptionaddYearOptionandaddTimeOptionaddAbsolutePathOptionaddJsonOption- Numeric range validation via
Validators.intRange(...)
This example also shows how to read validated values after parse:
- Use
getString("...")for helper-backed string values - Use
getInt("retries")when the option is configured with.value_type = .int - Use
getKeyValue("label")for options configured asKEY=VALUE
Run it with:
zig build run-data_input_validationTry a direct invocation shape:
zig build run-data_input_validation -- \
--email ops@example.com \
--endpoint https://api.example.com/v1/tasks \
--host-v6 2001:db8::1 \
--service api.example.com:443 \
--retries 4Network Endpoints Example ​
examples/network_endpoints.zig demonstrates network-centric typed helpers:
addIpv4Optionfor IPv4 addressesaddIpOptionfor a single IPv4-or-IPv6 inputaddIpv6Optionfor IPv6 literalsaddEndpointOptionforhost:portand[ipv6]:portaddPortOptionfor explicit port validation- Numeric retries via
.value_type = .int+Validators.intRange(...)
Run it with:
zig build run-network_endpointsError Handling Example ​
examples/error_handling.zig demonstrates practical parse error handling:
- Duplicate singleton options (
DuplicateArgument) - Validator failures (
CustomValidationFailed) - Unknown option guidance and suggestion behavior
- Option-level custom hints (
suggestion_hint) and custom messages (custom_error_message)
Run it with:
zig build run-error_handlingSubcommand Suggestions Example ​
examples/subcommand_suggestions.zig demonstrates built-in closest-match behavior for unknown subcommands and custom unknown-subcommand hints.
Run it with:
zig build run-subcommand_suggestionsDecryption Options Example ​
examples/decryption_options.zig demonstrates automatic Base64 decoding/decryption behavior for options:
addDecryptionOption("secret", .{})for standard Base64 inputaddDecryptionOption("session", .{ .url_safe = true })for URL-safe Base64 input
Run it with:
zig build run-decryption_optionsCounters and Choices Example ​
Using counters for verbosity and choices for validation:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parser = try args.ArgumentParser.init(allocator, .{
.name = "logger",
.description = "A logging utility with verbosity levels",
});
defer parser.deinit();
// Counter: -v, -vv, -vvv for increasing verbosity
try parser.addCounter("verbose", .{
.short = 'v',
.help = "Increase verbosity (can be repeated)",
});
// Choices: restricted set of valid values
try parser.addOption("level", .{
.short = 'l',
.help = "Log level",
.choices = &[_][]const u8{ "debug", "info", "warn", "error" },
.default = "info",
});
try parser.addOption("format", .{
.short = 'f',
.help = "Output format",
.choices = &[_][]const u8{ "json", "text", "csv" },
.default = "text",
});
var result = try parser.parseProcess(init);
defer result.deinit();
const verbose_val = result.get("verbose");
const verbosity: u32 = if (verbose_val) |v| v.counter else 0;
const level = result.getString("level") orelse "info";
const format = result.getString("format") orelse "text";
std.debug.print("Verbosity level: {d}\n", .{verbosity});
std.debug.print("Log level: {s}\n", .{level});
std.debug.print("Output format: {s}\n", .{format});
if (verbosity >= 1) std.debug.print(" [v] Basic verbose info\n", .{});
if (verbosity >= 2) std.debug.print(" [vv] Detailed verbose info\n", .{});
if (verbosity >= 3) std.debug.print(" [vvv] Maximum verbosity\n", .{});
}Usage:
logger # Verbosity: 0, level: info, format: text
logger -v # Verbosity: 1
logger -vv # Verbosity: 2
logger -vvv -l debug # Verbosity: 3, level: debug
logger --level error # level: error
logger --level warn # level: warn
logger -f json # format: jsonSoft Validation (Expect) Example ​
Using .expect to warn on unexpected values instead of erroring:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parser = try args.ArgumentParser.init(allocator, .{
.name = "expect-demo",
.description = "Demonstrates 'expect' validation",
});
defer parser.deinit();
// 'expect' suggests values. Warns on mismatch by default.
try parser.addOption("env", .{
.short = 'e',
.expect = &[_][]const u8{ "dev", "prod", "staging" },
.help = "Target environment (expected: dev, prod, staging)",
});
try parser.addOption("output", .{
.short = 'o',
.choices = &[_][]const u8{ "json", "text" }, // Strict validation
.help = "Output format (strict: json, text)",
});
var result = try parser.parseProcess(init);
defer result.deinit();
const env = result.getString("env") orelse "default";
const output = result.getString("output") orelse "text";
std.debug.print("Environment: {s}\n", .{env});
std.debug.print("Output: {s}\n", .{output});
}Usage:
# Valid input
expect-demo -e dev -o json
# Invalid 'expect' value (Warnings)
expect-demo -e unknown
# Output:
# Warning: Value 'unknown' is not in expected list for argument 'env'...
# Environment: unknownDeclarative Structs Example ​
Parsing arguments directly into a Zig struct:
const std = @import("std");
const args = @import("args");
const Config = struct {
verbose: bool,
dry_run: bool,
output: ?[]const u8,
count: i32,
};
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parsed = try args.parseInto(allocator, Config, .{
.name = "struct-demo",
}, null);
defer parsed.deinit();
const cfg = parsed.options;
std.debug.print("Verbose: {}\n", .{cfg.verbose});
std.debug.print("Count: {d}\n", .{cfg.count});
}Usage:
struct-demo --count 10 --verboseShell Completions Example ​
Generating shell completion scripts:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parser = try args.ArgumentParser.init(allocator, .{
.name = "myapp",
.version = "1.0.0",
});
defer parser.deinit();
try parser.addFlag("verbose", .{ .short = 'v' });
try parser.addOption("output", .{ .short = 'o' });
try parser.addSubcommand(.{
.name = "completion",
.help = "Generate shell completions",
.args = &[_]args.ArgSpec{
.{ .name = "shell", .positional = true, .required = true },
},
});
var result = try parser.parseProcess(init);
defer result.deinit();
if (result.subcommand) |cmd| {
if (std.mem.eql(u8, cmd, "completion")) {
const shell_str = result.subcommand_args.?.getString("shell").?;
if (args.Shell.fromString(shell_str)) |shell| {
const script = try parser.generateCompletion(shell);
defer allocator.free(script);
const stdout = std.io.getStdOut().writer();
try stdout.writeAll(script);
} else {
std.debug.print("Unknown shell: {s}\n", .{shell_str});
std.debug.print("Supported: bash, zsh, fish, powershell\n", .{});
}
}
}
}Usage:
# Generate and install Bash completions
myapp completion bash > ~/.local/share/bash-completion/completions/myapp
# Generate and install Zsh completions
myapp completion zsh > ~/.zfunc/_myapp
# Generate and install Fish completions
myapp completion fish > ~/.config/fish/completions/myapp.fishDisabling Update Checker ​
For production or CI/CD environments:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
// Method 1: Global disable
args.disableUpdateCheck();
// Method 2: Use minimal config
var parser = try args.ArgumentParser.init(allocator, .{
.name = "production-app",
.config = args.Config.minimal(),
});
defer parser.deinit();
// Your argument definitions...
}Typed Numeric Options Example ​
Using addIntOption, addFloatOption, and addUintOption helpers:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parser = try args.ArgumentParser.init(allocator, .{
.name = "numeric-demo",
.version = "1.0.0",
.description = "Demonstrates typed integer and float options",
});
defer parser.deinit();
try parser.addIntOption("count", .{
.short = 'n', .help = "Number of items", .default = "10",
});
try parser.addIntOption("retries", .{
.short = 'r', .help = "Retry count (0–10)", .default = "3",
.min = 0, .max = 10,
});
try parser.addUintOption("threads", .{
.short = 't', .help = "Worker thread count", .default = "4",
});
try parser.addFloatOption("threshold", .{
.short = 'h', .help = "Confidence threshold (0.0–1.0)", .default = "0.75",
.min = 0.0, .max = 1.0,
});
var result = try parser.parseProcess(init);
defer result.deinit();
std.debug.print("count = {d}\n", .{result.get("count").?.asInt().?});
std.debug.print("retries = {d} (range 0–10)\n", .{result.get("retries").?.asInt().?});
std.debug.print("threads = {d}\n", .{result.get("threads").?.asUint().?});
std.debug.print("threshold = {d:.2} (range 0.0–1.0)\n", .{result.get("threshold").?.asFloat().?});
}Usage:
numeric-demo --count 25 --retries 5 --threads 8 --threshold 0.95Bool Options Example ​
Case-insensitive boolean option parsing — TRUE/True/true, FALSE/False/false, YES/yes, NO/no, ON/on, OFF/off and single-letter variants are all accepted:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parser = try args.ArgumentParser.init(allocator, .{
.name = "bool-demo",
.version = "1.0.0",
.description = "Demonstrates case-insensitive boolean option parsing",
});
defer parser.deinit();
try parser.addOption("enabled", .{
.short = 'e',
.help = "Enable feature (accepts: true/TRUE/True/yes/YES/on/ON/1)",
.value_type = .bool,
.default = "true",
});
try parser.addOption("debug", .{
.short = 'd',
.help = "Debug mode (accepts: false/FALSE/False/no/NO/off/OFF/0)",
.value_type = .bool,
.default = "false",
});
try parser.addFlag("flag", .{
.short = 'f',
.help = "Simple flag (no value needed)",
});
var result = try parser.parseProcess(init);
defer result.deinit();
const enabled = result.getBool("enabled") orelse true;
const debug = result.getBool("debug") orelse false;
const flag = result.getBool("flag") orelse false;
std.debug.print("enabled = {} (type: bool)\n", .{enabled});
std.debug.print("debug = {} (type: bool)\n", .{debug});
std.debug.print("flag = {} (type: bool, store_true)\n", .{flag});
}Usage:
# All of these work the same way:
zig build run-bool_options -- --enabled TRUE --debug false
zig build run-bool_options -- -e True -d No
zig build run-bool_options -- --enabled yes --debug OFF
zig build run-bool_options -- --enabled 1 --debug 0
zig build run-bool_options -- -f # flag is store_true — no value neededHex Decode Option Example ​
Passing binary data as hex strings with addHexOption:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parser = try args.ArgumentParser.init(allocator, .{
.name = "hex-demo",
.version = "1.0.0",
.description = "Demonstrates hex-decode option",
});
defer parser.deinit();
try parser.addHexOption("data", .{
.short = 'd', .help = "Hex-encoded binary data", .metavar = "HEX",
});
try parser.addHexOption("key", .{
.short = 'k', .help = "Hex-encoded key material", .required = true,
});
var result = try parser.parseProcess(init);
defer result.deinit();
if (result.get("data")) |d| {
std.debug.print("--data decoded: {any} ({d} bytes)\n", .{ d.asString().?, (d.asString() orelse "").len });
}
if (result.get("key")) |k| {
std.debug.print("--key decoded: {any} ({d} bytes)\n", .{ k.asString().?, (k.asString() orelse "").len });
}
}Usage:
hex-demo --data deadbeef --key 0123456789abcdefLog Level Example ​
Using addLogLevel for --verbose / --quiet pairs:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parser = try args.ArgumentParser.init(allocator, .{
.name = "log-demo",
.version = "1.0.0",
.description = "Demonstrates log-level helpers",
});
defer parser.deinit();
try parser.addLogLevel(
.{ .name = "verbose", .short = 'v', .dest = "verbosity" },
.{ .name = "quiet", .short = 'q', .dest = "verbosity" },
);
try parser.addFlag("dry-run", .{ .help = "Simulate execution" });
var result = try parser.parseProcess(init);
defer result.deinit();
const verbosity = result.get("verbosity").?.asInt().? orelse 0;
std.debug.print("Verbosity level: {d}\n", .{verbosity});
if (verbosity >= 1) std.debug.print(" verbose mode\n", .{});
if (verbosity >= 2) std.debug.print(" debug output\n", .{});
}Usage:
log-demo -vvv # Verbosity level: 3
log-demo -v -q # Verbosity level: 0
log-demo -v -v -qq # Verbosity level: 0Advanced parseInto Example ​
Parsing into a struct with enums, u32, f64, and optional fields. Enum variants become --flag choices automatically:
const std = @import("std");
const args = @import("args");
const LogLevel = enum { debug, info, warn, err };
const OutputFormat = enum { json, yaml, csv, table };
const CliConfig = struct {
verbose: bool = false,
log_level: LogLevel = .info,
format: OutputFormat = .table,
port: u32 = 8080,
timeout: f64 = 30.0,
host: []const u8 = "localhost",
config_file: ?[]const u8 = null,
};
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var result = try args.parseInto(allocator, CliConfig, .{
.name = "struct-demo",
.version = "1.0.0",
.description = "parseInto with enums, u32, f64, and more",
}, null, init);
defer result.deinit();
const cfg = result.options;
std.debug.print("Configuration:\n", .{});
std.debug.print(" verbose = {}\n", .{cfg.verbose});
std.debug.print(" log-level = {s}\n", .{@tagName(cfg.log_level)});
std.debug.print(" format = {s}\n", .{@tagName(cfg.format)});
std.debug.print(" port = {d}\n", .{cfg.port});
std.debug.print(" timeout = {d:.1}s\n", .{cfg.timeout});
std.debug.print(" host = {s}\n", .{cfg.host});
if (cfg.config_file) |f| {
std.debug.print(" config-file = {s}\n", .{f});
}
}Usage:
struct-demo --verbose --log-level debug --format json --port 3000 --timeout 60.0 --host 0.0.0.0Environment Variable Configuration Example ​
Using env_var, env_prefix, and fromEnvOrDefault:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parser = try args.ArgumentParser.init(allocator, .{
.name = "env-demo",
.version = "1.0.0",
.description = "Demonstrates environment variable configuration",
.config = args.Config{ .env_prefix = "MYAPP" },
});
defer parser.deinit();
try parser.addOption("db-host", .{
.short = 'h', .help = "Database host", .default = "localhost",
.env_var = "MYAPP_DB_HOST",
});
try parser.addIntOption("db-port", .{
.short = 'p', .help = "Database port", .default = "5432",
.env_var = "MYAPP_DB_PORT",
});
try parser.addOption("db-name", .{
.short = 'd', .help = "Database name", .default = "mydb",
.env_var = "MYAPP_DB_NAME",
});
try parser.fromEnvOrDefault("api-key", "MYAPP_API_KEY", "no-key-set", .{
.help = "API key (from MYAPP_API_KEY env var)",
});
var result = try parser.parseProcess(init);
defer result.deinit();
std.debug.print("DB Host: {s}\n", .{result.get("db-host").?.asString().?});
std.debug.print("DB Port: {d}\n", .{result.get("db-port").?.asInt().?});
std.debug.print("DB Name: {s}\n", .{result.get("db-name").?.asString().?});
std.debug.print("API Key: {s}\n", .{result.get("api-key").?.asString().?});
}Usage:
# Values from command-line:
env-demo -h prod.example.com -p 5432 -d analytics
# Values from environment variables:
export MYAPP_DB_HOST=prod.example.com
export MYAPP_DB_PORT=5432
env-demoAdvanced Argument Relations Example ​
Demonstrates mutual exclusion, conditional requirements, and dependencies between options and flags:
const std = @import("std");
const args = @import("args");
pub fn main() !void {
const allocator = std.heap.page_allocator;
var ap = try args.createParser(allocator, "conflict-demo");
defer ap.deinit();
ap.description = "Advanced argument validation and relations (conflicts/requires/exclusions)";
try ap.addFlag("mysql", .{ .help = "Use MySQL backend" });
try ap.addFlag("postgres", .{ .help = "Use PostgreSQL backend" });
try ap.addOption("host", .{ .help = "Server host address" });
try ap.addOption("port", .{ .help = "Server port" });
try ap.addOption("user", .{ .help = "Username" });
try ap.addOption("password", .{ .help = "Password" });
// Exclude MySQL and Postgres backends from being used together
try ap.addMutualExclusion(&[_][]const u8{ "mysql", "postgres" });
// Host and user are conditionally required when backends are active
try ap.addRequiredIf("host", "mysql", null);
try ap.addRequiredIf("host", "postgres", null);
try ap.addRequiredIf("user", "mysql", null);
try ap.addRequiredIf("user", "postgres", null);
// Password requires username
try ap.addRequires("password", "user");
var init = std.process.Init.init;
var result = ap.parseProcess(init) catch |err| {
std.debug.print("Failed to parse arguments: {any}\n", .{err});
return;
};
defer result.deinit();
std.debug.print("Validated database configuration!\n", .{});
}Configuration Warnings & Auto-Resolution Example ​
Demonstrates checking configuration consistency at runtime and automatically resolving any conflicts:
const std = @import("std");
const args = @import("args");
pub fn main() !void {
const allocator = std.heap.page_allocator;
const cfg = args.Config{
.parsing_mode = .permissive,
.exit_on_error = true,
.use_colors = true,
.silent_errors = true,
.suggest_closest = true,
.suggestion_max_distance = 0,
};
var ap = try args.createParserWithConfig(allocator, "config-warnings-demo", cfg);
defer ap.deinit();
var warn_buf: [16]args.config.ConfigWarning = undefined;
const count = ap.getConfigWarnings(&warn_buf);
std.debug.print("Detected {d} configuration conflicts:\n", .{count});
for (warn_buf[0..count], 1..) |warn, idx| {
std.debug.print("{d}. [{s}] {s}\n", .{ idx, warn.field, warn.message });
}
ap.configureAutoResolve();
std.debug.print("Resolved Config color mode: {}\n", .{ap.cfg.use_colors});
}Duration, Byte-Size, & Range Validation Example ​
Demonstrates options parsing duration formats (e.g. 1h30m), byte sizes (e.g. 512MB), or range-bounded numbers:
const std = @import("std");
const args = @import("args");
pub fn main() !void {
const allocator = std.heap.page_allocator;
var ap = try args.createParser(allocator, "duration-size-demo");
defer ap.deinit();
try ap.addDurationOption("timeout", .{ .default = "30s" });
try ap.addSizeOption("buffer-size", .{ .default = "64MB" });
try ap.addRangeOption("concurrency", i64, comptime .{ .min = 1, .max = 8, .default = "2" });
var init = std.process.Init.init;
var result = ap.parseProcess(init) catch |err| {
std.debug.print("Argument validation failed: {any}\n", .{err});
return;
};
defer result.deinit();
std.debug.print("Timeout seconds: {d}\n", .{result.getDuration("timeout").?});
std.debug.print("Buffer bytes: {d}\n", .{result.getSize("buffer-size").?});
std.debug.print("Concurrency: {d}\n", .{result.get("concurrency").?.asInt().?});
}Bracketed List Example ​
Parse bracket-delimited inline lists as arrays:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parser = try args.ArgumentParser.init(allocator, .{
.name = "bracketed-list",
.version = "1.0.0",
.description = "Demonstrates bracket-delimited value parsing",
});
defer parser.deinit();
try parser.addBracketedListOption("tags", .{ .short = 't' });
try parser.addBracketedListOption("files", .{ .short = 'f', .bracket_type = .curly });
var result = try parser.parseProcess(init);
defer result.deinit();
if (result.getArray("tags")) |tags| {
for (tags, 0..) |tag, i| std.debug.print(" [{d}] {s}\n", .{ i, tag });
}
if (result.getArray("files")) |files| {
for (files, 0..) |f, i| std.debug.print(" [{d}] {s}\n", .{ i, f });
}
}Usage:
zig build run-bracketed_list -- --tags {a,b,c} --files {x,y}Format Option Example ​
File format detection and extension helpers:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parser = try args.ArgumentParser.init(allocator, .{
.name = "format-demo",
.version = "1.0.0",
});
defer parser.deinit();
try parser.addFormatOption("input-format", .{ .short = 'f', .default = "json", .formats = &[_][]const u8{ "json", "yaml", "csv" } });
try parser.addExtensionOption("output-ext", .{ .short = 'o', .default = ".json", .extensions = &[_][]const u8{ ".json", ".yaml", ".csv" } });
var result = try parser.parseProcess(init);
defer result.deinit();
const fmt = result.getString("input-format") orelse "json";
const ext = result.getString("output-ext") orelse ".json";
std.debug.print("Format: {s} / Ext: {s}\n", .{ fmt, ext });
}Usage:
zig build run-format_option -- --input-format yaml --output-ext .yamlFallback Parse Example ​
Use parseOr / parseProcessOr with getOr* methods for graceful error recovery:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parser = try args.ArgumentParser.init(allocator, .{
.name = "fallback-demo",
.version = "1.0.0",
});
defer parser.deinit();
try parser.addFlag("verbose", .{ .short = 'v' });
try parser.addCounter("verbosity", .{ .short = 'd' });
// parseOr never fails — returns empty result on error
var result = parser.parseOr(&[_][]const u8{}, null);
defer result.deinit();
const verbose = result.getOrBool("verbose", false);
const counter = result.getOrCounter("verbosity", 0);
// parseProcessOr wraps parseProcess with fallback
var result2 = parser.parseProcessOr(init, null);
defer result2.deinit();
const name = result2.getOrString("name", "default");
std.debug.print("verbose={} counter={} name={s}\n", .{ verbose, counter, name });
}Usage:
zig build run-fallback_parse -- -v -dddAppend Option Example ​
Repeated options stored as arrays:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parser = try args.ArgumentParser.init(allocator, .{
.name = "append-demo",
.version = "1.0.0",
});
defer parser.deinit();
try parser.addAppend("include", .{ .short = 'I', .metavar = "DIR" });
try parser.addOption("output", .{ .short = 'o', .default = "out" });
var result = try parser.parseProcess(init);
defer result.deinit();
if (result.getArray("include")) |paths| {
for (paths, 0..) |p, i| std.debug.print(" [{d}] {s}\n", .{ i, p });
}
std.debug.print("Output: {s}\n", .{result.getOrString("output", "out")});
}Usage:
zig build run-append_option -- -I src -I include -I lib -o resultMulti-Value (n-args) Example ​
Variadic argument collection using n-args:
const std = @import("std");
const args = @import("args");
pub fn main(init: std.process.Init) !void {
const allocator = init.arena.allocator();
var parser = try args.ArgumentParser.init(allocator, .{
.name = "multi-value",
.version = "1.0.0",
});
defer parser.deinit();
// one_or_more: requires at least one value
try parser.addOption("source", .{ .short = 's', .nargs = .one_or_more });
try parser.addPositional("target", .{ .required = true });
var result = try parser.parseProcess(init);
defer result.deinit();
if (result.getArray("source")) |sources| {
for (sources, 0..) |src, i| std.debug.print(" [{d}] {s}\n", .{ i, src });
}
std.debug.print("Target: {s}\n", .{result.getOrString("target", "?")});
}Usage:
zig build run-multi_value -- --source a.txt b.txt c.txt ./outputRunning the Examples ​
Build and run examples with:
# Build all examples
zig build
# Run basic example
zig build run-basic
# Run bool options example
zig build run-bool_options
# Run advanced example
zig build run-advanced
# Run conflict demo example
zig build run-conflict_demo
# Run config warnings example
zig build run-config_warnings
# Run duration and size example
zig build run-duration_size
# Run typed numeric options
zig build run-int_float_options
# Run hex decode example
zig build run-hex_option
# Run log level example
zig build run-log_level
# Run advanced struct/parseInto example
zig build run-advanced_struct
# Run env var config example
zig build run-env_var_config
# Run list option example
zig build run-list_option
# Run validation demo example
zig build run-validation_demo
# Run update check example
zig build run-update_check