Skip to main content
Glama
dainemawer
by dainemawer

Recount

CI License: MIT

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 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)

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 are resolved, so Recount can attach to a running app instead of requiring a pre-exported JSON file.

Contributing

See CODE_OF_CONDUCT.md. Issues and PRs welcome once this is pushed to a public repo.

License

MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/dainemawer/recount'

If you have feedback or need assistance with the MCP directory API, please join our Discord server