Skip to content
Back to skills

React Grab

BSecurity

Installs and configures React Grab for visual UI element selection in React/Electron apps. Use when user wants to edit UI visually, select components by hovering, or capture element context.

  • 57 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 17, 2026
developmentjavascripttypescriptjavabashreactnextjsnodesecurity

Works with

  • claude code
  • cli

Security analysis

B88/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies
  • mediumInstalls packages at runtime which could introduce malicious dependencies
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 17, 2026

npx -y skills add diegosouzapw/awesome-omni-skill --skill react-grab --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of React Grab?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for React Grab
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/diegosouzapw-react-grab/badge)](https://www.skillsdirectory.com/skills/diegosouzapw-react-grab)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: react-grab
description: Installs and configures React Grab for visual UI element selection in React/Electron apps. Use when user wants to edit UI visually, select components by hovering, or capture element context.
---

# React Grab Integration

## Step 1: Detect Project Type

**IMPORTANT: Before installing, detect the project type by checking these files:**

| Check For | Project Type |
|-----------|--------------|
| `electron-vite.config.*` | electron-vite |
| `forge.config.*` + `vite.*.config.*` | Electron Forge + Vite |
| `forge.config.*` + `webpack.*.config.*` | Electron Forge + Webpack |
| `electron` in package.json + `webpack.config.*` | Electron + Webpack |
| `electron` in package.json + `vite.config.*` | Electron + Vite |
| `electron` in package.json (no bundler) | Plain Electron |
| `next.config.*` | Next.js |
| `vite.config.*` (no electron) | Vite |
| `webpack.config.*` (no electron) | Webpack |

**Detection Commands:**
```bash
# Check package.json for framework
cat package.json | grep -E "(electron|next|vite)"

# Check for config files
ls -la | grep -E "(electron-vite|forge|next|vite|webpack)\.config"
```

---

## Step 2: Install

```bash
# Use the project's package manager (check lockfile)
pnpm add -D react-grab   # if pnpm-lock.yaml exists
npm install -D react-grab  # if package-lock.json exists
yarn add -D react-grab   # if yarn.lock exists
```

---

## Step 3: Configure Based on Project Type

### A. Next.js

**File to edit:** `app/layout.tsx` (App Router) or `pages/_app.tsx` (Pages Router)

**App Router - `app/layout.tsx`:**
```typescript
import Script from "next/script"

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <head>
        {process.env.NODE_ENV === "development" && (
          <Script src="//unpkg.com/react-grab/dist/index.global.js" strategy="beforeInteractive" />
        )}
      </head>
      <body>{children}</body>
    </html>
  )
}
```

**Pages Router - `pages/_app.tsx`:**
```typescript
import Script from "next/script"
import type { AppProps } from "next/app"

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      {process.env.NODE_ENV === "development" && (
        <Script src="//unpkg.com/react-grab/dist/index.global.js" strategy="beforeInteractive" />
      )}
      <Component {...pageProps} />
    </>
  )
}
```

---

### B. Vite (Web Only)

**File to edit:** `src/main.tsx` or `src/index.tsx`

```typescript
import React from "react"
import ReactDOM from "react-dom/client"
import App from "./App"

// Add this block at the top, after imports
if (import.meta.env.DEV) {
  import("react-grab").then(({ init }) => init())
}

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
)
```

---

### C. electron-vite

**Files to edit:**
1. `src/renderer/src/main.tsx` - Initialize react-grab
2. `src/main/index.ts` - Configure CSP

**Step C1 - `src/renderer/src/main.tsx`:**
```typescript
// Add at the top, after imports
if (import.meta.env.DEV) {
  import("react-grab").then(({ init }) => init())
}
```

**Step C2 - `src/main/index.ts`:** Find the `BrowserWindow` creation and add CSP:
```typescript
import { app, BrowserWindow } from "electron"
import { join } from "path"

function createWindow() {
  const mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    webPreferences: {
      preload: join(__dirname, "../preload/index.js"),
      sandbox: false  // Required for react-grab source mapping
    }
  })

  // Add this block for development CSP
  if (process.env.NODE_ENV === "development") {
    mainWindow.webContents.session.webRequest.onHeadersReceived((details, callback) => {
      callback({
        responseHeaders: {
          ...details.responseHeaders,
          "Content-Security-Policy": [
            "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"
          ]
        }
      })
    })
  }

  // ... rest of window setup
}
```

---

### D. Electron Forge + Vite

**Files to edit:**
1. `src/renderer.ts` or `src/renderer/index.tsx` - Initialize react-grab
2. `src/main.ts` - Configure CSP

**Step D1 - Renderer entry:**
```typescript
// Add at the top, after imports
if (import.meta.env.DEV) {
  import("react-grab").then(({ init }) => init())
}
```

**Step D2 - `src/main.ts`:** Add CSP configuration (same as electron-vite Step C2)

---

### E. Electron + Webpack

**Files to edit:**
1. `src/renderer/index.tsx` - Initialize react-grab
2. `src/main/main.ts` - Configure CSP

**Step E1 - `src/renderer/index.tsx`:**
```typescript
// Add at the top, after imports
if (process.env.NODE_ENV === "development") {
  import("react-grab").then(({ init }) => init())
}
```

**Step E2 - Main process:** Add CSP configuration (same as electron-vite Step C2)

---

### F. Plain Electron (No Bundler)

**Files to edit:**
1. `index.html` - Add script tag
2. `main.js` - Configure BrowserWindow
3. `renderer.js` - Initialize react-grab

**Step F1 - `index.html`:**
```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="Content-Security-Policy"
          content="default-src 'self'; script-src 'self' 'unsafe-inline' unpkg.com; style-src 'self' 'unsafe-inline'" />
    <script src="https://unpkg.com/react-grab/dist/index.global.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script src="./renderer.js"></script>
  </body>
</html>
```

**Step F2 - `main.js`:**
```javascript
const { app, BrowserWindow } = require("electron")
const path = require("path")

function createWindow() {
  const mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    webPreferences: {
      preload: path.join(__dirname, "preload.js"),
      contextIsolation: true,
      nodeIntegration: false,
      sandbox: false  // Required for react-grab source mapping
    }
  })

  mainWindow.loadFile("index.html")

  if (process.env.NODE_ENV === "development") {
    mainWindow.webContents.openDevTools()
  }
}

app.whenReady().then(createWindow)
```

**Step F3 - `renderer.js`:**
```javascript
// Initialize react-grab (loaded globally via script tag)
if (window.ReactGrab) {
  window.ReactGrab.init()
}
```

---

## Step 4: Verify Installation

**Run the dev server and check:**
1. Open browser DevTools console
2. Look for: `[react-grab] initialized` message
3. Hover over any element and press **Cmd+C** (Mac) or **Ctrl+C** (Windows)
4. Paste - you should see component info

**Expected output:**
```
<button class="btn">Submit</button>
in SubmitButton
components/button.tsx:42:19
```

---

## Troubleshooting

### All Projects

| Issue | Solution |
|-------|----------|
| "react-grab not defined" | Ensure script loads before React renders |
| Nothing copied on Cmd/Ctrl+C | Check browser console for errors |
| Wrong file paths | Enable source maps in bundler config |

### Electron-Specific

| Issue | Solution |
|-------|----------|
| CSP blocking script | Add `'unsafe-inline' 'unsafe-eval'` to CSP |
| Source maps not working | Set `sandbox: false` in webPreferences |
| Keyboard shortcut not working | Check for conflicting Menu accelerators |
| DevTools eval warning | Expected in dev - CSP needs `'unsafe-eval'` |

### CSP Reference for Electron

**Via Session Headers (Recommended):**
```typescript
// In main process after creating BrowserWindow
if (process.env.NODE_ENV === "development") {
  mainWindow.webContents.session.webRequest.onHeadersReceived((details, callback) => {
    callback({
      responseHeaders: {
        ...details.responseHeaders,
        "Content-Security-Policy": [
          "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"
        ]
      }
    })
  })
}
```

**Via Meta Tag:**
```html
<meta http-equiv="Content-Security-Policy"
      content="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'" />
```

---

## Optional: Claude Code Integration

**Add to `package.json` scripts:**

| Project Type | Script |
|--------------|--------|
| Next.js | `"dev:grab": "npx @react-grab/claude-code@latest & next dev"` |
| Vite | `"dev:grab": "npx @react-grab/claude-code@latest & vite"` |
| electron-vite | `"dev:grab": "concurrently \"npx @react-grab/claude-code@latest\" \"electron-vite dev\""` |
| Electron Forge | `"dev:grab": "concurrently \"npx @react-grab/claude-code@latest\" \"electron-forge start\""` |

**Client-side (add after react-grab init):**
```typescript
if (import.meta.env.DEV) {
  import("react-grab").then(() => {
    const script = document.createElement("script")
    script.src = "//unpkg.com/@react-grab/claude-code/dist/client.global.js"
    document.head.appendChild(script)
  })
}
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.