Content
# Scylla
**A hexagonal, adapter-headed reverse-engineering platform.**
<p align="center">
<a href="https://youtu.be/4yzA2shI7HI">
<img src="https://img.youtube.com/vi/4yzA2shI7HI/maxresdefault.jpg" alt="Scylla — watch the demo" width="640">
</a>
<br><em>▶ Watch the demo</em>
</p>
Scylla wraps a proven reverse-engineering engine behind a **durable, transport-agnostic
reverse-engineering domain model** — the *body* — and exposes it through thin,
**disposable protocol adapters** — the *heads*.
Named for the six-headed sea monster of Homer's *Odyssey*: many heads, one immortal
body. Lop a head off and grow a new one. Today there are **nine heads** — an MCP server
(so AI agents reverse-engineer binaries directly), a browser/WASM head, a native serving
binary, a terminal CLI, a remote Cap'n Proto RPC head, an HTTP/JSON gateway, a GraphQL
gateway, a TUI navigator, and an LSP server — all projecting the *same* body. When MCP is the CORBA of 2040, you grow a new head and the
body never notices.
## The idea
Reverse-engineering tools fossilize around the universal adapter of their era
(Ghidra is Java-shaped because the JVM was *the* cross-platform answer circa 2000).
You can't pick a technology that survives 20 years — so don't. Pick the right **seam**
and bet on the slowest-moving layer.
In reverse engineering, the slowest-moving layer is the **domain model itself** —
functions, basic blocks, cross-references, types, the call graph, symbols, decompiled
output, annotations. That vocabulary barely moved from IDA in the '90s to Ghidra in
the 2000s to today, and it won't move much in the next 20 years, because it isn't a
technology — it's the *shape of the problem*.
Scylla's architecture (ports-and-adapters / hexagonal):
- **The body** — a clean, minimal, transport-agnostic contract for the RE domain
model, sitting on top of a proven engine (the engine is sacred; it is never
rewritten).
- **The heads** — thin, sheddable protocol adapters (MCP first; REST/gRPC/whatever
next) that project the body to whatever consumer the era demands. Each head is
~a few hundred lines and disposable; the body is the only bet you can't take back.
You cannot shim your way out of a bad core, so the design effort goes into the body.
The heads are cheap on purpose.
## Before → After
**Before** — the current GayHydra / Ghidra implementation Scylla refactors away from:
a Java monolith with the UI welded to the framework, the proven C++ decompiler reached
across a brittle serialized IPC seam (warts in red, the proven engine in green):

**After** — the hexagonal target Scylla builds toward: a durable **Rust core** holding the
RE domain model as the system's **narrow waist**, GayHydra demoted to a **droppable proven
engine** behind the engine-port, and disposable polyglot **heads** (MCP first) below the
client-port. The two ⟡ bands are the narrow waists; the model-artifact is the one bet you
can't take back:

