React Grab used to stop at copying context for your coding agent. Now it can directly talk to the agent to edit the code -- all from the browser.
React Grab came from a simple (but very relevant!) annoyance.
Coding agents are good at generating code, but bad at guessing what I actually want. The loop looked like this:
I built the first version of React Grab2 to solve this: press ⌘C, click an element, and React Grab gives you the component stack with exact file paths and line numbers.

Now, instead of guessing where an element might live, the agent jumps straight to the exact file, line, and column.
In the benchmarks I ran on a shadcn dashboard, that alone made Claude Code roughly 66% faster on average for a set of UI tasks.1 The agent did fewer tool calls, read fewer files, and got to the edit sooner, because it no longer had to search.
React Grab worked. People wired it into their apps. It made coding agents feel less random for UI work.
It also had an obvious flaw.
React Grab solved the context problem and ignored everything else (this is actually intentional!). You still had to copy, switch to your agent, paste, wait, switch back, and refresh. For one-off tasks this was fine. After using it daily, I realized we can do a LOT better.
The browser had the best view of your intent. The agent had the power to edit the code. Why not put the agent in the browser?
(Theo predicted this months ago.)
React Grab for Agents is what happens when you let the browser do more of the loop.
The idea is simple.
You hold ⌘C, click an element, and a small label appears showing the component name and tag. Press Enter to expand the prompt input. Type what you want to change, press Enter again, and the agent starts working.
React Grab sends the context (file paths, line numbers, component stack, nearby HTML) along with your prompt to the agent. The agent edits your files directly while the label streams back status updates. When it finishes, the label shows "Completed" and your app reloads with the changes.
You never leave the browser. You never touch the clipboard.
You can run multiple tasks at once. Click one element, start an edit, then click another and start a different task. Each selection tracks its own progress independently. It starts to feel less like "I am chatting with an assistant" and more like a small job queue attached to my UI
Setup is designed to feel like adding one more feature to your existing React Grab integration, not like adopting a new framework.
Run this command at your project root to automatically install React Grab:
npx @react-grab/cli@latest
The CLI will detect your framework and add the necessary scripts automatically.
Server Setup
The server runs on port 4567 and interfaces with the Claude Agent SDK. Add to your package.json:
{
"scripts": {
"dev": "npx @react-grab/claude-code@latest && next dev"
}
}Client Setup
If you already have React Grab running via a script tag in a Next.js app, add the Claude Code client script in your <head>:
<script src="//unpkg.com/react-grab/dist/index.global.js"></script> <script src="//unpkg.com/@react-grab/claude-code/dist/client.global.js"></script>
Or using Next.js Script component in your app/layout.tsx:
import Script from "next/script";
export default function RootLayout({ children }) {
return (
<html>
<head>
{process.env.NODE_ENV === "development" && (
<>
<Script
src="//unpkg.com/react-grab/dist/index.global.js"
strategy="beforeInteractive"
/>
<Script
src="//unpkg.com/@react-grab/claude-code/dist/client.global.js"
strategy="lazyOnload"
/>
</>
)}
</head>
<body>{children}</body>
</html>
);
}Server Setup
The server runs on port 5567 and interfaces with the cursor-agent CLI. Add to your package.json:
{
"scripts": {
"dev": "npx @react-grab/cursor@latest && next dev"
}
}Client Setup
Add the Cursor client script in your <head>:
<script src="//unpkg.com/react-grab/dist/index.global.js"></script> <script src="//unpkg.com/@react-grab/cursor/dist/client.global.js"></script>
Or using Next.js Script component in your app/layout.tsx:
import Script from "next/script";
export default function RootLayout({ children }) {
return (
<html>
<head>
{process.env.NODE_ENV === "development" && (
<>
<Script
src="//unpkg.com/react-grab/dist/index.global.js"
strategy="beforeInteractive"
/>
<Script
src="//unpkg.com/@react-grab/cursor/dist/client.global.js"
strategy="lazyOnload"
/>
</>
)}
</head>
<body>{children}</body>
</html>
);
}Hold ⌘C, click an element, then press Enter to open the prompt. Type your query, pick an agent from the dropdown, and hit Enter again to run it.
Server Setup
The server runs on port 6567 and interfaces with the opencode CLI. Add to your package.json:
{
"scripts": {
"dev": "npx @react-grab/opencode@latest && next dev"
}
}Client Setup
Add the Opencode client script in your <head>:
<script src="//unpkg.com/react-grab/dist/index.global.js"></script> <script src="//unpkg.com/@react-grab/opencode/dist/client.global.js"></script>
Or using Next.js Script component in your app/layout.tsx:
import Script from "next/script";
export default function RootLayout({ children }) {
return (
<html>
<head>
{process.env.NODE_ENV === "development" && (
<>
<Script
src="//unpkg.com/react-grab/dist/index.global.js"
strategy="beforeInteractive"
/>
<Script
src="//unpkg.com/@react-grab/opencode/dist/client.global.js"
strategy="lazyOnload"
/>
</>
)}
</head>
<body>{children}</body>
</html>
);
}Under the hood, React Grab for Agents is built on the same mechanics as the original library.
When you select an element, React Grab:
This is the context that made the original benchmarks so much better. The agent gets a direct pointer instead of a fuzzy description.
The new part is the agent provider.
An agent provider is a small adapter that connects React Grab to a coding agent. When you submit a prompt, React Grab sends the context and your message to a local server. The server passes this to the actual CLI (claude or cursor-agent) which edits your codebase directly. Status updates stream back to the browser so you can watch the agent work.
The providers are open source. You can read through the implementation or use them as a starting point for your own: @react-grab/claude-code, @react-grab/cursor, @react-grab/opencode.
Right now, React Grab for Agents is tool-agnostic on purpose. It integrates with the agents that exist. If your tool has a CLI or an API, you can add a provider.
However, I do not think the long term story is just "wire up whatever you already have." There is a missing piece: a coding agent designed specifically for UI work, built around the way React Grab represents context.
Soon, we'll be releasing Ami.3
The idea is that React Grab handles the UI side: selections, stacks, file paths, and prompts. Ami handles the agent side: planning, editing, and understanding component hierarchies and design systems. The contract is narrow. React Grab says "here is exactly what the user clicked and what they asked for." Ami replies with "here is the minimal patch that makes that true, in a style you will recognize."
React Grab for Agents is the infrastructure that makes that relationship possible. Before Ami exists, it makes your existing tools faster and less random for frontend work. Once Ami is ready, it gives it a natural place to live.
1See the full benchmark writeup. Single trial per test case, so treat the exact number with appropriate skepticism. The direction is consistent across tasks.
2This only works in development mode. React strips source locations in production builds for performance and bundle size. React Grab detects this and falls back to showing component names without file paths. You can enable source maps in production if you need the full paths.
3Ami is under active development. If you want early access or want to help shape it, reach out on Twitter.