@wyverselabs/pinpoint
v0.2.1
Published
Pin rendered React and Electron UI to the source context an AI needs.
Readme
Pinpoint
Pinpoint is a dev-only UI source locator for AI coding agents.
Click any rendered element in an Electron React app and copy the source context needed to edit it. It feels like an element picker, but the clipboard output is optimized for handing precise code location to an AI agent.
Pinpoint is early 0.x software. It is usable today, but public APIs and the clipboard payload may evolve while the project settles.
What It Copies
<pinpoint-selection>
{
"kind": "pinpoint.selection",
"source": {
"location": "src/components/ExportButton.tsx:42:5",
"element": "Button",
"kind": "jsx-metadata"
},
"target": {
"tag": "button",
"name": "Export",
"role": "button"
},
"window": "main"
}
</pinpoint-selection>The XML wrapper makes the pasted block easy for an AI agent to identify. The JSON stays intentionally small: source location, target identity, and window label.
Install
npm install -D @wyverselabs/pinpointbun add -d @wyverselabs/pinpointPinpoint currently targets Electron + React + Vite apps.
Peer dependencies are optional at package install time because each subpath has different runtime needs:
vitefor@wyverselabs/pinpoint/viteelectronfor@wyverselabs/pinpoint/electron/*
Set It Up With An AI Agent
If you use Codex, Claude Code, Cursor, or another coding agent, paste this prompt from the root of your Electron app:
Install and wire @wyverselabs/pinpoint in this Electron React Vite app.
Goal:
- Add Pinpoint as a development dependency.
- Add the @wyverselabs/pinpoint/vite plugin to the renderer Vite config.
- Wire the Electron main process with registerElectronPinpointMain() and toggleElectronPinpointForFocusedWindow().
- Expose the preload bridge with exposeElectronPinpointPreload().
- Install the renderer listener with installElectronPinpoint() in every renderer window entrypoint.
- Keep all runtime hooks development-only so Pinpoint is inactive in production builds.
Constraints:
- Preserve this app's existing Electron lifecycle, shortcut system, and Vite config structure.
- Do not rewrite unrelated app code.
- Do not use Effect, generators, or yield unless this app already uses them in the surrounding integration point.
- Use the app's existing package manager.
- After editing, run the smallest relevant typecheck/build commands and summarize how Pinpoint is triggered.
Reference package:
- @wyverselabs/pinpoint
- Vite import: import pinpoint from "@wyverselabs/pinpoint/vite"
- Main import: import { DEFAULT_PINPOINT_ACCELERATOR, registerElectronPinpointMain, toggleElectronPinpointForFocusedWindow } from "@wyverselabs/pinpoint/electron/main"
- Preload import: import { exposeElectronPinpointPreload } from "@wyverselabs/pinpoint/electron/preload"
- Renderer import: import { installElectronPinpoint } from "@wyverselabs/pinpoint/electron/renderer"1. Add The Vite Plugin
Add the plugin to your renderer build:
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import pinpoint from "@wyverselabs/pinpoint/vite";
export default defineConfig({
plugins: [
pinpoint({
root: __dirname,
}),
react(),
],
});The plugin injects data-ui-context-source and data-ui-context-name attributes into JSX output so selected DOM nodes can be traced back to source files.
2. Wire Electron Main
Register the clipboard IPC handler and toggle Pinpoint from your app shortcut:
import { app, globalShortcut } from "electron";
import {
DEFAULT_PINPOINT_ACCELERATOR,
registerElectronPinpointMain,
toggleElectronPinpointForFocusedWindow,
} from "@wyverselabs/pinpoint/electron/main";
if (!app.isPackaged) {
app.whenReady().then(() => {
const disposePinpoint = registerElectronPinpointMain();
globalShortcut.register(DEFAULT_PINPOINT_ACCELERATOR, () => {
toggleElectronPinpointForFocusedWindow();
});
app.once("before-quit", () => {
disposePinpoint();
globalShortcut.unregister(DEFAULT_PINPOINT_ACCELERATOR);
});
});
}You can use your own shortcut lifecycle instead. The important part is that registerElectronPinpointMain() runs in development and toggleElectronPinpointForFocusedWindow() runs when your shortcut fires.
3. Wire Preload And Renderer
Expose the preload bridge:
import { exposeElectronPinpointPreload } from "@wyverselabs/pinpoint/electron/preload";
if (process.env.NODE_ENV === "development") {
exposeElectronPinpointPreload();
}Install the renderer listener in each window:
import { installElectronPinpoint } from "@wyverselabs/pinpoint/electron/renderer";
if (import.meta.env.DEV) {
installElectronPinpoint({ windowLabel: "main" });
}Then press the configured shortcut, hover an element, and click to copy the Pinpoint selection to your clipboard.
Production Safety
Pinpoint is designed to be dev-only:
- The Vite metadata plugin disables itself when Vite mode is
production. - Electron main, preload, and renderer hooks should be installed behind your app's development guards.
- The recommended snippets above avoid installing runtime hooks in packaged production apps.
API
@wyverselabs/pinpoint/vite
import pinpoint from "@wyverselabs/pinpoint/vite";Options:
root?: stringinclude?: RegExpexclude?: RegExpenabled?: boolean
@wyverselabs/pinpoint/electron/main
import {
DEFAULT_PINPOINT_ACCELERATOR,
registerElectronPinpointMain,
toggleElectronPinpointForFocusedWindow,
} from "@wyverselabs/pinpoint/electron/main";@wyverselabs/pinpoint/electron/preload
import { exposeElectronPinpointPreload } from "@wyverselabs/pinpoint/electron/preload";@wyverselabs/pinpoint/electron/renderer
import { installElectronPinpoint } from "@wyverselabs/pinpoint/electron/renderer";Release Checks
bun run release:checkThis runs tests, builds the package, and previews the npm tarball.
