@runhuman/sensor
v0.6.0
Published
Runhuman sensor — captures test session data from apps under test
Readme
@runhuman/sensor
Embed the Runhuman sensor in your mobile or web app to capture network requests, console errors, crashes, and user interactions during human QA testing. Captured telemetry is automatically included in the AI analysis, producing richer and more accurate bug reports.
The sensor has zero overhead when no test is running — it only activates when a tester starts a session.
Enterprise Pro — The Sensor SDK is available on the Enterprise Pro plan. Learn more.
Installation
npm install @runhuman/sensorWorks with React Native 0.70+ and all modern browsers. React 18+ required for the provider component.
Quick Start — React (Web or React Native)
Wrap your app with <RunhumanProvider>:
import { RunhumanProvider } from '@runhuman/sensor';
export default function App() {
return (
<RunhumanProvider apiKey="rh_your_api_key">
<YourApp />
</RunhumanProvider>
);
}The same import works for both platforms — the bundler automatically picks the right entry (web or React Native).
Quick Start — Vanilla JS (Vue, Svelte, etc.)
For non-React web apps, use initWeb():
import { initWeb } from '@runhuman/sensor';
const { runhuman, overlay } = initWeb({ apiKey: 'rh_your_api_key' });
// Later: overlay.unmount();Activation
Testers activate the sensor in two ways:
- Code entry — The overlay shows a code input panel. Testers enter the short code from their job assignment.
- URL parameter (web only) — Append
?runhuman_job=<id>to the URL and the sensor activates automatically. - Deep links (React Native) — The sensor listens for
<scheme>://runhuman?jobId=<id>deep links.
Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| apiKey | string | required | Your Runhuman API key |
| enabled | boolean | true | Set to false to disable the sensor entirely |
| position | 'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right' | 'bottom-right' | Corner for the overlay UI |
| baseUrl | string | Production URL | Runhuman API server URL |
| jobId | string | — | Pre-set job ID (e.g., from a URL param or deep link) |
| platform | 'react-native' \| 'web' \| 'ios' \| 'android' | Auto-detected | Target platform |
| flushIntervalMs | number | 5000 | Event batch flush interval (ms) |
| pollIntervalMs | number | 10000 | Job status poll interval (ms) |
| maxBufferSize | number | 1000 | Max buffered events before FIFO eviction |
| debug | boolean | false | Log events to console |
| interceptors | Interceptor[] | — | Additional interceptors (e.g., navigation tracker) |
| storageAdapter | StorageAdapter | Auto (localStorage / AsyncStorage) | Custom storage for session persistence |
| sessionTtlMs | number | 1800000 (30 min) | How long a persisted session remains resumable |
Disabling in Production
<RunhumanProvider apiKey="rh_your_api_key" enabled={__DEV__}>
<YourApp />
</RunhumanProvider>When enabled is false, no initialization occurs and no overlay is rendered.
What Gets Captured
| Category | Web | React Native |
|----------|-----|--------------|
| Network requests | URLs, methods, status codes, timing, response sizes | Same |
| Console errors | Error and warning messages | Same |
| JavaScript crashes | Unhandled exceptions with stack traces | Same |
| Clicks / taps | Click coordinates + element descriptor (tag, id, class, text) | Touch coordinates |
| Keyboard input | Buffered text input (password fields redacted to ***) | — |
| Navigation | Page loads + SPA route changes (pushState, popstate) | Opt-in via createNavigationTracker() |
All telemetry is session-scoped — nothing is collected or sent when idle.
Session Persistence
Sessions survive app restarts. If a tester closes the app mid-test and reopens within 30 minutes, the sensor shows a "Continue session?" prompt instead of the code entry panel.
- Web — Uses
localStorageautomatically. - React Native — Uses
@react-native-async-storage/async-storageif installed. Install it as a peer dependency for persistence to work. - Custom storage — Pass a
storageAdapterprop implementing{ getItem, setItem, removeItem }. - TTL — Default 30 minutes. Configure with
sessionTtlMs.
Resumed sessions maintain timestamp continuity — events pick up where they left off.
React Native Navigation Tracking
Navigation tracking is opt-in on React Native. Pass a navigation tracker as an interceptor:
import { RunhumanProvider, createNavigationTracker } from '@runhuman/sensor';
import { useRef } from 'react';
import { NavigationContainer } from '@react-navigation/native';
export default function App() {
const navigationRef = useRef(null);
return (
<RunhumanProvider
apiKey="rh_your_api_key"
interceptors={[createNavigationTracker(navigationRef)]}
>
<NavigationContainer ref={navigationRef}>
<AppNavigator />
</NavigationContainer>
</RunhumanProvider>
);
}React Hook
Build custom UI with useSensorState:
import { useSensorState } from '@runhuman/sensor';
const { state, activeJobId, sessionId, persistedSession } = useSensorState();
// state: 'idle' | 'polling' | 'active' | 'ending'
// persistedSession: previous session data if resumable, null otherwiseDocumentation
Full docs at runhuman.com/docs/sensor.
License
ISC
