Covering the full lifecycle of projectcreation(generating standard skeletons) andchecking(verifying compliance).
Capability Boundaries
✅ Strengths
- Generate standard Zig project skeletons (
build.zig+build.zig.zon+src/) - Support four project templates: basic exe, basic lib, multi-module layered project, project with third-party dependencies
- Check whether the project directory structure conforms to the official Zig layout
- Verify whether file naming conforms to the
TitleCase.zig/snake_case.zigspecification - Check whether the
build.zigAPI uses removed syntax (such asroot_source_file) - Check the completeness of the
build.zig.zonfields (name, version, paths, minimum_zig_version) - Detect non-standard directory/file naming (vague naming prohibited by TigerStyle such as
utils/、misc.zig) - Output a structured compliance report (error/warning/info three levels)
⚠️ Prerequisites
- Zig compiler installed (recommended ≥ 0.16.0)
- When creating, confirm the target Zig version (run
zig version) - When checking, the project root directory must contain
build.zigorbuild.zig.zon
❌ Not applicable (alternatives)
- Not for writing project logic code → use the
zig-0.16skill - Not for code logic/style review → use the
zig-code-revieworzig-tiger-styleskill - Not for game/graphics development → use the
zig-rayliborzig-sdl3-bindingsskill
When to use
Creation scenarios:
- "Create a new Zig project"
- "Create a multi-module Zig library project"
- "Help me generate a standard build.zig and build.zig.zon"
- "Add a third-party dependency to the project"
Check scenarios:
- "Check whether my Zig project structure is standard"
- "Verify whether my directory organization and file naming conform to Zig standards"
- "Help me review the configuration of build.zig and build.zig.zon"
- "Audit my Zig project compliance"
Data Privacy
This skill does not collect, store, or transmit any user data. All code generation and checking are done locally.
Part One: Project Generation
Workflow
Step 1. Confirm requirements — Project name? exe/lib? Zig version? Are dependencies needed? Step 2. Select template — Select the corresponding template based on the project type Step 3. Generate skeleton — Output the directory structure, build.zig, build.zig.zon, entry file
Template One: Basic Executable Project
{project-name}/
├── build.zig
├── build.zig.zon
├── src/
│ └── main.zig
├── .gitignore
└── README.md
build.zig.zon
.{
.name = "{project-name}",
.version = "0.1.0",
.minimum_zig_version = "0.16.0",
.dependencies = .{},
.paths = .{ "build.zig", "build.zig.zon", "src" },
}
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 = "{project-name}",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
}),
});
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd.addArgs(args);
const run_step = b.step("run", "Run the application");
run_step.dependOn(&run_cmd.step);
}
src/main.zig
const std = @import("std");
pub fn main() void {
std.debug.print("Hello from {s}!\n", .{"{project-name}"});
}
test "simple test" {
try std.testing.expectEqual(2 + 2, 4);
}
Template Two: Library Project
Use src/root.zig as the public API entry point:
{project-name}/
├── build.zig
├── build.zig.zon
├── src/
│ └── root.zig
├── .gitignore
└── README.md
build.zig
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const lib = b.addLibrary(.{
.name = "{project-name}",
.root_module = b.createModule(.{
.root_source_file = b.path("src/root.zig"),
.target = target,
.optimize = optimize,
}),
});
b.installArtifact(lib);
}
Template Three: Large Multi-module Project (Production-grade Pattern)
Refer to the layered architecture of real production Zig projects (such as AgentScope-Zig, 1400+ files):
{project-name}/
├── build.zig # 单一根构建脚本
├── build.zig.zon # 单一根依赖
│
├── {module-core}/ # 核心库(基础类型、消息、状态)
│ └── src/
│ ├── root.zig # 公共 API 入口(显式 re-export)
│ ├── agent/ # 智能体类型
│ ├── message/ # 消息基元
│ ├── session/ # 会话管理
│ ├── memory/ # 记忆管理
│ ├── model/ # 模型适配器
│ ├── formatter/ # 格式化器
│ ├── event/ # 事件系统
│ ├── state/ # 状态管理
│ ├── tool/ # 工具定义
│ ├── skill/ # 技能系统
│ ├── middleware/ # 中间件
│ ├── credential/ # 凭证提供者
│ ├── util/ # 工具类
│ └── tracing/ # 追踪系统
│
├── {module-harness}/ # 基础设施库(依赖 core)
│ └── src/
│ ├── root.zig
│ ├── agent/filesystem/ # 文件系统抽象
│ ├── agent/middleware/ # 服务端中间件
│ ├── agent/sandbox/ # 沙箱接口
│ ├── agent/store/ # 持久化存储
│ ├── agent/subagent/ # 子智能体管理
│ ├── agent/workspace/ # 工作区管理
│ └── main/main.zig
│
├── {module-extensions}/ # 扩展插件(独立包,无 build.zig)
│ ├── {ext-database}/src/root.zig
│ ├── {ext-cache}/src/root.zig
│ └── {ext-storage}/src/root.zig
│
├── examples/{agent}/src/root.zig
├── tests/integration/{test}.zig
├── .gitignore
└── README.md
Multi-module build.zig
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// 模块 1:core 库
const core_mod = b.createModule(.{
.root_source_file = b.path("{module-core}/src/root.zig"),
.target = target,
.optimize = optimize,
});
const core_lib = b.addLibrary(.{ .linkage = .static, .name = "core", .root_module = core_mod });
core_lib.linkLibC();
b.installArtifact(core_lib);
// 模块 2:harness 库(依赖 core)
const harness_mod = b.createModule(.{
.root_source_file = b.path("{module-harness}/src/root.zig"),
.target = target,
.optimize = optimize,
});
harness_mod.addImport("core", core_mod);
const harness_lib = b.addLibrary(.{ .linkage = .static, .name = "harness", .root_module = harness_mod });
harness_lib.linkLibC();
b.installArtifact(harness_lib);
// 聚合测试
const test_step = b.step("test", "运行所有单元测试");
for ([_]*std.Build.Module{ core_mod, harness_mod }) |mod| {
const tests = b.addTest(.{ .root_module = mod });
tests.linkLibC();
test_step.dependOn(&b.addRunArtifact(tests).step);
}
}
Module entry convention ({module-core}/src/root.zig)
The root.zig of each module is the only public API facade, explicitly re-exported grouped by domain:
//! {module-core} 模块入口
pub const Msg = @import("message/msg.zig");
pub const Session = @import("session/session.zig").Session;
pub const Agent = @import("agent/agent.zig").Agent;
pub const AgentBase = @import("agent/agent_base.zig").AgentBase;
pub const ModelConfig = @import("agent/config/model_config.zig").ModelConfig;
pub const JsonCodec = @import("util/json_codec.zig").JsonCodec;
Key design principles for multi-module
| Principles | Description |
|---|---|
| Single root build.zig | Do not split into sub-build.zig files; manage everything uniformly in the root file using createModule management |
| Modules are directories | Each module is a top-level directory with its own src/ + root.zig |
| Explicit import | harness_mod.addImport("core", core_mod) rather than implicit path references |
| Static library linking | .linkage = .static, link C libraries via linkLibC() linking C libraries |
| Extension plugins | Independent directory + its own root.zig, not part of the root build (compiled independently or loaded at runtime) |
Template 4: With third-party dependencies
build.zig.zon
.{
.name = "{project-name}",
.version = "0.1.0",
.minimum_zig_version = "0.16.0",
.dependencies = .{
.known_folders = .{
.url = "https://github.com/ziglibs/known-folders/archive/refs/tags/v0.1.0.tar.gz",
.hash = "1220...",
},
},
.paths = .{ "build.zig", "build.zig.zon", "src" },
}
build.zig(with dependencies)
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const dep = b.dependency("known_folders", .{ .target = target, .optimize = optimize });
const exe = b.addExecutable(.{
.name = "{project-name}",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
.imports = &.{
.{ .name = "known-folders", .module = dep.module("known-folders") },
},
}),
});
b.installArtifact(exe);
}
Part 2: Project specification check
Check Workflow
Step 1. Collect project information — Obtain the directory path, scan the file tree Step 2. Perform four-dimensional check — Directory structure / File naming / Build configuration / Directory naming Step 3. Output compliance report — Output at three levels: error/warning/info
Check 1: Directory structure
Basic project
| Check item | Rule |
|---|---|
build.zig |
Must exist |
build.zig.zon |
Recommended to exist (0.14+ projects should have it) |
src/ directory |
Must exist |
src/main.zig |
Executable project entry point |
src/root.zig |
Library project entry point naming convention |
zig-out/ |
Should be in .gitignore declared in |
.zig-cache/ |
Should be in .gitignore declared in |
Multi-module project
| Check item | Rule |
|---|---|
| Single root build.zig | Should notcreate an independent build.zig in a submodule |
| Module entry point | Each module directory should have src/root.zig as the public API |
| Module naming | Use snake_case(e.g. agentscope-core) |
| Module dependencies | In the root build.zig via addImport explicitly declared |
| Test completeness | Each module should have a corresponding addTest |
| paths coverage | build.zig.zon of paths should include all module directories |
.gitignore check
# 无前缀路径即可覆盖整个项目树
.zig-cache/
zig-out/
*.o
*.obj
*.dll
*.so
*.dylib
.DS_Store
Check 2: File naming
| File purpose | Naming rule | Example |
|---|---|---|
| Type definitions | TitleCase.zig |
User.zig, HttpResponse.zig |
| Namespace/module | snake_case.zig |
json.zig, http_client.zig |
| exe entry point | main.zig |
Fixed name |
| lib entry point | root.zig |
Fixed name |
Incorrect naming detection:
❌ user-service.zig # 中划线不允许,应为 user_service.zig
❌ Utils.zig # TigerStyle 禁止的模糊命名
❌ misc.zig # 同上
❌ DataManager.zig # "Manager" 是冗余词
Check 3: Build configuration
build.zig
| Check item | Rule |
|---|---|
createModule |
Mustuse root_module = b.createModule(...),root_source_file removed |
standardTargetOptions |
Recommended to use |
standardOptimizeOption |
Recommended to use |
installArtifact |
At least one install step |
| Multi-module testing | Each module should have a corresponding addTest, aggregated into zig build test |
// ❌ 已移除
b.addExecutable(.{ .root_source_file = b.path("src/main.zig") });
// ✅ 正确
b.addExecutable(.{ .root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
})});
build.zig.zon
| Field | Required? | Rule |
|---|---|---|
.name |
✅ | All lowercase letters, numbers, and hyphens |
.version |
✅ Recommended | Semver format "0.1.0" or "2.0.0" |
.minimum_zig_version |
✅ Recommended | e.g. "0.16.0" |
.paths |
✅ Recommended | Explicitly declared; multi-module must include all module directories |
.dependencies |
Optional | Must have .url and .hash |
.fingerprint |
Optional | Zig 0.15+ package fingerprint |
Check Four: Directory Naming
| Check item | Rule |
|---|---|
| Directory name | snake_case(lowercase + underscores) |
| No hyphens | Hyphens are not allowed in directory names |
| Avoid vague naming | Avoid utils/、misc/、helpers/、common/ |
| No Java-style paths | Do not use src/main/zig/io/company/(unless left over from Java conversion) |
Shared reference: Naming conventions quick reference
| Element | Convention | Example |
|---|---|---|
| Type name | TitleCase |
XmlParser, HashMap |
| Namespace | snake_case |
std.json, std.mem |
| Function name | camelCase |
readU32Be, parseJson |
| Functions returning types | TitleCase |
ArrayList, HashMap |
| Variables/constants | snake_case |
const_name, global_var |
| Type file | TitleCase.zig |
ArrayList.zig |
| Namespace file | snake_case.zig |
mem.zig, json.zig |
| Directory name | snake_case |
std/, hash_map/ |
| Project name | snake-case (all lowercase with hyphens) | my-app |
══════════════════════════════
项目结构合规报告
══════════════════════════════
项目: {project-name} Zig: {version}
──────────────────────────
🔴 错误(必须修复)
──────────────────────────
1. [DIR-001] 缺少 src/ 目录
修复: mkdir src && mv *.zig src/
2. [BUILD-001] build.zig 使用了已移除的 root_source_file
修复: 使用 root_module = b.createModule(...)
──────────────────────────
⚠️ 警告(建议修复)
──────────────────────────
1. [FILE-001] 文件名不规范: data_manager_util.zig
建议: 若导出类型 DataManagerUtil,应命名为 DataManagerUtil.zig
2. [DIR-002] 模糊命名目录: src/utils/
建议: 使用更具语义化的名称
──────────────────────────
ℹ️ 信息(可选改进)
──────────────────────────
1. [ZON-001] build.zig.zon 缺少 minimum_zig_version
建议: 添加 .minimum_zig_version = "0.16.0"
2. [GIT-001] 缺少 .gitignore
建议: 添加 .gitignore 包含 zig-out/ 和 .zig-cache/
──────────────────────────
📊 汇总: 🔴 错误 2 | ⚠️ 警告 3 | ℹ️ 信息 2
══════════════════════════
Gotchas
root_source_fileremoved — must useroot_module = b.createModule(...)- Package names only allow snake-case —
build.zig.zonof.namecan only be[a-z0-9-]characters - paths must be explicitly declared —
build.zig.zonofpathscontrols the packaging scope; multi-module must include all modules - Entry file goes in src/ — placing
main.zigin the root directory is non-standard zig-out/no prefix needed — root-levelzig-out/automatically covers all submodule directories- Extension plugins do not participate in the root build — in multi-module projects, non-core modules can be independent packages (containing
root.zigbut notbuild.zig) - Only check
.zigfiles —README.md、LICENSEetc. are not constrained by naming conventions
FAQ
Q: Why not use zig init and instead use this skill's generation feature?
A:zig init only generates the most minimal skeleton. This skill provides four templates (exe/lib/multi-module/with dependencies) and has built-in naming convention validation and .gitignore。
Q: Which Zig version is generated? A: Default is Zig 0.16.0. If you need 0.15.x, you can specify the version during interaction.
Q: Does the check require running zig build?
A: No. It detects removed APIs and configuration issues through static analysis of build.zig text.
Q: What naming does TigerStyle prohibit?
A:Value、Data、Context、Manager、utils、misc etc.—because they are too generic to convey specific semantics.