click-to-agent
React component locator — Alt/Option+click to open source or send full context to Cursor & Claude. Next.js, Vite, TanStack Start, Rsbuild.
English · 简体中文
⌥ Option / ⎇ Alt + click any React component → jump to source, or hand it to your AI agent with full context.
React 18 & 19 · No browser extension · No Babel plugin.

1. What it does
Hold ⌥ Option (Mac) or ⎇ Alt (Win/Linux) and interact with any component:
| Gesture | Result |
|---|---|
| ⌥ / ⎇ + Hover | Red overlay, component name, source path, props/state preview |
| ⌥ / ⎇ + Click | Four-action picker (see below) |
| ⌥ / ⎇ + Right-click | Component ancestry tree → pick a parent → act on it |

Four actions on every component:
| Action | What happens | |
|---|---|---|
| Open in … | Open the file in each configured editor (see editor prop) |
|
| ▹ | Ask Cursor | Deeplink to Cursor with a rich, pre-filled prompt |
| ◎ | Ask Claude | Deeplink to Claude Code with the same context |
| ⧉ | Copy prompt | Copy the full prompt to clipboard |

Agent prompts include: component name · source path & line · props (JSON) · hook/class state · rendered DOM HTML · key computed CSS.
Why use it
- Zero friction — point at UI, don't hunt through the component tree
- Agent-ready context — Cursor / Claude get props, state, DOM, and CSS in one shot
- Works with your stack — Next.js zero-config; Vite / TanStack Start / Rsbuild need one
projectRootprop - Zero production impact — included in bundles only when
NODE_ENV === 'development'
2. Supported frameworks
| Framework | Example | |
|---|---|---|
| Next.js (Turbopack / webpack) | examples/nextjs |
|
| Vite + React | examples/vite |
|
| TanStack Start | examples/tanstack |
|
| Rsbuild / Rspack + React | examples/rsbuild |
React ≥ 18 · source maps enabled.
3. Quick start by framework
Install
pnpm add -D click-to-agent
npm install -D click-to-agent
yarn add -D click-to-agent
Place <Locator /> as high in your React tree as possible. Same pattern as @tanstack/react-query-devtools: no wrappers, no enabled prop — the package entry exports a no-op in production when process.env.NODE_ENV !== 'development'.
| Framework | projectRoot |
|---|---|
| Next.js | Optional (auto) |
| Vite / Rsbuild / TanStack Start | Required — define: { __PROJECT_ROOT__: JSON.stringify(process.cwd()) } |
Next.js
// app/layout.tsx (or pages/_app.tsx)
import { Locator } from 'click-to-agent';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
{children}
<Locator />
</body>
</html>
);
}
Optional: NEXT_PUBLIC_PROJECT_ROOT in .env.local instead of the projectRoot prop.
Vite
// vite.config.ts
export default defineConfig({
define: { __PROJECT_ROOT__: JSON.stringify(process.cwd()) },
});
// src/main.tsx
import { Locator } from 'click-to-agent';
declare const __PROJECT_ROOT__: string;
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
<Locator projectRoot={__PROJECT_ROOT__} />
</StrictMode>,
);
Rsbuild / Rspack
// rsbuild.config.ts
export default defineConfig({
source: {
define: { __PROJECT_ROOT__: JSON.stringify(process.cwd()) },
},
});
// src/index.tsx
import { Locator } from 'click-to-agent';
declare const __PROJECT_ROOT__: string;
root.render(
<StrictMode>
<App />
<Locator projectRoot={__PROJECT_ROOT__} />
</StrictMode>,
);
TanStack Start
// vite.config.ts
define: { __PROJECT_ROOT__: JSON.stringify(process.cwd()) },
// src/routes/__root.tsx — inside <body>
import { Locator } from 'click-to-agent';
declare const __PROJECT_ROOT__: string;
<Locator projectRoot={__PROJECT_ROOT__} />
4. <Locator /> props
| Prop | Type | Default | Description |
|---|---|---|---|
editor |
EditorProtocol[] |
['cursor', 'vscode'] |
Editors for Go to source — one menu item per entry |
projectRoot |
string |
— | Absolute project root for source-map path resolution. Overrides NEXT_PUBLIC_PROJECT_ROOT. Required for Vite / TanStack Start / Rsbuild unless paths already resolve absolutely |
modifier |
'alt' | 'ctrl' | 'meta' | 'shift' |
'alt' |
Modifier key: ⎇ Alt / ⌥ Option · ⌃ Ctrl · ⌘ Cmd · ⇧ Shift |
highlightColor |
string |
'#ef4444' |
Overlay border color (any CSS color) |
showPreview |
boolean |
true |
Props / hook-state preview panel on ⌥/⎇ + hover |
<Locator />
<Locator projectRoot={__PROJECT_ROOT__} />
<Locator editor={['cursor']} />
<Locator modifier="meta" highlightColor="#3b82f6" />
<Locator showPreview={false} />
Ask Cursor / Ask Claude use their own deeplinks — independent of the
editorprop.
TypeScript
import type { LocatorProps, EditorProtocol, AgentTarget, FiberInspection } from 'click-to-agent';
License
MIT — original stkang9409, fork stekovinbranturry.