grab 0.0.97 → 0.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,20 +6,36 @@
6
6
 
7
7
  Select context for coding agents directly from your website
8
8
 
9
- How? Point at any element and it'll send the file name, React component, and HTML source code.
9
+ How? Point at any element and press **⌘C** (Mac) or **Ctrl+C** (Windows/Linux) to copy the file name, React component, and HTML source code.
10
10
 
11
11
  It makes tools like Cursor, Claude Code, Copilot run up to [**3× faster**](https://react-grab.com/blog/intro) and more accurate.
12
12
 
13
13
  ### [Try out a demo! →](https://react-grab.com)
14
14
 
15
- https://github.com/user-attachments/assets/fdb34329-b471-4b39-b433-0b1a27a94bd8
15
+ ![React Grab Demo](https://github.com/aidenybai/react-grab/blob/main/packages/website/public/demo.gif?raw=true)
16
16
 
17
17
  ## Install
18
18
 
19
19
  Run this command to install React Grab into your project. Ensure you are running at project root (e.g. where the `next.config.ts` or `vite.config.ts` file is located).
20
20
 
21
21
  ```html
22
- npx grab@latest init
22
+ npx -y grab@latest init
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ Once installed, hover over any UI element in your browser and press:
28
+
29
+ - **⌘C** (Cmd+C) on Mac
30
+ - **Ctrl+C** on Windows/Linux
31
+
32
+ This copies the element's context (file name, React component, and HTML source code) to your clipboard ready to paste into your coding agent. For example:
33
+
34
+ ```js
35
+ <a class="ml-auto inline-block text-sm" href="#">
36
+ Forgot your password?
37
+ </a>
38
+ in LoginForm at components/login-form.tsx:46:19
23
39
  ```
24
40
 
25
41
  ## Manual Installation
@@ -120,428 +136,172 @@ if (process.env.NODE_ENV === "development") {
120
136
  }
121
137
  ```
122
138
 
123
- ## Coding agent integration
124
-
125
- React Grab can send selected element context directly to your coding agent. This enables a workflow where you select a UI element and an agent automatically makes changes to your codebase.
126
-
127
- This means **no copying and pasting** - just select the element and let the agent do the rest. [Learn more →](https://react-grab.com/blog/agent)
128
-
129
- <details>
130
- <summary><strong>Claude Code</strong></summary>
131
-
132
- #### Server Setup
133
-
134
- The server runs on port `4567` and interfaces with the Claude Agent SDK. Add to your `package.json`:
135
-
136
- ```json
137
- {
138
- "scripts": {
139
- "dev": "npx @react-grab/claude-code@latest && next dev"
140
- }
141
- }
142
- ```
143
-
144
- #### Client Setup
145
-
146
- ```html
147
- <script src="//unpkg.com/grab/dist/index.global.js"></script>
148
- <!-- add this in the <head> -->
149
- <script src="//unpkg.com/@react-grab/claude-code/dist/client.global.js"></script>
150
- ```
151
-
152
- Or using Next.js `Script` component in your `app/layout.tsx`:
153
-
154
- ```jsx
155
- import Script from "next/script";
156
-
157
- export default function RootLayout({ children }) {
158
- return (
159
- <html>
160
- <head>
161
- {process.env.NODE_ENV === "development" && (
162
- <>
163
- <Script
164
- src="//unpkg.com/grab/dist/index.global.js"
165
- strategy="beforeInteractive"
166
- />
167
- <Script
168
- src="//unpkg.com/@react-grab/claude-code/dist/client.global.js"
169
- strategy="lazyOnload"
170
- />
171
- </>
172
- )}
173
- </head>
174
- <body>{children}</body>
175
- </html>
176
- );
177
- }
178
- ```
179
-
180
- </details>
181
-
182
- <details>
183
- <summary><strong>Cursor CLI</strong></summary>
184
-
185
- You must have the [`cursor-agent` CLI](https://cursor.com/docs/cli/overview) installed.
186
-
187
- #### Server Setup
188
-
189
- The server runs on port `5567` and interfaces with the `cursor-agent` CLI. Add to your `package.json`:
190
-
191
- ```json
192
- {
193
- "scripts": {
194
- "dev": "npx @react-grab/cursor@latest && next dev"
195
- }
196
- }
197
- ```
198
-
199
- #### Client Setup
200
-
201
- ```html
202
- <script src="//unpkg.com/grab/dist/index.global.js"></script>
203
- <!-- add this in the <head> -->
204
- <script src="//unpkg.com/@react-grab/cursor/dist/client.global.js"></script>
205
- ```
206
-
207
- Or using Next.js `Script` component in your `app/layout.tsx`:
208
-
209
- ```jsx
210
- import Script from "next/script";
211
-
212
- export default function RootLayout({ children }) {
213
- return (
214
- <html>
215
- <head>
216
- {process.env.NODE_ENV === "development" && (
217
- <>
218
- <Script
219
- src="//unpkg.com/grab/dist/index.global.js"
220
- strategy="beforeInteractive"
221
- />
222
- <Script
223
- src="//unpkg.com/@react-grab/cursor/dist/client.global.js"
224
- strategy="lazyOnload"
225
- />
226
- </>
227
- )}
228
- </head>
229
- <body>{children}</body>
230
- </html>
231
- );
232
- }
233
- ```
234
-
235
- </details>
236
-
237
- <details>
238
- <summary><strong>OpenCode</strong></summary>
239
-
240
- #### Server Setup
241
-
242
- The server runs on port `6567` and interfaces with the OpenCode CLI. Add to your `package.json`:
243
-
244
- ```json
245
- {
246
- "scripts": {
247
- "dev": "npx @react-grab/opencode@latest && next dev"
248
- }
249
- }
250
- ```
251
-
252
- > **Note:** You must have [OpenCode](https://opencode.ai) installed (`npm i -g opencode-ai@latest`).
253
-
254
- #### Client Setup
139
+ ## MCP Server
255
140
 
256
- ```html
257
- <script src="//unpkg.com/grab/dist/index.global.js"></script>
258
- <!-- add this in the <head> -->
259
- <script src="//unpkg.com/@react-grab/opencode/dist/client.global.js"></script>
260
- ```
261
-
262
- Or using Next.js `Script` component in your `app/layout.tsx`:
263
-
264
- ```jsx
265
- import Script from "next/script";
266
-
267
- export default function RootLayout({ children }) {
268
- return (
269
- <html>
270
- <head>
271
- {process.env.NODE_ENV === "development" && (
272
- <>
273
- <Script
274
- src="//unpkg.com/grab/dist/index.global.js"
275
- strategy="beforeInteractive"
276
- />
277
- <Script
278
- src="//unpkg.com/@react-grab/opencode/dist/client.global.js"
279
- strategy="lazyOnload"
280
- />
281
- </>
282
- )}
283
- </head>
284
- <body>{children}</body>
285
- </html>
286
- );
287
- }
288
- ```
289
-
290
- </details>
291
-
292
- <details>
293
- <summary><strong>Codex</strong></summary>
294
-
295
- #### Server Setup
296
-
297
- The server runs on port `7567` and interfaces with the OpenAI Codex SDK. Add to your `package.json`:
298
-
299
- ```json
300
- {
301
- "scripts": {
302
- "dev": "npx @react-grab/codex@latest && next dev"
303
- }
304
- }
305
- ```
141
+ React Grab includes an MCP (Model Context Protocol) server that gives AI coding agents direct access to your browser. This enables agents to navigate, click, fill forms, and take screenshots.
306
142
 
307
- > **Note:** You must have [Codex](https://github.com/openai/codex) installed (`npm i -g @openai/codex`).
143
+ ### Setup
308
144
 
309
- #### Client Setup
145
+ Run during project init:
310
146
 
311
- ```html
312
- <script src="//unpkg.com/grab/dist/index.global.js"></script>
313
- <!-- add this in the <head> -->
314
- <script src="//unpkg.com/@react-grab/codex/dist/client.global.js"></script>
147
+ ```bash
148
+ npx -y grab@latest init
149
+ # When prompted, choose to add the MCP server
315
150
  ```
316
151
 
317
- Or using Next.js `Script` component in your `app/layout.tsx`:
152
+ Or add it separately:
318
153
 
319
- ```jsx
320
- import Script from "next/script";
321
-
322
- export default function RootLayout({ children }) {
323
- return (
324
- <html>
325
- <head>
326
- {process.env.NODE_ENV === "development" && (
327
- <>
328
- <Script
329
- src="//unpkg.com/grab/dist/index.global.js"
330
- strategy="beforeInteractive"
331
- />
332
- <Script
333
- src="//unpkg.com/@react-grab/codex/dist/client.global.js"
334
- strategy="lazyOnload"
335
- />
336
- </>
337
- )}
338
- </head>
339
- <body>{children}</body>
340
- </html>
341
- );
342
- }
154
+ ```bash
155
+ npx -y grab@latest add mcp --client cursor
343
156
  ```
344
157
 
345
- </details>
158
+ Supported clients: `cursor`, `claude-code`, `vscode`, `opencode`, `codex`, `gemini-cli`, `windsurf`, `zed`, `droid`
346
159
 
347
- <details>
348
- <summary><strong>Gemini</strong></summary>
349
-
350
- #### Server Setup
351
-
352
- The server runs on port `8567` and interfaces with the Gemini CLI. Add to your `package.json`:
160
+ Or add it manually to your `mcp.json` file:
353
161
 
354
162
  ```json
355
163
  {
356
- "scripts": {
357
- "dev": "npx @react-grab/gemini@latest && next dev"
164
+ "mcpServers": {
165
+ "react-grab-browser": {
166
+ "command": "npx",
167
+ "args": ["-y", "@react-grab/cli", "browser", "mcp"]
168
+ }
358
169
  }
359
170
  }
360
171
  ```
361
172
 
362
- > **Note:** You must have [Gemini CLI](https://github.com/google-gemini/gemini-cli) installed.
173
+ ### MCP Tools
363
174
 
364
- #### Client Setup
175
+ Once configured, your agent has access to:
365
176
 
366
- ```html
367
- <script src="//unpkg.com/grab/dist/index.global.js"></script>
368
- <!-- add this in the <head> -->
369
- <script src="//unpkg.com/@react-grab/gemini/dist/client.global.js"></script>
370
- ```
177
+ - `browser_snapshot` - Get ARIA accessibility tree with element refs (e1, e2...)
178
+ - `browser_execute` - Run Playwright code with helpers like `ref('e1').click()`
371
179
 
372
- Or using Next.js `Script` component in your `app/layout.tsx`:
180
+ ## Skill
373
181
 
374
- ```jsx
375
- import Script from "next/script";
182
+ For agents that support skills (like Codex), install the `react-grab-browser` skill:
376
183
 
377
- export default function RootLayout({ children }) {
378
- return (
379
- <html>
380
- <head>
381
- {process.env.NODE_ENV === "development" && (
382
- <>
383
- <Script
384
- src="//unpkg.com/grab/dist/index.global.js"
385
- strategy="beforeInteractive"
386
- />
387
- <Script
388
- src="//unpkg.com/@react-grab/gemini/dist/client.global.js"
389
- strategy="lazyOnload"
390
- />
391
- </>
392
- )}
393
- </head>
394
- <body>{children}</body>
395
- </html>
396
- );
397
- }
184
+ ```bash
185
+ npx -y grab@latest add skill
186
+ # or
187
+ npx -y openskills install aidenybai/react-grab -y
398
188
  ```
399
189
 
400
- </details>
190
+ The skill provides browser automation with Playwright using your real browser cookies. See the [skill documentation](https://github.com/aidenybai/react-grab/blob/main/skills/react-grab-browser/SKILL.md) for full details.
401
191
 
402
- <details>
403
- <summary><strong>Amp</strong></summary>
192
+ ## Claude Plugin
404
193
 
405
- #### Server Setup
194
+ React Grab includes a Claude plugin for Claude Code/Desktop. The plugin is located in `.claude-plugin/` and provides browser automation capabilities.
406
195
 
407
- The server runs on port `9567` and interfaces with the [Amp SDK](https://ampcode.com/manual/sdk). Add to your `package.json`:
196
+ To use it, ensure the plugin files are present:
197
+ - `.claude-plugin/marketplace.json` - Plugin manifest
198
+ - `.claude/skills/react-grab-browser/` - Skill files (SKILL.md, EXAMPLES.md, REFERENCE.md)
408
199
 
409
- ```json
410
- {
411
- "scripts": {
412
- "dev": "npx @react-grab/amp@latest && next dev"
413
- }
414
- }
415
- ```
200
+ The plugin triggers on browser-related requests like "browse", "navigate to", "screenshot", "click on", "fill form", etc.
416
201
 
417
- > **Note:** You must have an [Amp API key](https://ampcode.com/settings) set via `AMP_API_KEY` environment variable.
202
+ ## Extending React Grab
418
203
 
419
- #### Client Setup
204
+ React Grab uses a plugin system to extend functionality. Check out the [type definitions](https://github.com/aidenybai/react-grab/blob/main/packages/react-grab/src/types.ts) to see all available options.
420
205
 
421
- ```html
422
- <script src="//unpkg.com/grab/dist/index.global.js"></script>
423
- <!-- add this in the <head> -->
424
- <script src="//unpkg.com/@react-grab/amp/dist/client.global.js"></script>
425
- ```
206
+ #### Basic Usage
426
207
 
427
- Or using Next.js `Script` component in your `app/layout.tsx`:
208
+ ```typescript
209
+ import { init } from "grab/core";
428
210
 
429
- ```jsx
430
- import Script from "next/script";
211
+ const api = init();
431
212
 
432
- export default function RootLayout({ children }) {
433
- return (
434
- <html>
435
- <head>
436
- {process.env.NODE_ENV === "development" && (
437
- <>
438
- <Script
439
- src="//unpkg.com/grab/dist/index.global.js"
440
- strategy="beforeInteractive"
441
- />
442
- <Script
443
- src="//unpkg.com/@react-grab/amp/dist/client.global.js"
444
- strategy="lazyOnload"
445
- />
446
- </>
447
- )}
448
- </head>
449
- <body>{children}</body>
450
- </html>
451
- );
452
- }
213
+ api.activate();
214
+ api.copyElement(document.querySelector(".my-element"));
215
+ console.log(api.getState());
453
216
  ```
454
217
 
455
- </details>
218
+ #### Lifecycle Hooks Plugin
456
219
 
457
- <details>
458
- <summary><strong>Factory Droid</strong></summary>
220
+ Track element selections with analytics:
459
221
 
460
- #### Server Setup
461
-
462
- The server runs on port `10567` and interfaces with the [Factory CLI](https://docs.factory.ai/cli/droid-exec/overview). Add to your `package.json`:
463
-
464
- ```json
465
- {
466
- "scripts": {
467
- "dev": "npx @react-grab/droid@latest && next dev"
468
- }
469
- }
222
+ ```typescript
223
+ api.registerPlugin({
224
+ name: "analytics",
225
+ hooks: {
226
+ onElementSelect: (element) => {
227
+ analytics.track("element_selected", { tagName: element.tagName });
228
+ },
229
+ onDragEnd: (elements, bounds) => {
230
+ analytics.track("drag_end", { count: elements.length, bounds });
231
+ },
232
+ onCopySuccess: (elements, content) => {
233
+ analytics.track("copy", { count: elements.length });
234
+ },
235
+ },
236
+ });
470
237
  ```
471
238
 
472
- > **Note:** You must have [Factory CLI](https://app.factory.ai) installed (`curl -fsSL https://app.factory.ai/cli | sh`) and `FACTORY_API_KEY` environment variable set.
239
+ #### Context Menu Plugin
473
240
 
474
- #### Client Setup
241
+ Add custom actions to the right-click menu:
475
242
 
476
- ```html
477
- <script src="//unpkg.com/grab/dist/index.global.js"></script>
478
- <!-- add this in the <head> -->
479
- <script src="//unpkg.com/@react-grab/droid/dist/client.global.js"></script>
243
+ ```typescript
244
+ api.registerPlugin({
245
+ name: "custom-actions",
246
+ actions: [
247
+ {
248
+ id: "log-to-console",
249
+ label: "Log to Console",
250
+ onAction: ({ elements }) => console.dir(elements[0]),
251
+ },
252
+ ],
253
+ });
480
254
  ```
481
255
 
482
- Or using Next.js `Script` component in your `app/layout.tsx`:
256
+ #### Theme Plugin
483
257
 
484
- ```jsx
485
- import Script from "next/script";
258
+ Customize the UI appearance:
486
259
 
487
- export default function RootLayout({ children }) {
488
- return (
489
- <html>
490
- <head>
491
- {process.env.NODE_ENV === "development" && (
492
- <>
493
- <Script
494
- src="//unpkg.com/grab/dist/index.global.js"
495
- strategy="beforeInteractive"
496
- />
497
- <Script
498
- src="//unpkg.com/@react-grab/droid/dist/client.global.js"
499
- strategy="lazyOnload"
500
- />
501
- </>
502
- )}
503
- </head>
504
- <body>{children}</body>
505
- </html>
506
- );
507
- }
260
+ ```typescript
261
+ api.registerPlugin({
262
+ name: "theme",
263
+ theme: {
264
+ hue: 180, // shift colors (pink → cyan)
265
+ crosshair: { enabled: false },
266
+ elementLabel: { enabled: false },
267
+ },
268
+ });
508
269
  ```
509
270
 
510
- </details>
511
-
512
- ## Extending React Grab
271
+ #### Agent Plugin
513
272
 
514
- React Grab provides an public customization API. Check out the [type definitions](https://github.com/aidenybai/react-grab/blob/main/packages/react-grab/src/types.ts) to see all available options for extending React Grab.
273
+ Create a custom agent that processes selected elements:
515
274
 
516
275
  ```typescript
517
- import { init } from "grab/core";
518
-
519
- const api = init({
520
- theme: {
521
- enabled: true, // disable all UI by setting to false
522
- hue: 180, // shift colors by 180 degrees (pink → cyan/turquoise)
523
- crosshair: {
524
- enabled: false, // disable crosshair
525
- },
526
- elementLabel: {
527
- enabled: false, // disable element label
276
+ api.registerPlugin({
277
+ name: "my-custom-agent",
278
+ actions: [
279
+ {
280
+ id: "custom-agent",
281
+ label: "Ask AI",
282
+ onAction: ({ enterPromptMode }) => enterPromptMode?.(),
283
+ agent: {
284
+ provider: {
285
+ async *send({ prompt, content }, signal) {
286
+ yield "Analyzing element...";
287
+
288
+ const response = await fetch("/api/ai", {
289
+ method: "POST",
290
+ headers: { "Content-Type": "application/json" },
291
+ body: JSON.stringify({ prompt, content }),
292
+ signal,
293
+ });
294
+
295
+ yield "Processing response...";
296
+
297
+ const result = await response.json();
298
+ yield `Done: ${result.message}`;
299
+ },
300
+ },
301
+ },
528
302
  },
529
- },
530
-
531
- onElementSelect: (element) => {
532
- console.log("Selected:", element);
533
- },
534
- onCopySuccess: (elements, content) => {
535
- console.log("Copied to clipboard:", content);
536
- },
537
- onStateChange: (state) => {
538
- console.log("Active:", state.isActive);
539
- },
303
+ ],
540
304
  });
541
-
542
- api.activate();
543
- api.copyElement(document.querySelector(".my-element"));
544
- console.log(api.getState());
545
305
  ```
546
306
 
547
307
  ## Resources & Contributing Back