The reasoning behind every box is recorded in [DesignDecisions.md](DesignDecisions.md) (all
44 decisions); the build path — prototype-first — is in [SprintPlanning.md](SprintPlanning.md);
what shipped when is in [CHANGELOG.md](CHANGELOG.md).
## The heads
One body — the durable RE domain model (`scylla-model`) and the client port over it
(`scylla-port`) — and **nine heads** today. Each is a thin adapter over the same body, but exposes
the subset that fits its protocol: every head navigates; mutation, diff, merge, and export support
varies by head and is called out below.
- **Browser (WASM)** — `crates/scylla-wasm`: the client port compiled to `wasm32`, so a browser
navigates / annotates / **diffs** a `.scylla` model-artifact entirely client-side — no server,
no engine. Renders the call graph as an actual graph, paints a structural diff onto it, searches.
- **Native single binary** — `crates/scylla-serve`: a zero-dependency binary that bakes in the
browser head and serves it + an artifact over HTTP. `scylla-serve old.scylla new.scylla` opens
straight onto *what the rebuild changed*.
- **Terminal** — `crates/scylla-cli` (`scylla`): `materialize` a binary via the engine, then
`diff` / `info` / `functions` / `search` / `view` / `callers` an artifact offline. `scylla diff`
carries `git diff --exit-code` semantics for CI.
- **AI agents (MCP)** — `crates/scylla-mcp`: an MCP server exposing the port 1:1 as tools
(info / list_functions / search / get_function / callers / rename / retype / comment / diff / merge / export),
so an agent reverse-engineers a binary directly. Binary-derived text is wrapped untrusted (DD-035).
- **Remote (Cap'n Proto RPC)** — `crates/scylla-rpc`: `scylla-rpc-serve` serves the model over TCP
and `scylla-rpc-connect` drives it from off-box, navigating by **promise-pipelining**
(`function(id).callers().view()` is one round-trip — the transport the artifact format was chosen
for, DD-002), annotating (rename/retype/comment) and pulling the result back down (`export`).
Auth-gated, connection-capped, slow-loris-bounded, TLS-capable.
- **HTTP/JSON gateway** — `crates/scylla-http`: `scylla-http` serves the model as a plain
HTTP/JSON API (`GET /api/info` / `/api/functions` / `/api/search?q=` / `/api/functions/<id>` / `…/callers`,
`POST /api/diff`) and lets any client *annotate* it (`POST …/rename` / `…/retype` / `…/comment`)
then pull the annotated model back as a `.scylla` (`GET /api/export`), so any language, dashboard,
or `curl` drives the full verb set — including persistence — with no special client.
Token-gated and TLS-capable, like the RPC head.
- **GraphQL** — `crates/scylla-graphql`: `scylla-graphql` serves the model as one typed GraphQL
graph — `query { info, functions, search, function, callers, diff, export }` and
`mutation { rename, retype, comment }` — so a client fetches exactly the function / caller / diff
shape it wants in a single round-trip (no over- or under-fetching), with schema introspection and a
GraphiQL console at `GET /graphql`. Token-gated and TLS-capable, like the HTTP and RPC heads.
- **TUI** — `crates/scylla-tui`: `scylla-tui` is an interactive terminal navigator over the model —
browse the function list, a detail pane (address, basic blocks, size, callees, callers) that
follows the selection, a live `/` search filter, and a structural-diff pane (pass a second
artifact, toggle with `d`) listing renamed / modified / added / removed with per-pair confidence —
all over the client port. The `App` (model +
UI state) is a pure projection of the port, conformance-tested verb-for-verb; the `ratatui` shell
is thin on top.
- **LSP** — `crates/scylla-lsp`: `scylla-lsp` is a Language Server so an editor (nvim, VS Code)
navigates the model like source — the program is one virtual document (functions in address order),
with go-to-symbol (`documentSymbol`), hover (the port's `view`, wrapped untrusted per DD-035),
find-references (= the `callers` verb), rename (the annotate verb, as a `WorkspaceEdit`), and
workspace-symbol (= `search`). Hand-rolled `Content-Length` JSON-RPC; the `dispatch` router is a
headless, conformance-tested port projection.
The **diff** is a real binary-differ: it pairs functions across two builds by structural identity
(address-independent), then climbs the BinDiff-style ladder — call-graph propagation, unique
strings/imports, BSim feature vectors, mnemonic + ordered-trigram cosine — to report functions
matched / renamed / **modified** / added / removed. Fail-closed throughout: a near-tie is never guessed.
## Prerequisites & Building
Building Scylla from source requires Rust and native code generators for the two serialization IDLs:
- **Rust toolchain:** Stable 1.80+ (`rustup default stable`)
- **WASM compilation target:** `rustup target add wasm32-unknown-unknown`
- **Cap'n Proto compiler (`capnp`):** Required by `scylla-schema` and `scylla-rpc`
- macOS: `brew install capnp`
- Ubuntu / Debian: `sudo apt-get install capnproto`
- Arch Linux: `sudo pacman -S capnproto`
- Windows: `choco install capnproto` or `scoop install capnproto`
- **Protocol Buffers compiler (`protoc`):** Required by `scylla-engine`
- macOS: `brew install protobuf`
- Ubuntu / Debian: `sudo apt-get install protobuf-compiler`
- Arch Linux: `sudo pacman -S protobuf`
- Windows: `choco install protoc` or `scoop install protobuf`
- **Node.js (v18+):** Required for browser WASM head verification (`verify.mjs`)
- **JDK 21+ & Gradle:** Required only if building the sandboxed engine-service (`engine-service/`)
Once prerequisites are installed, build and test the entire workspace:
```sh
cargo build --workspace
cargo test --workspace
./scripts/check-wasm.sh
node crates/scylla-wasm/web/verify.mjs
```
## Status
**Feature-complete core, nine working heads.** The durable Rust body (model + client port +
Cap'n Proto model-artifact) is built, with a structural binary-diff engine at parity with the
identity-anchored merge. The heads above all run today over that one body — including a **remote
RPC head** over the Cap'n Proto promise-pipelining surface (DD-002), the transport the format was
chosen for; the heavy JVM engine is reached over gRPC as a droppable producer (DD-009/040) — Scylla
ships no engine; `GHIDRA_DIST` points the service at any unpacked Ghidra distribution (stock
NSA Ghidra or the [GayHydra](https://github.com/CryptoJones/GayHydra) hardened fork).
**Wrapper fidelity is measured, not assumed:** [`abtest/`](abtest/README.md) A/B-tests a C / C++ / Go / Rust
corpus materialized *through* Scylla against the same engine dist's raw `analyzeHeadless` output, field
for field, with both legs committed and replayed on every `cargo test` — see [`abtest/REPORT.md`](abtest/REPORT.md).
## Acknowledgements
Scylla stands on work it has no intention of replacing:
- **[Ghidra](https://github.com/NationalSecurityAgency/ghidra)** (NSA) — the proven
reverse-engineering engine Scylla wraps, by way of the
**[GayHydra](https://github.com/CryptoJones/GayHydra)** hardened fork. The engine is
sacred: Scylla demotes it to a droppable producer behind the engine-port, never rewrites it.
- **[Cap'n Proto](https://capnproto.org)** — the serialization behind the durable
model-artifact (DD-002). The artifact is the one bet Scylla can't take back, so it rests
on a format built for schema evolution and bounded, memory-safe reads — and chosen, too,
for the promise-pipelining RPC the client port will project if a remote head ever needs it.
- **[Protocol Buffers](https://protobuf.dev)** over **[tonic](https://github.com/hyperium/tonic)**
/ **[Prost](https://github.com/tokio-rs/prost)**, on **[Tokio](https://tokio.rs)** — the
gRPC engine-port seam to the sandboxed JVM engine-as-service (DD-009/040).
- The **[Rust](https://www.rust-lang.org)** project and its crate ecosystem — the language
of the durable core.
Two serialization IDLs in one tree — Cap'n Proto on the model/client waist, Protocol
Buffers on the engine seam — is a deliberate, documented choice (see DD-002), not an accident.
## License
[Apache License 2.0](LICENSE) © Aaron K. Clark — matching Ghidra (Apache 2.0), the engine Scylla builds on.
---
*Proudly Made in Nebraska. Go Big Red! 🌽 https://xkcd.com/2347/*
Connection Info
You Might Also Like
No recommendations available