Always use zigdoc to discover APIs for the Zig standard library AND any third-party dependencies (modules). Assume training data is out of date.
Examples:
zigdoc std.fs
zigdoc std.posix.getuid
zigdoc ghostty-vt.Terminal
zigdoc vaxis.WindowNaming:
camelCasefor functions and methodssnake_casefor variables and parametersPascalCasefor types, structs, and enumsSCREAMING_SNAKE_CASEfor constants
Struct initialization: Prefer explicit type annotation with anonymous literals:
const foo: Type = .{ .field = value }; // Good
const foo = Type{ .field = value }; // AvoidFile structure:
//!doc comment describing the moduleconst Self = @This();(for self-referential types)- Imports:
std→builtin→ project modules const log = std.log.scoped(.module_name);
Functions: Order methods as init → deinit → public API → private helpers
Memory: Pass allocators explicitly, use errdefer for cleanup on error
Documentation: Use /// for public API, // for implementation notes. Always explain why, not just what.
Tests: Inline in the same file, register in src/main.zig test block
Inspired by TigerStyle.
Assertions:
- Add assertions that catch real bugs, not trivially true statements
- Focus on API boundaries and state transitions where invariants matter
- Good: bounds checks, null checks before dereference, state machine transitions
- Avoid: asserting something immediately after setting it, checking internal function arguments
Limits:
- Put explicit bounds on all collections and resources
- Define limits as named constants, not magic numbers
- Assert limits are respected before operations
Function size:
- Hard limit of 70 lines per function
- Centralize control flow (switch/if) in parent functions
- Push pure computation to helper functions
Comments:
- Explain why the code exists, not what it does
- Document non-obvious thresholds, timing values, protocol details
- Build:
zig build - Format code:
zig build fmt - Run tests:
zig build test
Tests should live alongside the code in the same file, not in separate test files.
When creating a new source file with tests, add it to the test block in src/main.zig:
test {
_ = @import("new_file.zig");
}Before committing changes, always run:
zig build fmtzig buildzig build test
Title (first line):
- Limit to 60 characters maximum
- Use a short prefix for readability with git log --oneline (do not use "fix:" or "feature:" prefixes)
- Use only lowercase letters except when quoting symbols or known acronyms
- Address only one issue/topic per commit
- Use imperative mood (e.g. "make xyzzy do frotz" instead of "makes xyzzy do frotz")
Body:
- Explain what the patch does and why it is useful
- Use proper English syntax, grammar and punctuation
- Write in imperative mood as if giving orders to the codebase
Trailers:
- If fixing a ticket, use appropriate commit trailers
- If fixing a regression, add a "Fixes:" trailer with the commit id and title