
Research
/Security News
Mini Shai-Hulud Campaign Hits Red Hat Cloud Services npm Packages
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.
rnbugkit-sdk
Advanced tools
Lightweight crash reporting and network monitoring SDK for React Native.
rnbugkit-sdk captures uncaught errors, render-time exceptions, unhandled promise rejections, and network failures in your app — along with rich context (recent screens, user actions, device info) — and ships them to the RNBugKit backend. It does not collect request or response bodies.
fetch + XMLHttpRequest, failures and slow requestsnpm install rnbugkit-sdk
# or
yarn add rnbugkit-sdk
Optional, for persistent offline queue across app restarts:
npm install @react-native-async-storage/async-storage
Initialize the SDK as early as possible — ideally in index.js, before AppRegistry.registerComponent:
// index.js
import { AppRegistry } from 'react-native';
import { BugKit } from 'rnbugkit-sdk';
import App from './App';
import { name as appName } from './app.json';
BugKit.init({
apiKey: 'your_api_key',
appVersion: '1.0.0',
});
AppRegistry.registerComponent(appName, () => App);
That's it. From this point on, every uncaught exception, unhandled promise rejection, and failed/slow network request is captured automatically.
BugKit.init({
apiKey: 'your_api_key', // required
appVersion: '1.0.0', // required
// Optional — defaults shown
enabled: true, // master switch
enabledInDev: false, // capture in __DEV__ builds
slowRequestThreshold: 3000, // ms — requests slower than this are reported
flushInterval: 30000, // ms — network batch flush cadence
redactedKeys: ['password', 'token', 'secret', 'card', 'cvv', 'pin'],
persistQueue: false, // persist offline queue via AsyncStorage
sampleRate: 1, // 0..1 — fraction of crashes to report
dedupWindowMs: 30000, // suppress identical crashes within this window
onBeforeSend: (payload) => payload, // mutate or drop a report before send
});
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | — | Your RNBugKit project key. Required. |
appVersion | string | — | Attached to every report. Required. |
enabled | boolean | true | Master switch. When false, init is a no-op. |
enabledInDev | boolean | false | Capture in __DEV__ builds. Off by default so the RedBox isn't shadowed. |
slowRequestThreshold | number | 3000 | Any request taking longer than this (ms) is reported as slow. |
flushInterval | number | 30000 | How often (ms) batched network stats/failures are flushed. |
redactedKeys | string[] | see below | Keys (case-insensitive substring match) redacted from context and screenState. |
persistQueue | boolean | false | Persist the offline queue across app launches. Requires @react-native-async-storage/async-storage. |
sampleRate | number | 1 | Probability (0..1) that a crash is emitted. |
dedupWindowMs | number | 30000 | Same crash (by stack hash) within this window is folded into repeated_count. |
onBeforeSend | (p) => p | null | identity | Inspect/mutate/drop a payload right before send. Return null to drop. |
Default redactedKeys: password, token, secret, card, cvv, pin.
// One-off manual report (no Error needed)
BugKit.reportManually('User said the camera froze');
// Log a message at a level
BugKit.captureMessage('Cache miss for user profile', 'warning');
// Log a caught exception
try {
await fetchProfile();
} catch (e) {
BugKit.captureException(e as Error);
}
// Track screen transitions (keeps the last 5)
BugKit.onNavigationStateChange({ name: 'CheckoutScreen' });
// Track user actions (keeps the last 10)
BugKit.recordAction('tap', 'submitButton');
BugKit.recordAction('scroll', 'productList');
BugKit.recordAction('navigate', 'Profile');
BugKit.recordAction('shake');
BugKit.recordAction('submit', 'loginForm');
BugKit.recordAction('focus', 'emailInput');
// Persistent context — included on every report until cleared
BugKit.setContext({ userId: 'u_123', plan: 'pro' });
BugKit.clearContext();
// Snapshot of the current screen — overwritten on each call
BugKit.setScreenState({ tab: 'orders', filter: 'pending' });
Both context and screenState are redacted using redactedKeys before sending.
// Restore original handlers, clear in-memory queue, drop config
BugKit.destroy();
You usually don't need this — call only when wholly disabling the SDK at runtime.
<BugKitBoundary>A React error boundary that captures render-time exceptions and forwards them to the backend.
import { BugKitBoundary } from 'rnbugkit-sdk';
<BugKitBoundary
fallback={(error) => <ErrorScreen message={error.message} />}
onError={(error, info) => console.log(error)}
>
<App />
</BugKitBoundary>
| Prop | Type | Notes |
|---|---|---|
fallback | ReactNode | (error: Error) => ReactNode | Rendered when a child throws. |
onError | (error, info) => void | Called in addition to the automatic report. |
Wrap your screens or feature roots — granular boundaries give better UX than a single top-level one.
<BugKitTouchBoundary>Wraps a subtree and automatically records recordAction("tap", label) for every interactive press. The label is taken from testID → accessibilityLabel → component display name (TouchableOpacity, Pressable, etc.).
import { BugKitTouchBoundary } from 'rnbugkit-sdk';
<BugKitTouchBoundary>
<App />
</BugKitTouchBoundary>
| Prop | Type | Default | Notes |
|---|---|---|---|
disabled | boolean | false | Turn off without unmounting. |
ignoreNames | string[] | [] | Display names to skip (e.g. ['DebugButton']). |
dedupeWindowMs | number | 300 | Same label within this window is recorded once. |
maxDepth | number | 20 | How far up the fiber tree to walk looking for a label. |
Touch instrumentation never throws — failures are swallowed silently so it can't break your app.
<ReportBugButton>Floating button with a modal that lets users describe a bug and submit it.
import { ReportBugButton } from 'rnbugkit-sdk';
<ReportBugButton
label="Report bug"
placeholder="What went wrong?"
onReported={(success, description) => console.log({ success })}
/>
| Prop | Type | Default |
|---|---|---|
label | string | "Report bug" |
placeholder | string | "What went wrong?" |
submitLabel | string | "Send" |
cancelLabel | string | "Cancel" |
onPress | () => void | opens modal |
onReported | (ok, description) => void | — |
style, textStyle | — | override styling |
useReportBug()Hook for custom reporting UIs.
import { useReportBug } from 'rnbugkit-sdk';
function Feedback() {
const { report, isReporting, lastError } = useReportBug();
return (
<Button
title={isReporting ? 'Sending…' : 'Send feedback'}
onPress={() => report('Feedback text here')}
disabled={isReporting}
/>
);
}
Every bug report includes:
title, stack_trace, kind (crash | manual | message), levelapp_version, occurred_atdevice_info — platform, OS version, screen size, RN version, is_devnavigation_history — last 5 screensuser_actions — last 10 actions (tap/scroll/navigate/shake/submit/focus)component_state — last setScreenState value (redacted)context — setContext values (redacted)repeated_count — when deduplication folds in repeatsNetwork monitoring captures only metadata:
url, method, status_code, duration_ms, failure_type, error_messageFailure types: error_status (4xx/5xx), timeout, no_connection, slow.
Aggregated stats (count, error count, avg/max duration) are computed per endpoint per hour and shipped in batches.
rnbugkit-sdk is built to minimize what leaves the device:
context / screenState is yours to populate.context and screenState keys matching redactedKeys (case-insensitive substring) are replaced with [REDACTED].onBeforeSend escape hatch. Inspect, mutate, or drop any payload before it's sent.Note on URLs. Query strings are captured as-is. If your endpoints encode sensitive values in the query string (e.g.
?token=…), strip them inonBeforeSendor move them to headers.
When the network is unavailable or the backend is unreachable, reports are queued in memory (up to 50 items, 3 retry attempts each) and retried automatically when the app returns to the foreground.
To survive app restarts, enable persistence:
BugKit.init({
apiKey: '…',
appVersion: '…',
persistQueue: true,
});
This requires @react-native-async-storage/async-storage as a peer install.
By default, the SDK is disabled in __DEV__ so the RedBox stays the source of truth while you're developing. To enable it during development (useful for testing reporting flows):
BugKit.init({
apiKey: '…',
appVersion: '…',
enabledInDev: true,
});
Sync errors thrown from event handlers in dev are sometimes intercepted by Metro's RedBox before the SDK sees them — test crash flows in a release build for accurate behavior.
sampleRate: 0.1 reports ~10% of crashes. Useful at scale.dedupWindowMs is folded into a single report with repeated_count incremented.BugKit.init({
apiKey: '…',
appVersion: '…',
sampleRate: 0.25,
dedupWindowMs: 60000,
});
MIT © PMI Software Systems
FAQs
Bug reporting and network monitoring SDK for React Native
We found that rnbugkit-sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.

Research
/Security News
The North Korean malware loader hides in a Packagist-listed package and its GitHub branch to fetch and execute remote code in a likely Contagious Interview-style lure.

Security News
The Rust project is moving toward formal rules on LLM use in contributions after months of internal debate over maintainer burden, code quality, and contributor experience.