All but React Native are in beta.
All but React Native are in beta.

This tool works with both Expo and React Native CLI projects. Just install and go.
Rank the callback origins JS Top can observe by execution time and call count. Compare timers, animation callbacks, and Promise reactions while reproducing a slow interaction. Work outside the wrapped paths appears as unattributed.
The tool uses JavaScript instrumentation and can run in Expo Go. Production access requires Pro.

what's busy, in 74 secondsThis interactive JS Top demo uses simulated busy percentages and callback timings. It does not profile your device.
npm install @buoy-gg/js-topWith auto-discovery, installing the package is all you need — the JS TOP tool and its toggleable busy-pill HUD appear in your floating menu automatically. Or register it explicitly:
import { FloatingDevTools } from "@buoy-gg/core";
import { jsTopPreset, jsTopModalPreset } from "@buoy-gg/js-top";
<FloatingDevTools apps={[jsTopModalPreset, jsTopPreset]} />
import { FloatingDevTools } from "@buoy-gg/core";
import { jsTopPreset, jsTopModalPreset } from "@buoy-gg/js-top";
<FloatingDevTools apps={[jsTopModalPreset, jsTopPreset]} />
You can't sample a blocked JS thread from JavaScript — so JS Top doesn't sample. Instead it wraps every entry point work can take onto the thread (setTimeout, setInterval, setImmediate, requestAnimationFrame, queueMicrotask, Promise reactions, and legacy-bridge call-ins) and measures each callback precisely, attributing the time to where the callback was scheduled from.
Alongside that, a calibrated high-frequency probe measures estimated thread occupancy from timer-gap inflation, and React Native's built-in longtask observer flags every 50ms+ block. Anything the wrappers can't see shows up honestly as an unattributed row — the tool never pretends to a coverage it doesn't have.
With the MCP server, an agent can call get_js_thread_top — the device samples for a few seconds and returns the ranked table, so "why is JS FPS low?" becomes a one-tool-call answer. On a free account it returns the busy % and freezes. The ranked table needs Pro.
async/await continuations through an internal path that bypasses .then — async function bodies also land in unattributed.Install @buoy-gg/js-top and open JS TOP — it ranks every task origin (setInterval ← startPolling, Promise.then ← api.ts, requestAnimationFrame ← rafSpinLoop) by the time it consumed, so the runaway timer or callback appears in the ranking when captured.
No. JS Top is pure JavaScript — it wraps the entry points work takes onto the thread instead of sampling, so it runs in Expo Go, dev builds, and release builds with no debugger attached.
On the New Architecture, touch handlers and React commit work enter the JS thread through paths pure JavaScript can't wrap. That time is reported honestly as unattributed rather than being blamed on the wrong origin. Timers, rAF, microtasks, and Promise chains are attributed when they use the wrapped paths.
Register this package’s /web namespace in FloatingDevTools modules to use its shared panels and actions in a browser app. Import it from the package's /web entry (7.0.41 or later). See Web installation for registration, dependencies, and browser boundaries.