erne-universal 0.12.8 → 0.13.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 +26 -16
- package/lib/claude-md.js +2 -2
- package/lib/dashboard.js +13 -5
- package/lib/doctor.js +1 -1
- package/lib/init.js +31 -5
- package/lib/update.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,19 +13,28 @@
|
|
|
13
13
|
|
|
14
14
|
> **Prerequisite:** [Claude Code](https://claude.ai/claude-code) is required for the full experience (13 agents, pipeline orchestration, dashboard, hooks). Other IDEs receive adaptive rules and configuration — see [IDE Support](#%EF%B8%8F-ide--editor-support).
|
|
15
15
|
|
|
16
|
-
### Install
|
|
16
|
+
### Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Install globally (recommended)
|
|
20
|
+
npm i -g erne-universal
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Setup
|
|
17
24
|
|
|
18
25
|
```bash
|
|
19
26
|
# One-time setup in your React Native / Expo project
|
|
20
|
-
|
|
27
|
+
erne init
|
|
21
28
|
|
|
22
29
|
# Launch the dashboard
|
|
23
|
-
|
|
30
|
+
erne dashboard
|
|
24
31
|
|
|
25
32
|
# Or do both at once
|
|
26
|
-
|
|
33
|
+
erne start
|
|
27
34
|
```
|
|
28
35
|
|
|
36
|
+
> **Without global install:** use `npx erne-universal` instead of `erne` (slower — downloads each time).
|
|
37
|
+
|
|
29
38
|
### What `init` does:
|
|
30
39
|
|
|
31
40
|
1. 🔍 **Deep-scans your project** — detects 15 stack dimensions (state management, navigation, styling, lists, images, forms, storage, testing, build system, component style, monorepo, New Architecture, and more)
|
|
@@ -36,14 +45,15 @@ npx erne-universal start
|
|
|
36
45
|
### CLI Commands
|
|
37
46
|
|
|
38
47
|
```bash
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
erne init # Setup ERNE in your project
|
|
49
|
+
erne dashboard # Launch dashboard
|
|
50
|
+
erne start # Init + dashboard
|
|
51
|
+
erne doctor # Health check (22 checks)
|
|
52
|
+
erne audit # Generate project documentation
|
|
53
|
+
erne worker --config w.json # Start autonomous worker
|
|
54
|
+
erne sync-configs # Export rules to other IDEs
|
|
55
|
+
erne update # Update to latest version
|
|
56
|
+
erne uninstall # Clean removal
|
|
47
57
|
```
|
|
48
58
|
|
|
49
59
|
---
|
|
@@ -54,7 +64,7 @@ npx erne-universal uninstall # Clean removal
|
|
|
54
64
|
| -------------------- | ----- | -------------------------------------------------------------------------------------------- |
|
|
55
65
|
| 🤖 Agents | 13 | Specialized AI agents incl. visual debugger, doc generator, smart routing |
|
|
56
66
|
| 🔀 Agent variants | 9 | Stack-adaptive agent configurations (StyleSheet vs NativeWind, Zustand vs Redux, etc.) |
|
|
57
|
-
| ⚡ Commands |
|
|
67
|
+
| ⚡ Commands | 24 | Slash commands for every React Native workflow (incl. /erne-debug-video, /erne-update) |
|
|
58
68
|
| 📏 Rule layers | 5 | Conditional rules: common, expo, bare-rn, native-ios, native-android |
|
|
59
69
|
| 🎯 Rule variants | 15 | Stack-specific rules selected by deep detection (state, navigation, styling, security, etc.) |
|
|
60
70
|
| 📚 Knowledge rules | 29 | Expo SDK 55, RN 0.84, React 19.2, Reanimated, Skia, Gesture Handler, SVG, ExecuTorch, more |
|
|
@@ -74,9 +84,9 @@ npx erne-universal uninstall # Clean removal
|
|
|
74
84
|
ERNE includes a real-time dashboard with 6 pages, pixel-art agent HQ, and adaptive fix integration.
|
|
75
85
|
|
|
76
86
|
```bash
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
87
|
+
erne dashboard # Start on auto-detected port, open browser
|
|
88
|
+
erne dashboard --port 4444 # Custom port
|
|
89
|
+
erne start # Init + dashboard in one command
|
|
80
90
|
```
|
|
81
91
|
|
|
82
92
|
### Command Center
|
package/lib/claude-md.js
CHANGED
|
@@ -217,7 +217,7 @@ function generateFullClaudeMd(cwd, detection, ruleLayers, profile) {
|
|
|
217
217
|
'',
|
|
218
218
|
'## Dashboard',
|
|
219
219
|
'ERNE includes a visual dashboard for monitoring agents, project health, worker status, and documentation.',
|
|
220
|
-
'Launch: `
|
|
220
|
+
'Launch: `erne dashboard`',
|
|
221
221
|
'The dashboard shows 6 tabs: HQ (pixel-art agent office), Worker (autonomous tickets), Health (doctor score), Docs (generated documentation), Project (stack & MCP), Insights (analytics).',
|
|
222
222
|
'',
|
|
223
223
|
'## Rules',
|
|
@@ -270,7 +270,7 @@ function generateAppendSection(ruleLayers, profile) {
|
|
|
270
270
|
AVAILABLE_COMMANDS,
|
|
271
271
|
'',
|
|
272
272
|
'## Dashboard',
|
|
273
|
-
'ERNE includes a visual dashboard. Launch: `
|
|
273
|
+
'ERNE includes a visual dashboard. Launch: `erne dashboard`',
|
|
274
274
|
'',
|
|
275
275
|
);
|
|
276
276
|
|
package/lib/dashboard.js
CHANGED
|
@@ -274,14 +274,22 @@ async function dashboard() {
|
|
|
274
274
|
} catch {
|
|
275
275
|
if (explicitPort) {
|
|
276
276
|
console.error(` Error: Port ${port} is already in use`);
|
|
277
|
+
console.error(` Try a different port: erne dashboard --port ${port + 1}`);
|
|
277
278
|
process.exit(1);
|
|
278
279
|
}
|
|
279
280
|
console.log(` Port ${port} is busy, finding a free port...`);
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
281
|
+
// Scan ports directly instead of relying on registry
|
|
282
|
+
let found = false;
|
|
283
|
+
for (let candidate = port + 1; candidate <= 3399; candidate++) {
|
|
284
|
+
try {
|
|
285
|
+
await checkPort(candidate);
|
|
286
|
+
port = candidate;
|
|
287
|
+
found = true;
|
|
288
|
+
break;
|
|
289
|
+
} catch { continue; }
|
|
290
|
+
}
|
|
291
|
+
if (!found) {
|
|
292
|
+
console.error(` Error: No free ports in range ${port}-3399`);
|
|
285
293
|
process.exit(1);
|
|
286
294
|
}
|
|
287
295
|
}
|
package/lib/doctor.js
CHANGED
|
@@ -353,7 +353,7 @@ function checkVariants(cwd) {
|
|
|
353
353
|
if (hasVariantHint) {
|
|
354
354
|
return { pass: true, message: `Variants: stack-tailored rules applied (${state})` };
|
|
355
355
|
}
|
|
356
|
-
return { pass: false, message: `Variants: state-management.md may be generic (expected ${state} variant). Re-run:
|
|
356
|
+
return { pass: false, message: `Variants: state-management.md may be generic (expected ${state} variant). Re-run: erne init` };
|
|
357
357
|
}
|
|
358
358
|
return { pass: true, message: 'Variants: no state management detected' };
|
|
359
359
|
} catch {
|
package/lib/init.js
CHANGED
|
@@ -61,7 +61,7 @@ const frameworkLabels = {
|
|
|
61
61
|
|
|
62
62
|
function parseArgs() {
|
|
63
63
|
const args = process.argv.slice(3); // skip node, cli.js, init
|
|
64
|
-
const opts = { profile: null, mcp: null, yes: false, noMcp: false };
|
|
64
|
+
const opts = { profile: null, mcp: null, yes: false, noMcp: false, fresh: false };
|
|
65
65
|
|
|
66
66
|
for (let i = 0; i < args.length; i++) {
|
|
67
67
|
switch (args[i]) {
|
|
@@ -80,6 +80,9 @@ function parseArgs() {
|
|
|
80
80
|
case '-y':
|
|
81
81
|
opts.yes = true;
|
|
82
82
|
break;
|
|
83
|
+
case '--fresh':
|
|
84
|
+
opts.fresh = true;
|
|
85
|
+
break;
|
|
83
86
|
}
|
|
84
87
|
}
|
|
85
88
|
|
|
@@ -171,7 +174,20 @@ module.exports = async function init() {
|
|
|
171
174
|
const cwd = process.cwd();
|
|
172
175
|
|
|
173
176
|
try {
|
|
174
|
-
|
|
177
|
+
// ─── Check for existing installation ───
|
|
178
|
+
const settingsPath = path.join(cwd, '.claude', 'settings.json');
|
|
179
|
+
let existingSettings = null;
|
|
180
|
+
try {
|
|
181
|
+
existingSettings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
182
|
+
} catch { /* no existing installation */ }
|
|
183
|
+
|
|
184
|
+
const isUpdate = existingSettings && existingSettings.erneVersion && !opts.fresh;
|
|
185
|
+
|
|
186
|
+
if (isUpdate) {
|
|
187
|
+
console.log(`\n ${c.bold}erne${c.reset} ${c.dim}\u2014 Updating ERNE (${existingSettings.erneVersion} → ${require('../package.json').version})${c.reset}\n`);
|
|
188
|
+
} else {
|
|
189
|
+
console.log(`\n ${c.bold}erne${c.reset} ${c.dim}\u2014 Setting up AI agent harness for React Native & Expo${c.reset}\n`);
|
|
190
|
+
}
|
|
175
191
|
|
|
176
192
|
// ─── Step 1: Detect project type ───
|
|
177
193
|
console.log(` ${c.bold}Step 1:${c.reset} Deep-scanning project...`);
|
|
@@ -179,8 +195,8 @@ module.exports = async function init() {
|
|
|
179
195
|
printDetectionReport(detection);
|
|
180
196
|
|
|
181
197
|
if (!detection.isRNProject) {
|
|
182
|
-
if (nonInteractive) {
|
|
183
|
-
console.log(`\n ${warn} No React Native project detected \u2014 continuing
|
|
198
|
+
if (nonInteractive || isUpdate) {
|
|
199
|
+
console.log(`\n ${warn} No React Native project detected \u2014 continuing.`);
|
|
184
200
|
} else {
|
|
185
201
|
console.log(`\n ${warn} No React Native project detected in current directory.`);
|
|
186
202
|
const proceed = await rl.question(' Continue anyway? (y/N) ');
|
|
@@ -198,6 +214,9 @@ module.exports = async function init() {
|
|
|
198
214
|
if (opts.profile && validProfiles.includes(opts.profile)) {
|
|
199
215
|
profile = opts.profile;
|
|
200
216
|
console.log(`\n ${c.bold}Step 2:${c.reset} Hook profile \u2192 ${c.cyan}${profile}${c.reset}`);
|
|
217
|
+
} else if (isUpdate && existingSettings.profile && validProfiles.includes(existingSettings.profile)) {
|
|
218
|
+
profile = existingSettings.profile;
|
|
219
|
+
console.log(`\n ${c.bold}Step 2:${c.reset} Hook profile \u2192 ${c.cyan}${profile}${c.reset} ${c.dim}(preserved)${c.reset}`);
|
|
201
220
|
} else if (nonInteractive) {
|
|
202
221
|
profile = 'standard';
|
|
203
222
|
console.log(`\n ${c.bold}Step 2:${c.reset} Hook profile \u2192 ${c.cyan}standard${c.reset}`);
|
|
@@ -222,6 +241,13 @@ module.exports = async function init() {
|
|
|
222
241
|
if (opts.noMcp) {
|
|
223
242
|
console.log(`\n ${c.bold}Step 3:${c.reset} MCP servers \u2192 ${c.dim}none${c.reset}`);
|
|
224
243
|
for (const key of allMcpKeys) mcpSelections[key] = false;
|
|
244
|
+
} else if (isUpdate && existingSettings.mcpSelections) {
|
|
245
|
+
// Preserve existing MCP selections on update
|
|
246
|
+
const preserved = existingSettings.mcpSelections;
|
|
247
|
+
for (const key of allMcpKeys) mcpSelections[key] = Array.isArray(preserved) ? preserved.includes(key) : !!preserved[key];
|
|
248
|
+
const enabledNames = allMcpKeys.filter(k => mcpSelections[k]);
|
|
249
|
+
const mcpDisplay = enabledNames.length > 0 ? enabledNames.join(', ') : 'none';
|
|
250
|
+
console.log(`\n ${c.bold}Step 3:${c.reset} MCP servers \u2192 ${c.cyan}${mcpDisplay}${c.reset} ${c.dim}(preserved)${c.reset}`);
|
|
225
251
|
} else if (opts.mcp !== null) {
|
|
226
252
|
const mcpDisplay = opts.mcp.length > 0 ? opts.mcp.join(', ') : 'none';
|
|
227
253
|
console.log(`\n ${c.bold}Step 3:${c.reset} MCP servers \u2192 ${c.cyan}${mcpDisplay}${c.reset}`);
|
|
@@ -309,7 +335,7 @@ module.exports = async function init() {
|
|
|
309
335
|
|
|
310
336
|
// ─── Footer ───
|
|
311
337
|
console.log();
|
|
312
|
-
console.log(` ${info} Dashboard: run ${c.cyan}
|
|
338
|
+
console.log(` ${info} Dashboard: run ${c.cyan}erne dashboard${c.reset} to launch`);
|
|
313
339
|
console.log();
|
|
314
340
|
console.log(` ${c.green}${c.bold}Done!${c.reset}`);
|
|
315
341
|
console.log();
|
package/lib/update.js
CHANGED
|
@@ -19,7 +19,7 @@ module.exports = async function update() {
|
|
|
19
19
|
// Check if ERNE is installed in this project
|
|
20
20
|
if (!fs.existsSync(settingsPath)) {
|
|
21
21
|
console.log(' ⚠ ERNE not found in this project.');
|
|
22
|
-
console.log(' Run "
|
|
22
|
+
console.log(' Run "erne init" to set up.');
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -70,6 +70,6 @@ module.exports = async function update() {
|
|
|
70
70
|
});
|
|
71
71
|
} catch (err) {
|
|
72
72
|
console.error(' Update failed:', err.message);
|
|
73
|
-
console.error(' Manual update: npm
|
|
73
|
+
console.error(' Manual update: npm i -g erne-universal@latest && erne init');
|
|
74
74
|
}
|
|
75
75
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "erne-universal",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Complete AI coding agent harness for React Native and Expo \u2014 13 specialized agents, autonomous worker mode, visual debugging, smart routing",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|