Skip to main content
Glama
dainemawer
by dainemawer
README.md
# Recount

[![CI](https://github.com/dainemawer/recount/actions/workflows/ci.yml/badge.svg)](https://github.com/dainemawer/recount/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./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