grab 0.0.98 → 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
@@ -19,7 +19,7 @@ It makes tools like Cursor, Claude Code, Copilot run up to [**3× faster**](http
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
23
  ```
24
24
 
25
25
  ## Usage
@@ -136,430 +136,172 @@ if (process.env.NODE_ENV === "development") {
136
136
  }
137
137
  ```
138
138
 
139
- ## Coding agent integration
139
+ ## MCP Server
140
140
 
141
- 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.
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.
142
142
 
143
- This means **no copying and pasting** - just select the element and let the agent do the rest. [Read more about coding agent integration →](https://react-grab.com/blog/agent)
143
+ ### Setup
144
144
 
145
- > **Click to expand** setup instructions for your coding agent:
145
+ Run during project init:
146
146
 
147
- <details>
148
- <summary><strong>Claude Code</strong></summary>
149
-
150
- #### Server Setup
151
-
152
- The server runs on port `4567` and interfaces with the Claude Agent SDK. Add to your `package.json`:
153
-
154
- ```json
155
- {
156
- "scripts": {
157
- "dev": "npx @react-grab/claude-code@latest && next dev"
158
- }
159
- }
160
- ```
161
-
162
- #### Client Setup
163
-
164
- ```html
165
- <script src="//unpkg.com/grab/dist/index.global.js"></script>
166
- <!-- add this in the <head> -->
167
- <script src="//unpkg.com/@react-grab/claude-code/dist/client.global.js"></script>
168
- ```
169
-
170
- Or using Next.js `Script` component in your `app/layout.tsx`:
171
-
172
- ```jsx
173
- import Script from "next/script";
174
-
175
- export default function RootLayout({ children }) {
176
- return (
177
- <html>
178
- <head>
179
- {process.env.NODE_ENV === "development" && (
180
- <>
181
- <Script
182
- src="//unpkg.com/grab/dist/index.global.js"
183
- strategy="beforeInteractive"
184
- />
185
- <Script
186
- src="//unpkg.com/@react-grab/claude-code/dist/client.global.js"
187
- strategy="lazyOnload"
188
- />
189
- </>
190
- )}
191
- </head>
192
- <body>{children}</body>
193
- </html>
194
- );
195
- }
196
- ```
197
-
198
- </details>
199
-
200
- <details>
201
- <summary><strong>Cursor CLI</strong></summary>
202
-
203
- You must have the [`cursor-agent` CLI](https://cursor.com/docs/cli/overview) installed.
204
-
205
- #### Server Setup
206
-
207
- The server runs on port `5567` and interfaces with the `cursor-agent` CLI. Add to your `package.json`:
208
-
209
- ```json
210
- {
211
- "scripts": {
212
- "dev": "npx @react-grab/cursor@latest && next dev"
213
- }
214
- }
215
- ```
216
-
217
- #### Client Setup
218
-
219
- ```html
220
- <script src="//unpkg.com/grab/dist/index.global.js"></script>
221
- <!-- add this in the <head> -->
222
- <script src="//unpkg.com/@react-grab/cursor/dist/client.global.js"></script>
223
- ```
224
-
225
- Or using Next.js `Script` component in your `app/layout.tsx`:
226
-
227
- ```jsx
228
- import Script from "next/script";
229
-
230
- export default function RootLayout({ children }) {
231
- return (
232
- <html>
233
- <head>
234
- {process.env.NODE_ENV === "development" && (
235
- <>
236
- <Script
237
- src="//unpkg.com/grab/dist/index.global.js"
238
- strategy="beforeInteractive"
239
- />
240
- <Script
241
- src="//unpkg.com/@react-grab/cursor/dist/client.global.js"
242
- strategy="lazyOnload"
243
- />
244
- </>
245
- )}
246
- </head>
247
- <body>{children}</body>
248
- </html>
249
- );
250
- }
251
- ```
252
-
253
- </details>
254
-
255
- <details>
256
- <summary><strong>OpenCode</strong></summary>
257
-
258
- #### Server Setup
259
-
260
- The server runs on port `6567` and interfaces with the OpenCode CLI. Add to your `package.json`:
261
-
262
- ```json
263
- {
264
- "scripts": {
265
- "dev": "npx @react-grab/opencode@latest && next dev"
266
- }
267
- }
268
- ```
269
-
270
- > **Note:** You must have [OpenCode](https://opencode.ai) installed (`npm i -g opencode-ai@latest`).
271
-
272
- #### Client Setup
273
-
274
- ```html
275
- <script src="//unpkg.com/grab/dist/index.global.js"></script>
276
- <!-- add this in the <head> -->
277
- <script src="//unpkg.com/@react-grab/opencode/dist/client.global.js"></script>
278
- ```
279
-
280
- Or using Next.js `Script` component in your `app/layout.tsx`:
281
-
282
- ```jsx
283
- import Script from "next/script";
284
-
285
- export default function RootLayout({ children }) {
286
- return (
287
- <html>
288
- <head>
289
- {process.env.NODE_ENV === "development" && (
290
- <>
291
- <Script
292
- src="//unpkg.com/grab/dist/index.global.js"
293
- strategy="beforeInteractive"
294
- />
295
- <Script
296
- src="//unpkg.com/@react-grab/opencode/dist/client.global.js"
297
- strategy="lazyOnload"
298
- />
299
- </>
300
- )}
301
- </head>
302
- <body>{children}</body>
303
- </html>
304
- );
305
- }
306
- ```
307
-
308
- </details>
309
-
310
- <details>
311
- <summary><strong>Codex</strong></summary>
312
-
313
- #### Server Setup
314
-
315
- The server runs on port `7567` and interfaces with the OpenAI Codex SDK. Add to your `package.json`:
316
-
317
- ```json
318
- {
319
- "scripts": {
320
- "dev": "npx @react-grab/codex@latest && next dev"
321
- }
322
- }
323
- ```
324
-
325
- > **Note:** You must have [Codex](https://github.com/openai/codex) installed (`npm i -g @openai/codex`).
326
-
327
- #### Client Setup
328
-
329
- ```html
330
- <script src="//unpkg.com/grab/dist/index.global.js"></script>
331
- <!-- add this in the <head> -->
332
- <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
333
150
  ```
334
151
 
335
- Or using Next.js `Script` component in your `app/layout.tsx`:
152
+ Or add it separately:
336
153
 
337
- ```jsx
338
- import Script from "next/script";
339
-
340
- export default function RootLayout({ children }) {
341
- return (
342
- <html>
343
- <head>
344
- {process.env.NODE_ENV === "development" && (
345
- <>
346
- <Script
347
- src="//unpkg.com/grab/dist/index.global.js"
348
- strategy="beforeInteractive"
349
- />
350
- <Script
351
- src="//unpkg.com/@react-grab/codex/dist/client.global.js"
352
- strategy="lazyOnload"
353
- />
354
- </>
355
- )}
356
- </head>
357
- <body>{children}</body>
358
- </html>
359
- );
360
- }
154
+ ```bash
155
+ npx -y grab@latest add mcp --client cursor
361
156
  ```
362
157
 
363
- </details>
364
-
365
- <details>
366
- <summary><strong>Gemini</strong></summary>
158
+ Supported clients: `cursor`, `claude-code`, `vscode`, `opencode`, `codex`, `gemini-cli`, `windsurf`, `zed`, `droid`
367
159
 
368
- #### Server Setup
369
-
370
- 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:
371
161
 
372
162
  ```json
373
163
  {
374
- "scripts": {
375
- "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
+ }
376
169
  }
377
170
  }
378
171
  ```
379
172
 
380
- > **Note:** You must have [Gemini CLI](https://github.com/google-gemini/gemini-cli) installed.
173
+ ### MCP Tools
381
174
 
382
- #### Client Setup
175
+ Once configured, your agent has access to:
383
176
 
384
- ```html
385
- <script src="//unpkg.com/grab/dist/index.global.js"></script>
386
- <!-- add this in the <head> -->
387
- <script src="//unpkg.com/@react-grab/gemini/dist/client.global.js"></script>
388
- ```
177
+ - `browser_snapshot` - Get ARIA accessibility tree with element refs (e1, e2...)
178
+ - `browser_execute` - Run Playwright code with helpers like `ref('e1').click()`
389
179
 
390
- Or using Next.js `Script` component in your `app/layout.tsx`:
180
+ ## Skill
391
181
 
392
- ```jsx
393
- import Script from "next/script";
182
+ For agents that support skills (like Codex), install the `react-grab-browser` skill:
394
183
 
395
- export default function RootLayout({ children }) {
396
- return (
397
- <html>
398
- <head>
399
- {process.env.NODE_ENV === "development" && (
400
- <>
401
- <Script
402
- src="//unpkg.com/grab/dist/index.global.js"
403
- strategy="beforeInteractive"
404
- />
405
- <Script
406
- src="//unpkg.com/@react-grab/gemini/dist/client.global.js"
407
- strategy="lazyOnload"
408
- />
409
- </>
410
- )}
411
- </head>
412
- <body>{children}</body>
413
- </html>
414
- );
415
- }
184
+ ```bash
185
+ npx -y grab@latest add skill
186
+ # or
187
+ npx -y openskills install aidenybai/react-grab -y
416
188
  ```
417
189
 
418
- </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.
419
191
 
420
- <details>
421
- <summary><strong>Amp</strong></summary>
192
+ ## Claude Plugin
422
193
 
423
- #### 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.
424
195
 
425
- 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)
426
199
 
427
- ```json
428
- {
429
- "scripts": {
430
- "dev": "npx @react-grab/amp@latest && next dev"
431
- }
432
- }
433
- ```
200
+ The plugin triggers on browser-related requests like "browse", "navigate to", "screenshot", "click on", "fill form", etc.
434
201
 
435
- > **Note:** You must have an [Amp API key](https://ampcode.com/settings) set via `AMP_API_KEY` environment variable.
202
+ ## Extending React Grab
436
203
 
437
- #### 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.
438
205
 
439
- ```html
440
- <script src="//unpkg.com/grab/dist/index.global.js"></script>
441
- <!-- add this in the <head> -->
442
- <script src="//unpkg.com/@react-grab/amp/dist/client.global.js"></script>
443
- ```
206
+ #### Basic Usage
444
207
 
445
- Or using Next.js `Script` component in your `app/layout.tsx`:
208
+ ```typescript
209
+ import { init } from "grab/core";
446
210
 
447
- ```jsx
448
- import Script from "next/script";
211
+ const api = init();
449
212
 
450
- export default function RootLayout({ children }) {
451
- return (
452
- <html>
453
- <head>
454
- {process.env.NODE_ENV === "development" && (
455
- <>
456
- <Script
457
- src="//unpkg.com/grab/dist/index.global.js"
458
- strategy="beforeInteractive"
459
- />
460
- <Script
461
- src="//unpkg.com/@react-grab/amp/dist/client.global.js"
462
- strategy="lazyOnload"
463
- />
464
- </>
465
- )}
466
- </head>
467
- <body>{children}</body>
468
- </html>
469
- );
470
- }
213
+ api.activate();
214
+ api.copyElement(document.querySelector(".my-element"));
215
+ console.log(api.getState());
471
216
  ```
472
217
 
473
- </details>
474
-
475
- <details>
476
- <summary><strong>Factory Droid</strong></summary>
477
-
478
- #### Server Setup
218
+ #### Lifecycle Hooks Plugin
479
219
 
480
- 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`:
220
+ Track element selections with analytics:
481
221
 
482
- ```json
483
- {
484
- "scripts": {
485
- "dev": "npx @react-grab/droid@latest && next dev"
486
- }
487
- }
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
+ });
488
237
  ```
489
238
 
490
- > **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
491
240
 
492
- #### Client Setup
241
+ Add custom actions to the right-click menu:
493
242
 
494
- ```html
495
- <script src="//unpkg.com/grab/dist/index.global.js"></script>
496
- <!-- add this in the <head> -->
497
- <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
+ });
498
254
  ```
499
255
 
500
- Or using Next.js `Script` component in your `app/layout.tsx`:
256
+ #### Theme Plugin
501
257
 
502
- ```jsx
503
- import Script from "next/script";
258
+ Customize the UI appearance:
504
259
 
505
- export default function RootLayout({ children }) {
506
- return (
507
- <html>
508
- <head>
509
- {process.env.NODE_ENV === "development" && (
510
- <>
511
- <Script
512
- src="//unpkg.com/grab/dist/index.global.js"
513
- strategy="beforeInteractive"
514
- />
515
- <Script
516
- src="//unpkg.com/@react-grab/droid/dist/client.global.js"
517
- strategy="lazyOnload"
518
- />
519
- </>
520
- )}
521
- </head>
522
- <body>{children}</body>
523
- </html>
524
- );
525
- }
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
+ });
526
269
  ```
527
270
 
528
- </details>
529
-
530
- ## Extending React Grab
271
+ #### Agent Plugin
531
272
 
532
- 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:
533
274
 
534
275
  ```typescript
535
- import { init } from "grab/core";
536
-
537
- const api = init({
538
- theme: {
539
- enabled: true, // disable all UI by setting to false
540
- hue: 180, // shift colors by 180 degrees (pink → cyan/turquoise)
541
- crosshair: {
542
- enabled: false, // disable crosshair
543
- },
544
- elementLabel: {
545
- 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
+ },
546
302
  },
547
- },
548
-
549
- onElementSelect: (element) => {
550
- console.log("Selected:", element);
551
- },
552
- onCopySuccess: (elements, content) => {
553
- console.log("Copied to clipboard:", content);
554
- },
555
- onStateChange: (state) => {
556
- console.log("Active:", state.isActive);
557
- },
303
+ ],
558
304
  });
559
-
560
- api.activate();
561
- api.copyElement(document.querySelector(".my-element"));
562
- console.log(api.getState());
563
305
  ```
564
306
 
565
307
  ## Resources & Contributing Back