Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"permissions": {
"allow": [
"Bash(pnpm install)",
"Bash(pnpm build:*)",
"Bash(chmod:*)",
"Bash(./scripts/generate-icons.sh:*)",
"Bash(cat:*)",
"Bash(pnpm add:*)",
"Bash(pnpm --filter react-grab build:*)",
"Bash(pnpm --filter chrome-extension build:*)"
]
},
"enableAllProjectMcpServers": true,
"enabledMcpjsonServers": [
"shadcn",
"nuxt-ui",
"Better Auth",
"supabase"
]
}
171 changes: 171 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Overview

React Grab is a developer tool that allows you to grab any element in your React app and provide it to AI coding assistants (Cursor, Claude Code, etc.) by holding ⌘C (or Ctrl+C) and clicking elements. The library captures HTML snippets and React component ownership stacks to provide rich context.

## Monorepo Structure

This is a pnpm workspace monorepo with three packages:

- **`packages/react-grab`**: Main library package (TypeScript)
- Core instrumentation logic in `src/instrumentation.ts` - captures component stacks and HTML snippets
- Overlay UI in `src/overlay.ts` - visual feedback when hovering/selecting elements
- Hotkey tracking in `src/hotkeys.ts` - keyboard event handling
- Adapters in `src/adapters.ts` - integration with external tools (e.g., Cursor)
- Vite plugin in `src/plugins/vite.ts` - automatic script injection for Vite projects

- **`packages/kitchen-sink`**: Demo/testing application using Vite + React 19
- Used to manually test react-grab functionality during development

- **`packages/website`**: Documentation website built with Next.js 16 App Router
- Marketing site and installation instructions
- Uses Tailwind CSS v4 and Framer Motion

## Development Commands

**Build the main library:**
```bash
pnpm build
```

**Watch mode (rebuilds on file changes):**
```bash
pnpm dev
```

**Linting:**
```bash
pnpm lint # Check for issues
pnpm lint:fix # Auto-fix issues
```

**Formatting:**
```bash
pnpm format # Format all files with Prettier
pnpm check # Run both linting and format check
```

**Testing changes:**
```bash
cd packages/kitchen-sink
pnpm dev # Start Vite dev server
# Then hold ⌘C and click elements to test functionality
```

**Run single package commands:**
```bash
pnpm --filter react-grab build
pnpm --filter kitchen-sink dev
pnpm --filter website dev
```

## Build System

The main library uses `tsup` for bundling (config: `packages/react-grab/tsup.config.ts`):

1. **IIFE build** (`dist/index.global.js`): Browser-ready script tag version with global `ReactGrab` namespace
2. **ESM/CJS builds** (`dist/index.js`, `dist/index.cjs`): For npm package consumers
3. **Vite plugin build** (`dist/plugins/vite.js`, `dist/plugins/vite.cjs`): Separate entry point for Vite integration

The library automatically initializes when loaded via script tag by reading `data-*` attributes from the script element.

## Code Architecture

