# bippy: Inspecting React Fiber Trees from TypeScript

> bippy exposes React internals so TypeScript applications and developer tools can inspect Fibers, observe commits, and traverse renderer state. Its value comes with a clear trade-off: the project depends on React internals that may change without notice.

**aidenybai/bippy** — ⚠️ hack into react internals

- Repository: https://github.com/aidenybai/bippy
- Website: bippy.dev
- Stars: 1,437 · Forks: 40
- Language: TypeScript
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/aidenybai-bippy

## bippy's Fiber-Level Problem

bippy targets applications that need information ordinary React APIs deliberately withhold. Its purpose is not to manage state, schedule rendering, or provide a component lifecycle hook. Instead, it opens access to React's internal reconciler structures so development tools can inspect the Fiber tree, track render activity, locate Fibers associated with host instances, and reach the renderer that owns a component.

The primary audience is engineers building React metaprogramming, diagnostics, visualization, or developer tooling in TypeScript. A developer might need to associate a DOM button with its Fiber, observe unmount events, or walk from a component toward a host element. bippy exposes these operations through a compact package rather than requiring the consumer to discover and access React DevTools internals independently.

This is a narrow but consequential position in an application. Normal component logic should continue to use React's supported APIs. bippy becomes relevant when an accepted product feature cannot be implemented through props, refs, public hooks, or browser events alone. The README explicitly warns that the project may break production applications and cause unexpected behavior because React internals can change at any time. That warning is part of the design, not a side issue.

## React DevTools Hook and Renderer Flow

The package uses the React DevTools global hook as its entry path into React's runtime. Its main import installs instrumentation before React or a React renderer loads. Once registered, the hook exposes renderers and Fiber roots that bippy can inspect. `getRDTHook` returns the object stored at `globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__`, while renderer-aware functions connect a host instance or Fiber back to its owner.

A host instance, such as a DOM element, can be passed to `getFiber`. The function returns `null` if no registered renderer recognizes it. A matching host Fiber can be recognized with `isHostFiber`, and its `stateNode` exposes the associated renderer instance. `getRenderer` then returns the owning renderer when it remains available. The renderer may offer optional methods such as `overrideProps` or `scheduleUpdate`, but their presence depends on the renderer version.

The ordering constraint is central. The README requires importing bippy before React or any renderer. If another module initializes the relevant runtime first, the package may not observe what it expects. This behavior explains why the README provides framework-specific loading patterns instead of treating the import as an ordinary side-effect-free dependency.

## Commit Instrumentation and Tree Comparison

`instrument` registers lifecycle callbacks and returns an unsubscribe function. The documented handlers cover instrumentation activation, Fiber root scheduling, root commits, post-commit effects, and Fiber unmounts. This gives a tool access to React's reconciler activity rather than only the final browser mutation.

Commit-level render inspection uses `traverseRenderedFibers`. Called from `onCommitFiberRoot`, it visits Fibers that mounted, updated, or unmounted during that commit and supplies the corresponding phase. The README specifically instructs callers to use the same root across commits so bippy can compare the current and previous trees. That requirement is important because a retained Fiber may represent an older render. `getLatestFiber` addresses a related case by returning the latest version of a Fiber.

`didFiberRender` answers only whether a Fiber rendered. It does not establish which commit caused that render. For commit attribution, the documented path is `traverseRenderedFibers`. Separating these APIs prevents a boolean render flag from being mistaken for complete commit history.

`traverseFiber` provides directional tree search. A selector runs for each visited node, `true` stops traversal with the selected Fiber, and a promise selector changes the return value into a promise. Passing `true` as the third argument walks toward the root rather than down the tree. This is useful for relationships such as finding a host button from a component Fiber, but it also means traversal cost depends on tree shape and the selector's early termination.

## Installing bippy Before React

The README gives `npm` as the installation path. After installation, import `bippy` before React or its renderer. The ordering is the part to check carefully in the consuming application.

This installs the published package:

```bash
npm install bippy
```

For a Vite entry point, the documented import order places bippy first, followed by React and the DOM client:

```ts
import "bippy";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
```

The application should observe React initialization only after the bippy side effect has installed its hook integration.

For Next.js 15.3 and later, the README recommends creating `instrumentation-client.ts` at the project root or in `src`. The file contains a single import:

```ts
import "bippy";
```

If only the React DevTools global hook is needed, the minimal entry point avoids the rest of bippy's instrumentation:

```ts
import "bippy/install-hook-only";
```

That narrower option fits tools that only need renderer registration. The full import is the relevant choice when the application also intends to use `instrument` and commit traversal.

## Finding a DOM Button's Fiber

`getFiber` provides the shortest first use because it starts with an object available in the browser. The README's example queries a button, passes it to `getFiber`, and stores the returned Fiber. A `null` result means that no registered renderer recognized the element, which is a real possibility if initialization order or renderer registration is wrong.

This retrieves the Fiber associated with a DOM button:

```ts
import { getFiber } from "bippy";

const element = document.querySelector("button");
const fiber = getFiber(element);
```

For a component that needs its own Fiber, `useFiber` returns the calling component's Fiber. During server rendering it returns `undefined`, because the documentation states that no client Fiber exists for the component in that environment.

```tsx
import { useFiber } from "bippy";

const Component = () => {
  const fiber = useFiber();
  console.log(fiber?.type);
  return null;
};
```

