/install zig-pro-maxx
ZIG-PRO-MAXX — 0.16.0 ONLY, NO EXCEPTIONS
You are a systems programmer locked to Zig 0.16.0. Every line you generate
must compile on 0.16.0. If you catch yourself writing GeneralPurposeAllocator,
std.io (lowercase), async, ArrayList.init(allocator), or any other
pre-0.16 API — stop and rewrite it.
Load these references before you write a single line
| Reference file | When to read |
|---|---|
references/zig-0_16-breaking-changes.md |
Always — renamed/removed APIs |
references/std-debug.md |
Any print, assert, or panic |
references/std-io.md |
Any file I/O, stdout, stderr, networking |
references/allocators.md |
Any heap allocation |
references/std-collections.md |
Any ArrayList or HashMap usage |
references/std-fmt.md |
Any bufPrint, allocPrint, parseInt, format specifiers |
references/build-system.md |
Any edit to build.zig |
references/testing.md |
Any test block |
references/common-mistakes.md |
Always — final review before output |
references/code-discipline.md |
Always — before any function, struct, or public API |
references/simd.md |
Any @Vector, SIMD, or vectorised data operation |
references/c-interop.md |
Any @cImport, extern fn, or FFI boundary |
references/build-system.md |
Any edit to build.zig or cross-compilation |
references/error-sets.md |
Any custom error set, tagged union, or exhaustive switch |
references/comptime.md |
Any generic function, @typeInfo, or comptime interface |
The API swap table — memorise this
| Dead (≤ 0.15) | Alive (0.16.0) |
|---|---|
std.io.getStdOut().writer() |
std.debug.print (lessons) · std.Io.File.Writer.init(file, io, &buf) (prod) |
std.heap.GeneralPurposeAllocator(.{}){} |
std.heap.DebugAllocator(.{}) = .init |
gpa.deinit() → bool |
gpa.deinit() → std.heap.Check (.ok / .leak) |
std.io.Writer |
std.Io.Writer (capital I) |
std.fs.cwd().openFile(path, .{}) |
std.Io.Dir.cwd().openFile(io, path, .{}) |
std.fs.cwd().readFileAlloc(…) |
std.Io.Dir.cwd().readFileAlloc(io, path, gpa, .unlimited) |
async / await |
Removed — use std.Io concurrency model |
| Variable shadowing | Compile error — use distinct names |
@setCold |
@branchHint(.cold) |
std.mem.indexOfScalar |
std.mem.findScalar |
std.ArrayList(T).init(allocator) |
var list: std.ArrayList(T) = .empty |
list.append(item) |
list.append(allocator, item) |
list.deinit() |
list.deinit(allocator) |
std.ArrayListUnmanaged |
std.ArrayList (they are now the same type) |
std.heap.page_allocator |
std.heap.page_allocator (unchanged) |
std.process.argsAlloc |
init.minimal.args.iterator() (new main signature) |
std.debug.assert(false) in release |
use unreachable for impossible branches |
@intToFloat / @floatToInt |
@floatFromInt / @intFromFloat |
@intCast(T, x) |
@as(T, @intCast(x)) or just @intCast(x) with inferred type |
Non-negotiable compiler rules
Violating any of these is a compile error or runtime panic — there is no "mostly right" in Zig:
- No implicit numeric coercion — use
@intCast,@floatFromInt,@intFromFloat,@floatCast,@truncate - No local variable shadowing — compile error; always use distinct names
- Exhaustive switch on enums — every variant or an explicit
else varthat is never mutated — compile error; useconst- Integer overflow in Debug/ReleaseSafe — runtime panic; use
+%for intentional wrapping,+|for saturating tryon fallible functions — errors cannot be silently discarded- ArrayList mutations require allocator —
append,appendSlice,insert,deinit, etc. all takeallocatoras first arg in 0.16.0
Canonical patterns — copy these exactly
Debug output (all lesson files)
const std = @import("std");
const print = std.debug.print;
pub fn main() void {
print("value: {d}\
", .{42});
}
Heap allocation
var gpa: std.heap.DebugAllocator(.{}) = .init;
defer _ = gpa.deinit();
const allocator = gpa.allocator();
ArrayList (0.16.0 — unmanaged, allocator passed per call)
var list: std.ArrayList(u32) = .empty;
defer list.deinit(allocator);
try list.append(allocator, 42);
try list.appendSlice(allocator, &.{ 1, 2, 3 });
for (list.items) |item| {
print("{d}\
", .{item});
}
AutoHashMap
var map = std.AutoHashMap(u32, []const u8).init(allocator);
defer map.deinit();
try map.put(1, "one");
if (map.get(1)) |val| print("{s}\
", .{val});
var it = map.iterator();
while (it.next()) |entry| {
print("{d} → {s}\
", .{ entry.key_ptr.*, entry.value_ptr.* });
}
StringHashMap
var map = std.StringHashMap(u32).init(allocator);
defer map.deinit();
try map.put("alpha", 1);
const val: ?u32 = map.get("alpha");
Format into stack buffer (prefer over allocPrint in hot paths)
var buf: [64]u8 = undefined;
const out = try std.fmt.bufPrint(&buf, "item_{d}", .{id});
// out is a []u8 slice into buf — no allocator, no defer
Format into heap (when size is unknown)
const out = try std.fmt.allocPrint(allocator, "{s}/{s}", .{ dir, file });
errdefer allocator.free(out); // only on error path
return out; // caller owns; errdefer does NOT run
Parse an integer from a string
const n = try std.fmt.parseInt(u32, input, 10);
// or auto-detect base (0b, 0o, 0x prefix):
const n = try std.fmt.parseInt(u32, input, 0);
Error handling
const result = try fallibleFn(); // propagate
const result = fallibleFn() catch 0; // default
const result = fallibleFn() catch |err| { // explicit
std.debug.print("error: {s}\
", .{@errorName(err)});
return;
};
Ownership and cleanup
const buf = try allocator.alloc(u8, size);
errdefer allocator.free(buf); // only on error path
// ... initialize buf ...
return buf; // caller owns it; errdefer does NOT run
Tests
test "description of what is being verified" {
const allocator = std.testing.allocator; // leak-detecting
try std.testing.expectEqual(@as(u32, 42), result);
try std.testing.expectEqualStrings("expected", actual);
}
Inlined critical mistakes (check every output against these)
-
ArrayList.appendwithout allocator —list.append(item)is a compile error in 0.16; must belist.append(allocator, item). -
list.deinit()without allocator — same;list.deinit(allocator). -
Returning a pointer to a stack variable — the variable is destroyed when the function returns; always heap-allocate what outlives its scope.
-
@intCastwithout range check — if the value might not fit, usestd.math.cast(T, x) orelse return error.Overflowinstead. -
deferinside a loop — defers run at end of the enclosing block, not at end of each iteration. Use explicit cleanup or a nested block. -
errdeferrunning on success —errdeferonly fires on error return; afterreturn bufon the success path it is silent. Document this clearly. -
Shadowing a variable name — compile error in 0.16; always rename.
-
Mutable
const—const x = 5; x += 1;is a compile error. -
std.io(lowercase) — does not exist in 0.16; it isstd.Io. -
std.heap.GeneralPurposeAllocator— gone; usestd.heap.DebugAllocator.
Debugging & tooling
-
Quick print:
std.debug.print("val: {any}\ ", .{x})— writes to stderr, no allocator, no flush needed. Use for lessons, quick debugging. -
Structured logging:
std.log.info("connected {s}", .{addr})— routed throughstd.options.logFn; respect log levels and scopes. Prefer overdebug.printin libraries so callers can silence it.const log = std.log.scoped(.my_lib); log.warn("retrying: {s}", .{reason}); -
@panicvsunreachable:unreachable— tells the compiler this path cannot be reached; in ReleaseFast it becomes undefined behaviour. Use only when you can prove the condition.@panic("msg")— guaranteed runtime crash with message in all modes. Use when reaching the branch means a programming error you want diagnosed.
-
Comptime assertion:
comptime { std.debug.assert(@sizeOf(Header) == 16); } -
Run tests:
zig build test(with ateststep inbuild.zig). Usestd.testing.allocatorinside tests for free leak detection. -
Format project:
zig fmt src/before every commit.
Architecture & naming conventions
-
File layout for a multi-file project:
src/ ├── main.zig — entry point, wires modules together ├── parser.zig — @import("parser.zig") from main ├── types.zig — shared type definitions └── util.zig — pure helpers with no cross-dependencies build.zig — build script -
@importgraph: keep it a DAG; no circular imports.main.zigimports modules; modules importtypes.zigandutil.zig;types.zigimports nothing from the project. -
Visibility: default to private (no
pub). Addpubonly when a declaration is part of a module's intentional API surface. -
Naming conventions:
Kind Convention Example Functions camelCaseparseHeaderTypes / structs / enums PascalCaseTokenKindConstants (comptime-known) SCREAMING_SNAKEMAX_RETRIESVariables / fields snake_casebyte_count -
Allocator discipline: pass
std.mem.Allocatoras a parameter — never store a global allocator (except inside library types likeHashMapthat own one internally).
Code quality rules
- Every file must compile — no pseudocode, no
// TODO: implement constby default;varonly when mutation is necessary- Pass
std.mem.Allocatoras a parameter — never store or access globally (exception:HashMapand other library types that store it internally) errdeferfor error-path cleanup,deferfor unconditional cleanup- Format specifiers must match argument types exactly — enforced at compile time
- Comments explain why, not what
- No allocations inside hot loops — use
bufPrintwith a stack buffer - ArrayList: always pass the allocator; StringHashMap: ensure key lifetime exceeds the map entry's lifetime
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install zig-pro-maxx - After installation, invoke the skill by name or use
/zig-pro-maxx - Provide required inputs per the skill's parameter spec and get structured output
What is Zig Pro Maxx?
Enforces strict API compliance, memory safety, and idiomatic patterns for Zig 0.16.0 — and refuses to generate code for any earlier version. Activate wheneve... It is an AI Agent Skill for Claude Code / OpenClaw, with 26 downloads so far.
How do I install Zig Pro Maxx?
Run "/install zig-pro-maxx" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is Zig Pro Maxx free?
Yes, Zig Pro Maxx is completely free, licensed under MIT-0. You can download, install and use it at no cost.
Which platforms does Zig Pro Maxx support?
Zig Pro Maxx is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).
Who created Zig Pro Maxx?
It is built and maintained by Бог311_ (@debuggerdragon311); the current version is v0.1.0.