recount
by dainemawer
README.md
# Recount
[](https://github.com/dainemawer/recount/actions/workflows/ci.yml)
[](./LICENSE)
Your app re-renders too much, and nothing explains why in plain English.
Recount does, for both React (web) and React Native, because it's built on
the same fiber-level change-tracking data both platforms already share
through React DevTools.
Instead of a flame graph or a console.log of raw prop diffs, Recount gives
you a sentence:
> `ProductCard` re-rendered 42 times this session (avg 2.1ms, 88.4ms total).
> Prop `onSelect` changed on every render. Scheduled by `ProductList`.
## Status
Early scaffold. `@recount/core` (the analysis engine) is implemented and
tested against a realistic fixture. The web and React Native connectors are
stubs — see [SPIKE.md](./SPIKE.md) for exactly what's verified versus what
still needs a hands-on spike before they're real. Nothing here is faked or
guessed at: where something is uncertain, it's marked as uncertain rather
than papered over.
## Packages
| Package | What it does |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `@recount/core` | Platform-agnostic analysis engine. Takes normalized `RenderCommit[]` data, returns ranked, narrated `Finding[]`. No AI call — deterministic templates over real numbers. |
| `@recount/cli` | `recount analyze <file>` — run the engine against a JSON export or the bundled demo fixture and print findings to the terminal. |
| `@recount/mcp` | MCP server exposing `list_render_hotspots` and `explain_component` so Claude Code, Cursor, etc. can ask "why is this slow" directly. |
| `@recount/web` | Connector stub for browser React apps, built on `react-devtools-inline`. |
| `@recount/native` | Connector stub for React Native apps, built on `react-devtools-core` (the same package RN's own standalone DevTools uses). |
## Why this is possible for both platforms
React Native's DevTools and the browser extension aren't two separate
tools — both are frontends for the same `react-devtools-shared` backend
agent embedded in the running app. They differ in transport (RN connects
over a WebSocket via `react-devtools-core`; web can attach via
`react-devtools-inline`'s message-channel API), but the data shape —
which fiber committed, which props/state/hooks changed, who scheduled the
update — is identical. `@recount/core` only ever consumes that normalized
shape, so one analysis engine covers both.
## Quick start (core + CLI, works today)
```bash
npm install
npm run build
node packages/cli/dist/index.js analyze --demo
```
This runs the bundled fixture (a `ProductList` / `ProductCard` scenario)
through the engine and prints the findings — no live app or DevTools
connection required yet.
## Roadmap
1. **v1 (this scaffold):** decode-and-rank engine, CLI, MCP server, demo
fixture. No source-level root-cause analysis yet.
2. **v2:** static-analysis heuristics layer — use `SerializedElement.stack`
/ `InspectedElement.source` to point at the file/line responsible, and
flag common causes (inline literals, unstable context values, missing
memoization). Suppress noise for components already compiled by the
React Compiler (`compiledWithForget`).
3. **v3:** real `@recount/web` and `@recount/native` connectors once the
spikes in [SPIKE.md](./SPIKE.md) are resolved, so Recount can attach to
a running app instead of requiring a pre-exported JSON file.
## Contributing
See [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md). Issues and PRs welcome once
this is pushed to a public repo.
## License
MIT
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues