clone-react-skill
v1.0.1
Published
Extract and recreate React components from any website
Downloads
85
Maintainers
Readme
CloneReact - Steal Any React Component
Reverse engineer and extract React components from any production website using Electron-powered visual selection.
How It Works
The Key Insight: HTML + Screenshot = One-Shot Accuracy
Traditional component extraction from HTML alone requires multiple iterations:
- Parse HTML structure
- Generate component
- View in browser
- Notice layout issues
- Fix and repeat
This tool combines BOTH data sources upfront:
- HTML provides exact structure (classes, nesting, props)
- Screenshot provides visual verification (spacing, colors, alignment)
Result: Accurate extraction on first try.
Complete Flow
/clonereact https://example.com
↓
Electron browser opens (Chromium)
↓
Injection: selector-ui.html + extractor.js
↓
User Interface:
- Hover → Blue outline highlights element
- Click → Purple outline selects element
- Click "Extract Component" button
↓
Extraction Process:
1. Access React Fiber tree (__reactFiber$)
2. Walk component tree (props, state, children)
3. Capture element screenshot (canvas → base64)
4. Get computed CSS styles
5. Extract raw HTML as fallback
↓
Send via IPC (preload.js bridge)
↓
main.js writes /tmp/clonereact-output.json
↓
Electron closes, handler.sh continues
↓
generate-component.js processes JSON
↓
Output files:
- ComponentName.tsx (React code)
- ComponentName.css (Styles)
- ComponentName.json (Full data)
- README.md (Usage docs)Architecture Components
- Launch Electron browser - Opens target URL in a chromium window
- Visual element picker - Hover and click to select elements
- Extract both HTML + screenshot - Captures structure AND visual appearance
- Access React Fiber tree - If React detected, extracts component internals
- Generate React components - Creates standalone .tsx/.jsx files with styles
Installation
Option 1: As Claude Code Skill (agentskills.io)
# Clone to skills folder
git clone https://github.com/jasonkneen/clone-react-skill ~/.claude/skills/clonereact
# Use via Claude
/clonereact https://stripe.comOption 2: Via npm
# Global install
npm install -g clone-react-skill
clonereact https://stripe.com
# Or via npx (no install)
npx clone-react-skill https://stripe.comRequirements
- Node.js 18+
- macOS, Linux, or Windows
First run downloads Electron (~200MB) via cluso-inspector dependency.
Usage
Interactive Selection
/clonereact https://stripe.com
/clonereact https://airbnb.com --typescript
/clonereact https://github.com --output ./my-components --depth 10What happens:
- Electron browser opens to the URL
- Black toolbar appears at top with instructions
- Hover over elements → blue highlight appears
- Click element → purple outline marks selection
- Click "Extract Component" → closes and generates files
- Click "Cancel" → aborts
Options
--output <dir>- Output directory (default: ./cluso-inspect/cloned)--depth <N>- Component tree depth (default: 5)--typescript- Generate .tsx instead of .jsx
Output
Each extraction creates a timestamped subfolder with meaningful names:
./cluso-inspect/cloned/
└── StripePricingTable_20260111_151030/
├── StripePricingTable.tsx
├── StripePricingTable.css
├── StripePricingTable.json
├── StripePricingTable-screenshot.png
└── README.mdFor each extracted element:
ComponentName.tsx
import React from 'react';
import './ComponentName.css';
export function ComponentName() {
return (
// Reconstructed JSX from Fiber tree
);
}ComponentName.css
.componentname {
/* Extracted computed styles */
}ComponentName.json
{
"selector": ".original-class",
"isReact": true,
"reactVersion": "18.2.0",
"component": { /* Fiber tree */ },
"screenshot": "data:image/png;base64,...",
"html": "<div>...</div>",
"styles": { /* computed CSS */ }
}README.md - Usage instructions and metadata
Visual Selection UI
Toolbar (top center):
- Shows selection count
- "Clear" button - deselect all
- "Extract Component" button - process and generate
- "Cancel" button - abort
Hover state:
- Blue outline highlights element under cursor
- Label shows tag name + class
Selected state:
- Purple outline marks selected elements
- Click again to deselect
What Gets Extracted
React Sites ✅
- Component tree structure
- Props (names, values, types)
- State (initial values, hooks)
- Computed CSS styles
- Element screenshot
- Raw HTML fallback
Non-React Sites ⚠️
- Computed CSS styles
- Element screenshot
- Raw HTML structure
- No component tree (obviously)
Advantages Over Manual Extraction
| Manual | With Electron | |--------|---------------| | Guess CSS selector | Visual click selection | | Copy/paste HTML | Auto-extracted | | No screenshot | Screenshot included | | Iterate blindly | See it as you extract |
File Structure
~/.claude/skills/clonereact/
├── SKILL.md # Skill definition
├── handler.sh # CLI entry point (calls cluso-inspector)
├── README.md # This file
├── generate-component.js # JSON → React component generator
└── package.json # Dependencies
# cluso-inspector (separate package)
# Live: npx cluso-inspector
# Dev: ~/Documents/GitHub/flows/cluso/cluso-inspector/Technical Details
Electron App Architecture
main.js - Electron Main Process
- Creates BrowserWindow (1440x900)
- Loads target URL
- Injects selector UI after page load
- Handles IPC from renderer
- Writes extraction data to /tmp/
- Exits when complete
preload.js - Secure IPC Bridge
- Uses contextBridge for security
- Exposes only safe methods:
window.clonereact.sendExtraction(data)window.clonereact.cancel()window.clonereact.getConfig()
selector-ui.html - Visual Picker Overlay
- Injected into target page DOM
- Black toolbar at top (fixed position, z-index 999999)
- Blue highlight on hover
- Purple outline on selection
- Buttons: Clear, Extract, Cancel
- Calls
window.__REACT_COMPONENT_EXTRACTOR__when extracting
extractor.js - React Fiber Extractor
findFiberNode(element)- Locates __reactFiber$ keywalkFiberTree(fiber, depth)- Recursively builds component treeextractProps(fiber)- Serializes props (functions → stubs)extractState(fiber)- Extracts hooks/stateextractStyles(element)- Gets computed CSScaptureElementScreenshot(element)- Canvas-based screenshotgetSelector(element)- Generates CSS selector- Returns complete extraction object
Security
- Context isolation enabled
- No nodeIntegration
- Preload script for safe IPC
- Web security maintained
Data Flow
User clicks element
↓
extractor.js accesses React Fiber
↓
Captures screenshot + styles
↓
Sends via IPC to main process
↓
Writes JSON to /tmp/
↓
handler.sh reads JSON
↓
generate-component.js creates filesExtraction Data Format
The Electron app sends this JSON structure via IPC:
{
"success": true,
"url": "https://example.com",
"timestamp": "2026-01-11T08:00:00.000Z",
"extractions": [
{
"selector": "div.chat-input > form",
"isReact": true,
"reactVersion": "18.2.0",
"component": {
"name": "ChatInput",
"type": "component",
"props": {
"className": "input-wrapper",
"onSubmit": "[Function: handleSubmit]"
},
"state": {
"hooks": [
{ "value": "", "queue": "[Queue]" }
]
},
"children": [ /* nested components */ ],
"depth": 0
},
"html": "<div class='chat-input'>...</div>",
"styles": {
"display": "flex",
"padding": "16px",
"borderRadius": "12px",
"backgroundColor": "rgb(24, 24, 27)"
},
"screenshot": "data:image/png;base64,iVBORw0KG...",
"dimensions": {
"width": 600,
"height": 120,
"top": 800,
"left": 100
},
"meta": {
"tagName": "div",
"id": "chat-input-container",
"classes": ["chat-input", "rounded-lg"]
}
}
]
}Generated File Structure
For each extracted component, generates:
ComponentName.tsx (or .jsx)
import React from 'react';
import './ComponentName.css';
interface ComponentNameProps {
className?: string;
onSubmit?: () => void;
}
export function ComponentName({ }: ComponentNameProps) {
return (
<div className="chat-input rounded-lg">
{/* Reconstructed JSX from Fiber tree */}
</div>
);
}ComponentName.css
.componentname {
display: flex;
padding: 16px;
border-radius: 12px;
background-color: rgb(24, 24, 27);
}ComponentName.json - Full extraction metadata (for debugging/reference)
README.md - Usage instructions, source URL, extraction timestamp
Troubleshooting
Installation Issues
"Electron not found"
cd ~/.claude/skills/clonereact/electron-app
npm install"npx: command not found"
- Install Node.js 18+ from nodejs.org
- Verify:
node --versionandnpm --version
"Permission denied" on handler.sh
chmod +x ~/.claude/skills/clonereact/handler.shExtraction Issues
"No React Fiber found"
- Site doesn't use React (check console for framework)
- React DevTools may be disabled in production
- Try a different page/route
- Still extracts HTML + styles + screenshot
Electron window blank/white screen
- Wait 2-3 seconds for page to load
- Check console for errors
- Some sites block Electron user-agent
- Try adding User-Agent override in main.js
Screenshot is blank or black
- Element may use canvas/WebGL rendering
- Try extracting parent container instead
- Some elements render async (wait longer)
- Check if element is actually visible on screen
Styles don't match original
- Some styles from CSS-in-JS (styled-components, emotion)
- Hover/active states not captured
- Media queries not evaluated
- Screenshot shows actual rendered appearance (trust it)
Component won't render after extraction
- Event handlers are stubs (implement manually)
- Missing data/state from parent
- Check props interface - may need data passed in
- Review .json file for full Fiber tree structure
Selection Issues
Can't select element (clicking does nothing)
- Element may be covered by another (z-index)
- Try clicking parent container
- Check browser console for errors
Selected wrong element
- Click "Clear" in toolbar to deselect
- Select again more precisely
- Use browser DevTools to find exact selector first
Multiple elements selected accidentally
- Click "Clear" to start over
- Currently single-select only (multi-select coming)
Generation Issues
"Error generating component"
- Check /tmp/clonereact-output-*.json for raw data
- Verify JSON is valid
- May have non-serializable objects in Fiber tree
Generated code has TypeScript errors
- Run with
--typescriptflag for proper types - Check that react/react-dom are in dependencies
- Some props may be typed as
any(refine manually)
CSS classes not applying
- Ensure Tailwind is configured if using Tailwind classes
- Check for CSS-in-JS dependencies (styled-components)
- Computed styles are extracted as vanilla CSS
Examples
Basic Extraction
Extract Stripe navigation:
/clonereact https://stripe.com
# Opens browser, click nav bar, extractExtract with TypeScript:
/clonereact https://linear.app --typescript
# Click form, generates .tsx filesCustom output:
/clonereact https://vercel.com --output ~/Desktop/componentsReal-World Examples
Extract Airbnb search bar:
/clonereact https://airbnb.com --typescript --depth 8
# Wait for page load
# Click the search input component
# Extract generates full search bar with calendar picker structureExtract GitHub repo card:
/clonereact https://github.com/trending --output ./github-components
# Click on a repository card
# Gets card layout, avatar, stats, descriptionExtract Notion page element:
/clonereact https://notion.so --typescript --depth 10
# Click on a block (heading, list, etc)
# Extracts Notion's component structureBest Practices
Selecting Elements
DO:
- ✅ Click the outermost container of the component you want
- ✅ Wait for page to fully load before selecting
- ✅ Select parent containers (not individual text/icons)
- ✅ Use browser DevTools to inspect first if unsure
DON'T:
- ❌ Select individual text nodes or icons
- ❌ Select nested children when you want the parent
- ❌ Click immediately after page load (wait 2-3s)
Depth Settings
| Depth | Use Case | |-------|----------| | 3-5 | Simple components (buttons, cards) | | 5-8 | Medium complexity (forms, modals) | | 8-12 | Complex components (data tables, dashboards) | | 12+ | Full page sections (may generate huge files) |
Rule of thumb: Start with 5, increase if nested components are missing.
Output Organization
Single component:
/clonereact https://example.com --output ./components/ButtonMultiple components from same site:
# Extract nav
/clonereact https://example.com --output ./components/Nav
# Extract footer (opens new Electron instance)
/clonereact https://example.com --output ./components/FooterPost-Extraction Refinement
Generated components are 85-95% complete. You'll need to:
Implement event handlers
- Replace
[Function: handleClick]stubs - Add actual onClick/onSubmit logic
- Replace
Add data/state management
- Hook up real API calls
- Connect to Redux/Context if needed
Refine TypeScript types
- Generated interfaces use
anyfor complex props - Add proper types for functions and objects
- Generated interfaces use
Test responsive behavior
- Extracted styles are from desktop viewport
- Add mobile breakpoints if needed
Review dependencies
- Check package.json for missing deps
- May need framer-motion, styled-components, etc.
Limitations
Cannot extract:
- Server-side logic
- Event handler implementations (extracted as stubs)
- Dynamic imports
- Redux/Zustand store logic (only initial values)
May not work on:
- Sites that disable DevTools
- Heavily obfuscated builds
- React Native (different Fiber structure)
- Shadow DOM components
Legal & Ethics
✅ Use for:
- Your own sites
- Open source projects (learning)
- With explicit permission
- Educational purposes
❌ Don't use for:
- Stealing proprietary code
- Violating ToS
- Commercial use without permission
Advanced Usage
Debugging Extraction
Check raw extraction data:
# Extraction data is written to /tmp/clonereact-output-<pid>.json
# Before it's deleted, you can inspect it:
/clonereact https://example.com --output ./test
# In another terminal while Electron is open:
ls -lt /tmp/clonereact-output-* | head -1
cat /tmp/clonereact-output-12345.json | jq '.extractions[0].component'React Fiber Internals
The extractor accesses these Fiber node properties:
element.__reactFiber$abc123 = {
type: ComponentFunction, // Component constructor
memoizedProps: { /* props */ }, // Current props
memoizedState: { /* state */ }, // Current state/hooks
child: FiberNode, // First child
sibling: FiberNode, // Next sibling
stateNode: HTMLElement, // DOM node
key: "unique-key", // React key
elementType: { name: "Button" } // Component name
}Screenshot Capture
Uses HTML5 Canvas API:
canvas.width = rect.width * devicePixelRatio
canvas.height = rect.height * devicePixelRatio
// Returns base64 PNGLimitations:
- Canvas/WebGL content may not capture
- Cross-origin images blocked (CORS)
- Some CSS effects lost (filters, blend modes)
CSS Extraction
Extracts these computed style properties:
- Layout: display, position, width, height, flex, grid
- Spacing: margin, padding, gap
- Visual: background, border, borderRadius, color
- Typography: fontSize, fontFamily, fontWeight
Not extracted:
- Pseudo-elements (::before, ::after)
- Pseudo-classes (:hover, :active)
- CSS animations/transitions
- Media queries
Use the screenshot to verify visual accuracy.
Performance
Typical extraction times:
- Simple component: 2-3 seconds
- Complex component: 5-8 seconds
- Full page section: 10-15 seconds
Bottlenecks:
- Page load time (network)
- Screenshot capture (rendering)
- Fiber tree walk (depth × children)
Optimization:
- Use lower --depth for faster extraction
- Select smaller containers
- Close DevTools in Electron window
Security Notes
What the Electron app does:
- Loads target URL in isolated window
- Injects JavaScript into page DOM
- Reads React internals and DOM structure
- Captures screenshot using Canvas API
- Sends data via IPC (no network requests)
What it does NOT do:
- Execute code on your behalf
- Send data to external servers
- Persist cookies/sessions
- Modify the target website
- Run with elevated permissions
Safe for:
- Public websites
- Development/testing environments
- Your own applications
Use caution with:
- Sites with sensitive data (logged in accounts)
- Banking/financial sites
- Sites with restrictive ToS
Contributing
Ideas for improvements:
- [ ] Multi-select with Cmd/Ctrl
- [ ] Export as Storybook stories
- [ ] Auto-detect lazy-loaded components
- [ ] Convert to Tailwind classes option
- [ ] Extract animations/transitions
- [ ] Support for Shadow DOM
- [ ] Better screenshot capture (use Electron's native API)
- [ ] CSS-in-JS detection and extraction
- [ ] Generate unit tests from component structure
Credits
Inspired by: David Fant's "How to Steal Any React Component" (fant.io/react/)
Built for: Claude Code
Key innovation: Combines HTML structure + screenshot for one-shot accurate extraction
Architecture pattern: Electron + Visual Selection + React Fiber Access
Documentation
- README.md (this file) - User guide and quick start
- ARCHITECTURE.md - Complete technical documentation
- System overview and architecture layers
- Data flow diagrams
- React Fiber internals explained
- Security model details
- Performance characteristics
- Code generation process
- Future improvements and known limitations
Key Files Reference
| File | Lines | Purpose | |------|-------|---------| | handler.sh | 110 | CLI entry point, Electron launcher | | electron-app/main.js | 115 | Electron window + IPC management | | electron-app/preload.js | 16 | Secure IPC bridge | | electron-app/selector-ui.html | 200+ | Visual picker overlay UI | | electron-app/extractor.js | 244 | React Fiber + screenshot extraction | | generate-component.js | 270+ | JSON → React component generator |
License
MIT - Use responsibly and ethically.
Changelog
v1.0.1 (2026-01-11)
- Separated cluso-inspector into standalone npm package
- Added dev/live mode switching
- Improved component naming (domain + content based)
- Each component now gets unique timestamped folder
- Updated default output to
./cluso-inspect/cloned - Made agentskills.io compliant
v1.0.0 (2026-01-11)
- Initial release
- Electron-based visual selection
- React Fiber tree extraction
- Screenshot capture
- Multi-format output (TSX/JSX/CSS/JSON)
- TypeScript support
- Automated component generation
