claude-web-feedback-widget
A dev-only browser widget to point at elements (or select text) on your running
app, leave an inline comment, and have it land in your local Claude Code session
— in your real browser, with no IDE-embedded browser and no app code changes
beyond one script tag.
The comment arrives with a layered source anchor so Claude can jump straight
to the code:
- Source location —
fileName:lineNumber:column from a data-source-loc
attribute stamped by the bundled babel plugin (runtime-agnostic; works on React 19)
- Component name + the component stack that rendered the node
data-testid
- CSS selector (stable, structural)
outerHTML snippet, bounding rect, aria-label, recent console errors
- Text quote (W3C exact + prefix/suffix) for text selections
- Screenshot (optional, oklch-safe via
html2canvas-pro)
How it works
Browser (your app) Local machine
┌─────────────────┐ WebSocket ┌──────────────────────────────┐
│ widget.js │ ───────────▶ │ receiver (127.0.0.1:4747) │
│ (Shadow DOM) │ │ ├─ in-memory pending queue │
└─────────────────┘ │ ├─ .claude-feedback/*.json │
│ └─ MCP stdio server ◀── Claude Code
└──────────────────────────────┘
One process is both the loopback receiver (the browser talks to it) and the MCP
stdio server (Claude Code talks to it), so feedback the browser sends is
immediately available to Claude's MCP tools.
Install as a Claude Code plugin (recommended)
This repo doubles as a Claude Code plugin: installing it registers the MCP server
(and its loopback receiver) once, for use across all your projects — no
claude mcp add, no per-machine config. The bundled CLI is self-contained, so the
plugin needs no node_modules.
# from a local clone (persistent)
/plugin marketplace add /path/to/claude-web-feedback-widget
/plugin install web-feedback@claude-web-feedback
# …or from GitHub
/plugin marketplace add zebapy/claude-web-feedback-widget
/plugin install web-feedback@claude-web-feedback
For a quick, session-only try without installing:
claude --plugin-dir /path/to/claude-web-feedback-widget
The plugin ships two slash commands:
/web-feedback:setup — run it inside any project; it detects the framework
and wires the widget (dev script tag + optional file:line babel plugin) for you.
/web-feedback:run — pick up all pending comments and dispatch one background
agent per comment.
The dist/ build output is committed so the plugin works on install. After
changing source, run pnpm build before committing.
Install as an npm package
npm install -D claude-web-feedback-widget # or pnpm add -D
1. Add the widget to your dev app
Option A — script tag (zero bundler coupling). Render this only in dev:
<script src="http://127.0.0.1:4747/widget.js"></script>
The receiver serves the script and the widget auto-connects back to the port it
was served from.
Option B — import it (bundler users):
if (import.meta.env.DEV) {
const { init } = await import("claude-web-feedback-widget/widget");
init(); // or init({ host, port })
}
Enable the file:line source anchor (recommended)
Add the babel plugin in dev so every JSX element carries a data-source-loc
attribute. The widget reads it off the DOM, so the source anchor works on any
React version and JSX runtime (React 19 removed the fiber source the old
__source approach relied on).
Vite (@vitejs/plugin-react):
import react from "@vitejs/plugin-react";
import sourceLocation from "claude-web-feedback-widget/babel";
export default defineConfig({
plugins: [react({ babel: { plugins: [sourceLocation] } })]
});
Next.js / Babel: add "claude-web-feedback-widget/babel" to your dev Babel
plugins. Without the plugin you still get component name → selector → outerHTML.
2. Register the MCP server with Claude Code
claude mcp add --scope user web-feedback -- npx claude-web-feedback
That single process also starts the loopback receiver, so the browser widget can
connect as soon as Claude Code launches the server.
3. Use it
- Start your app's dev server and open it in your browser.
- Click Comment in the widget toolbar (bottom-right) — or press the hotkey
⌘/Ctrl+Shift+K — then click an element or select text. Type a comment and
Send to Claude. (Screenshots are opt-in: tick the box to include one.)
- In Claude Code, ask it to read your feedback. It calls
wait_for_feedback
(or get_pending_feedback) and receives the comment plus the source anchor.
The hotkey is configurable: init({ hotkey: "mod+shift+k" }) (mod = ⌘/Ctrl),
or pass "" to disable it.
MCP tools