claude/skills/zig/SKILL.md
Use when writing Zig code. Contains Zig 0.15 API changes and patterns.
npx skillsauth add nounder/dotfiles zigInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
In 0.15, std.ArrayList is now the unmanaged version (previously ArrayListUnmanaged). It doesn't store the allocator - you pass it to each method.
// OLD (0.14)
var list = std.ArrayList(T).init(allocator);
defer list.deinit();
try list.append(item);
// NEW (0.15) - std.ArrayList is unmanaged
var list: std.ArrayList(T) = .empty;
defer list.deinit(allocator);
try list.append(allocator, item);
// If you need the managed version (stores allocator):
var list = std.array_list.Managed(T).init(allocator);
defer list.deinit();
try list.append(item);
Note: std.ArrayListUnmanaged is deprecated and now just an alias for std.ArrayList.
// OLD (0.14)
const stdout = std.io.getStdOut().writer();
try stdout.print("{s}\n", .{msg});
// NEW (0.15)
const stdout = std.fs.File.stdout();
try stdout.writeAll(msg);
try stdout.writeAll("\n");
// For formatted output, use bufPrint
var buf: [256]u8 = undefined;
const line = try std.fmt.bufPrint(&buf, "{d}: {s}\n", .{num, str});
try stdout.writeAll(line);
// OLD (0.14)
const file = try std.fs.createFileAbsolute(path, .{});
var writer = file.writer();
try writer.print("{s}\n", .{data});
// NEW (0.15)
const file = try std.fs.createFileAbsolute(path, .{});
var buf: [4096]u8 = undefined;
const line = try std.fmt.bufPrint(&buf, "{s}\n", .{data});
try file.writeAll(line);
// OLD (0.14)
var buf_reader = std.io.bufferedReader(file.reader());
var reader = buf_reader.reader();
while (reader.readUntilDelimiterOrEof(&buf, '\n')) |line| { ... }
// NEW (0.15) - Read whole file, split manually
var buf: [65536]u8 = undefined;
const len = try file.readAll(&buf);
var it = std.mem.splitScalar(u8, buf[0..len], '\n');
while (it.next()) |line| { ... }
fn readFile(allocator: std.mem.Allocator, path: []const u8) ![]u8 {
const file = try std.fs.openFileAbsolute(path, .{});
defer file.close();
var buf: [4096]u8 = undefined;
const len = try file.readAll(&buf);
if (len == 0) return error.EmptyFile;
// Trim trailing newlines
var end = len;
while (end > 0 and (buf[end - 1] == '\n' or buf[end - 1] == '\r')) end -= 1;
const result = try allocator.alloc(u8, end);
@memcpy(result, buf[0..end]);
return result;
}
const home = std.posix.getenv("HOME") orelse return error.NoHome;
const pwd = std.posix.getenv("PWD") orelse ".";
const path = try std.fs.path.join(allocator, &.{ dir, filename });
defer allocator.free(path);
const parent = std.fs.path.dirname(path);
const basename = std.fs.path.basename(path);
const resolved = try std.fs.path.resolve(allocator, &.{ base, relative });
fn isDirectory(path: []const u8) bool {
const stat = std.fs.cwd().statFile(path) catch return false;
return stat.kind == .directory;
}
const args = try std.process.argsAlloc(allocator);
defer std.process.argsFree(allocator, args);
// args[0] is program name, args[1..] are arguments
// Check prefix
if (std.mem.startsWith(u8, str, "prefix")) { ... }
// Split
var it = std.mem.splitScalar(u8, str, '|');
while (it.next()) |part| { ... }
// Index of
if (std.mem.indexOf(u8, haystack, needle)) |pos| { ... }
// Equal
if (std.mem.eql(u8, a, b)) { ... }
// To lowercase (in place with buffer)
var buf: [256]u8 = undefined;
for (str, 0..) |c, i| buf[i] = std.ascii.toLower(c);
const lower = buf[0..str.len];
const now = std.time.timestamp(); // i64 seconds since epoch
const Context = struct { now: i64 };
const ctx = Context{ .now = std.time.timestamp() };
std.mem.sort(T, items, ctx, struct {
fn lessThan(c: Context, a: T, b: T) bool {
return a.value < b.value;
}
}.lessThan);
# Debug build
zig build-exe src/main.zig
# Release build (small)
zig build-exe src/main.zig -O ReleaseSmall -fstrip -fsingle-threaded --name output
# Clean artifacts
rm -f output.o
testing
Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions "grill me".
development
Use this skill any time a spreadsheet file is the primary input or output. This means any task where the user wants to: open, read, edit, or fix an existing .xlsx, .xlsm, .csv, or .tsv file (e.g., adding columns, computing formulas, formatting, charting, cleaning messy data); create a new spreadsheet from scratch or from other data sources; or convert between tabular file formats. Trigger especially when the user references a spreadsheet file by name or path — even casually (like "the xlsx in my downloads") — and wants something done to it or produced from it. Also trigger for cleaning or restructuring messy tabular data files (malformed rows, misplaced headers, junk data) into proper spreadsheets. The deliverable must be a spreadsheet file. Do NOT trigger when the primary deliverable is a Word document, HTML report, standalone Python script, database pipeline, or Google Sheets API integration, even if tabular data is involved.
tools
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.
tools
macOS automation using AppleScript and JavaScript for Automation (JXA). Use when automating macOS apps, controlling system features, scripting applications like Music, Notes, Finder, Safari, or any scriptable app. Use when the user asks about currently opened screens, UI elements, or visible content in any macOS app.