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 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 & Setup
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
- npx erne-universal init
27
+ erne init
21
28
 
22
29
  # Launch the dashboard
23
- npx erne-universal dashboard
30
+ erne dashboard
24
31
 
25
32
  # Or do both at once
26
- npx erne-universal start
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
- npx erne-universal init # Setup ERNE in your project
40
- npx erne-universal dashboard # Launch dashboard
41
- npx erne-universal start # Init + dashboard
42
- npx erne-universal doctor # Health check (22 checks)
43
- npx erne-universal audit # Generate project documentation
44
- npx erne-universal worker --config w.json # Start autonomous worker
45
- npx erne-universal sync-configs # Export rules to other IDEs
46
- npx erne-universal uninstall # Clean removal
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 | 23 | Slash commands for every React Native workflow (incl. /erne-debug-video) |
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
- npx erne-universal dashboard # Start on port 3333, open browser
78
- npx erne-universal dashboard --port 4444 # Custom port
79
- npx erne-universal start # Init + dashboard in one command
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: `npx erne-universal dashboard`',
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: `npx erne-universal dashboard`',
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
- try {
281
- port = await findFreePort();
282
- await checkPort(port);
283
- } catch (err) {
284
- console.error(` Error: ${err.message}`);
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: npx erne-universal init` };
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
- console.log(`\n ${c.bold}erne${c.reset} ${c.dim}\u2014 Setting up AI agent harness for React Native & Expo${c.reset}\n`);
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 (non-interactive mode).`);
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}npx erne-universal dashboard${c.reset} to launch`);
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 "npx erne-universal init" to set up.');
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 install -g erne-universal@latest && erne init');
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.12.8",
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",