ExecBro
← back to docs

execbro-sdk

Optional, but recommended — it supercharges your coding agent by wiring your state stores, navigation, and any custom reference you choose to expose directly into its reach.

Why use this SDK?

ExecBro works with zero app changes, but installing execbro-sdkis the single biggest upgrade to what your agent can do. It wires the important parts of your app — state stores, navigation, and any other object you pass in — directly into the agent's reach, so it inspects and controls real app state instead of guessing from the outside.

It also closes gaps in the MCP server's default connection. The server talks to your app via Chrome DevTools Protocol (CDP), which works great for most features, but CDP has limitations on newer React Native architectures (Expo SDK 52+, Bridgeless):

Without SDKWith SDK
Startup network requests (auth, config)MissedCaptured from first fetch
Request/response headersPartialFull
Request/response bodiesNot availableFull (including GraphQL)
Console logs from startupMay miss early logsCaptured from first log
State store accessManual via execute_in_appDirect references exposed
Works on Bridgeless (Expo SDK 52+)PartialFull
SetupNoneOne import
Response mocking (network_mock)FullFull

The SDK patches fetch and console at import time and stores everything in an in-app buffer. The MCP server automatically detects the SDK and reads from it, no extra configuration needed.

Installation

Install this package inside your React Native application— it's an in-app SDK, not a CLI or an editor plugin. It belongs in the dependencies of the React Native / Expo app you want to debug, and must be imported from that app's entry file. Installing it anywhere else (globally, in a backend, or next to the MCP server) does nothing.

Run this from the root of your React Native / Expo app:

npm install execbro-sdk

Legacy package name

This SDK was previously published as react-native-ai-devtools-sdk. The legacy name continues to receive identical builds via mirror-publish, existing installations keep working. New installs should use execbro-sdk.

Setup

Add to your app's entry file (index.js, App.tsx, or app/_layout.tsx for Expo Router), must be the first import:

import { init } from 'execbro-sdk';
if (__DEV__) {
  init();
}

// ... rest of your imports

That's it. The MCP tools (get_network_requests, get_logs, etc.) will automatically use the SDK data when available.

Note on response mocking

network_mock, network_condition and network_replaywork identically with or without the SDK. Mocking lives in the MCP server's injected interceptor, not in this SDK, so installing the SDK neither enables nor disables it.

One presentation difference: with the SDK installed, capture comes from the SDK's own buffer under its own request ids, so individual rows are not tagged [MOCK m1]. The active-rules banner on every network read and the per-rule hit counts in network_mock({action:"list"}) still report that traffic is being altered.

With state stores

Pass references to your state management stores for direct AI access:

import { init } from 'execbro-sdk';
import { store } from './store'; // Redux store
import { queryClient } from './queryClient'; // TanStack Query

if (__DEV__) {
  init({
    stores: {
      redux: store,
      queryClient: queryClient,
    },
  });
}

The AI assistant can then inspect store state directly:

execute_in_app with expression="globalThis.__RN_AI_DEVTOOLS__.stores.redux.getState()"

With navigation

Pass your navigation reference for AI-powered navigation inspection:

import { init } from 'execbro-sdk';
import { navigationRef } from './navigation';

if (__DEV__) {
  init({
    navigation: navigationRef,
  });
}

With custom references

Use customto hand the agent direct control over anything that doesn't belong to stores or navigation — AsyncStorage, MMKV, an analytics client, a feature-flag service, your own singletons. Whatever object you pass in, the agent can read from and act through directly:

import { init } from 'execbro-sdk';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { storage } from './mmkv';

if (__DEV__) {
  init({
    custom: {
      asyncStorage: AsyncStorage,
      mmkv: storage,
    },
  });
}

Configuration options

init({
  // Max network entries to buffer (default: 500)
  maxNetworkEntries: 500,

  // Max console entries to buffer (default: 500)
  maxConsoleEntries: 500,

  // State store references for AI access
  stores: {
    redux: reduxStore,
    queryClient: queryClient,
    userStore: useUserStore,
  },

  // Navigation reference
  navigation: navigationRef,

  // Any additional references for AI access
  custom: {
    asyncStorage: AsyncStorage,
    mmkv: storage,
  },
});

How it works

Architecture

React Native App
  |
  |  1. import { init } from 'execbro-sdk'
  |     -> patches globalThis.fetch (captures all network requests)
  |     -> patches console.log/warn/error/info/debug (captures all logs)
  |     -> stores references to state management stores
  |     -> exposes globalThis.__RN_AI_DEVTOOLS__ with query methods
  |
  |  2. App runs normally - all fetch() calls and console output
  |     are intercepted, stored in circular buffers, and passed
  |     through to their original implementations unchanged
  |
  v
