Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
{
"name": "zig-claude-kit",
"source": "./plugins/zig-claude-kit",
"description": "Corrective context for Zig 0.15.x that fixes Claude's outdated training data. Covers I/O (Writergate), build.zig, format strings, ArrayList, BoundedArray, and usingnamespace.",
"description": "Corrective context for Zig 0.15.x and 0.16 that fixes Claude's outdated training data. Auto-detects target from build.zig.zon. Covers Writergate, Io-as-Interface, std.fs->std.Io, Juicy Main, indexOf->find, build.zig, format strings, ArrayList, BoundedArray, usingnamespace.",
"strict": true
},
{
Expand Down
27 changes: 18 additions & 9 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ when working with code in this repository.

A Claude Code plugin marketplace containing three plugins:

- **zig-claude-kit** -- corrective context for Zig 0.15.x
that fixes Claude's outdated training data
- **zig-claude-kit** -- corrective context for Zig 0.15.x and
0.16 that fixes Claude's outdated training data;
auto-detects target from build.zig.zon
- **tdd-pipeline** -- language-agnostic TDD pipeline with
seven agents across separate stages
- **cross-review** -- multi-model code review with
Expand All @@ -26,8 +27,10 @@ plugins/
.claude-plugin/plugin.json # manifest (version here)
skills/ # zig-init, zig-patterns, zig-check
hooks/hooks.json # SessionStart hook
scripts/ # eval suite + session-start
docs/ # fragment, breaking changes ref
scripts/ # eval suite, audit-0.15/0.16,
# session-start, detect-zig-version
docs/ # claude-md-fragment-{0.15,0.16}.md,
# ZIG_BREAKING_CHANGES-{0.15,0.16}.md
tdd-pipeline/
.claude-plugin/plugin.json # manifest (version here)
skills/ # tdd-orchestrate, tdd-init
Expand Down Expand Up @@ -80,13 +83,19 @@ file patterns. No code-level coupling between plugins.
Run from `plugins/zig-claude-kit/`:

```bash
make eval # test all models
make eval-model MODEL=claude-haiku-4-5 # test one model
make compile-test MODEL=claude-sonnet-4-6
make audit # probe current Zig
make audit # auto-detect Zig version
make audit-0.15 # validate 0.15.x claims
make audit-0.16 # validate 0.16 claims

make eval TARGET=0.16 # blind-test default models
make eval-model MODEL=claude-haiku-4-5 TARGET=0.16
make compile-test MODEL=claude-sonnet-4-6 TARGET=0.16
```

Requires `ANTHROPIC_API_KEY` and `uv`.
`make eval` requires `ANTHROPIC_API_KEY` and `uv`; `make audit`
requires `zig` on `PATH`. The `TARGET` variable labels output
probe directories; what actually validates the code is the
locally installed Zig.

## Writing Style

Expand Down
4 changes: 2 additions & 2 deletions plugins/zig-claude-kit/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "zig-claude-kit",
"description": "Corrective context for Zig 0.15.x that fixes Claude's outdated training data. Covers I/O (Writergate), build.zig, format strings, ArrayList, BoundedArray, usingnamespace, division, tokenize, args, JSON, and for-loop index.",
"version": "0.2.1",
"description": "Corrective context for Zig 0.15.x and 0.16 that fixes Claude's outdated training data. Auto-detects target version from build.zig.zon. Covers I/O (Writergate + Io-as-Interface), std.fs -> std.Io move, Juicy Main, std.mem.indexOf -> find, sync primitives moved to Io, @Type split, ArrayList, BoundedArray, usingnamespace, format strings, build.zig, division, tokenize, args, JSON, for-loop index.",
"version": "0.3.0",
"author": {
"name": "Travis Cole"
},
Expand Down
35 changes: 24 additions & 11 deletions plugins/zig-claude-kit/Makefile
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
.PHONY: help eval eval-model compile-test audit clean
.PHONY: help eval eval-model compile-test audit audit-0.15 audit-0.16 clean

help: ## Show available targets
@grep -E '^[a-zA-Z_-]+:.*##' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*## "}; {printf " %-16s %s\n", $$1, $$2}'
@grep -E '^[a-zA-Z_.0-9-]+:.*##' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*## "}; {printf " %-18s %s\n", $$1, $$2}'

# Default Zig target for evals
TARGET ?= 0.16

# --- Model Evaluation ---

eval: ## Blind-test all default models (sonnet + opus 4.6)
uv run scripts/zig-knowledge-eval.py
eval: ## Blind-test default models (TARGET=0.16 or 0.15)
uv run scripts/zig-knowledge-eval.py --target $(TARGET)

eval-model: ## Blind-test a specific model (MODEL=claude-haiku-4-5)
uv run scripts/zig-knowledge-eval.py --models $(MODEL)
eval-model: ## Blind-test one model (MODEL=claude-haiku-4-5 TARGET=0.16)
uv run scripts/zig-knowledge-eval.py --target $(TARGET) --models $(MODEL)

compile-test: ## Compile-test saved probes (MODEL=claude-sonnet-4-6)
./scripts/zig-knowledge-test.sh probes/$(MODEL)
compile-test: ## Compile-test saved probes (MODEL=... TARGET=0.16)
./scripts/zig-knowledge-test.sh probes/$(TARGET)/$(MODEL)

# --- Compiler Probes ---

audit: ## Validate breaking change claims against current Zig
./scripts/zig-knowledge-audit.sh
audit: ## Validate breaking-change claims (auto-detects Zig version)
@if zig version 2>/dev/null | grep -q '^0\.15'; then \
./scripts/zig-knowledge-audit-0.15.sh; \
else \
./scripts/zig-knowledge-audit-0.16.sh; \
fi

audit-0.15: ## Validate 0.15.x claims (requires Zig 0.15.x)
./scripts/zig-knowledge-audit-0.15.sh

audit-0.16: ## Validate 0.16 claims (requires Zig 0.16)
./scripts/zig-knowledge-audit-0.16.sh

# --- Cleanup ---

Expand Down
151 changes: 81 additions & 70 deletions plugins/zig-claude-kit/README.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,64 @@
# zig-claude-kit

Claude generates broken Zig 0.15.x code. This plugin
fixes it by injecting correct patterns into your
project's CLAUDE.md.
Claude generates broken Zig code. This plugin fixes it by
injecting correct patterns into your project's CLAUDE.md.
Supports both **Zig 0.15.x** and **Zig 0.16** -- detected
automatically from `build.zig.zon`.

## The Problem

Claude's Zig training predates 0.15.x. Fourteen test
probes cover twelve broken patterns that produce code
which fails to compile. Testing against Opus 4.6 and
Sonnet 4.6 without project context confirmed all twelve
persist across fresh conversations.
Claude's Zig training predates 0.15.x and is doubly outdated
for 0.16 (the I/O-as-Interface release, 2026-04-14). Fourteen
test probes cover the patterns models consistently get wrong
in blind testing.

## What It Corrects

1. **Writergate** -- `getStdOut()`/`getStdErr()` removed;
buffered writer pattern required
2. **build.zig** -- `.root_source_file` moved inside
`.root_module = b.createModule(...)`
3. **Format specifiers** -- generic `{}` removed; use
`{s}`, `{d}`, `{any}`, or `{f}` for format methods
4. **usingnamespace** -- removed from language
5. **BoundedArray** -- removed; use
**Carried over from 0.15 (still wrong in 0.16):**

1. `usingnamespace` -- removed from the language
2. `async` / `await` keywords -- removed from the language
3. `std.BoundedArray` -- removed; use
`ArrayListUnmanaged.initBuffer`
6. **ArrayList.init()** -- managed API removed; use
`ArrayListUnmanaged{}` with allocator per call
7. **Signed division** -- `/` on runtime signed integers
requires `@divTrunc`
8. **tokenize** -- renamed to `tokenizeAny`,
`tokenizeScalar`, `tokenizeSequence`
9. **process.args()** -- now `argsAlloc(allocator)`;
returns owned slice
10. **For-loop index** -- requires explicit range:
`for (items, 0..) |item, i|`
11. **async/await** -- removed from the language
12. **JSON Parser** -- redesigned to
`std.json.parseFromSlice`
4. `std.ArrayList(T).init(allocator)` -- managed API removed
5. `/` on runtime signed integers -- requires `@divTrunc`
6. `std.mem.tokenize` -- renamed to `tokenizeAny` /
`tokenizeScalar` / `tokenizeSequence`
7. `std.json.Parser` -- redesigned to
`std.json.parseFromSlice`
8. `for (items) |item, i|` -- requires explicit
`for (items, 0..)`
9. Format method signature: `pub fn format(self, writer)`
10. `build.zig` uses `.root_module = b.createModule(...)`

**New in 0.16:**

11. `std.io` -> `std.Io` (and `std.fs.File` -> `std.Io.File`,
`std.fs.Dir` -> `std.Io.Dir`, `std.fs.cwd()` ->
`std.Io.Dir.cwd()`)
12. "Juicy Main": `pub fn main(init: std.process.Init) !void`
brings `gpa`, `io`, `arena`, `environ_map`, `preopens`
13. Every blocking call takes `io` -- `file.close(io)`,
`file.writeStreaming(io, ...)`, `dir.createDir(io, name)`
14. `std.mem.indexOf*` renamed to `find*` (note
`findScalarLast`, with `Last` after `Scalar`)
15. `std.os.environ` gone -- use `init.environ_map`
16. `std.process.argsAlloc` / `argsFree` gone -- use
`init.minimal.args.toSlice(allocator)`
17. `std.process.getCwd` -> `currentPath(io, buf)`
18. `std.process.Child.init(...).spawn()` -> spawn(io, {...})`
19. `std.Thread.Mutex` / `Condition` / `WaitGroup` /
`Pool` -- moved to `std.Io.*` (Pool replaced by
`std.Io.async` / `Group.async`)
20. `std.crypto.random.bytes` -> `io.random(&buf)`
21. `std.time.Instant` / `Timer` / `timestamp` -> single
`std.Io.Timestamp`
22. `@Type` -> 8 builtins (`@Int`, `@Tuple`, `@Struct`, etc.)
23. Managed hash maps gone -- `array_hash_map.Auto` / `String`
/ `Custom` with `.empty`
24. Error renames: `RenameAcrossMountPoints` /
`NotSameFileSystem` -> `CrossDevice`, `SharingViolation`
-> `FileBusy`, `FileTooBig` -> `StreamTooLong`

## Install

Expand All @@ -46,63 +69,51 @@ persist across fresh conversations.

## Use

Open a Zig project. The plugin detects Zig source files
and prompts you to run `/zig-init`. That command appends
corrections to your CLAUDE.md. Every agent reads them
as project context.
Open a Zig project. The plugin detects Zig source files,
reads `build.zig.zon`'s `minimum_zig_version` (or falls back
to `zig version` or the default 0.16), and prompts you to
run `/zig-init`. That command appends the matching
corrections to your CLAUDE.md. Every agent reads them as
project context.

**Commands:**
- `/zig-init` -- inject corrections into CLAUDE.md
- `/zig-patterns` -- quick reference with code examples
- `/zig-check` -- audit source files for outdated APIs
- `/zig-init` -- inject version-matched corrections into
CLAUDE.md
- `/zig-patterns` -- quick reference for both 0.15 and 0.16
- `/zig-check` -- audit source files for outdated APIs (uses
the detected version's ruleset)

If detection picks the wrong version (e.g. you haven't bumped
`build.zig.zon` yet), set `minimum_zig_version` to match and
re-run `/zig-init`.

## Verify

Run the blind-test suite to confirm corrections remain
necessary:
necessary against the current Zig:

```bash
make eval # test all models
make eval-model MODEL=claude-haiku-4-5 # test one model
make audit # probe current Zig
make compile-test MODEL=claude-sonnet-4-6
```

**Prerequisites:** `ANTHROPIC_API_KEY` and `uv`.
make audit # auto-detects from `zig version`
make audit-0.15 # validate 0.15.x claims
make audit-0.16 # validate 0.16 claims

## Latest Results (2026-02-27)

Tested against Zig 0.15.2, no project context.

| Probe | Sonnet 4.6 | Opus 4.6 |
|-------|------------|----------|
| 01 stdout (Writergate) | FAIL | FAIL |
| 02 stderr (Writergate) | FAIL | FAIL* |
| 03 ArrayList | FAIL | FAIL |
| 04 BoundedArray | FAIL | FAIL |
| 05 tokenize | pass | FAIL |
| 06 testing | pass | pass |
| 07 process args | FAIL | FAIL |
| 08 JSON | pass | FAIL |
| 09 format method | FAIL | FAIL |
| 10 mixin (usingnamespace) | FAIL | FAIL |
| 11 division | pass | pass |
| 12 for loop with index | pass | pass |
| 13 build.zig | FAIL* | FAIL* |
| 14 async/await | FAIL | FAIL |
make eval TARGET=0.16 # blind-test default models
make eval-model MODEL=claude-haiku-4-5 TARGET=0.16
make compile-test MODEL=claude-sonnet-4-6 TARGET=0.16
```

\* Compiled only due to lazy analysis. Manual inspection
confirmed wrong patterns.
**Prerequisites:** `ANTHROPIC_API_KEY` and `uv` for eval;
`zig` on `PATH` for audit and compile-test.

When all probes pass without corrections, retire this
plugin.

## Reference

- [Breaking Changes](docs/ZIG_BREAKING_CHANGES.md) --
full reference with error diagnostics
- [CLAUDE.md Fragment](docs/claude-md-fragment.md) --
corrections appended by `/zig-init`
- [Breaking Changes -- 0.15.x](docs/ZIG_BREAKING_CHANGES-0.15.md)
- [Breaking Changes -- 0.16](docs/ZIG_BREAKING_CHANGES-0.16.md)
- [CLAUDE.md Fragment -- 0.15.x](docs/claude-md-fragment-0.15.md)
- [CLAUDE.md Fragment -- 0.16](docs/claude-md-fragment-0.16.md)

## License

Expand Down
Loading