Coverage dashboard for binary-matching decompilation projects.
See every byte. Track every match. Ship the decomp.
Install Β· Quick Start Β· Screenshots Β· Potato Mode
recoverage serves a local web dashboard that visualises per-byte match
status across .text, .data, .bss, and other PE sections of a
decompilation project. Think of it as a defrag map for your decomp β
every byte of the original binary is a cell in a grid, colored by how
closely your C code matches the original compiled output.
- Byte-Perfect Confidence: Stop guessing if your C code produced the correct assembly. See exact byte comparisons visually.
- Fast Iteration: Quickly identify which parts of a function are matching and which parts have diverged (e.g. register allocation differences, instruction reordering).
- Interactive Triage: Click any block in the grid to immediately view the corresponding C source, disassembled binary, and hex diff.
| π§± Defrag-style grid | One cell per chunk β Exact (green), Reloc (cyan), Matching (yellow), Stub (red), None (gray) |
| π Function detail panel | Click any cell to see metadata, C source, disassembly, and hex dump side-by-side |
| π Light & dark themes | Retro CRT dark mode by default, clean light mode one click away |
| π Clickable cross-references | Hex addresses in disassembly are live links β click to jump to that chunk |
| π Interactive progress bar | Segmented by status; click a segment to filter the grid |
| ποΈ First draw in first TCP packet | HTML + CSS + JS inlined & compressed (Brotli/Zstd) to ~14.5 KB |
| π₯ Potato Mode | Zero-JS server-rendered fallback for constrained environments |
| π Live regen | One-click re-catalog + rebuild without restarting the server |
Potato Mode is a zero-JavaScript, server-side rendered HTML fallback. Every view is a plain HTML table β no CSS, no JS β so it works on low-spec machines, restricted browsers, or anywhere you just want a quick glance without loading the full SPA.
pip install recoverageFor development:
uv pip install -e .Install an extra to enable its feature: pip install 'recoverage[<extra>]'
(or uv sync --extra <extra> in a workspace).
| Extra | Package | What it does |
|---|---|---|
capstone |
capstone | Enables on-demand disassembly in the detail panel |
pygments |
pygments | Syntax highlighting in Potato Mode |
playwright |
playwright, pytest-playwright | Browser integration tests (tests/test_playwright.py) |
# 1. Generate the coverage database (from your project directory)
uv run rebrew catalog --json
# Analyzes the target binary, parses your annotations, and dumps raw match data to db/data_*.json
uv run rebrew build-db
# Consumes the JSON files and builds a fast SQLite database (db/coverage.db) for the dashboard
# 2. Start the dashboard
uv run recoverage serve
# Starts a lightweight Bottle web server serving the frontend SPA and providing the API backendNote
The server resolves coverage.db from the current working directory:
[project] db_dir in rebrew-project.toml when set, falling back to
db/coverage.db β so run it from your project root.
Start the dashboard web server.
| Flag | Default | Description |
|---|---|---|
--port |
8001 |
HTTP port to serve on |
--bind |
127.0.0.1 |
Interface to bind to (use 0.0.0.0 for LAN access) |
--allow-remote |
off | Required with a non-loopback --bind: acknowledge the API is reachable on the network |
--token |
off | Require this token for every request (Authorization: Bearer, ?token=, or open /?token=<token> to set the SPA cookie) |
--no-open |
off | Don't auto-open the browser |
--regen |
off | Run rebrew catalog + rebrew build-db before starting |
--cors |
off | Enable CORS processing (allowlisted origins only; the wildcard is never emitted) |
--cors-origin |
none | Origin URL allowed to read the API cross-origin (repeatable; without it --cors allows no cross-origin reads) |
Print per-section coverage stats as a Rich table, or as JSON with --json.
recoverage stats # all targets
recoverage stats --target SERVER # single target
recoverage stats --json # machine-readableExport coverage data to stdout.
recoverage export --format json # JSON (default)
recoverage export --format csv # CSV
recoverage export --format md # Markdown tableCI gate β exits non-zero if coverage is below a threshold. Sections the
grid never records matches for (e.g. .bss/.data when only .text
matches are tracked) are skipped, not failed.
recoverage check --min-coverage 60 # all targets, all sections
recoverage check --min-coverage 60 --target SERVER --section .text # specific
recoverage check --min-coverage 60 --json # machine-readable verdictExit codes: 0 = gate passed, 1 = coverage below threshold (or bad input), 2 = infrastructure error (database missing/unreadable).
Re-run rebrew catalog + rebrew build-db to regenerate coverage.db.
recoverage regenrecoverage calls rebrew's catalog and build-db functions as a library, in its
own process, not by spawning the rebrew console script. The run has no
timeout, so it always runs to completion; the dashboard's threaded server keeps
serving while it is busy. A failure exits 1.
Open the dashboard in a browser (useful when --no-open was used).
recoverage open --port 8001| Path | Method | Description |
|---|---|---|
/ |
GET | Main SPA dashboard |
/potato |
GET | Potato Mode (pure-HTML fallback) |
/api/health |
GET | Server version, DB info, installed extras |
/api/targets |
GET | List available targets |
/api/targets/<target>/stats |
GET | Per-section coverage stats with percentages |
/api/targets/<target>/data |
GET | Section + cell data (?section=.text for partial) |
/api/targets/<target>/functions |
GET | Paginated list (?status=&search=&sort=&limit=&offset=) |
/api/targets/<target>/functions |
POST | Batch lookup: {"vas": [...]} β function/global details in input order |
/api/targets/<target>/functions/<va> |
GET | Single function/global detail |
/api/targets/<target>/asm |
GET | Disassembly (?format=json for structured output) |
/api/targets/<target>/sections/<section>/bytes |
GET | Raw byte slice (?offset=&size=) |
/api/events |
GET | Server-Sent Events: db-updated when coverage.db changes (SPA auto-refresh) |
/api/regen |
POST | Re-run catalog + build-db (localhost only, rate-limited) |
recoverage is designed as a standalone consumer of the data that rebrew produces β the two packages are intentionally decoupled.
rebrew catalog --json rebrew build-db recoverage (Bottle + SQLite)
β β β
db/data_*.json βββββββββββΆ db/coverage.db βββββββββββΆ VanJS Dashboard
rebrew catalog --json: Scans your project's source annotations and writes intermediatedb/data_*.jsonfiles containing coverage metrics. Jump table / switch data bytes are absorbed into their parent function's size. Use--export-ghidra-labelsto generateghidra_data_labels.jsonfor round-trip Ghidra sync.rebrew build-db: Consumes those JSON files and builds a structureddb/coverage.db(SQLite,db_version"7") database, storing per-function metadata (detected_by,size_by_tool,textOffset), per-global metadata (module,size), per-cell metadata (label,parent_function), and stampingdb_versionfor schema detection. It also materializes the two objects the dashboard reads instead of re-deriving them on every request: the per-section coverage buckets (section_cell_stats) and the per-section cell JSON (section_cells_json, zstd). Both are derived fromcellsand rebuilt on every build, so a database produced by an older rebrew is still served β the server falls back to the equivalent live queries.rebrew build-dbitself requires--forceto migrate a pre-v7 database. See DB_FORMAT.md for the full schema.recoverage: Starts a Bottle web server. The backend serves API endpoints querying the SQLite database, while the frontend is a zero-build Single Page Application (SPA) powered by VanJS, rendering the interactive defrag grid.
You can run recoverage independently on any machine (or even host it remotely) as long as it has access to a compiled coverage.db. rebrew is a required dependency (it provides the shared workspace/config resolution and the in-process regen), but no project workspace or compiler toolchain is required to serve the dashboard.
recoverage/
βββ pyproject.toml
βββ README.md
βββ docs/ # Screenshots, mascot & design doc
β βββ DESIGN.md # Detailed architecture & design doc
β βββ DESIGN_PRINCIPLES.md # Core operational philosophies
β βββ USER_STORIES.md # User stories with acceptance criteria
β βββ ideas.md # Future improvement ideas
βββ tests/
β βββ conftest.py # Shared fixtures (synthetic coverage.db)
β βββ test_api.py # API validation & security tests
β βββ test_cli.py # CSV export, formatting tests
β βββ test_lifecycle.py # Lifecycle (regen ordering, opener reaping, deadlines)
β βββ test_paths.py # DB path resolution tests
β βββ test_server.py # Compression, encoding tests
β βββ test_potato.py # Potato Mode rendering tests
β βββ test_playwright.py # Browser integration tests
βββ src/recoverage/
βββ __init__.py
βββ __main__.py # python -m recoverage
βββ _paths.py # DB path resolution (rebrew-project.toml db_dir)
βββ cli.py # Typer CLI entry point
βββ server.py # Bottle app, shared helpers & compression
βββ regen.py # In-process rebrew regen (catalog + build-db)
βββ api.py # REST API routes (/api/*)
βββ ui.py # UI routes (/, /potato, static files)
βββ potato.py # Potato Mode renderer
βββ webapp.py # Composition root: imports api+ui so app has every route
βββ assets/
βββ index.html # SPA shell
βββ style.css # All styles
βββ print.css # Print stylesheet
βββ app.js # VanJS frontend
βββ detail.js # Deferred panel logic (hex dump, modal, live reload)
βββ van.min.js # VanJS library (~2 KB)
βββ favicon.svg # Retro "R" logo favicon
βββ hljs.min.js # Highlight.js core
βββ hljs-c.min.js # Highlight.js C grammar
βββ hljs-x86asm.min.js # Highlight.js x86 asm grammar (hex lang is in detail.js)
βββ hljs.css # Highlight.js theme
The browser libraries under src/recoverage/assets/ are vendored so the
dashboard works air-gapped (see docs/DESIGN.md); nothing is fetched from a
CDN at runtime. Licenses and versions are recorded here because the minified
blobs themselves carry little provenance:
| File | Upstream | Version | License |
|---|---|---|---|
van.min.js |
VanJS core, classic-script build (window.van) |
not embedded in the blob | MIT (upstream license) |
hljs.min.js |
Highlight.js core | 11.11.1 (in-file banner) | BSD-3-Clause |
hljs-c.min.js |
Highlight.js c grammar |
compiled for 11.11.1 | BSD-3-Clause |
hljs-x86asm.min.js |
Highlight.js x86asm grammar |
compiled for 11.11.1 | BSD-3-Clause |
hljs.css is a first-party theme (not upstream Highlight.js CSS). When
re-vendoring any of these files, keep the upstream license banner in the
minified output so this table stays verifiable against the blobs.
MIT



