ALPHA Rust · Go · TypeScript · MIT

The AI writes the code.
Two gates decide
if it counts.

hexa scaffolds a project, lets an AI agent build it, and keeps the work only when your test command exits 0 and the architecture grade holds. One binary. No daemon, no database.

$ curl -fsSL https://raw.githubusercontent.com/gaberger/hexa/main/install.sh | bash
~/code — hexa scaffold
$ hexa scaffold "A bookmark service: SQLite store,  HTTP API, tag search" --lang rust --grade A ✓ 8 files (rust) — gate: cargo test✓ floor gate green: cargo test✓ 2 designs → 2 critiques → build GREEN✓ gate re-run: PASS — 27 test(s) ran✓ architecture grade: A+ — 100/100 (floor A) $ 
A+ 100hexa's own grade
0boundary violations
6example projects, re-run clean
3languages: Rust, Go, TS
1binary, nothing running
Why it exists

Generating code stopped being the bottleneck. Checking it didn't.

An AI agent can ship a feature whose tests pass and whose shape is wrong: a use case that imports a database driver, a domain type that depends on an HTTP client. The suite stays green.

Tests answer does it run. Nothing answers is it still the system I designed. hexa adds that second question, as a gate.

Same agent · same task · illustrative
Without hexa
✓ tests pass
– shape not checked
– use case imports the DB driver
merged
With hexa
✓ tests pass
✗ rule 4: use case → adapter
✗ grade below floor A
rejected, edit reverted
Spec-drivenGate-driven (hexa)
The artifactprosea command
Can it fail?noyes, with an exit code
When code driftsthe spec quietly stops being truethe gate goes red
What decides donea person reading two documentsthe exit code
How it works

A deterministic floor, an AI build, and two gates it has to pass.

The model only touches step 3. Everything before it is reproducible, and everything after it is a command with an exit code.

STEP 1

Floor

A skeleton from templates compiled into the binary. Byte-identical on every machine.

deterministic
STEP 2

Floor gate

Does the skeleton build and test here, before any model call?

exit 0
✗ stop
STEP 3

AI build

Designs, critiques, then code onto the floor. The only step a model runs.

model
GATE 1

Does it run?

Your test command, e.g. cargo test.

exit 0
✗ revert
GATE 2

Is it the shape?

The architecture grade must meet your floor.

grade ≥ A
✗ fail build
ship
01

A floor you can reproduce

A scaffold you can't reproduce isn't a foundation, it's a draft. The floor gate runs first because a skeleton that won't build makes everything after it meaningless.

02

Commits only on exit 0

hexa edits, runs your command, and commits only if it passes. Otherwise the edit reverts. A model that wanders commits nothing.

03

Rules travel with the project

Every scaffold ships .hexa/ADR-rules.toml. It's the contract the project keeps being graded against, not a starting point you leave behind.

04

The loop is recorded

.hexa/loop.json keeps each session's decision, gate and evidence. Hooks read it, and feature-sized edits with no gate are stopped.

Specs that can fail

A decision becomes sealed tests before any code exists.

The scenarios come from the decision record and its ports, never the code. A person signs off on what "correct" means, and no agent commit may edit the tests.

MODEL
1

Draft

Given/when/then scenarios from the ADR and its ports alone.

hexa spec draft <ADR>
PERSON
2

Accept

You agree on what "correct" will mean.

hexa spec accept <ADR>
RED
3

Seal

One test per scenario. Each must fail first.

hexa spec tests <ADR>
CI
4

Verify

Every sealed test runs alone. Drift fails the build.

hexa spec verify --ci
Quick start

Install once. Every verb is gated.

The script installs one binary from the latest release. Then hexa bootstrap sets up prerequisites, the inference server and config, and hexa self-update keeps it current.

# the floor alone: deterministic, runnable
$ hexa init ./myapp --scaffold --lang rust

# the floor plus what you described,
# gated on the build AND the grade
$ hexa scaffold "A bookmark service: SQLite store, HTTP API, tag search" \
    --target ./myapp --lang rust --grade A

Longer walkthrough: Getting started. hexa --help lists every verb.

Four concentric layers: adapters outside, then use cases, then ports, with the domain at the centre. Every dependency points inward.ADAPTERSUSE CASESPORTSDOMAINprimaryCLI · HTTPsecondaryDB · LLMevery arrow points inward
Why hexagonal

Because its rules can be checked by a machine.

"Good separation of concerns" can't be graded. Dependencies pointing inward can. hexa analyze walks the AST of every file to check these six rules. Hover one to see its layer.

