Point your agent at the line,
not the page
Click any element in your running app, type what's wrong, and get a prompt that names the exact file, line, and column. No backend, no account — it lands on your clipboard.
$npm install local-feedbackerView on npm →## Feedback: "Primary button should be white" ## Clicked UI - Element: button.btn-primary - Nearby copy: Save changes ## Confirmed implementation source — start here - Call site: src/components/OrderPanel.tsx:142:8 - Definition: src/ui/Button.tsx:24:1 ## Supporting context - Route: /orders/new ## Requested agent behavior Inspect the confirmed call site first. Preserve unrelated behavior. Ask a question if the requested change is ambiguous.
A selector is a search. A line number is an answer.
Most visual feedback tools hand your agent a CSS selector and a bounding box. The agent still has to go find the code — grepping class names across the repo, guessing which of four Button components rendered this one. That search is where the tokens and the minutes go.
### 1. Button Location:body > div > main > button.btn-primary Classes: btn btn-primary Position: 412px, 288px Feedback: Should be white
## Confirmed source - Call site: src/components/ OrderPanel.tsx:142:8 - Definition: src/ui/Button.tsx:24:1
Resolved at compile time, not guessed at runtime
Runtime approaches read React's internal _debugSource field. That field only exists in development builds, React 19 removed it, and walking the fiber tree upward can land on an ancestor rather than the element you clicked. local-feedbacker injects the location during your build instead — so it survives production bundles and doesn't depend on React internals at all.
Wrap your bundler config
A Babel-based loader stamps each JSX call site with its origin as your app compiles.
// next.config.mjs import { withLocalFeedbacker } from "local-feedbacker/next"; export default withLocalFeedbacker({});
Mount the widget
One component. It hides itself in production by default, and Ctrl/Cmd+Shift+. toggles it either way.
import { ImpakersFeedbackProvider } from "local-feedbacker/react"; <ImpakersFeedbackProvider language="ko" />
Click, describe, paste
The prompt is on your clipboard the moment you submit. Hand it to Claude Code, Cursor, or anything that reads text.
Every section earns its tokens
- Call site
- Where this instance is rendered — the line you almost always want to edit.
- Definition
- Where the component itself lives, for when the fix belongs to every instance.
- Clicked UI
- Element, any text you selected, nearby copy, and accessibility name.
- Modal context
- If you left feedback inside a dialog, how that dialog was opened — a URL alone can't get the agent back there.
- Requested behavior
- Explicit instructions: start at the call site, preserve unrelated behavior, and ask before guessing at anything ambiguous.
Built for review sessions, not just single clicks
Screenshots that follow your scroll
Captures the viewport you're actually looking at, with the modal itself captured when feedback lands inside one.
Voice dictation
Describe the problem out loud using the browser's own speech recognition. Nothing is uploaded.
Four languages
Korean, English, Spanish, and Chinese — the prompt itself is localized, not just the interface.
One-click export
A whole review session downloads as a single zip of markdown and screenshots. No folder picker, no permission dialog.
Pins that persist
Markers stay put across reloads and routes, so you can sweep a whole flow before handing anything over.
No backend
Everything lives in localStorage. No account, no server, no telemetry — it works offline.
Where it isn't the right fit
The build-step integration is the trade. If you can't touch your bundler config, or you need feedback from a device you don't control, a zero-config runtime tool will get you moving faster — you'll just be handing your agent selectors instead of lines.
It's React-only, and the source locations are only as good as your build. If a file never goes through the loader, you fall back to the element context without a confirmed line.