Genie React
Setup

React Native and Expo

Wire a native app or run the Expo demo against the local hub.

The repository includes a real Expo and Metro integration at examples/expo-demo. It mounts Genie with the same QueryClient used by QueryClientProvider and also passes its TanStack Router.

Add Genie to an existing app

Import genie-react/hook first in the entry file, before any import that loads React. Mount the native component once in development:

import { Genie } from 'genie-react/native'

// Inside the app root, using the same QueryClient as QueryClientProvider:
{__DEV__ && (
  <Genie
    appName="My native app"
    url="ws://127.0.0.1:4390/__genie/ws"
    queryClient={queryClient}
  />
)}

Omit queryClient if the app does not use TanStack Query. The optional router prop accepts a TanStack Router. React Navigation and Expo Router need their own app tools for navigation actions.

Start npx @genie-react/cli hub --port 4390 on the development machine. Choose the hub address below for the target. The init command does not wire Metro or native entry files.

Run the Expo demo

From the repository root, install dependencies once:

pnpm install

Start the fixed-port hub in the first terminal:

Terminal 1 — hub
pnpm --filter @genie-react/expo-demo hub

Start one supported local target in a second terminal:

Terminal 2 — iOS Simulator
pnpm --filter @genie-react/expo-demo ios
Terminal 2 — Android Emulator
pnpm --filter @genie-react/expo-demo android

The package also exposes the Expo launcher when you want to choose the target interactively:

Terminal 2 — Expo launcher
pnpm --filter @genie-react/expo-demo start

The bundled defaults cover local virtual devices only:

TargetHub URL
iOS Simulatorws://127.0.0.1:4390/__genie/ws
Android Emulatorws://10.0.2.2:4390/__genie/ws

For a desktop React Native app running on the development machine, use ws://127.0.0.1:4390/__genie/ws.

The hub listens on the development machine's loopback interface. A physical device cannot use these loopback examples directly; it requires an external, tested port forward. This repository does not provide a tunnel command. After that forward exists, point Expo at its reachable address:

EXPO_PUBLIC_GENIE_URL=ws://<forwarded-host>:4390/__genie/ws \
  pnpm --filter @genie-react/expo-demo start

Verify the mounted runtime

After Expo has opened the app, inspect the machine-readable session state from a third terminal and pin subsequent calls to the one ready Expo demo session:

Terminal 3 — agent checks
export GENIE_BRIDGE_URL='ws://localhost:4390/__genie/ws'

status_json="$(
  pnpm --filter @genie-react/expo-demo exec genie-react status
)"
jq '{
  connected,
  ready,
  sessionId,
  sessions: [
    .sessions[]
    | {sessionId, app: .app.name, ready, staleMs, domains, toolCount}
  ]
}' <<<"$status_json"

export GENIE_SESSION="$(
  jq -er '
    [
      .sessions[]
      | select(
          .ready == true and
          .staleMs == null and
          .app.name == "Expo demo"
        )
    ] as $matches
    | if ($matches | length) == 1
      then $matches[0].sessionId
      else error("expected exactly one ready Expo demo session")
      end
  ' <<<"$status_json"
)"

pnpm --filter @genie-react/expo-demo exec genie-react call \
  react_find_components '{"query":"App","exact":true}' \
  | jq '{matches}'

pnpm --filter @genie-react/expo-demo exec genie-react tools

If session selection fails, keep both long-running terminals open, make sure Expo has mounted the screen, then rerun the whole status_json block. Do not reuse an empty or stale session ID.

Import genie-react/hook at the very top of the app's entry file (before anything that loads React), as examples/expo-demo/index.ts does. Without it, tree and inspect tools still work but every render report stays at zero; react_get_renders reports renderCollection as unavailable in that case so the empty report is not mistaken for "nothing re-rendered".

The demo source defines increment-button, counter-value, and genie-hub-url test IDs for a device driver. React Native has no DOM selectors: react_dom_for_component returns native view details, while browser memory and FPS readings are unavailable. Use device-native performance evidence for those measurements.

Run the repository's TypeScript and Metro export checks with:

pnpm --filter @genie-react/expo-demo check

The interaction timeline reports native request timing as unavailable. React events and the supplied Query and TanStack Router integrations can still provide evidence. It does not measure native UI-thread performance or observe every native navigation library.

On this page