Emetgate: a verification gate between an LLM and your code
Emetgate is an open-source verification kernel on GitHub that sits between a language model and a TypeScript or JavaScript source tree on Windows. The model can only propose changes. The kernel checks hashes, re-parses the result, computes the blast radius, runs tests in a sandbox when needed, and then commits atomically or rejects. The README calls it early.
What Emetgate is
Emetgate is an open-source project on GitHub (emetgate/emetgate) that describes itself as "a deterministic verification kernel that sits between a language model and your source tree". Its motto is "Nothing passes but the truth." The README labels the project as early and deliberately narrow. It targets Windows, is written in Zig 0.16.0, works with TypeScript and JavaScript code, and speaks the Model Context Protocol (MCP), so an MCP client such as Claude Code can talk to it.
The idea is simple to state. A language model may read code and propose a change to one symbol. It may not write a file, and it may not declare work finished. A small kernel checks every proposal and either commits it atomically or rejects it with a reason. The README summarises this as: "The model proposes. The kernel verifies. Nothing unverified reaches the disk."
Why the author built it
The README lists failure modes that anyone who uses LLM-generated code seriously will know: code that compiles and is still wrong, a model that reports a task as done when it is not, a rule stated three turns ago that is silently forgotten, and a plan that has evaporated by the end of a session. The author argues that these look like separate problems but share one cause: nothing between the model and the disk is responsible for checking what the model produced.
According to the README, current tools compete on autonomy and speed, which raises the volume of unverified output. The model cannot close the gap itself, because it is "a sampler, not an oracle" with no persistent memory. So Emetgate gives the model no authority at all and puts all of it in the kernel. The README compares this to LCF-style theorem provers, where tactics may suggest anything but only a small trusted kernel can produce a theorem. The name comes from the legend of the Golem of Prague, in which the word *emet* ("truth") on the golem's forehead animates it, and erasing one letter leaves *met* ("dead").
How a change moves through the gate
The README describes six steps.
1. **Address.** Each symbol is identified by a reference such as `Class.method` or `add`, plus a 128-bit hash of its current content. A proposal must name the hash it was based on. If the file changed in the meantime, the hash no longer matches and the proposal is rejected, so the model cannot overwrite code it has not seen.
2. **Parse.** The new function body is spliced into the source by byte range, and the whole file is re-parsed with tree-sitter.
3. **Guard.** The kernel checks that the result parses cleanly, that the body did not break out of its braces, that it is not empty or a placeholder, and that every byte outside the target span is untouched.
4. **Bound.** The kernel computes the blast radius. The analysis is a positive, closed-world count: a change is `BOUNDED` only when every way it could escape has been ruled out. Anything it cannot account for is `UNBOUNDED`.
5. **Test.** `UNBOUNDED` changes are applied to a shadow copy, and the project's test command runs against it inside a sandbox. The sandbox is a Windows Job Object with kill-on-close, wall-clock and memory limits, and an output cap. The command runs under a low-integrity restricted token. If that token cannot be built and verified, the command is refused rather than run unconfined. A failed test rejects the change and returns the output to the model.
6. **Commit.** Accepted changes go through a write-ahead journal and an atomic write-rename. A crash leaves either the old file or the new one, never a torn write. The `recover` command replays the journal and refuses anything it cannot prove.
The kernel is described as fail-closed: when it cannot prove that a change is safe, the change is refused.
The MCP surface and lockdown
The server exposes tools for reading and for changing code. Read tools include `emetgate_symbols`, `emetgate_skeleton`, `emetgate_read_symbol`, `emetgate_read_file`, `emetgate_list` and `emetgate_search`; the last three are confined to the repository. `emetgate_mutate` verifies a proposed body structurally without writing. `emetgate_try` verifies, gates and commits one body. `emetgate_try_batch` treats several proposals as one unit. `emetgate_scan` measures one check expression against the repository and writes nothing.
The command `emetgate lockdown` starts Claude Code with only these tools available, so the model has no path to the disk other than the gate. The repository also ships a Claude Code skill, `md-audit`, that sorts each instruction sentence in a CLAUDE.md or AGENTS.md file into enforceable, waiting for a mechanism, unverifiable or belief, and measures the enforceable ones with `emetgate_scan`. It changes nothing.
How the kernel is verified
The README says a verification layer that has not been verified "is only a more elaborate way of hoping". It names two practices. The first is mutation testing: guards are mutated (a check removed, a condition weakened, a comparison flipped) and the test suite must fail for each mutant. For the engine modules `cas`, `boundedness`, `symbol` and `functions`, the README reports 44 mutants: 37 killed, 4 proven equivalent, 1 redundant guard kept as defense in depth, and 2 open. The second practice is red-team test suites for escaping bodies, stale hashes, torn journal entries, poisoned repository configuration and file access outside the repository.
The README also reports a token benchmark. On six scenarios (two of them real files) with the `o200k_base` tokenizer, symbol-level proposals used a median of 1.80 times fewer tokens than search-and-replace editing, with a range of 1.15 to 3.77 times. On the real files the gain was 1.15 to 1.17 times. The README calls token savings "a side effect, not the point".
Our analysis
The design choice worth noting is where the trust sits. Many coding tools ask how to make the model more reliable. Emetgate asks how to make its unreliability harmless. Because the checks are deterministic functions of their inputs, a reviewer can read them, test them and attack them. That is a different kind of assurance from a model's own claim that a task is done.
Two details stand out. Content hashes turn "the model edited stale code" from a silent bug into a rejected proposal. And the closed-world boundedness rule defaults to running the tests when unsure, which trades speed for safety.
Limits and open questions
The README is candid about limits. Code that parses, stays in bounds and passes tests can still be wrong. The test gate is only as strong as the tests. The guarantees hold only for changes that go through the gate, so edits from other tools bypass it, which is why lockdown exists. The low-integrity token stops writes outside the shadow copy but does not restrict reading or network access, so a hostile test command could still read files and reach the network. An AppContainer is planned. Architecture, API design and user experience are not things a kernel can check.
From the status table, decision-ledger tools are not yet exposed over MCP and rule enforcement at the edit gate is in progress. Support covers TypeScript and JavaScript only, and Windows only. We only read the README. We did not run the tool, and the benchmark and mutation numbers are the author's own.
Practical takeaways
Teams on Windows with TypeScript or JavaScript can download the release binary and its SHA-256 checksum, compare them, and register the server with `claude mcp add`. The README notes the binary is not code-signed, so SmartScreen warns on first run. Building needs Zig 0.16.0 and uses `zig build`.
The typecheck and test commands come from the operator, through `--typecheck` and `--test` or from `.emetgaterc.json` with `--allow-repo-config`. The model can never supply them. Everyone else can treat the README as a compact statement of a useful principle: give the model no write access, and make every accepted change pass a check that a person can inspect.
Sources
FAQ
What does Emetgate do?
It is a deterministic verification kernel between a language model and your source tree. The model proposes changes to a symbol, and the kernel checks each one and either commits it atomically or rejects it with a reason.
How does it decide whether to run the tests?
It computes a blast radius. A change is BOUNDED only when every way it could escape is ruled out. UNBOUNDED changes run the project's test command on a shadow copy inside a sandbox.
What are the stated limits?
Passing code can still be wrong, the test gate is only as strong as the tests, and edits from other tools bypass the gate. The sandbox does not restrict reading or network access yet. It supports only Windows, TypeScript and JavaScript.