ExecBro MCP Server (npm: execbro)
  |
  |  3. Connects to app via CDP (Chrome DevTools Protocol)
  |     Detects SDK: typeof globalThis.__RN_AI_DEVTOOLS__?.getNetworkEntries === "function"
  |
  |  4. MCP tools read SDK data via Runtime.evaluate:
  |     get_network_requests -> globalThis.__RN_AI_DEVTOOLS__.getNetworkEntries()
  |     get_logs             -> globalThis.__RN_AI_DEVTOOLS__.getConsoleEntries()
  |
  v
AI Assistant (Claude Code, Cursor, VS Code Copilot, etc.)

What gets captured

Network requests — every fetch() call is intercepted. The SDK captures method, URL, status, statusText, duration, full request and response headers, full request and response bodies (via response.clone().text(), the original response is untouched), and errors and timing.

Console output — every console.log/warn/error/info/debug call is captured with log level, timestamp, and formatted message. Original console methods still work, logs appear in Xcode/Metro/DevTools as normal.

State stores — references passed via the stores option are exposed globally for the MCP server to query on demand.

Why it must be the first import

The SDK patches globalThis.fetch and console when init() is called. If other code (your app, libraries like Apollo/Axios) calls fetchbefore the SDK patches it, those requests won't be captured. Placing the import first ensures the SDK intercepts everything from the very beginning, including OAuth token refresh on app launch, initial GraphQL/REST API calls, config/feature flag fetches, and early console output during initialization.

Production safety

The SDK is a no-op in production builds: the if (__DEV__) guard in your code prevents init() from being called; even if called without the guard, init() checks __DEV__ internally as a safety net; and tree-shaking removes the SDK code from production bundles when wrapped in if (__DEV__).

Circular buffers

Both network and console data are stored in circular buffers (default: 500 entries each). When the buffer is full, the oldest entries are evicted. This bounds memory usage regardless of how many requests or logs the app produces.

Exposed global API

The SDK exposes globalThis.__RN_AI_DEVTOOLS__ with these methods. You don't need to call these directly, the MCP tools use them automatically.

globalThis.__RN_AI_DEVTOOLS__ = {
  version: '0.5.1',

  // Capabilities - tells MCP server what's available
  capabilities: {
    network: true,
    console: true,
    stores: true,      // true if stores were passed
    navigation: true,  // true if navigation was passed
    render: false,      // future: render profiling
  },

  // State store references
  stores: { redux: store, queryClient: qc, ... },

  // Navigation reference
  navigation: navigationRef,

  // Custom references (AsyncStorage, MMKV, etc.)
  custom: { asyncStorage: AsyncStorage, mmkv: storage, ... },

  // Network
  getNetworkEntries(),  // all buffered network entries (incl. headers + bodies)
  clearNetwork(),       // returns number of entries cleared

  // Console
  getConsoleEntries(),  // all buffered console entries
  clearConsole(),       // returns number of entries cleared
}

Compatibility

React NativeArchitectureStatus
Expo SDK 54+ (RN 0.79+)BridgelessFully supported
Expo SDK 52-53 (RN 0.76-0.78)BridgelessFully supported
RN 0.73-0.75Hermes + BridgeFully supported
RN 0.70-0.72Hermes + BridgeShould work (untested)
RN < 0.70JSCNot tested

The SDK has zero native dependencies, it's pure JavaScript that patches standard globals (fetch, console). It works on any React Native version that supports these globals.

Relationship to ExecBro

This SDK is optional, but recommended. The MCP server works without it: it connects via CDP and provides console logs, component inspection, UI interaction, and basic network tracking out of the box.

Installing it supercharges the agent: it wires your state stores, navigation, and any custom references you pass in directly into the agent's reach, turning read-only inspection into direct control over the parts of your app you choose to expose, and it closes CDP's gaps (Bridgeless architecture, startup request capture, response bodies). When the MCP server detects the SDK, it automatically prefers SDK data; when the SDK is absent, it falls back to CDP.

  • You do NOT need the SDK for: console log viewing, component tree inspection, UI interaction, JavaScript execution, app reload, bundle error detection, or device management.
  • The SDK adds: network request capture (especially startup requests and response bodies), console log capture (startup logs that CDP might miss), and direct control over state stores, navigation, and any custom reference you choose to wire in.