zig-best-practiceslisted
Install: claude install-skill aiskillstore/marketplace
# Zig Best Practices
Follows type-first, functional, and error handling patterns from CLAUDE.md. This skill covers Zig-specific idioms only.
## Type System Patterns
**Tagged unions for mutually exclusive states** — prevents invalid combinations that a struct with multiple nullable fields would allow:
```zig
const RequestState = union(enum) {
idle,
loading,
success: []const u8,
failure: anyerror,
};
```
**Explicit error sets** — documents exactly what can fail; `anyerror` hides failure modes:
```zig
const ParseError = error{ InvalidSyntax, UnexpectedToken, EndOfInput };
fn parse(input: []const u8) ParseError!Ast { ... }
```
**Distinct types for domain IDs** — compiler prevents mixing up different ID types:
```zig
const UserId = enum(u64) { _ };
const OrderId = enum(u64) { _ };
```
**Comptime validation** — catch invalid configurations at compile time, not runtime:
```zig
fn Buffer(comptime size: usize) type {
if (size == 0) @compileError("buffer size must be greater than 0");
return struct { data: [size]u8 = undefined, len: usize = 0 };
}
```
## Memory Management
- Pass allocators explicitly to every function that allocates; no global allocator state.
- Place `defer resource.deinit()` immediately after acquisition — keeps cleanup co-located with creation.
- Use `errdefer` for cleanup on error paths; `defer` for unconditional cleanup.
- Use arena allocators for batch/temporary work; they free everything at once.
- Use `std.testing.allocator` in t