Website • enola • GitHub Action • Quickstart • Docs • CLI • Benchmarks • Architecture
Builds and tests verify that the code still works. Enola measures what the change did to the structure of the system: new dependencies, cycles, crossed boundaries and unintended spread.
It gives coding agents an exact architectural map before they edit, compares the graph afterward, and fails only the rules your team chose to enforce. The same verdict runs in the agent loop, a local shell and pull-request CI. Local, deterministic parsers extract the graph directly from multi-language source; no model or embeddings are involved.
The compiler was happy. storage now emails the buyer a receipt. go build and go vet both pass — nothing in the toolchain has an opinion about the innermost layer reaching the outermost one. The next command enforces the layer order this repository declared, the same change fails, and the fix makes the identical command go green.
A real run against examples/layers-gate — no editing, no compositing. No hosted service, API key or account. The four-line layer declaration lives beside the code. Nothing leaves the machine.
Before a change, your agent gets the real structure — modules, symbols, routes, storage and how they depend on each other, extracted from source rather than inferred. It can ask what actually depends on the thing it's about to touch, instead of guessing from a grep.
After a change, enola grades what the change did. It pins the architecture beforehand, compares afterwards, and reports the delta. It's a delta, not a linter — completely silent about everything that was already there, so when it does speak, something moved:
FAIL — 1 structural regression introduced.
Regressions (fail):
- [layers] 1.00 — Layer violation: storage -> delivery
import of notify
Policy: fail on new findings from [layers] at confidence >= 1.00.
Runs in your agent as a hook, in your shell (enola check to report; enola check --fail-on=layers to enforce), and in CI via the GitHub Action — the same verdict and policy in all three.
Nothing fails out of the box. All eighteen explainers run, every finding is reported, and the default run exits 0 while stating that nothing was enforced. You choose what breaks: --fail-on=layers,cycles,intent,constraints, or a change that spread beyond the scope you declared. What counts as an architectural regression is a decision about your codebase; Enola measures the change and makes the active policy explicit. See exactly what can fail and how confidence affects it.
Not a language model, and not embeddings: tree-sitter plus language-specific extractors, a typed fact model, and real graph algorithms. The same commit yields the same answer — across 91 open-source repositories indexed three times each, once cold and twice warm, all 91 produced a byte-identical snapshot ID and a byte-identical fact file: 273 runs, 8.0 million facts, zero parse errors, zero drift. Nothing leaves your machine.
The graph is the substrate; the check is one thing built on it.
- Declared intent — layer order, cross-repo seams and knowledge pages compile into the graph, so what you meant is a fact your agent can query, not a comment.
- A repository's law — what this codebase is not allowed to do, in 21 rule forms, bound from shipped recipes in one command or written as sentences in Ruby.
- The provider seam — facts enola did not extract, admitted fail-closed: Rubydex, Prism, runtime capture, RBS/Sorbet.
- History —
blameanddiffover a shareable store, for the question a single snapshot structurally cannot answer: when did this happen? - 19 MCP tools and eighteen explainers, all of it in the open-source engine — nothing gated, metered or degraded behind a key.
docs/ is the map: every page and the question it answers.
enola-labs/enola— the engine: extractors, cross-repo linker, MCP server, CLI and thecheckgate. Written in Go, Apache 2.0, and it is the whole engine.enola-labs/enola-action— the GitHub Action. Two lines in a workflow file and every pull request is graded against its own base: new findings as source annotations, the structural delta in the job summary, and the same exit code asenola check. No baseline artifact to publish or restore, and the source never leaves the runner.enola-labs/enola-rb— four pure-Ruby gems.enolawraps the released binary, fetches it on first use and forwards every command and exit code unchanged;enola-rbadds the Rails layer — a generator plusenola:snapshotandenola:checkrake tasks.munolaandmunola-rbare the same pair over a second channel.enola-labs/enola-guides— the content layer: guides, worked examples, recipes, twenty-six complete laws, skills and templates, packaged as a gem so a team can pin the guidance it adopted.
The last two are forks. Both were created and are maintained by Muhamed Isabegović, at misabegovic/enola-rb and misabegovic/enola-guides. enola-labs keeps them in step to carry the attribution and to endorse them as the Ruby and Rails integration for enola; the published gems come from upstream, and issues and pull requests belong there.
bundle add enola-rb
bin/rails generate enola:install
bin/rake enola:checkThe generator writes the starter laws, binds the shipped recipes whose roles resolve in your app, and turns both Ruby fact providers on. Rails routes across every engine and plugin route file, mount composed into the mounted engine's own routes, Grape APIs found by transitive inheritance, ActiveRecord / Sequel / Packwerk. The workflow with the output each step prints: docs/RAILS.md.
23 languages and formats, detected rather than configured — enola looks for the markers in your tree and indexes whatever it finds, so a repository that is two languages is indexed as two without being told, and the boundary worth grading is usually the one between them.
Per language, exactly which construct becomes which fact — and what each extractor deliberately does not resolve, stated next to the capability: docs/extraction/. Every example on those pages is copied from a golden file the test suite asserts against.
Point it at a second repository and it links them into one graph — a web client's fetch() to the backend route that serves it, a mobile endpoint enum to that same route, a gRPC call site to the .proto service behind it — so an agent can answer if I change this endpoint, which screens break? by traversal instead of inference.
Read our technical deep-dives on enola.tech/blog:
- We asked enola. to audit HuggingFace's chat-ui. Here's what a staff engineer would notice
- Parsing code is not the same as mapping architecture
- The four memory layers every coding agent needs
- Primary repository: github.com/enola-labs/enola
- Report issues: GitHub Issues
- Contributing: CONTRIBUTING.md
