Auditing REA: 15,095 Stars, 133 MCP Tools, and the 209,619-Token Bill for Analysing Eight Files

REA promises to let a coding agent reverse engineer anything, from app behaviour down to native binaries, and 15,095 stars say the pitch landed. I installed rea-agents 5.0.0 and measured the bill: a 90 MB install, a tools/list response of 2,201,441 bytes across 133 MCP tools with only five marked read-only, and a real analysis of an eight-file Electron app that cost 209,619 tokens in output. The evidence model is genuinely excellent — it paired both IPC channels across the process boundary and labelled every inference — and that is exactly why the output is priced for a machine rather than a model. The same query answers in 193 tokens if you know one flag.

“See a feature you like. Understand how it works, down to the binary level.” That is REA’s pitch — one MCP server for reverse engineering across binaries, applications and runtime behaviour — and 15,095 stars on morluto/rea say it landed. The repository is pushed to within an hour of my writing this, ships 26 npm versions in 88 days, and runs 16 GitHub Actions workflows with names like Real Hopper E2E and Real Ghidra Windows E2E.

So I installed rea-agents@5.0.0, spoke raw JSON-RPC to its MCP server, built an eight-file Electron application as a fixture, and pointed the analyser at a 14 MB JavaScript directory to find the edge. What came back is one of the more honest tools I have audited this year, and a bill nobody quotes in the README.

The numbers that reproduce

Everything below is measured on Debian 13, Node.js 26.5.1, npm 11.17.0, rea-agents 5.0.0 from npm, on 2026-10-08.

MeasurementValue
Stars / watchers / forks15,095 / 44 / 1,569
Watcher-to-star ratio0.29%
Open issues + PRs75 + 15
Closed issues + PRs303 + 636
npm versions in 88 days26
npm downloads (38 days)5,778 (≈152/day)
npm install rea-agents@5.0.0131 packages, 11 s, 90 MB
Package itself15 MB, 910 files
MCP tools advertised133
tools/list response size2,201,441 bytes (2.10 MiB)
Tools marked readOnlyHint5 of 133
CLI entries in --help90
Commits by top 4 contributors1,273 of 1,332 (95.6%)

The watcher number is the one I keep coming back to. Watchers are the only GitHub signal that costs the user something — you have to actively ask to be notified — and 44 people want to know what this project does next. The 1,569 forks against those 44 watchers tell a different story than the star count does. And this is not a dormant repository: the weekly commit histogram runs 122, 44, 3, 11, 0, 1, 0, 1, 0, 0, 101, 420 — a near-total standstill from mid-August to late September, then a restart four times larger than the original burst.

What the evidence model actually does

The default advice for tool reviews is to distrust the marketing and read the code, but REA’s selling point is that its output is auditable. So I built the smallest thing that could falsify it: eight files, 2,595 bytes on disk, registering two ipcMain handlers, exposing a contextBridge API with three members, reading one URL constant and one environment variable, and spawning a child process.

REA paired both IPC channels correctly across the main/renderer boundary — license:activate (main handle plus renderer invoke) and sync:start (main on plus renderer send) — and reported 2 paired_renderer_transmissions, 0 unpaired. It resolved preload.js from a filesystem expression, detected the contextBridge API named desktop with three exposed members and zero unknown members, and found the native addon binding. Forty nodes, fifty-seven edges, thirty-one findings, 334 AST nodes visited.

More importantly, it labelled its own work. Every observation carries an authority (for example ast-static-analysis), a state (observed, inferred or unknown), a confidence, an artifact sha256, and a source line/column range. The native addon binding is tagged native_export_verification: not-performed with the limitation “JavaScript syntax identifies requested member names; it does not prove that the native binary exports or implements them.” It reports sender_validation_observations: 0 rather than dropping the field. When I accidentally built a directory where two files differed only in case, it refused with a structured error — category: execution_failure, retryable: false, and a detail naming both colliding files by the exact path difference — instead of guessing.

That is rare. Most agent tooling in this category returns confident JSON and lets you discover the caveats in production.

The bill for that discipline

Here is the same analysis, priced for a model. REA ships its own token counter, so these are the tool’s numbers, not my estimate:

