A modern Zig TUI framework & CLI toolkit with zero dependencies.
sailor is a batteries-included library for building terminal applications in Zig. From simple CLI tools with colored output to full-featured TUI applications with complex layouts and widgets β sailor has you covered.
Key Features:
- π¨ Rich CLI - Styled output, progress bars, tables, REPL
- π₯οΈ Full TUI - Layout system, 17+ widgets, event handling
- π§ Modular - Use only what you need, each module is independent
- π Cross-platform - Linux, macOS, Windows (x86_64 & ARM64)
- π Zero dependencies - Only the Zig standard library
- π¦ Library-first - No global state, bring your own allocator
const std = @import("std");
const sailor = @import("sailor");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
var terminal = try sailor.tui.Terminal.init(gpa.allocator());
defer terminal.deinit();
try terminal.run(render);
}
fn render(frame: *sailor.tui.Frame) !void {
const block = sailor.tui.widgets.Block.init()
.setTitle(sailor.tui.Line.fromString("Hello, sailor!"))
.setBorders(sailor.tui.Borders.all);
const para = sailor.tui.widgets.Paragraph.init(
sailor.tui.Line.fromString("Press Ctrl+C to exit")
).setBlock(block);
frame.renderWidget(para, frame.size());
}| Module | Description | Version |
|---|---|---|
| term | Terminal backend (raw mode, key reading, TTY detection, size) | β v0.1.0 |
| color | Styled output (ANSI codes, 256/truecolor, NO_COLOR support) | β v0.1.0 |
| arg | Argument parser (flags, subcommands, auto-help) | β v0.1.0 |
| repl | Interactive REPL (line editing, history, completion) | β v0.2.0 |
| progress | Progress indicators (bar, spinner, multi-progress) | β v0.2.0 |
| fmt | Result formatting (table, JSON, CSV, plain text) | β v0.2.0 |
| tui | Full-screen TUI framework (layout, widgets, events) | β v0.3.0 |
Core Widgets (v0.4.0): Block, Paragraph, List, Table, Input, Tabs, StatusBar, Gauge
Advanced Widgets (v0.5.0): Tree, TextArea, Sparkline, BarChart, LineChart, Canvas, Dialog, Popup, Notification
See the Widget Gallery for examples.
- Getting Started Guide - Tutorials and examples
- API Reference - Complete API documentation
- PRD - Design rationale and architecture
Requirements: Zig 0.15.x or later
Add to your build.zig.zon:
.{
.name = "myapp",
.version = "0.1.0",
.paths = .{""},
.dependencies = .{
.sailor = .{
.path = "../sailor", // Local development
// .url = "https://...", // Or git URL when published
},
},
}Update build.zig:
const sailor = b.dependency("sailor", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("sailor", sailor.module("sailor"));See the installation guide for details.
const sailor = @import("sailor");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
try sailor.color.ok(stdout, "β Build successful\n");
try sailor.color.err(stdout, "β Test failed\n");
try sailor.color.warn(stdout, "β Deprecated API\n");
}var parser = sailor.arg.Parser.init(allocator);
defer parser.deinit();
parser.addFlag(.{
.long = "output",
.short = 'o',
.type = .string,
.description = "Output file path",
.required = true,
});
const args = try parser.parse();
const output = args.flag("output").?;var bar = try sailor.progress.Bar.init(allocator, 100);
defer bar.deinit();
for (0..101) |i| {
bar.set(i);
try bar.render(std.io.getStdOut().writer());
std.time.sleep(20 * std.time.ns_per_ms);
}var terminal = try sailor.tui.Terminal.init(allocator);
defer terminal.deinit();
const app = App{ .counter = 0 };
while (app.running) {
try terminal.draw(app, render);
if (try terminal.pollEvent(100)) |event| {
switch (event) {
.key => |key| switch (key) {
.char => |c| if (c == 'q') app.running = false,
.ctrl_c => app.running = false,
else => {},
},
else => {},
}
}
}See examples/ for complete applications.
# Build library
zig build
# Run tests (308+ tests)
zig build test
# Run examples
zig build example -- hello
zig build example -- counter
zig build example -- dashboard
# Cross-compile verification
zig build -Dtarget=x86_64-linux-gnu
zig build -Dtarget=x86_64-windows-msvc
zig build -Dtarget=aarch64-macos| Platform | x86_64 | ARM64 |
|---|---|---|
| Linux | β | β |
| macOS | β | β |
| Windows | β | β |
All platforms are tested in CI on every commit.
| Version | Features |
|---|---|
| v0.1.0 | Terminal backend, styled output, argument parsing |
| v0.2.0 | REPL, progress indicators, table formatting |
| v0.3.0 | TUI core (layout, buffer, rendering) |
| v0.4.0 | Core widgets (Block, List, Table, Input, Tabs, etc.) |
| v0.5.0 | Advanced widgets (Tree, TextArea, Charts, Dialog, etc.) |
| v1.0.0 | Polish, theming, animation, comprehensive docs |
- Library-first - No global state, you control allocations
- Writer-based - All output via
std.io.Writer, never direct stdout/stderr - Error-aware - No panics in library code, explicit error handling
- Modular - Use
sailor.colorwithout importingsailor.tui - Cross-platform - Platform differences handled internally
- Well-tested - 308+ tests with 100% coverage of public APIs
sailor draws inspiration from:
- ratatui (Rust) - Widget architecture and layout system
- bubbletea (Go) - Event-driven TUI model
- colored (Rust) - ANSI color API design
Contributions welcome! Please:
- Read CLAUDE.md for project structure
- Run
zig build testbefore submitting - Follow existing code style (see docs/GUIDE.md)
MIT License - see LICENSE for details.
Built with β€οΈ in Zig. Ship your CLI/TUI apps with sailor! π’