**Key Flow:**
1. User holds activation hotkey (default: ⌘C)
2. Progress indicator shows key hold duration (default: 500ms)
3. When threshold reached, overlay mode activates
4. Mouse movement tracked to identify element under cursor (excluding react-grab's own overlay elements)
5. Selection overlay highlights hovered element with visual feedback
6. On click, captures:
- HTML snippet of element (via `getHTMLSnippet`)
- React component ownership stack (via `getStack` using React DevTools internals)
- Filters and serializes stack for clarity
7. Copies formatted text to clipboard wrapped in `<referenced_element>` tags
8. If adapter configured, opens in external tool (e.g., Cursor composer)

**State Management:**
- Custom store implementation in `src/utils/store.ts` with subscription support
- Global `libStore` tracks: pressed keys, mouse position, overlay mode (hidden/visible/copying)

**Performance Optimizations:**
- RequestAnimationFrame-based rendering to batch DOM updates
- Throttled mouse move handling to avoid excessive updates
- Element visibility checks before selection (filters invisible elements)
- Continuous render loop only updates when state changes

## Code Style Guidelines

**From `.cursor/rules/codebase-guidelines.mdc`:**

- Use **TypeScript interfaces** over types
- Use **arrow functions** over function declarations
- Use **kebab-case** for filenames
- Use **descriptive variable names** (avoid abbreviations like `x`, prefer `innerElement`)
- Remove unused code and avoid repetition
- Only add comments when absolutely necessary
- Prefix hacks with `// HACK: reason for hack`
- Keep interfaces/types at global scope
- React component layout: Props interface first, then named arrow function export
- Avoid type casting ("as") unless absolutely necessary
- Move inline SVGs to `icon-NAME.tsx` files with component name `IconNAME`

**Example:**
```typescript
interface UserPreferences {
enableOverlay: boolean;
hotkey: string;
}

const getUserPreferences = (): UserPreferences => {
// Implementation
};
```

## Release Process

Uses [Changesets](https://github.com/changesets/changesets) for version management:

1. Create a changeset when making changes affecting the public API:
```bash
pnpm changeset
```

2. Follow prompts to describe changes (patch/minor/major)
3. Commit the generated changeset file
4. Maintainers will handle versioning and publishing:
```bash
pnpm version # Bumps versions based on changesets
pnpm release # Builds and publishes to npm
```

## Requirements

- **Node.js**: v18 or higher
- **pnpm**: v8 or higher (enforced via engines in package.json)

## Testing Strategy

No automated unit tests currently. Testing is done manually via the kitchen-sink demo:

1. Start kitchen-sink dev server
2. Hold ⌘C (or Ctrl+C on Windows/Linux) for 500ms
3. Click various elements to verify:
- Overlay positioning and styling
- HTML snippet capture
- Component stack extraction
- Clipboard copying
- External adapter integration (if configured)
4. Test across multiple browsers: Chrome, Firefox, Safari
5. Test edge cases: deeply nested components, elements with transforms, scrolled containers

## Common Gotchas

- The library uses React DevTools internals (via `bippy` package) to extract component stacks - this is fragile and may break with React updates
- Overlay positioning respects element transforms and border radius by reading computed styles
- Script tag must be in `<head>` with `strategy="beforeInteractive"` for Next.js to ensure it loads before React hydration
- Vite plugin only applies in development mode (`apply: "serve"`)
- Elements with `data-react-grab-ignore` attribute (using `ATTRIBUTE_NAME` constant) are excluded from selection
86 changes: 86 additions & 0 deletions LLMS/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# React Grab - Agentic LLM Guide

This file provides context and instructions for AI agents working on the React Grab codebase.

## Project Overview
React Grab is a developer tool that allows users to "grab" elements in a React app to capture their HTML and component stack for use with AI coding assistants.

## Monorepo Structure
The project is a **pnpm workspace** monorepo.

- **`packages/react-grab`**: The core library.
- `src/instrumentation.ts`: Core logic for capturing component stacks.
- `src/overlay.ts`: UI overlay for element selection.
- `src/hotkeys.ts`: Keyboard event handling.
- `src/plugins/vite.ts`: Vite plugin implementation.
- **`packages/kitchen-sink`**: Demo/testing application (Vite + React 19).
- **`packages/website`**: Documentation site (Next.js 16).

## Development Commands
Run these from the root directory:

- **Build**: `pnpm build` (Builds all packages)
- **Dev (Watch)**: `pnpm dev` (Rebuilds on change)
- **Lint**: `pnpm lint` / `pnpm lint:fix`
- **Format**: `pnpm format`
- **Test**: No automated unit tests. Use `packages/kitchen-sink` for manual verification.
- `cd packages/kitchen-sink && pnpm dev`
- Hold `Cmd+C` and click elements to test.

## Code Style Guidelines
- **Language**: TypeScript (use interfaces, not types).
- **Functions**: Arrow functions preferred.
- **Naming**: Kebab-case for filenames. Descriptive variable names.
- **Components**: Props interface first, then named export.
- **Icons**: Move inline SVGs to `icon-NAME.tsx`.

## Key Architecture Notes
- **Instrumentation**: Uses `bippy` (React DevTools internals) to extract component stacks.
- **Overlay**: Renders a visual overlay over the DOM using `requestAnimationFrame`.
- **State**: Custom store in `src/utils/store.ts`.

### React Internals Access (IMPORTANT)

React Grab relies on **React's internal fiber tree** to map DOM elements back to their React components. This is accessed via the `bippy` library.

**What is React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED?**
- React's **intentionally scary-named** internal API exposing the fiber tree
- The name is a warning: "This is unstable and subject to change without notice"
- Not a public API = no semver guarantees

**How React Grab Uses It:**
```typescript
// packages/react-grab/src/instrumentation.ts
import { _fiberRoots, getFiberFromHostInstance, instrument } from "bippy";
```

**Why bippy?**
- Abstracts direct access to React internals
- Handles fiber tree traversal safely
- Provides utilities for:
- Finding which component "owns" a DOM element
- Building component hierarchy (Parent → Child → GrandChild)
- Source mapping (file + line number)

**The Flow:**
```
User clicks element
getFiberFromHostInstance(element)
bippy → React internals
Fiber node retrieved
Walk fiber tree for component stack
"Button → Form → LoginPage"
```

**⚠️ IMPORTANT LIMITATION:**
This approach is **fragile**. React can change its internal structure at any time since it's not a public API. Updates to React may break `bippy` until it's updated. Always test with new React versions.

## Release Process
- Uses **Changesets**.
- Run `pnpm changeset` to generate a version bump for public API changes.

Loading