npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lensmcp/react-instrumentation

v1.16.8

Published

Zero-config React instrumentation for LensMCP (Babel transform + flow/render runtime).

Readme

@lensmcp/react-instrumentation

Zero-config React instrumentation for LensMCP — a Babel transform plus a render/flow runtime that lets the LensMCP lens see a running React app: which components rendered, which hooks re-ran, and how a click in the browser stitches together with the server request and DB query it triggered.

This package is the React-side half of LensMCP's observability lens. A small Babel plugin rewrites your JSX at build time (stamping component identity, wrapping useEffect/useMemo/useCallback, wrapping interaction handlers, and wrapping the root render). A matching runtime — traced hooks, a <LensmcpRoot> wrapper, and a fetch wrapper (flow-fetch) — emits structured events and propagates a flowId across the network boundary so a single user action can be read end to end (click → fetch → server span → DB query).

You normally don't import any of this by hand. @lensmcp/vite-plugin wires the Babel plugin into your React build, injects the publish channel into the served HTML, and bridges the emitted events to the lens. The exports below are available for projects that can't run the global transform (e.g. opt-in tracing) or want to start a flow manually.

Install

yarn add @lensmcp/react-instrumentation

In practice you don't add it directly — it's pulled in and configured by @lensmcp/vite-plugin, which applies the Babel plugin and sets up the transport. Install it explicitly only for the opt-in, hand-wired path described under Usage.

Usage

The realistic path (automatic). Add @lensmcp/vite-plugin to your Vite config. It loads this package's Babel plugin, so every component, hook, conditional, and interaction handler in your source is instrumented with no app-code changes — and it installs the publish channel that the runtime emits into.

If you can't run the global transform, the runtime is usable directly:

import { createRoot } from 'react-dom/client';
import { LensmcpRoot, installFlowFetch } from '@lensmcp/react-instrumentation';

// Wrap browser fetches so they carry the active flow's headers.
installFlowFetch();

createRoot(document.getElementById('root')!).render(
  <LensmcpRoot page="home" route="/">
    <App />
  </LensmcpRoot>,
);

(This is exactly what the Babel plugin generates automatically when autoWrapRoot is on.) From there you can opt individual pieces in:

import { withTraceComponent, withFlow, tracedUseEffect } from '@lensmcp/react-instrumentation';

// Trace a single component's renders without the global transform.
const TracedPanel = withTraceComponent(Panel, { source: 'src/Panel.tsx' });

// Start a correlated flow from a handler the transform didn't reach.
<button onClick={withFlow(save, { originType: 'user-click', originNodeId: 'ui:save' })}>
  Save
</button>;

// Drop-in useEffect that emits effect-run / effect-cleanup events.
tracedUseEffect('Panel:42:0', () => subscribe(), [topic]);

If you build your own bundler integration, point the runtime at your transport with setPublisher(fn); until a publisher is set, every event is buffered (capped) so the library is safe to import in tests and SSR.

What it captures

  • Component renders — the Babel transform stamps each JSX element with data-agent-component (the component name) and data-agent-source (file:line), and wraps the root in <LensmcpRoot>, whose React <Profiler> emits a render event (mount/update, durations, commit times) on every commit. withTraceComponent does the same for a single opt-in component.
  • HooksuseEffect/useMemo/useCallback are rewritten to traced variants that emit effect-run (plus effect-cleanup) and hook-run events, including a cheap depsHash so the lens can tell whether a hook re-ran because its dependencies changed.
  • Conditional slots<TraceSlot> emits slot-content-changed when the type of the rendered child changes (e.g. a branch swap in a JSX conditional).
  • Browser→server flow correlation (flow-fetch) — interaction handlers are wrapped with withFlow, which opens a flow with a generated flowId. The patched fetch injects x-lensmcp-flow-id + x-lensmcp-origin-node-id headers so the server-side @lensmcp/nest-instrumentation stamps its spans and DB queries with the same flowId, and it publishes fetch-start / fetch-done / fetch-error legs. A short causality window (and an auto-started page-load flow) attributes async post-response re-renders to the action that caused them.
  • Identity — stable logicalIds for components, hooks, and slots plus per-mount instanceIds, so the lens can attribute every event to a specific component instance across re-renders.