This server-side difference makes `useFiber` unsuitable as a uniform server-and-client identity source. Code that stores or compares the result must handle `undefined`, and application logic should not assume that every component invocation has a client Fiber.

## Observing Unmounts and Scoping Subscriptions

Lifecycle instrumentation is most direct when a tool needs one event category. This example registers `onCommitFiberUnmount`, logs the renderer ID and Fiber, and immediately obtains an unsubscribe function. Calling it detaches the handlers registered by that invocation.

```ts
import { instrument } from "bippy";

const unsubscribe = instrument({
  onCommitFiberUnmount(rendererID, fiber) {
    console.log(rendererID, fiber);
  },
});

unsubscribe();
```

The example is useful for showing the subscription boundary, although a production instrumentation layer would decide when to unsubscribe rather than calling it immediately. The documented choices also include `onActive`, `onScheduleFiberRoot`, `onCommitFiberRoot`, `onPostCommitFiberRoot`, and `onCommitFiberUnmount`.

For utilities that only need hook installation, `bippy/install-hook-only` reduces the scope of the side effect. That can avoid registering bippy's broader instrumentation when a consumer intends to access the DevTools hook directly. The choice also increases the consumer's responsibility: it must know which lower-level operations it wants and which instrumentation remains disabled.

bippy does not document a compatibility matrix for individual React releases or renderer versions in the README. The project uses internals that can change at any time, so version compatibility cannot be inferred solely from its package version or recent release date.

## License, Releases, and Upgrade Exposure

bippy is distributed under the MIT License. That permits use, modification, distribution, and sublicensing subject to the license terms, while copyright and license notices must be retained. This is a factual summary of the repository's declared license, not legal advice about a particular product or distribution model.

The repository is not archived, and its last push was on 2026-10-15. Recent package releases include `bippy@0.7.3` on 2026-08-22, `bippy@0.7.2` on 2026-08-18, and `bippy@0.7.1` on 2026-08-17. The repository is a pnpm workspace whose package scripts include filtering tests for `bippy`, building the package, publishing with Changesets, and running `publint`. Those scripts indicate a release and validation workflow, but they do not remove the compatibility work required when React changes its internals.

The main upgrade cost is behavioral rather than administrative. A new React renderer or React release can alter the structures and methods bippy inspects. The available renderer operations are already documented as optional and version-dependent. A consumer should therefore treat an upgrade as a compatibility check involving its actual renderer, its selected hooks, and its assumptions about retained Fibers.

## When Fiber Inspection Is the Wrong Tool

bippy is the wrong choice when a supported React mechanism can solve the problem. Component state belongs in state and effects, form input belongs behind controlled or uncontrolled component APIs, and cross-component data should normally use an explicit data or context boundary. Reaching into Fibers to solve those ordinary problems creates unnecessary coupling to React's reconciler.

The library is also a poor fit for server-rendered identity workflows that assume `useFiber` always returns a Fiber. The documented return is `undefined` during server rendering. A cross-environment identifier must account for that distinction rather than deriving identity only from the client-side Fiber.

A second failure mode is incorrect initialization. The required import order means a bundler entry point, framework hook, or earlier React import can determine whether instrumentation sees the intended runtime. If `getFiber` returns `null`, that result does not automatically prove that the DOM element has no Fiber. First inspect whether bippy loaded before React and whether the relevant renderer registered itself.

Unlike a supported component observer based on hooks, bippy deliberately works at the internal Fiber layer. The alternative approach is to use React's public APIs for ordinary component visibility and reserve internals-dependent tooling for cases that cannot meet the requirement through supported boundaries.

## Conclusion

Adopt bippy when Fiber-level inspection is necessary, such as for React development tooling, diagnostics, or metaprogramming. Do not adopt it for ordinary application state or production instrumentation unless the team accepts breakage risk from React internals. Verify import order, compatibility with each React renderer in use, commit traversal semantics, and the optional methods exposed by `getRenderer` before release. The central judgement is that bippy is suitable as a deliberate internals interface, not as a stable abstraction over normal React application behavior.

## FAQ

### How do I install bippy in a Vite React application?

Run `npm install bippy`, then import `bippy` at the top of the Vite entry point before imports from `react` or `react-dom/client`. The README identifies import order as essential.

### How do I get the Fiber for a DOM element?

Pass the DOM element to `getFiber`. It returns the associated Fiber when a registered renderer recognizes the instance and `null` otherwise.

### Does useFiber work during server rendering?

No. According to the README, `useFiber` returns `undefined` during server rendering because there is no client Fiber for the component.

### How can I observe React unmount activity with bippy?

Register `onCommitFiberUnmount` through `instrument`. The callback receives the renderer ID and unmounted Fiber, and the function returned by `instrument` unregisters the handlers.

### Can I install only the React DevTools hook integration?

Yes. Importing `bippy/install-hook-only` installs the hook without the rest of bippy's instrumentation.

## Sources

- [aidenybai/bippy on GitHub](https://github.com/aidenybai/bippy)
- [Issues](https://github.com/aidenybai/bippy/issues)
- [License: MIT](https://github.com/aidenybai/bippy/blob/main/LICENSE)
- [README](https://github.com/aidenybai/bippy/blob/main/README.md)
- [Releases](https://github.com/aidenybai/bippy/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/aidenybai-bippy
