zig

Zig ecosystem skill with emerging patterns from zig-syrup

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "zig" with this command: npx skills add plurigrid/asi/plurigrid-asi-zig

zig

Zig ecosystem for systems programming without hidden control flow.

Atomic Skills

SkillCommandsDomain
zig buildbuild systemCompile, link, cross-compile
zig testtestingRun test blocks
zig fmtformatterCanonical formatting
zlsLSPAutocomplete, diagnostics

Quick Start

# New project
mkdir myproject && cd myproject
zig init

# Build and run
zig build run

# Test
zig build test

# Format
zig fmt src/

# Cross-compile to WASM
zig build -Dtarget=wasm32-freestanding

build.zig (0.15.2)

const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "myapp",
        .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());

    const run_step = b.step("run", "Run the application");
    run_step.dependOn(&run_cmd.step);

    const tests = b.addTest(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    const test_step = b.step("test", "Run unit tests");
    test_step.dependOn(&b.addRunArtifact(tests).step);
}

build.zig Module Registration (0.15.2)

When registering many modules in build.zig, Zig 0.15.2 enforces unused-const rules:

// If a module has downstream imports, keep the named const:
const message_frame_mod = b.addModule("message_frame", .{
    .root_source_file = b.path("src/message_frame.zig"),
});

// If a module has NO downstream imports, discard the return value directly:
_ = b.addModule("terminal", .{
    .root_source_file = b.path("src/terminal.zig"),
});

// WRONG — "pointless discard of local constant" error:
// const terminal_mod = b.addModule(...);
// _ = terminal_mod;

// Dependency chaining:
const qrtp_frame_mod = b.addModule("qrtp_frame", .{
    .root_source_file = b.path("src/qrtp_frame.zig"),
    .imports = &.{ .{ .name = "fountain", .module = fountain_mod } },
});

Core Patterns

Explicit Allocators

const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    var list = std.ArrayList(u8).init(allocator);
    defer list.deinit();

    try list.appendSlice("hello");
}

Error Handling

fn readFile(path: []const u8) ![]u8 {
    const file = try std.fs.cwd().openFile(path, .{});
    defer file.close();
    return file.readToEndAlloc(allocator, 1024 * 1024);
}

// Usage with catch
const data = readFile("config.txt") catch |err| {
    std.log.err("Failed: {}", .{err});
    return err;
};

Comptime Metaprogramming

fn Vec(comptime T: type, comptime N: usize) type {
    return struct {
        data: [N]T,

        const Self = @This();

        pub fn dot(self: Self, other: Self) T {
            var sum: T = 0;
            inline for (0..N) |i| {
                sum += self.data[i] * other.data[i];
            }
            return sum;
        }
    };
}

const Vec3 = Vec(f32, 3);

Defer/Errdefer

fn process() !void {
    const resource = try acquire();
    defer release(resource);  // Always runs

    const temp = try allocate();
    errdefer free(temp);  // Only on error

    try doWork(resource, temp);
    // temp ownership transferred, no errdefer needed
}

C Interop

const c = @cImport({
    @cInclude("stdio.h");
    @cInclude("mylib.h");
});

pub fn main() void {
    _ = c.printf("Hello from C\n");
}

Emerging Patterns (zig-syrup)

Pattern 1: SplitMix64 Bijection (Gay.jl Integration)

Comptime modular multiplicative inverse via Newton's method. Enables invertible hashing with Strong Parallelism Invariance (SPI): same (seed, index) gives the same result regardless of call order or parallelism.

pub const SplitMix64 = struct {
    pub const GOLDEN: u64 = 0x9e3779b97f4a7c15;
    pub const MIX1: u64 = 0xbf58476d1ce4e5b9;
    pub const MIX2: u64 = 0x94d049bb133111eb;
    pub const MIX1_INV: u64 = modInverse64(MIX1);
    pub const MIX2_INV: u64 = modInverse64(MIX2);
    state: u64,

    /// Forward bijection: deterministic, invertible.
    pub fn mix(x: u64) u64 {
        var z = x +% GOLDEN;
        z = (z ^ (z >> 30)) *% MIX1;
        z = (z ^ (z >> 27)) *% MIX2;
        return z ^ (z >> 31);
    }

    /// Inverse: unmix(mix(x)) == x for all x.
    pub fn unmix(z: u64) u64 {
        var x = z;
        x ^= x >> 31; x ^= x >> 62;
        x *%= MIX2_INV;
        x ^= x >> 27; x ^= x >> 54;
        x *%= MIX1_INV;
        x ^= x >> 30; x ^= x >> 60;
        x -%= GOLDEN;
        return x;
    }

    /// O(1) random access. SPI-compatible.
    pub fn colorAt(seed: u64, index: u64) u64 {
        return mix(seed ^ index);
    }

    /// Comptime modular inverse mod 2^64 via Newton's method.
    fn modInverse64(a: u64) u64 {
        @setEvalBranchQuota(10000);
        var x: u64 = a;
        x *%= 2 -% a *% x; // doubling correct bits each step
        x *%= 2 -% a *% x;
        x *%= 2 -% a *% x;
        x *%= 2 -% a *% x;
        x *%= 2 -% a *% x; // 64 bits converged
        return x;
    }
};

