The Zig compiler that knows how much memory it has.
sig is a drop-in replacement for zig. All your code works. Then you rename a file to .sig and the compiler starts caring about where your bytes come from.
Four platforms. One verified LLVM closure. Sig builds Sig.
$ sig version
sig 0.3.0 (zig 0.17.0-dev)
The packaged zig alias preserves the upstream machine-readable version-only
output, while sig version identifies both the Sig and Zig versions.
| Platform | Backend | Download |
|---|---|---|
| x86_64-linux | Full LLVM 22.1.8 | tar.xz |
| aarch64-linux | Full LLVM 22.1.8 | tar.xz |
| aarch64-macos | Full LLVM 22.1.8 | tar.xz |
| x86_64-windows | Full LLVM 22.1.8 | zip |
Every package contains the same full LLVM target set and the same Sig standard library. Linux and macOS execute on their build hosts, Windows executes on a Windows runner, and aarch64 Linux executes under QEMU user-mode before the release can be published.
The final release is produced by Sig itself. CMake and upstream Zig are absent
from the release stage. The checked-in zig1.wasm chain is used only to create
the native bootstrap set; those bootstraps then compile the four final Sig
executables with immutable LLVM closures.
The .sig extension activates strict mode. Same syntax. Same parser. Same compiler. But allocator usage becomes a compile error.
// foo.zig — business as usual
var list = std.ArrayList(u8).init(allocator);
try list.appendSlice(data);
// foo.sig — you bring the buffer, you know the cost
var buf: [4096]u8 = undefined;
const result = try sig.fmt.formatInto(&buf, "{s}: {d}", .{ name, count });Four errors replace silent reallocation:
| Error | When |
|---|---|
BufferTooSmall |
Output exceeds the caller-provided buffer |
CapacityExceeded |
Bounded container is full |
DepthExceeded |
Recursion hit its limit |
QuotaExceeded |
Resource cap reached |
Standard Zig error unions. try, catch, orelse. Nothing new to learn.
Sig is not a fork. It stays synchronized with upstream Zig within minutes of every commit.
When a new commit lands in ziglang/zig, it fires a GitHub dispatch. The sig-sync workflow cherry-picks the commit, resolves conflicts (keeping sig-owned files), validates the bootstrap, and pushes. If the standard library changed in a way that breaks the bootstrap, it triggers a rebuild chain automatically.
The result: sig never drifts. You get upstream bug fixes, optimizations, and new features without waiting.
| Latest upstream commit | f74dac70 |
| Last sync | 2026-08-09 |
| Upstream | codeberg.org/ziglang/zig |
| Base version | zig 0.17.0-dev · LLVM 22.1.8 |
| Sync frequency | Every commit (< 1 min latency) |
# Download the latest release
mkdir -p sig-toolchain
curl -sL https://github.com/SB0LTD/sig/releases/latest/download/sig-x86_64-linux.tar.xz \
| tar -xJ -C sig-toolchain --strip-components=1
export PATH="$PWD/sig-toolchain/bin:$PATH"
# Or build from source (requires an existing Sig compiler)
git clone https://github.com/SB0LTD/sig.git && cd sig
sig build -OReleaseFastThe executable and lib/ directory are a matched toolchain unit. Normally Sig
finds the adjacent library automatically. If ZIG_LIB_DIR is set globally,
unset it or point it at the extracted sig-toolchain/lib; mixing compiler and
library versions can make the build runner fail before your build begins.
It's a drop-in replacement. Every .zig file compiles unchanged. Rename to .sig when you're ready to go strict.
build-llvm → build-bootstrap → release
7 immutable LLVM closures 4 verified host bootstraps 4 LLVM-backed toolchains
Each stage publishes an exact manifest, SHA-256 set, source commit, producer, and workflow run. Drafts become visible only after every required artifact and target-specific execution probe succeeds. Bootstrap and final compilers also run the canonical 210-test native compiler graph with an explicit fixed stack budget, then cross-compile and validate an AArch64 object.
Same as upstream Zig — MIT. See LICENSE.