elment
v0.1.3
Published
AI-powered element picker for React Native - select UI elements and let AI modify the code
Downloads
426
Maintainers
Readme
elment
AI-powered element picker for React Native. Select UI elements in your app and let AI (Claude, GPT, etc.) modify the code.
Installation
npm install --save-dev elmentQuick Start
1. Add the Babel Plugin
In your babel.config.js:
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'], // or your preset
plugins: [
process.env.NODE_ENV !== 'production' && [
'elment/babel-plugin',
{
autoWrapApp: true,
include: [
'View',
'Text',
'TouchableOpacity',
'TextInput',
'Image',
'ScrollView',
'Button',
],
},
],
].filter(Boolean),
};
};2. Start the Server
In a separate terminal:
npx elment-server --project ./your-app3. Run Your App
npx expo start --clear4. Select Elements
- Tap the floating picker button in your app
- Tap any element to select it
- The element info is written to
/tmp/element-picker-current.json
5. Use with AI
# Get the current element context
curl http://localhost:9848/context/text
# Pipe to Claude CLI
curl -s http://localhost:9848/context/text | claude "make this button blue"Manual Setup (Without Babel Plugin)
If you prefer manual control, wrap your app and elements:
import {
ElementPickerProvider,
Trackable,
useElementPicker,
} from 'elment';
function App() {
return (
<ElementPickerProvider highlightColor="#FF6B6B" showLabel={true}>
<MyContent />
<PickerToggle />
</ElementPickerProvider>
);
}
function MyContent() {
return (
<Trackable
name="MyButton"
source={{ fileName: 'App.tsx', lineNumber: 10, columnNumber: 0 }}
>
<TouchableOpacity style={styles.button}>
<Text>Press Me</Text>
</TouchableOpacity>
</Trackable>
);
}
function PickerToggle() {
const { isActive, toggle, isConnected } = useElementPicker();
return (
<TouchableOpacity onPress={toggle}>
<Text>{isActive ? 'Picker ON' : 'Picker OFF'}</Text>
<Text>{isConnected ? 'Connected' : 'Disconnected'}</Text>
</TouchableOpacity>
);
}Babel Plugin Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| autoWrapApp | boolean | false | Auto-wrap App.tsx with ElementPickerProvider |
| include | string[] | See below | Elements to wrap with Trackable |
| exclude | string[] | [] | Elements to never wrap |
| wrapAll | boolean | false | Wrap all JSX elements |
| trackableImport | string | 'elment' | Import path for Trackable |
Default include elements:
- View, Text, TouchableOpacity, TouchableHighlight, TouchableWithoutFeedback
- Pressable, TextInput, Image, ScrollView, FlatList, SectionList
- Button, Switch, Slider
Server API
HTTP Endpoints
| Endpoint | Method | Description |
|----------|--------|-------------|
| /ping | GET | Health check |
| /current | GET | Current selected element |
| /context | GET | AI-formatted context (JSON) |
| /context/text | GET | AI-formatted context (plain text) |
| /history | GET | Selection history |
| /toggle | POST | Toggle picker mode |
| /activate | POST | Activate picker mode |
| /deactivate | POST | Deactivate picker mode |
Server Options
npx elment-server [options]
Options:
--project, -p <path> Project root directory
--ws-port <port> WebSocket port (default: 9847)
--http-port <port> HTTP port (default: 9848)
--output, -o <file> Output file (default: /tmp/element-picker-current.json)Programmatic Server Usage
import { startServer } from 'elment/server';
const server = startServer({
projectRoot: '/path/to/your/app',
wsPort: 9847,
httpPort: 9848,
outputFile: '/tmp/element-picker-current.json',
});
// Get current selection
const selection = server.getCurrentSelection();
// Get history
const history = server.getHistory(10);Integration Examples
Claude CLI
# One-liner to modify selected element
curl -s http://localhost:9848/context/text | claude "change the background color to blue"VS Code Extension
Read /tmp/element-picker-current.json to get the current selection and jump to the file.
Custom Script
import Anthropic from '@anthropic-ai/sdk';
async function modifyElement(instruction: string) {
const res = await fetch('http://localhost:9848/context');
const { formatted } = await res.json();
const anthropic = new Anthropic();
const message = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 4096,
messages: [{
role: 'user',
content: `${formatted}\n\n${instruction}`,
}],
});
console.log(message.content[0].text);
}
modifyElement('Make the button larger and add a shadow');Exports
// Components
import {
ElementPickerProvider,
Trackable,
withTracking,
HighlightOverlay,
MultiHighlightOverlay,
} from 'elment';
// Hooks
import { useElementPicker } from 'elment';
// Transports
import {
WebSocketTransport,
HTTPTransport,
} from 'elment';
// Server
import { startServer, ElementPickerServer } from 'elment/server';
// Types
import type {
ElementInfo,
ElementPickerProviderProps,
TrackableProps,
Transport,
} from 'elment';Requirements
- React Native >= 0.72.0
- React >= 18.0.0
- react-native-gesture-handler >= 2.0.0
- Node.js >= 18.0.0 (for server)
License
MIT