Key insight: modInverse64 runs entirely at comptime — MIX1_INV and MIX2_INV are compile-time constants. The @setEvalBranchQuota is necessary for the comptime evaluator.

Pattern 2: Three-Mode Tagged Union PRNG

Tagged union for GF(3)-aligned PRNG modes. Each mode has a distinct role:

pub const PrngMode = enum {
    splitmix,  // -1 (MINUS): bijective, invertible, SPI. Default.
    xoshiro,   //  0 (ERGODIC): fast, non-cryptographic.
    chacha,    // +1 (PLUS): CSPRNG for identity proofs.
};

pub const Prng = union(PrngMode) {
    splitmix: SplitMix64,
    xoshiro: std.Random.Xoshiro256,
    chacha: std.Random.ChaCha,

    pub fn init(prng_mode: PrngMode, seed: u64) Prng {
        return switch (prng_mode) {
            .splitmix => .{ .splitmix = SplitMix64.init(seed) },
            .xoshiro => .{ .xoshiro = std.Random.Xoshiro256.init(seed) },
            .chacha => initChaCha(seed),
        };
    }

    pub fn next(self: *Prng) u64 {
        return switch (self.*) {
            .splitmix => |*s| s.next(),
            .xoshiro => |*x| x.next(),
            .chacha => |*c| c.random().int(u64),
        };
    }

    // IMPORTANT: Don't name a method the same as the active tag field.
    // Use `activeMode` instead of `mode` to avoid shadowing.
    pub fn activeMode(self: *const Prng) PrngMode {
        return self.*;
    }
};

Gotcha: pub fn mode(self) would shadow the union's internal mode tag — renamed to activeMode.

Pattern 3: C ABI Callback Abstraction

Platform-agnostic callbacks for hardware interaction (QRTP QR code rendering):

/// Platform renders QR code from raw bytes. Returns 0 on success.
pub const RenderQRFn = *const fn (
    data: [*]const u8,
    data_len: usize,
    context: ?*anyopaque,
) callconv(.c) c_int;

/// Platform scans QR code from camera. Returns decoded length, 0 if none.
pub const ScanQRFn = *const fn (
    buf: [*]u8,
    buf_len: usize,
    context: ?*anyopaque,
) callconv(.c) usize;

pub const TransportConfig = struct {
    render_qr: RenderQRFn,
    scan_qr: ScanQRFn,
    delay: DelayFn,
    context: ?*anyopaque = null,
    frame_delay_ms: u32 = 100,
};

Gotcha (0.15.2): Use callconv(.c) (lowercase). callconv(.C) is a compile error.

Pattern 4: SIMD XOR Block Combining

Fixed-size blocks enable SIMD vectorization without allocations:

pub fn xorBlocks(dst: []u8, src: []const u8) void {
    const len = @min(dst.len, src.len);
    const vec_len = 16;
    const full_vecs = len / vec_len;
    var i: usize = 0;

    while (i < full_vecs * vec_len) : (i += vec_len) {
        const d: @Vector(vec_len, u8) = dst[i..][0..vec_len].*;
        const s: @Vector(vec_len, u8) = src[i..][0..vec_len].*;
        dst[i..][0..vec_len].* = d ^ s;
    }

    // Scalar tail
    while (i < len) : (i += 1) {
        dst[i] ^= src[i];
    }
}

Pattern 5: Sheaf-Theoretic Decoder (Bumpus StructuredDecompositions.jl)

Fountain decoder maps to adhesion_filter from Bumpus's tree decompositions:

  • Source blocks = bags in the tree decomposition
  • Encoded blocks = adhesion spans between bags
  • XOR = pullback projection on the adhesion
  • Belief propagation = sheaf consistency filtering
/// Fountain decoder with adhesion_filter alias.
pub const Decoder = struct {
    // ... source blocks, state, pending buffer ...

    /// Public alias: StructuredDecompositions.jl naming convention.
    pub fn adhesionFilter(self: *Decoder) bool {
        return self.propagate();
    }

    /// Sheaf consistency propagation:
    /// When a bag (source block) is solved, check all adhesion spans
    /// (pending encoded blocks) for newly degree-1 solvable entries.
    fn propagate(self: *Decoder) bool {
        var progress = true;
        while (progress) {
            progress = false;
            // XOR out known blocks from pending, solve degree-1 entries
            // ... (see fountain.zig for full implementation)
        }
        return progress;
    }
};

Pattern 6: Compact Binary Framing (QRTP)

Fixed-layout binary serialization without allocators, fitting QR code capacity:

