← Platforms

React Native

Remote debugging for React Native: let your AI coding tool see the screen, read the logs and drive real input on a real device — from a TypeScript SDK with native bridges that autolink themselves.

What you get

OmniDebugLink connects your running React Native app to your AI tool over MCP. The tool calls a task on the device and waits for the result, so “find the button, tap it, screenshot, read the errors” is one conversation turn instead of a copy-paste loop.

TypeScript protocol layer

Built on the WebSocket React Native already ships — no third-party JS dependencies. Handshake, heartbeat, backoff reconnect and console capture are handled for you.

Kotlin + Swift native bridges

One native module per platform covers what JS cannot reach: full-window screenshots, the native view hierarchy, touch injection and the native preference store. No manual MainApplication.kt or AppDelegate edits.

AI-friendly inspect and act

find_objects returns coordinates plus an atomic-action hint; ui_click locates and clicks a node in a single call.

Read-only observation mode

setActionsEnabled(false) turns every write task into a no-op that returns ACTION_DISABLED — let an agent look around without touching anything.

Requirements

Install

The package is installed as a GitHub git dependency (it is not published to npm):

npm install omnidebuglink/omnidebuglink_react_native#v0.1.5
cd ios && pod install        # iOS autolinking (RN 0.60+); Android is automatic

Or pin it in package.json:

"dependencies": {
  "@omnidebuglink/react-native": "omnidebuglink/omnidebuglink_react_native#v0.1.5"
}

Connect your app

1

Create a token pair

Sign up, create a token pair, and copy the client token. One token pair per device: if the token is replaced, the old connection receives close code 4000 and stops permanently instead of reconnecting.

2

Start the client

import { OmniDebugLink } from '@omnidebuglink/react-native';

const client = new OmniDebugLink({
  onLog: (msg) => console.log('[ODL]', msg),
  onStateChange: (connected) => console.log('[ODL] connected:', connected),
});

client.start('your-device-token'); // from the console

Reconnects use exponential backoff (1s up to 30s). By default console.log/warn/error and global JS errors land in the log buffer, so read_logs sees your app’s output with no extra wiring.

3

Optionally register a navigator and custom tasks

// Report the react-navigation route stack in get_state
OmniDebugLink.setNavigator(navigationRef.current);

// Register custom tasks (registry changes auto-resend hello)
client.registry.register(
  'my_task',
  async (payload) => ({ status: 'done' }),
  'Does something meaningful, returns status.',
  { type: 'object', properties: { value: { type: 'string' } } },
);

registry.register(type, handler, description?, schema?, { write }) — the description and schema are what your AI tool sees when it lists tasks, and write: true marks the task as a write operation gated by actionsEnabled. Call client.stop() to disconnect.

4

Point your AI tool at the device

Sign in to the same account in your MCP client, pick the device, and start calling tasks — see how synchronous MCP calls work.

Built-in tasks

18 built-in tasks plus one registered in dev builds only. Pure-JS tasks work even without the native module; native-backed tasks return TASK_FAILED with install guidance when it is not linked.

Pure JS (no native code needed)

TaskWriteWhat it does
echo / ping / get_statsnoConnectivity basics.
read_logsno500-line ring buffer: console output, global errors and SDK events, with level / contains / sinceMs filters.
find_objectsnoFind nodes by text, type or id substring; returns center px, normalized coordinates and an atomic-action hint.
wait_fornoPolls every 200ms until a node appears; a timeout returns found:false without raising an error.
reloadyesReloads the JS bundle like the RN dev menu. Registered in dev builds only; pairs with Metro for an AI edit → reload → verify loop.

Native-backed (Android Kotlin / iOS Swift module)

TaskWriteWhat it does
screenshotnoJPEG capture of all windows, so RN <Modal> shows up; quality and size are reduced until the capture fits the message budget.
ui_traversenoView hierarchy dump, flat by default to save tokens (flat:false for nested), 3000-node cap, absolute screen px from the top-left origin, overlay windows included.
tap_screenyesTap at normalized [0,1] coordinates, top-left origin, routed to the topmost window covering the point.
long_pressyesLong press at normalized coordinates (default 800ms).
swipeyesSwipe gesture with a controlled durationMs.
ui_clickyesClick a node located by text / type / index / fieldId — locating and clicking happen atomically in one call, since React tags go stale after re-renders.
input_textyesWrite text into a field located by fieldId or type + index; text is the value to enter.
send_keyyesAndroid: back / home / recents (back dismisses dialogs via overlay-window dispatch). iOS: enter / escape / backspace / tab / space.
get_statenoScreen, network and native activity / view-controller stack, plus react-navigation routes (requires setNavigator).
get_perfno~1s fps sample (p50/p95/p99 frame times) plus process memory.
view_componentnoSingle-node detail: layout plus native view state.
prefsno/yesRead and write the native preference store (SharedPreferences / NSUserDefaults): get / set / delete / list with valueType coercion.

Good to know