1domain/ imports only domain/
2ports/ imports domain/ only
3usecases/ imports domain/ and ports/ only
4Adapters import ports/, never the domain directly. A primary adapter may also call usecases/.
5Adapters never import other adapters.
6Only a composition root imports an adapter.

Rule 4 is the one that breaks. Ports re-export the domain types adapters need, so each adapter has one edge into the core and swapping a database touches one file.

The agent loop

A model that wanders commits nothing.

One loop, in process. It gets graph context and ranked lessons, reads and checks with a short list of guarded tools (no arbitrary shell), and proposes one edit. Your evidence command decides.

A pass that exercised nothing is rejected. A failed edit reverts atomically. With several models configured, the first edit that passes wins.

The agent loop: context, reason, read and verify, propose an edit, run the evidence command. Exit 0 commits; anything else reverts and the loop goes again.Contextgraph + ranked lessonsReasonplan the changeRead & verifyguarded tools onlypropose_editone atomic editRun evidenceyour commandexit 0?✓ commit✗ revertgate decidestry again
Why Rust, Go and TypeScript

Each has a compiler, and a compiler is a gate.

A wrong shape fails in seconds, before any test runs. And the grade needs imports that are explicit at build time; duck typing and runtime loading hide the boundaries.

Rust

Strictest. crate::, super::, inline paths and paths inside macros are all read.

Go

Module paths from go.mod decide what's inside the project.

TypeScript

Most forgiving. tsconfig aliases, require() and import() are graded.

Strictness makes the gate stronger and the task harder: weaker models fail Rust and Go where they pass TypeScript. A gate a model can't pass is doing its job.

Evidence

Six projects, each from one sentence.

Every gate re-run from a clean build. The tests were broken on purpose to prove they fail: a passing test proves nothing until you've watched it go red.

10/10

Repaired code it didn't write

Ten single-token bugs in a 1,685-file project. Each line restored exactly, no test edited.

17/17

Refactored code it didn't write

Every boundary violation found, plus five more. A ports layer added, all 177 tests green.

3 bugs

Found what 14 tests missed

A u128 overflow made a rate limiter limit nothing. Only an adversary reading the code caught it.

Every number has a command that checks it in docs/EVIDENCE.md.

Local models

Local models have a ceiling, and it depends on the language.

Same task, pass rate per model. The leaderboard's top local model came last here, so rank doesn't predict how a model does in the loop. Measure yours with hexa bench agentic.

ModelRustTypeScriptGo
devstral-small-2:24b
5/5
3/3
2/3
gemma3:12b
4/5
2/3
1/3
qwen2.5-coder:14b
0/5
2/3
0/3
gpt-oss:20b
0/5
1/3
0/3
Architecture

hexa grades itself, and passes.

Seven crates, one binary, about 67k lines of Rust. Every source file has a layer and every import between crates is checked. A ratchet test fails on any new violation.

A+ 100architecture grade
0 / 0violations / cycles
165/165files with a layer
0runtime deps in hexa-core

Map: ARCHITECTURE.md. Decisions: the append-only ADR ledger.

hexa-clithe binary · every verb is a primary adapter
composes
hexa-execagent loop, harness, guarded tools
hexa-inferevery model adapter
hexa-analysistree-sitter boundary checks
hexa-graphcode knowledge graph
hexa-gitgit over libgit2
all point toward
hexa-coreports and contracts · zero runtime deps
Built with hexa

The badge says how it was made. CI keeps the grade true.

Wardian

Small apps, sealed, served from your own machine.

hexa analyze . --grade A && hexa adr gates

Built something with hexa?

Add the badge to your README and keep hexa analyze . in CI.

built with hexa
Limits

What it doesn't do yet.

Kept on the page on purpose.

Finding a bug from a failing test

Given a rule, hexa finds every file that breaks it. Given only a failing test name, it found the right file once in ten.

No "refactor to a grade" verb

The refactoring trial ran through hexa build with the analyzer as its gate. It worked; it isn't a verb yet.

What a static import can't show

Code a macro generates from an allowed crate, reflection, and FFI. Modules named at run time get a warning, not a pass.

It doesn't write the code

A frontier model does. hexa adds the floor, the gates, the grade and the adversary: it makes a capable model disciplined.

Stop reading two documents. Read the exit code.

One binary for Rust, Go and TypeScript. MIT licensed.

$ curl -fsSL https://raw.githubusercontent.com/gaberger/hexa/main/install.sh | bash