zig-debugging — Claude Code skill: debug Zig with GDB and LLDB
A skill that walks your agent through Zig debugging: panic messages, error return traces, GDB and LLDB sessions. Useful when a build crashes and the trace reads like noise.
npx skills add mohitmishra786/low-level-dev-skills --skill zig-debugging -a claude-codeWhat zig-debugging does
The skill guides an agent through debugging Zig programs. It covers panic messages with file and line, error return traces read bottom-up along the try chain, tracing with std.debug.print, and std.log levels. Build setup gets its own section: zig build-exe src/main.zig -O Debug gives full debug info and safety checks.
GDB and LLDB sessions come with concrete commands — breakpoints, step over and step into, printing variables, backtraces. You also get ways to stop right at a panic: break __zig_panic_start in GDB, b __zig_panic in LLDB. For VS Code there are ready launch.json and tasks.json files built around the zig.vscode-zig extension and CodeLLDB.
One thing to watch: error return traces are off in release builds by default. To keep them in ReleaseFast, set .error_tracing = true in build.zig — otherwise a release crash gives you a bare error code with no call chain. The skill points to related ones: zig-compiler for build modes, gdb and lldb for debugger basics, zig-cinterop for mixed Zig and C code.
What it helps with
- decode a Zig panic message and locate the failing line
- follow an error return trace back to where the error surfaced
- start a GDB or LLDB session on a Zig binary
- add std.debug.print tracing at the right spot
- set up Zig debugging in VS Code with CodeLLDB
Example prompts for the agent
- Build the project in Debug and show me how to break on a panic in GDB
- Here is a Zig panic message — explain what broke
- Why is my error return trace empty in ReleaseFast, and how do I turn it on
How to install zig-debugging
1Skills CLI (Vercel)
npx skills add mohitmishra786/low-level-dev-skills --skill zig-debugging -a claude-code2Manually: put the files in place
~/.claude/skills/zig-debugging/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/zig-debugging/
1Skills CLI (Vercel)
npx skills add mohitmishra786/low-level-dev-skills --skill zig-debugging -a codex2Manually: put the files in place
.agents/skills/zig-debugging/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add mohitmishra786/low-level-dev-skills --skill zig-debugging -a cursor2Manually: put the files in place
.cursor/skills/zig-debugging/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install mohitmishra786/low-level-dev-skills zig-debugging2Manually: put the files in place
.github/skills/zig-debugging/SKILL.md1Skills CLI (Vercel)
npx skills add mohitmishra786/low-level-dev-skills --skill zig-debugging -a gemini-cli2Platform CLI
gemini skills install https://github.com/mohitmishra786/low-level-dev-skills --path skills/zig/zig-debuggingManually: put the files in place
.devin/skills/zig-debugging/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add mohitmishra786/low-level-dev-skills --skill zig-debugging -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about zig-debugging
How do I install zig-debugging in Claude?
Run npx skills add mohitmishra786/low-level-dev-skills --skill zig-debugging -a claude-code. The skill lands in ~/.claude/skills/zig-debugging/SKILL.md.
What does zig-debugging do?
It helps an agent debug Zig programs: reading panics and error return traces, running GDB and LLDB sessions, tracing with std.debug.print, and configuring VS Code debugging.
Why are error return traces missing in release builds?
You have to enable them. Add .error_tracing = true to the executable in build.zig, and the try chain shows up in ReleaseFast too.
Source text
SKILL.md · MIT
---
name: zig-debugging
description: Zig debugging skill. Use when debugging Zig programs with GDB or LLDB, interpreting Zig runtime panics, using std.debug.print for tracing, configuring debug builds, or debugging Zig programs in VS Code. Activates on queries about debugging Zig, Zig panics, zig gdb, zig lldb, std.debug.print, Zig stack traces, or Zig error return traces.
---
# Zig Debugging
## Purpose
Guide agents through debugging Zig programs: GDB/LLDB sessions, interpreting Zig panics and error return traces, `std.debug.print` logging, debug build configuration, and IDE integration.
## Triggers
- "How do I debug a Zig program with GDB?"
- "How do I interpret a Zig panic message?"
- "How do I use std.debug.print for debugging?"
- "Zig is showing an error return trace — what does it mean?"
- "How do I set up Zig debugging in VS Code?"
- "How do I get a stack trace from a Zig crash?"
## Workflow
### 1. Build for debugging
```bash
# Debug build (default) — full debug info, safety checks
zig build-exe src/main.zig -O Debug
# With build system
zig build # uses Debug by default
zig build -Doptimize=Debug
# Run directly with debug output
zig run src/main.zig
```
### 2. GDB with Zig
Zig emits standard DWARF debug information compatible with GDB:
```bash
# Build with debug info
zig build-exe src/main.zig -O Debug -femit-bin=myapp
# Launch GDB
gdb ./myapp
# GDB session
(gdb) break main
(gdb) run arg1 arg2
(gdb) next # step over
(gdb) step # step into
(gdb) continue
(gdb) print my_var
(gdb) info locals
(gdb) bt # backtrace
```
Break on Zig panics:
```gdb
(gdb) break __zig_panic_start
(gdb) break std.builtin.default_panic
```
### 3. LLDB with Zig
```bash
lldb ./myapp
(lldb) b main
(lldb) r arg1 arg2
(lldb) n # next
(lldb) s # step into
(lldb) p my_var # print
(lldb) frame variable
(lldb) bt # backtrace
(lldb) c # continue
# Break on panic
(lldb) b __zig_panic
```
### 4. Interpreting Zig panics
Zig panics include the source location and reason:
```
thread 'main' panic: index out of bounds: index 5, len 3
/home/user/src/main.zig:15:14
/home/user/src/main.zig:42:9
???:?:?: (name not available)
```
Common panic messages:
| Panic | Cause |
|-------|-------|
| `index out of bounds: index N, len M` | Slice/array OOB access |
| `integer overflow` | Arithmetic overflow in Debug/ReleaseSafe |
| `attempt to unwrap null` | Optional access `.?` on null |
| `reached unreachable code` | `unreachable` executed |
| `casting...` | Invalid enum tag or union access |
| `integer cast truncated bits` | `@intCast` with value out of range |
| `out of memory` | Allocator failed |
### 5. Error return traces
Zig tracks where errors propagate with error return traces:
```
error: FileNotFound
/home/user/src/main.zig:30:20: 0x10a3b in openConfig (main)
const f = try std.fs.openFileAbsolute(path, .{});
^
/home/user/src/main.zig:15:25: 0x10b12 in run (main)
const cfg = try openConfig("/etc/myapp.conf");
^
/home/user/src/main.zig:8:20: 0x10c44 in main (main)
try run();
^
```
The trace shows the exact `try` chain where the error propagated. Read bottom-up: `main → run → openConfig`.
Enable in release builds:
```zig
// build.zig
const exe = b.addExecutable(.{
.name = "myapp",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
.error_tracing = true, // enable even in ReleaseFast
});
```
### 6. std.debug.print for tracing
```zig
const std = @import("std");
pub fn main() !void {
const x: u32 = 42;
const name = "world";
// Basic print (always to stderr)
std.debug.print("x = {d}, name = {s}\n", .{ x, name });
// Print any value (useful for structs)
const point = Point{ .x = 1, .y = 2 };
std.debug.print("point = {any}\n", .{point});
// Formatted output
std.debug.print("hex: {x}, binary: {b}\n", .{ x, x });
// Log levels (respects compile-time log level)
const log = std.log.scoped(.my_module);
log.debug("debug info: {d}", .{x});
log.info("started processing", .{});
log.warn("unusual condition", .{});
log.err("failed: {s}", .{"reason"});
}
```
### 7. std.log configuration
```zig
// Override default log level at root
pub const std_options = std.Options{
.log_level = .debug, // .debug | .info | .warn | .err
};
// Custom log handler
pub fn logFn(
comptime level: std.log.Level,
comptime scope: @TypeOf(.enum_literal),
comptime format: []const u8,
args: anytype,
) void {
const prefix = "[" ++ @tagName(level) ++ "] (" ++ @tagName(scope) ++ "): ";
std.debug.print(prefix ++ format ++ "\n", args);
}
pub const std_options = std.Options{
.logFn = logFn,
};
```
### 8. VS Code / IDE integration
Install the `zig.vscode-zig` extension and CodeLLDB.
`.vscode/launch.json`:
```json
{
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug Zig",
"program": "${workspaceFolder}/zig-out/bin/myapp",
"args": [],
"cwd": "${workspaceFolder}",
"preLaunchTask": "zig build"
}
]
}
```
`.vscode/tasks.json`:
```json
{
"version": "2.0.0",
"tasks": [
{
"label": "zig build",
"type": "shell",
"command": "zig build",
"group": { "kind": "build", "isDefault": true },
"problemMatcher": ["$zig"]
}
]
}
```
## Related skills
- Use `skills/zig/zig-compiler` for build modes and debug info flags
- Use `skills/debuggers/gdb` for GDB fundamentals
- Use `skills/debuggers/lldb` for LLDB fundamentals
- Use `skills/zig/zig-cinterop` when debugging mixed Zig/C code
© mohitmishra786 · MIT · mohitmishra786/low-level-dev-skills