pub fn encodeFrame(block: *const fountain.EncodedBlock) QrtpFrame {
    var frame = QrtpFrame{};
    var pos: usize = 0;

    @memcpy(frame.data[pos..][0..4], "qrtp");  // 4-byte tag
    pos += 4;
    frame.data[pos] = PROTOCOL_VERSION;         // 1-byte version
    pos += 1;
    writeU64BE(frame.data[pos..], block.seed);  // 8-byte big-endian
    pos += 8;
    // ... indices, payload ...

    frame.len = pos;
    return frame;
}

Zig 0.15.2 Gotchas

IssueWrongRight
C calling conventioncallconv(.C)callconv(.c)
Unused module constconst m = b.addModule(...); _ = m;_ = b.addModule(...)
Method name = tag fieldpub fn mode(self) on union(PrngMode)pub fn activeMode(self)
Hex literal0xGAY, 0xPASSOnly [0-9a-fA-F] valid
Wrapping arithmetica + b (overflow trap)a +% b (wrapping)

Version Detection

// Feature detection over version checks
const has_new_api = @hasDecl(std, "Build");
const T = if (has_new_api) std.Build else std.build.Builder;

Debug

std.debug.print("value: {any}\n", .{x});
std.log.info("structured: {}", .{data});
@breakpoint();  // Debugger trap

Cross-Compile Targets

# List all targets
zig targets | jq '.native'

# Common targets
zig build -Dtarget=x86_64-linux-gnu
zig build -Dtarget=aarch64-macos
zig build -Dtarget=wasm32-wasi
zig build -Dtarget=thumb-none-eabi  # Embedded

Reference: zig-syrup Module Map

ModuleLOCTritRole
fountain.zig907+1Luby Transform encoder/decoder, 3-mode PRNG
qrtp_frame.zig4270Binary framing for QR/TCP transport
qrtp_transport.zig403-1Send/recv via C ABI QR callbacks
message_frame.zig0TCP length-prefixed framing
tcp_transport.zig-1TCP OCapN transport
propagator.zig0Scoped propagators (lattice cells)
color.zig+1Gay.jl Okhsl color space

Related Skills

SkillTritRole
zig-programming-1223 recipes, full docs
rama-gay-zig-1Rama + Gay.jl + Zig interleave
structured-decomp0Bumpus tree decompositions
zig-1Ecosystem wrapper + emerging patterns

GF(3) Triads

zig(-1) ⊗ zls-integration(0) ⊗ c-interop(+1) = 0 ✓
zig(-1) ⊗ acsets(0) ⊗ gay-mcp(+1) = 0 ✓  [Schema coloring]
zig(-1) ⊗ babashka(0) ⊗ duckdb-ies(+1) = 0 ✓  [Build analytics]
zig(-1) ⊗ structured-decomp(0) ⊗ fountain(+1) = 0 ✓  [Sheaf decoder]
zig(-1) ⊗ qrtp-frame(0) ⊗ qrtp-transport(+1) = 0 ✓  [Air-gapped transport]

SDF Interleaving

This skill connects to Software Design for Flexibility (Hanson & Sussman, 2021):

Primary Chapter: 2. Domain-Specific Languages

Concepts: DSL, wrapper, pattern-directed, embedding

GF(3) Balanced Triad

zig (−) + SDF.Ch2 (−) + [balancer] (−) = 0

Skill Trit: -1 (MINUS - verification)

Secondary Chapters

  • Ch4: Pattern Matching
  • Ch6: Layering
  • Ch7: Propagators (fountain decoder = belief propagation)

Connection Pattern

DSLs embed domain knowledge. This skill defines domain-specific operations.

Cat# Integration

This skill maps to Cat# = Comod(P) as a bicomodule:

Trit: -1 (MINUS/Validator)
Home: Prof
Poly Op: ⊗
Kan Role: Ran (right Kan extension)
Color: #3B82F6 (blue)

Why -1 (MINUS)?

Zig validates and constrains:

  • No hidden allocations
  • No hidden control flow
  • No exceptions
  • Explicit error handling
  • Compile-time safety checks

The language itself is a validator — it refuses to compile unsafe patterns.

zig-syrup Cat# Morphisms

fountain.Encoder (+1, Lan_K) →[qrtp_frame (0, Adj)]→ qrtp_transport (-1, Ran_K)
  Presheaves                     Prof                    Span

SplitMix64.mix (−1, Ran) ↔ SplitMix64.unmix (−1, Ran)
  Bijection = isomorphism in Cat#, self-dual in Span

Philosophy

"Zig is not designed to make fancy high-level things. It's designed to make it easy to write correct low-level code."

  • Explicit over implicit
  • Compile-time over runtime
  • No hidden control flow
  • Allocator-aware by design
  • C interop without FFI overhead
  • SPI: same seed → same output regardless of execution order

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

alife

No summary provided by upstream source.

Repository SourceNeeds Review
General

asi-integrated

No summary provided by upstream source.

Repository SourceNeeds Review
General

beeper-mcp

No summary provided by upstream source.

Repository SourceNeeds Review