API

Exports from the package entry (@lensmcp/react-instrumentation):

| Export | Description | | --- | --- | | LensmcpRoot / LensmcpRootProps | Root wrapper: a <Profiler> + context provider that emits render events and tags hooks with renderer/page/route. | | LensmcpContext / useLensmcpContext / LensmcpIdentityContext | React context (and hook) carrying the active renderer/page/route and component instance identity. | | tracedUseEffect / tracedUseMemo / tracedUseCallback | Drop-in hook replacements that emit effect-run/hook-run events; the transform rewrites bare hooks to these. | | TraceSlot / TraceSlotProps | Wrapper that emits slot-content-changed when its primary child's type changes. | | withTraceComponent / WithTraceOptions | HOC for opt-in render tracing when the global transform isn't available. | | installFlowFetch / FlowFetchOptions | Monkeypatches globalThis.fetch to inject flow headers and publish network legs; returns an uninstall function. | | withFlow | Wraps an event handler so each call runs inside a fresh correlated flow (idempotent; passes non-functions through). | | runInFlow / beginBackgroundFlow / currentFlow / activeFlow / extendFlowWindow | Flow-stack and causality-window primitives for starting/inspecting/extending flows manually. | | publish / setPublisher / drainQueue | The publish channel: emit an event, install the transport, or drain the buffered queue (tests). | | PublishEnvelope / PublishCategory / FlowSpec | Types for the publish envelope, event category, and a flow descriptor. | | componentLogicalId / hookLogicalId / slotLogicalId / makeInstanceId / depsHash / resetIdentityState | Identity helpers — build stable logical ids, per-mount instance ids, and dependency hashes. | | RenderRecord / EffectRecord / HookRecord / SlotChangeRecord / ComponentMountRecord / ReactPublishPayload | Wire-shape types for the events the library publishes. |

Subpath export @lensmcp/react-instrumentation/babel-plugin (also re-exported from the entry as lensmcpBabelPlugin, with LensmcpBabelOptions): the JSX identity transform. Options: production, includeSource, rootDir, autoWrapHooks, autoWrapRoot, autoFlowHandlers, flowEvents. It's dev-only — a no-op when production is true or NODE_ENV === 'production' — and honors // @lensmcp-ignore (file) and data-lensmcp-ignore (element) opt-outs.

// vite.config.ts — applied for you by @lensmcp/vite-plugin
import lensmcpBabel from '@lensmcp/react-instrumentation/babel-plugin';
react({ babel: { plugins: [lensmcpBabel] } });

How it fits

  • Configured by @lensmcp/vite-plugin. The Vite plugin runs lensmcpBabelPlugin over your React source and injects a client runtime that sets window.__LENSMCP_PUBLISH__ — the transport this package's publish() looks for. In dev, events flow over a WebSocket to the lens; in production, over the FrontMCP server transport.
  • Pairs with @lensmcp/valtio-instrumentation. The Vite plugin aliases valtio@lensmcp/valtio-instrumentation so state mutations publish into the same channel, and flowId correlation lets a render here be tied to the state change (and the fetch) that caused it.
  • Server side: @lensmcp/nest-instrumentation. Its TraceInterceptor reads the x-lensmcp-flow-id header set by flow-fetch and stamps server-request, span, and DB-query events with the matching flowId — completing the browser→server story.
  • Events use @lensmcp/protocol-types. The published record shapes (RenderPhase, RenderWhy, etc.) mirror the shared protocol so the lens and reducers can consume them.

Part of LensMCP. Apache-2.0.