loaders.zig is a production-oriented Zig library for animated spinners, progress bars, and multi-progress terminal UIs. It is designed for low overhead, clean output, and cross-platform terminal behavior on Linux, Windows, and macOS.
Note
This project is still evolving, but the current API is built to be practical for real CLI tools and long-running terminal workflows.
⭐ If you find loaders.zig useful, consider starring the repository.
Table of Contents (click to expand)
Features (click to expand)
| Feature | Description | Documentation |
|---|---|---|
| Simple & Fluent API | Add progress indicators in just a few lines. | Guide |
| Progress Bars | Animated single-bar progress with percentage, ETA, and rate display. | Guide |
| Spinners | Background-threaded terminal spinners for non-blocking work. | Guide |
| Multi Progress | Render multiple concurrent bars or spinners together. | Guide |
| Styling | Configure brackets, fills, colors, and suffixes. | Guide |
| Themes | Use built-in visual presets for bars and spinners. | Guide |
| ANSI Colors | Support for 16-color ANSI, 256-color, and RGB output. | Guide |
| Cross-Platform TTY Handling | Detects terminal capabilities on Windows and POSIX systems. | Guide |
| No-Color Friendly | Respects NO_COLOR and redirected output. |
Guide |
| Stack-Friendly | Designed to work well in small CLI tools and longer-running programs. | API |
Prerequisites & Supported Platforms (click to expand)
Before using loaders.zig, ensure you have:
| Requirement | Version | Notes |
|---|---|---|
| Zig | 0.16.0 | Install from ziglang.org |
| Operating System | Windows, Linux, macOS | Cross-platform support |
| Terminal | Any modern terminal | For color and cursor control |
| Platform | Status |
|---|---|
| Windows | Full support |
| Linux | Full support |
| macOS | Full support |
| Terminal | Support |
|---|---|
| Windows Terminal | Native ANSI |
| PowerShell / CMD | Supported with terminal capabilities |
| iTerm2 / Terminal.app | Native |
| GNOME Terminal / Konsole | Native |
| VS Code Terminal | Native |
Pin to a specific tagged release for reproducible builds:
zig fetch --save https://github.com/muhammad-fiaz/loaders.zig/archive/refs/tags/0.0.1.tar.gzThis automatically adds the dependency to your build.zig.zon:
.dependencies = .{
.loaders = .{
.url = "https://github.com/muhammad-fiaz/loaders.zig/archive/refs/tags/0.0.1.tar.gz",
.hash = "...", // auto-filled by zig fetch --save
},
},Use the latest unreleased code from main. This tracks HEAD and may include breaking changes:
zig fetch --save git+https://github.com/muhammad-fiaz/loaders.zig.gitThis adds a git dependency to your build.zig.zon:
.dependencies = .{
.loaders = .{
.url = "git+https://github.com/muhammad-fiaz/loaders.zig.git",
.hash = "...", // auto-filled by zig fetch --save
},
},Tip
Use zig fetch --save (with URL) for the automatic flow. It resolves the hash and writes it into build.zig.zon for you.
git clone https://github.com/muhammad-fiaz/loaders.zig.git
cd loaders.zig
zig buildconst std = @import("std");
const loaders = @import("loaders");
pub fn main(init: std.process.Init) !void {
const io = init.io;
var bar = loaders.Bar.init(io, .{
.label = "Processing",
.total = 100,
.show_percent = true,
.show_elapsed = true,
});
defer bar.done();
for (0..100) |i| {
bar.setCompleted(i + 1);
bar.render();
try io.sleep(std.Io.Duration.fromMilliseconds(30), .awake);
}
}const std = @import("std");
const loaders = @import("loaders");
pub fn main(init: std.process.Init) !void {
const io = init.io;
const sp = try loaders.Spinner.start(io, .{
.text = "Syncing local database...",
.style = loaders.SpinnerStyle.dots,
});
try io.sleep(std.Io.Duration.fromSeconds(2), .awake);
sp.succeed(io, "Database synchronized successfully!");
}const std = @import("std");
const loaders = @import("loaders");
pub fn main(init: std.process.Init) !void {
const io = init.io;
var mb = loaders.MultiBar.init(io, std.Io.File.stderr(), null, .{});
const a = mb.addBar(.{ .label = "Asset A", .total = 100 });
const b = mb.addBar(.{ .label = "Asset B", .total = 100 });
for (0..100) |i| {
a.setCompleted(i + 1);
b.setCompleted(i + 1);
mb.render();
try io.sleep(std.Io.Duration.fromMilliseconds(20), .awake);
}
mb.done();
}The core options are available through BarOptions and SpinnerOptions in the API reference.
label,text, andprefixfor user-facing messagestotal,show_percent,show_elapsed,show_eta, andshow_ratefor progress detailsstyle,color_enabled, and custom bracket/fill fields for output controlfileandtermfor stream selection and terminal capability detection
See the full API at API Reference.
Full documentation is available at: https://muhammad-fiaz.github.io/loaders.zig/
cd docs
bun install
bun run buildThe output is written to docs/.vitepress/dist/.
zig build test
zig build examples
zig fmt --check build.zig src/ examples/Contributions are welcome! Please read the Contributing Guide for details on how to get started, run tests, and submit pull requests.
MIT License - see LICENSE for details.
- Documentation: https://muhammad-fiaz.github.io/loaders.zig/
- API Reference: https://muhammad-fiaz.github.io/loaders.zig/api/
- Guide: https://muhammad-fiaz.github.io/loaders.zig/guide/
- Repository: https://github.com/muhammad-fiaz/loaders.zig
- Issues: https://github.com/muhammad-fiaz/loaders.zig/issues
