agentleFS
kaynetikkaynetik/skills/ziglang/SKILL.md

ziglang

Skill1 starsChanged 8 months agoMITView on GitHub

Guides correct Zig 0.16.x programming, build system configuration, and standard library usage. Covers breaking API changes from prior versions (ArrayList, I/O rewrite, build.zig, Ed25519, JSON, HTTP client, @typeInfo enum casing, usingnamespace removal). Use when writing Zig code, debugging Zig compiler errors, configuring build.zig, or when the user mentions Zig, zig build, zig test, or Zig standard library.

The file

We split this skill into the rules it gives an agent

6 rules. About 0 are common, 0 are distinctive, and 6 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    All mutating methods require an explicit allocator parameter.

    line 30
  2. Very specific:

    Use b.path("src/main.zig") instead of .{ .path = "src/main.zig" }

    line 135
  3. Very specific:

    Test target: use b.graph.host for native

    line 138
  4. Very specific:

    Run zig build to check compilation

    line 208
  5. Very specific:

    Run zig build test to verify functionality

    line 210
  6. Very specific:

    Use zig build -Doptimize=ReleaseFast test to catch UB

    line 211

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Zig 0.16.x Programming

Version scope: Pinned to Zig 0.16.x (specifically 0.16.0). For master/nightly, APIs may differ. Always check official docs for the target version.

Many LLMs have outdated Zig knowledge (0.11-0.14) that causes compilation errors. This skill ensures correct 0.16.x API usage.

Official Documentation

Critical API Changes in 0.16

ArrayList -- Allocator Now Required

All mutating methods require an explicit allocator parameter. AssumeCapacity variants do not.

var list = try std.ArrayList(T).initCapacity(allocator, 16);
defer list.deinit(allocator);
try list.append(allocator, item);
try list.appendSlice(allocator, items);
_ = try list.addOne(allocator);
_ = try list.toOwnedSlice(allocator);

list.appendAssumeCapacity(item); // no allocator needed

I/O Rewrite (Writergate)

New std.Io.Writer and std.Io.Reader are non-generic, buffer-in-interface, ring-buffer-based types.

// stdout (0.16+)
var stdout_buffer: [1024]u8 = undefined;
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
const stdout: *std.Io.Writer = &stdout_writer.interface;
try stdout.print("Hello\n", .{});
try stdout.flush();

// adapter for old-style writers
fn useOldWriter(old_writer: anytype) !void {
    var adapter = old_writer.adaptToNewApi(&.{});
    const w: *std.Io.Writer = &adapter.new_interface;
    try w.print("{s}", .{"example"});
}

@typeInfo Enum Cases -- Lowercase

// 0.16+ uses lowercase / @"" escaped names
if (@typeInfo(T) == .slice) { ... }
if (@typeInfo(T) == .pointer) { ... }
if (@typeInfo(T) == .@"struct") { ... }
if (@typeInfo(T) == .@"enum") { ... }
if (@typeInfo(T) == .@"union") { ... }

Custom Format Functions -- {f} Specifier

// 0.16+: use {f}, simplified signature
pub fn format(self: Self, writer: anytype) !void {
    try writer.writeAll("...");
}
// Usage: std.fmt.bufPrint(&buf, "{f}", .{value});

usingnamespace Removed

// explicit re-exports instead
pub const foo = @import("other.zig").foo;
// or namespace via field
pub const other = @import("other.zig");

async/await Keywords Removed

Async functionality will be provided via the standard library's new I/O interface in a future release.

Build System (build.zig)

const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "hello",
        .root_module = b.createModule(.{
            .root_source_file = b.path("src/main.zig"),
            .target = target,
            .optimize = optimize,
        }),
    });
    b.installArtifact(exe);

    const run_exe = b.addRunArtifact(exe);
    const run_step = b.step("run", "Run the application");
    run_step.dependOn(&run_exe.step);

    const unit_tests = b.addTest(.{
        .root_module = b.createModule(.{
            .root_source_file = b.path("src/main.zig"),
            .target = b.graph.host,
        }),
    });
    const run_tests = b.addRunArtifact(unit_tests);
    const test_step = b.step("test", "Run unit tests");
    test_step.dependOn(&run_tests.step);
}

Key changes from 0.14:

  • root_source_file moved inside b.createModule(...) via root_module
  • Use b.path("src/main.zig") instead of .{ .path = "src/main.zig" }
  • Libraries: b.addLibrary(.{ .linkage = .dynamic, ... }) replaces addSharedLibrary
  • Module deps: exe.root_module.addImport("sdk", sdk_module) replaces exe.addModule
  • Test target: use b.graph.host for native

Common Patterns

HashMap

// Managed (stores allocator)
var map = std.StringHashMap(V).init(allocator);
defer map.deinit();
try map.put(key, value);

// Unmanaged (allocator per call)
var map = std.StringHashMapUnmanaged(V){};
defer map.deinit(allocator);
try map.put(allocator, key, value);

JSON

// Parse
const parsed = try std.json.parseFromSlice(MyStruct, allocator, json_str, .{});
defer parsed.deinit();
const data = parsed.value;

// Serialize (no stringifyAlloc in 0.16.2)
const formatted = try std.fmt.allocPrint(allocator, "{f}", .{std.json.fmt(data, .{})});
defer allocator.free(formatted);

Testing

test "no memory leaks" {
    const allocator = std.testing.allocator;
    const data = try allocator.alloc(u8, 100);
    defer allocator.free(data);
}

test "assertions" {
    try std.testing.expect(condition);
    try std.testing.expectEqual(expected, actual);
    try std.testing.expectEqualSlices(u8, expected, actual);
    try std.testing.expectError(error.SomeError, result);
    try std.testing.expectEqualStrings("hello", str);
}

Memory Operations

@memcpy(dest, src);
@memset(buffer, 0);
const equal = std.mem.eql(u8, slice1, slice2);
const index = std.mem.indexOf(u8, haystack, needle);

Common Error Messages

ErrorCauseFix
expected 2 argument(s), found 1ArrayList method missing allocatorAdd allocator as first arg
no field named root_source_fileOld build.zig APIUse root_module = b.createModule(...)
enum has no member named 'Slice'@typeInfo case changedUse lowercase .slice
expected error union, found 'Signature'Ed25519 Signature.fromBytes doesn't return errorRemove try
no member function named 'open'Old HTTP APIUse client.request() or client.fetch()

Verification Workflow

  1. Run zig build to check compilation
  2. Match errors against the table above and apply fixes
  3. Run zig build test to verify functionality
  4. Use zig build -Doptimize=ReleaseFast test to catch UB

Additional References

  • For stdlib API details (HTTP, Ed25519, Base64): references/stdlib-api-reference.md
  • For build system details: references/build-system.md
  • For migration patterns from 0.13/0.14: references/migration-patterns.md

Community Resources

Production Codebases

ProjectURLFocus
Bunhttps://github.com/oven-sh/bunJS runtime, async I/O, FFI
Tigerbeetlehttps://github.com/tigerbeetle/tigerbeetleFinancial DB, deterministic execution
Ghosttyhttps://github.com/ghostty-org/ghosttyTerminal emulator, GPU rendering
Machhttps://github.com/hexops/machGame engine, graphics
ZLShttps://github.com/zigtools/zlsLanguage Server

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.