TargetSource bytesOutput tokens (--token-count)Wall time
8-file Electron fixture2,331209,619~1 s
144 JS files58,5703,296,75410 s
250 JS files188,87110,904,86124 s
500 JS files885,28852,951,339127 s
883 JS files (11.7 MB)11,721,249aborted133 s

That is roughly 60,000 tokens of evidence per kilobyte of JavaScript, holding steady across the curve. Eight small files — a toy app a beginner would write in an afternoon — consume more context than most models can hold in a single request. At 500 files the output is 52.9 million tokens, about twenty-six times a two-million-token window. At 883 files the process died with FATAL ERROR: Ineffective mark-compacts near heap limit and a native V8 stack trace, exit code 134, 133 seconds in, on a host with 8 GB of RAM and a default ~2 GB heap.

Where does 209,619 tokens for 2,595 bytes of input go? I dissected the result:

  • 18,391 leaf values, of which 3,422 are identity fields. Identity strings are 199,081 characters — 53.0% of all string bytes in the document, 15.5% of the file.
  • 53 distinct SHA-256 digests, 40 of which appear exactly once. Most digests identify a single observation rather than being reused, so every record carries its own cryptographic name.
  • 604 limitations entries but only 35 distinct strings — a repetition factor of about 17. The same caveats are re-attached to all 586 coverage objects.
  • 12 extractor families, all 12 reporting partial, none reporting complete — even though the top-level coverage.status says complete and truncated: false. Internally consistent, but an agent gating on “is extraction complete?” reads a green light while every extractor says otherwise.
  • call-flow retained 0 relations and logged 33 unknowns. data-flow retained 123, object-flow 17, closure 13.

One detail is worth flagging for anyone who plans to filter that ledger. My fixture’s single child-process site — a spawn whose argv is built with .concat() — is recorded as a call-flow unknown: “Call target spawn has ambiguous or unsupported assignments”, pinned to src/updater.js line 6, column 9. Which is correct and useful. But the child-process extractor family reports status: partial with 0 retained, 0 omitted, 0 unknowns. An agent asked to “show me what the child-process extractor missed” would receive a clean slate.

The 2.10 MiB handshake

The CLI has a token-budget story. The MCP side does not.

Speaking raw JSON-RPC over stdio, tools/list for the shipped 5.0.0 server returns 133 tools in 2,201,441 bytes. All 133 carry an outputSchema; outputSchema is 65% of the payload and inputSchema another 32%, with only 38,739 characters of actual prose description. There are 337 input-schema properties across the whole catalog — 2.53 per tool — and 13 tools whose input schema has no properties at all.

Two more things surfaced in the handshake:

  • Only 5 of 133 tools set annotations.readOnlyHint: true — evaluate_reconstruction_coverage, binary_session, get_evidence_bundle, list_unknowns, verify_unknown_resolution. The other 128, including every inspect_*, list_*, get_*, search_* and read_* tool, leave the hint unset. Clients that gate auto-approval on that annotation will prompt for a read of a string table.
  • The response must be drained concurrently. My first probe read the child process’s stdout into a single buffer after the process exited and captured 63,861 bytes — a truncated JSON object. The payload exceeds the 64 KB pipe buffer, so the server blocks mid-write until someone reads. That is a client-side problem to solve, not a REA defect, but it is a sharp edge for anyone writing their own MCP harness, and it is why my first tools/list parse “failed”.

prompts/list returns six investigation workflows, matching the documentation exactly. resources/list returns an error: there is no resources capability.

Documented versus shipped

REA’s generated catalog is precise enough to be checked, so I checked it against the wire.

