@mushi-mushi/web
@mushi-mushi/web
Your AI wrote it. Mushi tells you why it broke.
A bug widget for any website. When a user reports a problem, it sends a screenshot, the route, their note and the last console and network events to Mushi Mushi. Mushi explains the cause in plain English and hands your editor a fix. It renders in a Shadow DOM, so your CSS and the widget's never mix.
flowchart LR
A["User taps the widget"] --> B["Mushi diagnoses the bug"] --> C["Fix lands in your editor"]
Quick start
npx mushi-mushi # wizard: picks the right SDK, installs it, writes env vars
# or: npm install @mushi-mushi/web
import { Mushi } from '@mushi-mushi/web';
Mushi.init({
projectId: '00000000-0000-0000-0000-000000000000', // from the console's Projects page
apiKey: 'mushi_xxx', // report:write key from Setup → Verify
});
A launcher appears in the corner. That is the whole integration. On React, Vue, Svelte, Angular, React Native or Capacitor, use the framework package instead: react · vue · svelte · angular · react-native · capacitor.
What's inside
| Report screen | A free-text note, an optional type, a screenshot the reporter can mark up or remove. Reporters see your replies and fix status under Your reports. |
| Capture | Screenshot, console, network, Web Vitals, and a timeline of routes and clicks before the report. |
| Offline | Reports queue in IndexedDB and send when the connection is back. An on-device spam filter and rate limit run first. |
| Privacy | A built-in PII scrubber, selector masking for screenshots, and opt-in session replay. |
| Stays out of the way | Zero-size host with pointer-events: none, keyboard-first, respects reduced motion. |
| Runtime config | Change the widget from the console without a deploy. Values you set in code win. |
| Size | CI caps the core bundle at 89.5 KB gzipped (105 KB uncompressed). Screenshot markup and the Your reports views load only when used. |
Recipes
Use your own button instead of the launcher. Other modes: auto, edge-tab, banner, manual, hidden (trigger modes).
const mushi = Mushi.init({
projectId: 'proj_xxx',
apiKey: 'mushi_xxx',
widget: { trigger: 'attach', attachToSelector: '[data-mushi-feedback]' },
});
mushi.attachTo('#support-menu-feedback');
Ask for a report when users get stuck (rage clicks, long tasks, failing API calls). Session limits and cooldowns are always on.
Mushi.init({ projectId: 'proj_xxx', apiKey: 'mushi_xxx', proactive: { rageClick: true, longTask: true, apiCascade: true } });
Keep private data out of screenshots. Masked elements are painted over; blocked ones are removed.
Mushi.init({
projectId: 'proj_xxx',
apiKey: 'mushi_xxx',
privacy: { maskSelectors: ['input'], blockSelectors: ['[data-payment]'], allowUserRemoveScreenshot: true },
});
Record a session replay of the moments before a report. Install rrweb in your app and pass your own import, so your bundler can split it into a lazy chunk (coexisting with Sentry Replay).
Mushi.init({ projectId: 'proj_xxx', apiKey: 'mushi_xxx', capture: { replay: 'rrweb', rrweb: () => import('rrweb') } });
Send through your own domain so ad blockers don't drop reports. Your proxy must allow only your host, project and /v1/ paths.
Mushi.init({ projectId: 'proj_xxx', apiKey: 'mushi_xxx', tunnel: '/api/mushi-tunnel', ignoreErrors: ['ResizeObserver loop'] });
Tag users and report caught errors. Breadcrumbs, tags and any active Sentry scope are attached for you.
const mushi = Mushi.init({ projectId: 'proj_xxx', apiKey: 'mushi_xxx' });
mushi.identify('usr_42', { email: 'aya@example.com', segment: 'beta' });
try {
await runCheckout();
} catch (err) {
mushi.captureException(err, { severity: 'high', tags: { surface: 'checkout' } });
}
Track product events for funnels and paths in the same console. Do Not Track and Global Privacy Control are respected.
const mushi = Mushi.init({ projectId: 'proj_xxx', apiKey: 'mushi_xxx', analytics: { consent: 'required' } });
mushi.setConsent('granted');
mushi.track('checkout_started', { plan: 'pro' });
Check the install. Safe to call before Mushi.init(); reports endpoint, CSP and widget health.
const health = await Mushi.diagnose(); // { apiEndpointReachable, cspAllowsEndpoint, widgetMounted, widgetHostPointerSafe, ... }
Name the current screen for the "what happened before" timeline.
const mushi = Mushi.init({ /* ... */ });
mushi.setScreen({ name: 'Chat', route: '/chat', feature: 'roleplay' });
Match your brand. The widget uses your page's font and light/dark colors. Override any token in CSS (all tokens):
#mushi-mushi-widget { --mushi-accent: #b8860b; --mushi-accent-fg: #000; --mushi-font: Georgia, serif; }
Screenshots cannot capture cross-origin iframes or tainted <canvas> elements, and strict CSP can block them. Playwright and jsdom helpers live in @mushi-mushi/web/test-utils, which production bundles never load.
Learn more
Web SDK reference · Runtime config · Presets · Analytics · Rewards and replies
License
MIT
Related Packages
Mushi CLI: SDK setup, MCP wiring, bug triage. The bug mediator for AI-built apps...
One command adds a bug report widget to any app. The bug mediator for AI-built a...
Run `npm create mushi-mushi` to add the Mushi Mushi bug-reporting SDK to your ex...
Version History
| Version | Released | License |
|---|---|---|
| 1.33.1 | MIT | |
| 1.33.0 | MIT | |
| 1.32.3 | MIT | |
| 1.32.2 | MIT | |
| 1.32.1 | MIT | |
| 1.32.0 | MIT | |
| 1.31.2 | MIT | |
| 1.31.1 | MIT | |
| 1.31.0 | MIT | |
| 1.30.0 | MIT | |
| 1.29.0 | MIT | |
| 1.28.0 | MIT | |
| 1.27.0 | MIT | |
| 1.26.0 | MIT | |
| 1.25.0 | MIT | |
| 1.24.0 | MIT | |
| 1.23.0 | MIT | |
| 1.22.5 | MIT | |
| 1.22.4 | MIT | |
| 1.22.3 | MIT | |
| 1.22.2 | MIT | |
| 1.22.1 | MIT | |
| 1.22.0 | MIT | |
| 1.21.1 | MIT | |
| 1.21.0 | MIT | |
| 1.20.0 | MIT | |
| 1.19.2 | MIT | |
| 1.19.0 | MIT | |
| 1.18.0 | MIT | |
| 1.17.0 | MIT |
Showing the latest 30 of 66. See every release on npm