https://github.com/kingrashy12/ziglet
A concise and powerful CLI builder for Zig.
https://github.com/kingrashy12/ziglet
cli-builder zig-package
Last synced: 25 days ago
JSON representation
A concise and powerful CLI builder for Zig.
- Host: GitHub
- URL: https://github.com/kingrashy12/ziglet
- Owner: Kingrashy12
- License: mit
- Created: 2025-07-12T18:52:29.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2026-04-08T01:03:32.000Z (2 months ago)
- Last Synced: 2026-04-08T03:06:18.394Z (2 months ago)
- Topics: cli-builder, zig-package
- Language: Zig
- Homepage:
- Size: 103 KB
- Stars: 2
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Ziglet
A concise and powerful CLI builder for Zig.
## β¨ Features
- Add and organize custom commands with ease
- Execute commands with `parse` built into Ziglet
- Minimal dependencies, maximum speed
- Built in Zig for clarity, performance, and control
## π How to Use
1. Fetch the package:
```bash
zig fetch --save git+https://github.com/Kingrashy12/ziglet
```
2. Add the module to your `build.zig`:
```zig
// Add the ziglet dependency
const ziglet = b.dependency("ziglet", .{});
// Add the ziglet module to the executable
exe.root_module.addImport("ziglet", ziglet.module("ziglet"));
```
3. Import and use in your code:
### Basic Usage
```zig
const std = @import("std");
const ziglet = @import("ziglet");
const CommandContext = ziglet.BuilderTypes.CommandContext;
const CLIBuilder = ziglet.CLIBuilder;
pub fn main(init: std.process.Init) !void {
const arena = init.arena;
const allocator = init.gpa;
const args = try init.minimal.args.toSlice(arena.allocator());
var cli = CLIBuilder.init(allocator, init, "my-cli", "0.1.0", "A simple CLI example");
defer cli.deinit();
// Add a command with options
cli.addCommand(.{
.name = "greet",
.description = "Greet someone",
.action = greet,
.options = cli.defOptions(&.{.{
.name = "name",
.alias = "n",
.type = .string,
.required = true,
.description = "Name to greet",
}}),
});
try cli.parse(args, null);
}
fn greet(ctx: CommandContext) !void {
const name = ctx.options.get("name");
if (name) |n| {
std.debug.print("Hello, {s}!\n", .{n.string});
}
}
```
### Global Options
Ziglet supports global options that apply to all commands:
```zig
// ... (same setup as above)
var cli = CLIBuilder.init(allocator, init, "example-cli", "1.0.0", "A CLI with global options");
defer cli.deinit();
// Enable global options (adds --help and --version automatically)
cli.setGlobalOptions();
// Add a global option
cli.option(.{
.alias = "v",
.name = "verbose",
.type = .bool,
.description = "Enable verbose output",
});
// Add commands that can access global options
cli.addCommand(.{
.name = "greet",
.description = "Greet someone",
.action = greet,
.options = cli.defOptions(&.{.{
.name = "name",
.alias = "n",
.type = .string,
.required = true,
.description = "Name to greet",
}}),
});
try cli.parse(args, null);
// In your action function, access both global and command options
fn greet(ctx: CommandContext) !void {
const verbose = ctx.options.get("verbose");
const name = ctx.options.get("name");
if (verbose) |v| if (v.bool) {
std.debug.print("Verbose mode enabled.\n", .{});
}
if (name) |n| {
std.debug.print("Hello, {s}!\n", .{n.string});
}
}
```
### Factory Pattern (Fluent API)
For a more fluent and readable way to build commands:
```zig
// ... (same setup as above)
var cli = CLIBuilder.init(allocator, init,"my-cli", "0.1.0", "Factory builder example");
defer cli.deinit();
cli.setGlobalOptions();
// Global option
_ = cli.option(.{
.alias = "v",
.name = "verbose",
.type = .bool,
.description = "Enable verbose output",
});
// Build commands using fluent API
const greet_cmd = cli.command("greet", "Greet someone")
.option(.{
.alias = "n",
.name = "name",
.required = true,
.type = .string,
.description = "Name to greet",
})
.action(greet)
.finalize();
const calc_cmd = cli.command("calc", "Calculate sum of two numbers")
.option(.{
.alias = "a",
.name = "a",
.required = true,
.type = .number,
.description = "First number",
})
.option(.{
.alias = "b",
.name = "b",
.required = true,
.type = .number,
.description = "Second number",
})
.action(calc)
.finalize();
// Command without options
_ = cli.command("status", "Show status")
.action(status)
.finalize();
// Parse with factory commands
try cli.parse(args, &.{ greet_cmd, calc_cmd });
fn greet(ctx: CommandContext) !void {
const name = ctx.options.get("name");
std.debug.print("Greeting someone from '{s}'.\n", .{ctx.name});
if (name) |n| {
std.debug.print("Hello, {s}!\n", .{n.string});
}
}
fn calc(ctx: CommandContext) !void {
const a_opt = ctx.options.get("a");
const b_opt = ctx.options.get("b");
if (a_opt) |a| if (b_opt) |b| {
const sum = a.number + b.number;
std.debug.print("Sum: {d}\n", .{sum});
}
}
fn status(ctx: CommandContext) !void {
_ = ctx;
std.debug.print("System status: All good!\n", .{});
}
```
## π Examples
For runnable examples, see the [examples/](examples/) directory:
- [`examples/plain.zig`](examples/plain.zig) - Comprehensive example with multiple commands, global options, and different option types
- [`examples/factory.zig`](examples/factory.zig) - Demonstrates the fluent factory pattern for building commands
## π€ Contributing
Want to make Ziglet even snappier? Feel free to open issues, suggest features, or submit pull requests. Letβs build something sharp together.
## π License
MIT β free to use, modify, and share.