docs/product-catalog.json on main declares tools.total: 134 and mcp_tools: 134, with a browser family of 12 tools. The live 5.0.0 server advertises 133. The one tool in the catalog but not in the shipped server is inspect_web_network_capture, which corresponds exactly to the commit feat(browser): inspect historical web network captures (#992) landed 2026-10-07 — after 5.0.0 was published. The released README’s own family table sums to 133, so the shipped artifact is self-consistent and the repository main is simply one feature ahead.

Same shape on the CLI: the catalog declares 89 primary commands, and rea --help lists 90 entries including the infrastructure commands mcp and completions. The released package matches its own documentation; the gap is main-versus-release, which the README does disclose. It is a good sign that the difference is one tool and not thirty.

Where the frontier actually is

REA raises the quality of the evidence an agent works from. It cannot raise the agent. For calibrating that gap, the useful reference is not REA’s own material but SRE-Bench, The Next Challenge for Agentic Cybersecurity (arXiv:2608.11469, 2026-08-11, twelve authors including Raluca Ada Popa and Eric Wallace): 19 private, real-world-scale programs averaging 16.9K lines of code, 44 in-house anti-analysis mechanisms, 262 binary instances and 1,572 deterministically graded tasks. Across 13 agentic settings and 11 models, the paper reports that “GPT-5.6-Sol and Claude-Fable-5.1, despite strong source-code security capabilities, fully solve only 31.5% and 26.9% of graded instances.”

That is the ceiling REA is trying to raise, and 27–32% is where it currently sits. It also reframes what a tool like this is for: not for letting an agent clone an app, but for making each step of an investigation citable, so a wrong conclusion can be found and corrected. REA’s own documentation is explicit that “REA shows how it reached its conclusions. It does not claim to recover original source code or automatically clone an application.”

Who is validating whom

None of REA’s sources publish an accuracy figure, pass rate or precision score for REA itself. The evidence of utility is three case studies the project authored about itself — DX-Ball, Notion, TH04 — and the DX-Ball one is worth inspecting closely because it is the one with numbers attached.

The website reports 55 maintained C functions, 45,380 comparisons with original code, and 33 functions with matching compiled bytes, project checkpoint 7 October 2026. The README separately reports that the sound-pan investigation “passes 3,205 original-x86 cases and reproduces all 63 compiled function bytes” — a narrower claim about a single function, not a contradiction, just two scopes that read alike at a glance.

The artifact behind it, N0zoM1z0/dx-ball, is where things get structurally interesting. As of this measurement:

  • It was created 2026-10-07 at 04:55 UTC — one day before this audit, and the same day as the checkpoint the case study cites.
  • It has 2 stars, 0 watchers, 0 forks, 0 issues, 0 releases, 0 tags.
  • All 49 commits come from a single contributor, and every commit subject is prefixed gpt-6.1-sol: — an agent writing the history of the project that demonstrates the agent tool.
  • Its homepage field points at https://github.com/morluto/rea, and its topics include rea-showcase.
  • Its sole contributor is also REA’s second-largest committer (248 commits).

So the tool, the showcase, the demonstration repository and the repository’s own commit messages are all produced by the same two people and one model, and the public history of the verification artifact is one day deep. That does not make the 45,380 differential comparisons fake — the repository genuinely contains 24 differential test modules and the case study’s assembly-to-C derivation is checkable line by line. It does mean a reader cannot independently corroborate the multi-week trajectory the case study implies, because the git history does not reach back that far.

In fairness, the same audit discipline cuts the other way. This project’s verification culture is unusually deep: 16 workflows, 5,448 total runs, including separate Real Hopper E2E, Real Hopper Linux E2E, Real Ghidra Windows E2E, Real browser verification, Real JavaScript recovery and Real website source-map verification lanes. Of the last 100 runs across all workflows, 80 succeeded, 13 failed, 6 were cancelled. The most recent CI failure (2026-10-08T00:29) is a single job out of twenty-three: Native package baseline (darwin x64) failing at npm run verify:package, with the other 22 jobs green. A 15,000-star project with a red headline check on a feature branch is normal; a 15,000-star project with named real-toolchain E2E lanes is not.

The remedies are real, and they are dramatic

The most useful thing I can hand you is not a verdict, it is a flag. REA costs 209,619 tokens for my fixture by default. The same command with one filter:

rea analyze-javascript-application ./app --filter-output normalized_result.summary --token-count
# 193

193 tokens instead of 209,619. A reduction of about 1,086×, for the summary an agent actually reasons over first. --format md renders the same result in 265,409 bytes against 1,285,968 for --json — 4.8× smaller — and --token-limit / --token-offset exist for paging.

One caveat I can only report, not explain: --token-count returns 209,619 for both --json and the default TOON format, even though TOON renders 1,002,841 bytes against JSON’s 1,285,968. The counter appears to measure the result envelope rather than the text you actually receive, so treat it as a magnitude, not an invoice.

Practical configuration for an agent session: run rea doctor --provider ghidra --json for a scoped readiness check (only scope_checks decide the healthy flag, so an unused missing engine stays informational), start every investigation with a filtered summary, then pull filtered sub-trees on demand rather than ingesting the envelope.

Should you use it

Use it if you want an agent to explain how a feature works, you already own Hopper or Ghidra, and you value a result that says “this is inferred, here is the artifact hash, here is the line” over a result that says nothing about its own confidence. For Electron and JavaScript IPC work specifically, the channel pairing I verified is the kind of output that is genuinely hard to get elsewhere.

Be careful if your target is a real application rather than a fixture. A 500-file directory already produces 52.9 million tokens, and 883 files of 11.7 MB abort with a V8 out-of-memory error rather than a structured “target too large” refusal — the one place where the tool’s discipline about actionable failure did not hold in my testing.

Know before you commit commercially:

ItemStatus
REA licenceMIT
HopperSeparate commercial software, own licence, demo mode with vendor-defined limits; REA does not license it
Ghidra / IDABring-your-own; REA does not install, upgrade or modify them. Ghidra adapter verified with Ghidra 12.1.4 + JDK 21
IDA coverage“A Windows GUI and Windows x64 headless IDA 9.3; other engine/platform combinations remain unverified”
Ghidra on WindowsExplicitly experimental P0, native non-managed non-DLL x86/x86-64 PE on local NTFS, read-only, no mutation authority
Other enginesWakaru 1.13.0, Binwalk, Unblob, JADX, Chromium — all caller-supplied
SandboxingNone. “This is not a sandbox and does not protect against malicious processes already running as the same operating-system user.”
Legal“REA provides tools for lawful reverse-engineering research, analysis, and reconstruction. You are responsible for obtaining any required authorization and complying with applicable laws.”

The platform list is also narrower than “Linux” suggests: macOS 12+, Ubuntu 24.04+, Fedora 41+, 64-bit Arch or CachyOS. On Debian 13, rea doctor --json returns healthy: false with unsupported_host, detail debian 13 — while static JavaScript analysis runs perfectly on that same host, exit code 0, because it needs no disassembler. The host check is a support statement, not a functional gate, and it is worth knowing which one you are reading.

FAQ

Does REA need Ghidra, Hopper or IDA? No. Static JavaScript and Electron analysis needs only Node.js. Native binary analysis needs one of the three engines; the README states that gated workflows need “a selected deep provider”.

Why is the MCP catalog 2.10 MiB? Because all 133 tools publish a full JSON outputSchema, which is 65% of the payload. Models do not normally consume outputSchema, but clients that log or validate it will move 2 MiB on connect.

Can I connect it to any agent? It ships setup for twelve clients (Claude Code, Claude Desktop, Codex, Cursor, Gemini CLI, Windsurf, Devin, OpenCode, Antigravity, GitHub Copilot CLI, Command Code, VS Code) and documents manual MCP configuration for anything else.

Can it recover an application’s source? No, and it says so. It produces pseudocode, assembly, symbols, strings, metadata and relationships — an evidence base an agent can reason over.

What if it hangs on a big target? Two distinct cases: exceeding memory aborts the Node process with a V8 fatal error (mine took 133 s at 883 files), while a structural problem returns a proper error, as it did when my fixture contained two files differing only in case.

Is the evidence trustworthy? Trust the labels, not the volume. observed with confidence: exact and a line range is checkable; inferred with confidence: medium is a candidate. In my fixture, just under half of the extraction families returned zero retained relations while logging their unknowns, which is honest — and also a reminder that 40 nodes and 57 edges is a partial map.

Conclusion

REA is a serious piece of engineering pointed at a hard problem, and it does the hard part well: it produces evidence an auditor can check instead of prose a reader has to trust. Its verification culture — sixteen workflows, real Hopper and Ghidra end-to-end lanes, 80% of recent runs green — is better than most projects with ten times its download volume.

The gap is economic rather than technical. A tool built to feed a model charges that model by the byte, and at ~60,000 tokens per kilobyte of source, its default output is priced for a machine reading files and not for a context window reasoning about them. The fix is already shipped, hidden behind a flag: 193 tokens for the summary instead of 209,619. Start there, pull deeper only when the summary tells you to, and keep the enclosure of self-authored case studies in mind when you decide how much of the 45,380-comparison claim to take on faith.

15,095 stars, 44 watchers, 133 tools and a 2.10 MiB handshake. The craftsmanship is visible; the watcher count is the honest number in the room.