Help us improve
Share bugs, ideas, or general feedback.
From zig
Write correct, idiomatic Zig 0.15 code. Use when writing new Zig code, editing existing Zig files, debugging Zig compilation errors, reviewing Zig code, or working with build.zig files. Triggers on any task involving .zig files. Critical: LLM training data contains outdated Zig patterns (0.11-0.13) that will produce broken code — this skill provides the current 0.15 patterns.
npx claudepluginhub mattrobenolt/pi-configs --plugin zigHow this skill is triggered — by the user, by Claude, or both
Slash command
/zig:writeThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
LLM training data is based on Zig 0.11-0.13. Zig 0.15 has massive breaking changes. ALWAYS consult [references/zig-0.15-migration.md](references/zig-0.15-migration.md) before writing Zig code.
Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Structures git workflow practices for committing, branching, resolving conflicts, and organizing work across parallel streams. Use when making any code change.
Share bugs, ideas, or general feedback.
LLM training data is based on Zig 0.11-0.13. Zig 0.15 has massive breaking changes. ALWAYS consult references/zig-0.15-migration.md before writing Zig code.
Always available — use these before guessing at APIs:
zigdoc — Discover current APIs for std and third-party deps. Use before writing any code involving unfamiliar APIs.
zigdoc std.fs
zigdoc std.posix.getuid
zigdoc vaxis.Window
ziglint — Lint Zig code for style and correctness issues.std.io.getStdOut().writer() is GONE. The entire I/O system was redesigned:
// WRONG (old):
const stdout = std.io.getStdOut().writer();
try stdout.print("hello\n", .{});
// RIGHT (0.15):
var buf: [4096]u8 = undefined;
var writer = std.fs.File.stdout().writer(&buf);
defer writer.interface.flush() catch {};
try writer.interface.print("hello {s}\n", .{"world"});
std.io.Writer → std.Io.Writerstd.io.Reader → std.Io.Readerstd.io.AnyWriter/AnyReader/GenericWriter/GenericReader → std.Io.Writer/std.Io.Readerstd.io.BufferedWriter/BufferedReader → REMOVED (buffering is in the interface now)*std.Io.Writer parameter typeflush()Allocating writer (writes to allocated memory):
var writer: std.Io.Writer.Allocating = .init(allocator);
defer writer.deinit();
try writer.writer.print("hello {s}", .{"world"});
const output = try writer.toOwnedSlice();
JSON writing:
var buf: [4096]u8 = undefined;
var writer = std.fs.File.stdout().writer(&buf);
defer writer.interface.flush() catch {};
var jw: std.json.Stringify = .{
.writer = &writer.interface,
.options = .{ .whitespace = .indent_2 },
};
try jw.write(my_struct);
// WRONG (old):
var list = std.ArrayList(i32).init(allocator);
try list.append(42);
// RIGHT (0.15) — initialize with .empty, pass allocator to every mutating op:
var list: std.ArrayList(u32) = .empty;
defer list.deinit(allocator);
try list.append(allocator, 42);
HashMap/StringHashMap (same pattern — default to unmanaged):
var map: std.StringHashMapUnmanaged(u32) = .empty;
defer map.deinit(allocator);
try map.put(allocator, "key", 42);
Initialize with .empty, NOT .init() or .{}.
b.addExecutable(.{
.name = "foo",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
}),
});
addStaticLibrary() → addLibrary(.{ .linkage = .static })b.createModule() for root modules.root_source_file = .{ .path = "..." } → .root_source_file = b.path("...")LazyPath: .{ .cwd_relative = path }// WRONG: .Int, .Float, .Struct, .Enum
// RIGHT: .int, .float, .@"struct", .@"enum"
All casts infer return type from context. Do NOT pass destination type:
// WRONG: @ptrCast(DestType, ptr)
// RIGHT: const result: DestType = @ptrCast(ptr);
Same for @bitCast, @truncate, @floatFromInt, @intFromFloat, @enumFromInt, @ptrFromInt.
@intToPtr→@ptrFromInt, @ptrToInt→@intFromPtr@intToFloat→@floatFromInt, @floatToInt→@intFromFloat@intToEnum→@enumFromInt, @enumToInt→@intFromEnum@errSetCast→@errorCast@fieldParentPtr(T, "f", ptr) → @fieldParentPtr(ptr, .field_name)@setCold(true) → @branchHint(.cold)@export(fn, ...) → @export(&fn, ...)std.os → std.posixstd.rand → std.Randomstd.TailQueue → std.DoublyLinkedListcallconv(.C) → callconv(.c)async/await → REMOVEDcamelCase for functions/methodssnake_case for variables, parameters, constantsPascalCase for types, structs, enumsconst foo: Type = .{ .field = value }; over const foo = Type{ .field = value };//! module doc comment, const Self = @This();, imports, const log = std.log.scoped(...)errdefer for cleanup on error@splat for initializationUse @splat to initialize arrays and vectors with a uniform value. Do NOT manually repeat values or use ** multiplication:
// WRONG — verbose and error-prone:
const mask = [_]u8{ 0, 0, 0, 0 };
const zeroes = [_]u8{0} ** 16;
// RIGHT — use @splat:
const mask: [4]u8 = @splat(0);
const zeroes: [16]u8 = @splat(0);
// Also works for vectors:
const vec: @Vector(4, f32) = @splat(1.0);
Type aliases improve readability and self-document intent. Always prefer a named alias over a bare type when the type appears more than once or when the name adds semantic meaning:
// Import aliases — always extract frequently used imports:
const assert = std.debug.assert;
const Allocator = std.mem.Allocator;
const log = std.log.scoped(.my_module);
// Array/Vector type aliases — name what the type represents:
const Mask = [4]u8;
const MaskVec = @Vector(4, u8);
const Color = [4]f32;
// Instead of bare types scattered through signatures:
fn applyMask(data: []u8, mask: Mask) void { ... }
// NOT: fn applyMask(data: []u8, mask: [4]u8) void { ... }
A good type alias tells you what it is, not just what it's made of. Mask is more informative than [4]u8. When you see a raw array or vector type repeated in function signatures, fields, or local variables, extract an alias.
zigdoc to verify any std library API you're unsure aboutzig build test — don't guessSee references/zig-0.15-migration.md for complete migration details with all code examples, the new Writer/Reader VTable layout, signal handling patterns, format string changes, and allocator API updates.