
Security News
OpenCode User Hit with Hostile Backlash After Reporting Free AI Loophole
An OpenCode user faced harassment after reporting a free AI usage loophole, drawing a bitter backlash in a GitHub thread that has since been deleted.
@bugmojo/widget
Advanced tools
Framework-agnostic BugMojo on-site feedback + capture widget core. Powers the hosted /widget.js loader and the same-origin npm fallback (initWidgetBundled).
The framework-agnostic core of the BugMojo on-site feedback + bug capture widget — session replay, console/network logs, and PII-safe reporting from a single embed.
Bug reports without context are guesswork. This widget attaches an rrweb session
replay, console logs, and network activity to every report — redacted client-side
before anything leaves the browser — and files it straight into the
BugMojo platform, where your team (and your AI coding
agents, via MCP) can act on it. It targets a single page world only: zero
browser-extension (chrome/wxt) references.
Hosted loader (recommended) — a lightweight /widget.js IIFE served by
BugMojo. It boots the widget and lazy-loads a separate widget-capture.js chunk
containing the rrweb recording engine, so rrweb never bloats the initial script.
You do not need this npm package for the hosted mode:
<!-- Place early in <head> so capture installs before your app emits events -->
<script
src="https://www.bugmojo.com/widget.js"
data-project="YOUR_PUBLIC_EMBED_TOKEN"
data-position="bottom-right"
data-env="production"
async
></script>
The loader also reads data-release (release gating) and data-nonce (CSP
nonce), or an optional window.bugmojoSettings object for programmatic
configuration. Once booted it exposes window.BugMojo and dispatches a
bugmojo:ready event.
Same-origin npm fallback (this package) — for sites whose
Content-Security-Policy blocks the hosted script. Import initWidgetBundled,
serve the widget from your own origin under a strict script-src 'self' policy,
and everything (rrweb included) ships in your own bundle.
destroy() restores native console/fetch/XHR and
removes the UI (safe for SPA route changes).pnpm add @bugmojo/widget
# or
npm install @bugmojo/widget
# or
yarn add @bugmojo/widget
rrweb is a runtime dependency (used by the capture engine). It is kept external
in the published bundle so your bundler can dedupe / code-split it.
import { initWidgetBundled } from '@bugmojo/widget';
const api = await initWidgetBundled({
embedToken: 'YOUR_PUBLIC_EMBED_TOKEN', // the data-project identifier (not a secret)
apiBase: 'https://www.bugmojo.com',
position: 'bottom-right',
});
// Imperative API (the hosted loader exposes the same object as window.BugMojo):
api.setUser({ id: 'u_123', email: 'jane@example.com' });
api.open();
api.destroy(); // clean teardown on SPA route change
Grab your embed token from Project Settings → Widget in the BugMojo dashboard.
For the split loader/capture setup use the lower-level
initWidget(settings, { loadCapture }), exported alongside
createCaptureController.
Use @bugmojo/react instead — the
official React SDK wraps this core with a provider component, an error boundary,
and hooks for React and Next.js apps.
WidgetSettings)| Option | Type | Default | Description |
|---|---|---|---|
embedToken | string | required | Public embed token (the data-project value). An identifier, not a secret. |
apiBase | string | loader script origin | API origin. For npm usage, set it explicitly (e.g. https://www.bugmojo.com). |
position | 'bottom-right' | 'bottom-left' | 'right-middle' | 'left-middle' | from server config | Launcher position override. |
env | string | — | Environment label forwarded to GET /config?env= so the server resolves the right capture ruleset. Not access control. |
release | string | — | Release/version string forwarded to GET /config?release= for min/max release gating. |
nonce | string | — | CSP nonce applied to the Shadow-DOM <style>. |
screenshot | 'none' | 'html2canvas' | 'displaymedia' | 'none' | Screenshot strategy. none derives the visual from the rrweb snapshot (masking already applied). html2canvas is best-effort (only used when the host page provides window.html2canvas). displaymedia shows a browser permission prompt. |
user | WidgetUser | — | Initial reporter identity: { id?, email?, name?, cohort? }. cohort is matched client-side against the ruleset's allowed cohorts to gate capture. |
customData | Record<string, unknown> | — | Arbitrary metadata attached to every submission. |
onOpen / onClose | () => void | — | Lifecycle callbacks (also available via api.on(...)). |
onSubmit | (detail: SubmitDetail) => void | — | Called after a submission with { category, number?, pendingModeration? }. |
BugMojoApi)Returned by initWidgetBundled / initWidget; the hosted loader exposes the same
object as window.BugMojo.
| Method | Description |
|---|---|
open() | Open the feedback panel. |
close() | Close the panel. |
show() | Show the launcher button. |
hide() | Hide the launcher (the JS API keeps working). |
capture() | Start recording (if the capture gate allows it) and open the panel directly on the Bug category. |
setUser(user) | Merge the reporter identity ({ id?, email?, name?, cohort? }) into the current one. |
setReporter(user) | Alias of setUser. |
setCustomData(data) | Merge custom metadata into what is attached to submissions. |
on(event, cb) | Subscribe to 'open', 'close', or 'submit'. Returns an unsubscribe function. |
off(event, cb) | Remove a listener. |
destroy() | Full teardown: stops rrweb, uninstalls the console/network patches (restoring native console/fetch/XHR), and removes the Shadow-DOM UI. Idempotent. |
| Export | Purpose |
|---|---|
initWidgetBundled(settings) | All-in-one initializer with rrweb statically bundled. |
initWidget(settings, deps) | Loader-driven init; deps.loadCapture supplies the rrweb chunk. |
createCaptureController(opts) | The rrweb-bearing capture controller factory. |
WidgetSettings, BugMojoApi, … | Public TypeScript types. |
Note: the
./src/*subpath exports raw TypeScript source for BugMojo's own monorepo build. It is not a supported public entry point — use the package root import.
This package is ESM-only and browser-targeted — it must be processed by a
bundler (Vite, webpack, Next.js, etc. all work). It cannot be imported in a bare
Node runtime: rrweb@2.0.0-alpha.4 is not Node-ESM resolvable, so a plain
node/vitest-node import fails with
The requested module 'rrweb' does not provide an export named 'record'.
For SSR frameworks, import it only on the client — e.g. behind a browser guard:
if (typeof window !== 'undefined') {
const { initWidgetBundled } = await import('@bugmojo/widget');
await initWidgetBundled({ embedToken: '…', apiBase: 'https://www.bugmojo.com' });
}
The widget doesn't appear.
Check the browser console. [BugMojo] missing embed token means no
data-project / embedToken was provided; [BugMojo] widget failed to initialize means the config fetch failed — verify apiBase and that the embed
token matches your project's Widget Settings. On total config failure the JS API
still exists but the UI is a no-op by design (the widget never crashes the host
page).
Reports arrive without replay / console / network data.
Capture is gated by the server ruleset: it can be disabled for your environment,
sampled out (sample_rate), cohort-restricted (set user.cohort), or blocked by
require_login when no reporter identity (id/email) is set. The widget also
skips instrumentation if another BugMojo capture (e.g. the browser extension) is
already patching the page. Config changes propagate within the cache TTL
(60 seconds by default).
The requested module 'rrweb' does not provide an export named 'record'.
You imported the package in a bare Node runtime (plain script, vitest node
environment, or SSR with externalized deps). Use a bundler, or a client-only
dynamic import — see "Bundler required" above.
My CSP blocks the hosted widget.js.
That is exactly what this package is for: bundle initWidgetBundled into your own
app and serve it from your origin under script-src 'self'. Pass a nonce if
your policy requires one for the Shadow-DOM style tag.
How do I remove the widget on SPA route change?
Call api.destroy(). It is idempotent and fully restores the native
console/fetch/XHR before removing the UI, so you can safely re-init later.
| Package | Use it for |
|---|---|
@bugmojo/react | React / Next.js SDK — provider, error boundary, hooks |
@bugmojo/react-native | React Native + Expo SDK — shake-to-report |
@bugmojo/cli | Pull a bug's Playwright repro pack, verify fixes locally |
@bugmojo/mcp-server | Connect AI coding agents (Claude Code, Cursor) to BugMojo |
MIT © Softech Infra — see LICENSE.
FAQs
Framework-agnostic BugMojo on-site feedback + capture widget core. Powers the hosted /widget.js loader and the same-origin npm fallback (initWidgetBundled).
The npm package @bugmojo/widget receives a total of 0 weekly downloads. As such, @bugmojo/widget popularity was classified as not popular.
We found that @bugmojo/widget 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.

Security News
An OpenCode user faced harassment after reporting a free AI usage loophole, drawing a bitter backlash in a GitHub thread that has since been deleted.

Threat Research
/Security News
319 browser extensions installed by 13.4 million users hijack searches, capture queries, and collect referral payments from Yahoo and Bing.

Threat Research
Malicious Firefox extensions mimic Phantom, Jupiter, and Bitget wallets to steal recovery phrases and private keys, with one fetching its payload remotely.