arcanea 3.2.0 → 3.4.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/dist/cli/index.js CHANGED
@@ -2199,7 +2199,7 @@ var {
2199
2199
  } = import__.default;
2200
2200
 
2201
2201
  // src/cli/index.ts
2202
- var import_picocolors2 = __toESM(require_picocolors(), 1);
2202
+ var import_picocolors3 = __toESM(require_picocolors(), 1);
2203
2203
 
2204
2204
  // src/install.ts
2205
2205
  var import_picocolors = __toESM(require_picocolors(), 1);
@@ -2314,11 +2314,17 @@ async function installForPlatform(targetDir, packageRoot, platform, force) {
2314
2314
  await installClaudeCodeSettings(platformPath, force);
2315
2315
  } else if (platform === "cursor") {
2316
2316
  await installCursorRules(targetDir, packageRoot, force);
2317
+ } else if (platform === "codex") {
2318
+ await installCodexConfig(targetDir, packageRoot, force);
2319
+ } else if (platform === "gemini") {
2320
+ await installGeminiConfig(targetDir, packageRoot, force);
2317
2321
  }
2318
2322
  }
2319
2323
  async function installClaudeCodeSettings(platformPath, force) {
2320
2324
  const settingsPath = join(platformPath, "settings.json");
2321
2325
  if (!existsSync(settingsPath) || force) {
2326
+ const eventsDir = join(process.env.HOME || process.env.USERPROFILE || "~", ".arcanea").replace(/\\/g, "/");
2327
+ const logScript = `mkdir -p "${eventsDir}" && echo '{"type":"agent-spawn","agent":"'$(echo "$TOOL_INPUT" 2>/dev/null | node -e "try{const d=JSON.parse(require('fs').readFileSync(0,'utf8'));process.stdout.write((d.subagent_type||'unknown')+'","description":"'+(d.description||'').replace(/"/g,'')+'","team":"'+(d.subagent_type||''))}catch{process.stdout.write('unknown","description":"","team":"')}" 2>/dev/null)","timestamp":'$(date +%s000)'}' >> "${eventsDir}/swarm-events.jsonl"`;
2322
2328
  const settings = {
2323
2329
  hooks: {
2324
2330
  UserPromptSubmit: [
@@ -2357,6 +2363,15 @@ async function installClaudeCodeSettings(platformPath, force) {
2357
2363
  command: "echo '[ARCANEA_MODE=ultrawork] Maximum parallel execution. Spawn all relevant agents simultaneously using Task tool with run_in_background=true.'"
2358
2364
  }]
2359
2365
  }
2366
+ ],
2367
+ PreToolUse: [
2368
+ {
2369
+ matcher: "Task",
2370
+ hooks: [{
2371
+ type: "command",
2372
+ command: logScript
2373
+ }]
2374
+ }
2360
2375
  ]
2361
2376
  }
2362
2377
  };
@@ -2378,6 +2393,64 @@ ${claudeContent}`;
2378
2393
  }
2379
2394
  }
2380
2395
  }
2396
+ async function installCodexConfig(targetDir, packageRoot, force) {
2397
+ const codexMdPath = join(targetDir, "codex.md");
2398
+ if (!existsSync(codexMdPath) || force) {
2399
+ const claudeMdSource = join(packageRoot, "CLAUDE.md");
2400
+ if (existsSync(claudeMdSource)) {
2401
+ const content = readFileSync(claudeMdSource, "utf-8");
2402
+ const codexMd = [
2403
+ `# Codex Instructions — Generated by Arcanea v${VERSION}`,
2404
+ "",
2405
+ "> These instructions transform Codex into Arcanea, the Creative Intelligence Platform.",
2406
+ "> Agent definitions: `.codex/agents/` | Skills: `.codex/skills/` | Commands: `.codex/commands/`",
2407
+ "",
2408
+ content,
2409
+ "",
2410
+ "## Codex-Specific Notes",
2411
+ "",
2412
+ "- Read agent definitions from `.codex/agents/` for available specialist agents",
2413
+ "- Read skill definitions from `.codex/skills/` for creative and technical skills",
2414
+ "- Read command definitions from `.codex/commands/` for slash commands",
2415
+ "- MCP servers are configured in `.mcp.json`",
2416
+ "- When magic words (ultraworld, ultracode, etc.) are used, read the relevant agent files and apply their instructions",
2417
+ ""
2418
+ ].join(`
2419
+ `);
2420
+ writeFileSync(codexMdPath, codexMd);
2421
+ console.log(import_picocolors.default.green(" ✓ Created codex.md (Arcanea instructions for Codex CLI)"));
2422
+ }
2423
+ }
2424
+ }
2425
+ async function installGeminiConfig(targetDir, packageRoot, force) {
2426
+ const geminiMdPath = join(targetDir, "GEMINI.md");
2427
+ if (!existsSync(geminiMdPath) || force) {
2428
+ const claudeMdSource = join(packageRoot, "CLAUDE.md");
2429
+ if (existsSync(claudeMdSource)) {
2430
+ const content = readFileSync(claudeMdSource, "utf-8");
2431
+ const geminiMd = [
2432
+ `# Gemini Instructions — Generated by Arcanea v${VERSION}`,
2433
+ "",
2434
+ "> These instructions transform Gemini into Arcanea, the Creative Intelligence Platform.",
2435
+ "> Agent definitions: `.gemini/agents/` | Skills: `.gemini/skills/` | Commands: `.gemini/commands/`",
2436
+ "",
2437
+ content,
2438
+ "",
2439
+ "## Gemini-Specific Notes",
2440
+ "",
2441
+ "- Read agent definitions from `.gemini/agents/` for available specialist agents",
2442
+ "- Read skill definitions from `.gemini/skills/` for creative and technical skills",
2443
+ "- Read command definitions from `.gemini/commands/` for slash commands",
2444
+ "- MCP servers are configured in `.mcp.json`",
2445
+ "- When magic words (ultraworld, ultracode, etc.) are used, read the relevant agent files and apply their instructions",
2446
+ ""
2447
+ ].join(`
2448
+ `);
2449
+ writeFileSync(geminiMdPath, geminiMd);
2450
+ console.log(import_picocolors.default.green(" ✓ Created GEMINI.md (Arcanea instructions for Gemini CLI)"));
2451
+ }
2452
+ }
2453
+ }
2381
2454
  async function installMcpConfig(targetDir, force) {
2382
2455
  const mcpPath = join(targetDir, ".mcp.json");
2383
2456
  console.log(import_picocolors.default.blue(`
@@ -2457,7 +2530,7 @@ function printSuccessMessage(platforms) {
2457
2530
  }
2458
2531
 
2459
2532
  // src/index.ts
2460
- var VERSION = "3.2.0";
2533
+ var VERSION = "3.4.0";
2461
2534
  var NAME = "arcanea";
2462
2535
  var ORCHESTRATOR = "Arcanea";
2463
2536
  var defaultConfig = {
@@ -2583,9 +2656,387 @@ var AGENT_TEAMS = {
2583
2656
  }
2584
2657
  };
2585
2658
 
2586
- // src/cli/index.ts
2587
- import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync2 } from "fs";
2659
+ // src/viz/index.ts
2660
+ var import_picocolors2 = __toESM(require_picocolors(), 1);
2661
+ import { createServer } from "http";
2662
+ import { existsSync as existsSync2, readFileSync as readFileSync2, appendFileSync, mkdirSync as mkdirSync2, statSync } from "fs";
2588
2663
  import { join as join2 } from "path";
2664
+ import { execFile } from "child_process";
2665
+ var ARCANEA_DIR = join2(process.env.HOME || process.env.USERPROFILE || "~", ".arcanea");
2666
+ var EVENTS_FILE = join2(ARCANEA_DIR, "swarm-events.jsonl");
2667
+ function logEvent(event) {
2668
+ mkdirSync2(ARCANEA_DIR, { recursive: true });
2669
+ appendFileSync(EVENTS_FILE, JSON.stringify(event) + `
2670
+ `);
2671
+ }
2672
+ function readEvents() {
2673
+ if (!existsSync2(EVENTS_FILE))
2674
+ return [];
2675
+ const content = readFileSync2(EVENTS_FILE, "utf-8").trim();
2676
+ if (!content)
2677
+ return [];
2678
+ return content.split(`
2679
+ `).map((line) => {
2680
+ try {
2681
+ return JSON.parse(line);
2682
+ } catch {
2683
+ return null;
2684
+ }
2685
+ }).filter(Boolean);
2686
+ }
2687
+ var clients = new Set;
2688
+ function broadcast(event) {
2689
+ const data = `data: ${JSON.stringify(event)}
2690
+
2691
+ `;
2692
+ for (const client of clients) {
2693
+ try {
2694
+ client.write(data);
2695
+ } catch {
2696
+ clients.delete(client);
2697
+ }
2698
+ }
2699
+ }
2700
+ function handleSSE(req, res) {
2701
+ res.writeHead(200, {
2702
+ "Content-Type": "text/event-stream",
2703
+ "Cache-Control": "no-cache",
2704
+ Connection: "keep-alive",
2705
+ "Access-Control-Allow-Origin": "*"
2706
+ });
2707
+ clients.add(res);
2708
+ req.on("close", () => clients.delete(res));
2709
+ const events = readEvents();
2710
+ res.write(`data: ${JSON.stringify({ type: "initial", events })}
2711
+
2712
+ `);
2713
+ }
2714
+ function handleAPI(_req, res) {
2715
+ const events = readEvents();
2716
+ res.writeHead(200, { "Content-Type": "application/json" });
2717
+ res.end(JSON.stringify({ events }));
2718
+ }
2719
+ function openBrowser(url) {
2720
+ if (process.platform === "darwin") {
2721
+ execFile("open", [url], () => {});
2722
+ } else if (process.platform === "win32") {
2723
+ execFile("cmd", ["/c", "start", url], () => {});
2724
+ } else {
2725
+ execFile("xdg-open", [url], () => {});
2726
+ }
2727
+ }
2728
+ function getDashboardHTML() {
2729
+ return `<!DOCTYPE html>
2730
+ <html lang="en">
2731
+ <head>
2732
+ <meta charset="utf-8">
2733
+ <meta name="viewport" content="width=device-width, initial-scale=1">
2734
+ <title>Arcanea Swarm Viz</title>
2735
+ <style>
2736
+ *{margin:0;padding:0;box-sizing:border-box}
2737
+ :root{--bg:#0a0a1a;--surface:#111128;--border:#1e1e3a;--teal:#7fffd4;--gold:#ffd700;--blue:#78a6ff;
2738
+ --red:#ff4757;--text:#e0e0e0;--dim:#666;--green:#2ed573;--purple:#a855f7}
2739
+ body{background:var(--bg);color:var(--text);font-family:'Segoe UI',system-ui,sans-serif;min-height:100vh}
2740
+ .header{background:linear-gradient(135deg,#0d0d2b,#1a1a3e);border-bottom:1px solid var(--border);padding:16px 24px;display:flex;align-items:center;gap:16px}
2741
+ .header h1{font-size:20px;color:var(--teal);font-weight:600}
2742
+ .header .version{color:var(--dim);font-size:12px}
2743
+ .header .status{margin-left:auto;display:flex;align-items:center;gap:8px}
2744
+ .dot{width:8px;height:8px;border-radius:50%;background:var(--green);animation:pulse 2s infinite}
2745
+ @keyframes pulse{0%,100%{opacity:1}50%{opacity:0.4}}
2746
+ .stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;padding:16px 24px}
2747
+ .stat{background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:16px;text-align:center}
2748
+ .stat .label{font-size:11px;color:var(--dim);text-transform:uppercase;letter-spacing:1px;margin-bottom:4px}
2749
+ .stat .value{font-size:28px;font-weight:700;color:var(--teal)}
2750
+ .stat .value.gold{color:var(--gold)}
2751
+ .stat .value.blue{color:var(--blue)}
2752
+ .main{display:grid;grid-template-columns:1fr 300px;gap:16px;padding:0 24px 24px;height:calc(100vh - 200px)}
2753
+ .events{background:var(--surface);border:1px solid var(--border);border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
2754
+ .events .title{padding:12px 16px;border-bottom:1px solid var(--border);font-size:13px;font-weight:600;display:flex;align-items:center;gap:8px}
2755
+ .events .title .count{color:var(--dim);font-weight:400}
2756
+ .event-list{flex:1;overflow-y:auto;padding:8px}
2757
+ .event{padding:8px 12px;border-radius:6px;margin-bottom:4px;font-size:13px;display:flex;align-items:flex-start;gap:8px;animation:fadeIn 0.3s ease}
2758
+ @keyframes fadeIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
2759
+ .event .time{color:var(--dim);font-size:11px;min-width:60px;font-family:monospace}
2760
+ .event .badge{padding:2px 6px;border-radius:4px;font-size:10px;font-weight:600;text-transform:uppercase}
2761
+ .badge-spawn{background:#7fffd420;color:var(--teal)}
2762
+ .badge-complete{background:#2ed57320;color:var(--green)}
2763
+ .badge-error{background:#ff475720;color:var(--red)}
2764
+ .badge-magic{background:#ffd70020;color:var(--gold)}
2765
+ .event .desc{flex:1;word-break:break-word}
2766
+ .event .agent-name{color:var(--blue);font-weight:500}
2767
+ .event .dur{color:var(--dim);font-size:11px;font-family:monospace}
2768
+ .sidebar{display:flex;flex-direction:column;gap:12px}
2769
+ .panel{background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:12px 16px}
2770
+ .panel .title{font-size:13px;font-weight:600;margin-bottom:12px}
2771
+ .bar-row{display:flex;align-items:center;gap:8px;margin-bottom:8px;font-size:12px}
2772
+ .bar-label{min-width:80px;color:var(--dim)}
2773
+ .bar-track{flex:1;height:8px;background:var(--bg);border-radius:4px;overflow:hidden}
2774
+ .bar-fill{height:100%;border-radius:4px;transition:width 0.5s ease}
2775
+ .fill-creative{background:var(--teal)}.fill-coding{background:var(--blue)}.fill-writing{background:var(--green)}
2776
+ .fill-research{background:var(--gold)}.fill-production{background:var(--purple)}.fill-development{background:var(--blue)}
2777
+ .fill-teacher{background:#ff6b81}.fill-visionary{background:var(--gold)}.fill-default{background:var(--teal)}
2778
+ .bar-value{min-width:30px;text-align:right;font-family:monospace;color:var(--dim)}
2779
+ .timing{font-family:monospace;font-size:13px}
2780
+ .timing .row{display:flex;justify-content:space-between;padding:4px 0;border-bottom:1px solid var(--border)}
2781
+ .timing .row:last-child{border:none}
2782
+ .timing .label{color:var(--dim)}
2783
+ .timing .val{color:var(--teal)}
2784
+ .empty{text-align:center;padding:60px 20px;color:var(--dim)}
2785
+ .empty h3{color:var(--teal);margin-bottom:12px;font-size:16px}
2786
+ .empty p{font-size:13px;max-width:400px;margin:0 auto;line-height:1.6}
2787
+ .empty code{background:var(--bg);padding:2px 6px;border-radius:4px;font-size:12px;color:var(--gold)}
2788
+ </style>
2789
+ </head>
2790
+ <body>
2791
+ <div class="header">
2792
+ <h1>Arcanea Swarm Viz</h1>
2793
+ <span class="version">v${VERSION}</span>
2794
+ <div class="status">
2795
+ <span class="dot" id="statusDot"></span>
2796
+ <span id="statusText" style="font-size:12px;color:var(--dim)">Connecting...</span>
2797
+ </div>
2798
+ </div>
2799
+ <div class="stats">
2800
+ <div class="stat"><div class="label">Total Spawns</div><div class="value" id="statTotal">0</div></div>
2801
+ <div class="stat"><div class="label">Active Now</div><div class="value gold" id="statActive">0</div></div>
2802
+ <div class="stat"><div class="label">Success Rate</div><div class="value blue" id="statSuccess">-</div></div>
2803
+ <div class="stat"><div class="label">Avg Duration</div><div class="value" id="statAvg">-</div></div>
2804
+ </div>
2805
+ <div class="main">
2806
+ <div class="events">
2807
+ <div class="title">Live Event Feed <span class="count" id="eventCount">(0 events)</span></div>
2808
+ <div class="event-list" id="eventList"></div>
2809
+ </div>
2810
+ <div class="sidebar">
2811
+ <div class="panel"><div class="title">Team Utilization</div><div id="teamBars"></div></div>
2812
+ <div class="panel">
2813
+ <div class="title">Timing (ms)</div>
2814
+ <div class="timing">
2815
+ <div class="row"><span class="label">Avg</span><span class="val" id="timAvg">-</span></div>
2816
+ <div class="row"><span class="label">P50</span><span class="val" id="timP50">-</span></div>
2817
+ <div class="row"><span class="label">P95</span><span class="val" id="timP95">-</span></div>
2818
+ </div>
2819
+ </div>
2820
+ <div class="panel"><div class="title">Top Agents</div><div id="agentList" style="font-size:12px"></div></div>
2821
+ </div>
2822
+ </div>
2823
+ <script>
2824
+ // Uses safe DOM methods (createElement, textContent) — no innerHTML with untrusted data
2825
+ let allEvents = [];
2826
+ const fillClasses = {creative:'fill-creative',coding:'fill-coding',writing:'fill-writing',research:'fill-research',production:'fill-production',development:'fill-development',teacher:'fill-teacher',visionary:'fill-visionary'};
2827
+
2828
+ function fmtTime(ts) {
2829
+ return new Date(ts).toLocaleTimeString('en-US',{hour12:false,hour:'2-digit',minute:'2-digit',second:'2-digit'});
2830
+ }
2831
+ function fmtDur(ms) {
2832
+ if (!ms) return '';
2833
+ return ms < 1000 ? ms+'ms' : (ms/1000).toFixed(1)+'s';
2834
+ }
2835
+
2836
+ function mkEl(tag, cls, text) {
2837
+ const el = document.createElement(tag);
2838
+ if (cls) el.className = cls;
2839
+ if (text) el.textContent = text;
2840
+ return el;
2841
+ }
2842
+
2843
+ function showEmpty() {
2844
+ const list = document.getElementById('eventList');
2845
+ list.textContent = '';
2846
+ const d = mkEl('div','empty');
2847
+ const h = mkEl('h3',null,'Waiting for agent activity...');
2848
+ const p = mkEl('p',null,'Events appear here as agents spawn and complete. Use ultraworld or ultracode in Claude Code.');
2849
+ d.appendChild(h); d.appendChild(p);
2850
+ list.appendChild(d);
2851
+ }
2852
+
2853
+ function addEvent(event) {
2854
+ const list = document.getElementById('eventList');
2855
+ const empty = list.querySelector('.empty');
2856
+ if (empty) empty.remove();
2857
+
2858
+ const el = mkEl('div','event');
2859
+ el.appendChild(mkEl('span','time',fmtTime(event.timestamp)));
2860
+
2861
+ const badgeCls = event.type==='agent-spawn'?'badge badge-spawn':
2862
+ event.type==='agent-complete'?'badge badge-complete':
2863
+ event.type==='agent-error'?'badge badge-error':'badge badge-magic';
2864
+ const badgeTxt = event.type==='agent-spawn'?'SPAWN':
2865
+ event.type==='agent-complete'?'DONE':
2866
+ event.type==='agent-error'?'ERR':'MAGIC';
2867
+ el.appendChild(mkEl('span',badgeCls,badgeTxt));
2868
+ if (event.agent) el.appendChild(mkEl('span','agent-name',event.agent));
2869
+ if (event.description) el.appendChild(mkEl('span','desc',event.description));
2870
+ if (event.durationMs) el.appendChild(mkEl('span','dur',fmtDur(event.durationMs)));
2871
+
2872
+ list.appendChild(el);
2873
+ list.scrollTop = list.scrollHeight;
2874
+ }
2875
+
2876
+ function updateStats() {
2877
+ const spawns = allEvents.filter(e=>e.type==='agent-spawn');
2878
+ const completes = allEvents.filter(e=>e.type==='agent-complete');
2879
+ const errors = allEvents.filter(e=>e.type==='agent-error');
2880
+ const durs = completes.filter(e=>e.durationMs).map(e=>e.durationMs).sort((a,b)=>a-b);
2881
+
2882
+ document.getElementById('statTotal').textContent = spawns.length;
2883
+ document.getElementById('statActive').textContent = Math.max(0,spawns.length-completes.length-errors.length);
2884
+ document.getElementById('statSuccess').textContent = spawns.length>0?((completes.length/spawns.length)*100).toFixed(0)+'%':'-';
2885
+ document.getElementById('statAvg').textContent = durs.length>0?fmtDur(Math.round(durs.reduce((a,b)=>a+b,0)/durs.length)):'-';
2886
+ document.getElementById('timAvg').textContent = durs.length>0?Math.round(durs.reduce((a,b)=>a+b,0)/durs.length):'-';
2887
+ document.getElementById('timP50').textContent = durs.length>0?durs[Math.floor(durs.length*0.5)]:'-';
2888
+ document.getElementById('timP95').textContent = durs.length>0?durs[Math.floor(durs.length*0.95)]:'-';
2889
+ document.getElementById('eventCount').textContent = '('+allEvents.length+' events)';
2890
+
2891
+ // Team bars — built with safe DOM methods
2892
+ const teams = {};
2893
+ const total = (spawns.length+completes.length)||1;
2894
+ for (const e of [...spawns,...completes]) if(e.team) teams[e.team]=(teams[e.team]||0)+1;
2895
+ const barsEl = document.getElementById('teamBars');
2896
+ barsEl.textContent = '';
2897
+ for (const [team,count] of Object.entries(teams).sort((a,b)=>b[1]-a[1])) {
2898
+ const pct = ((count/total)*100).toFixed(0);
2899
+ const row = mkEl('div','bar-row');
2900
+ row.appendChild(mkEl('span','bar-label',team));
2901
+ const track = mkEl('div','bar-track');
2902
+ const fill = mkEl('div','bar-fill '+(fillClasses[team]||'fill-default'));
2903
+ fill.style.width = pct+'%';
2904
+ track.appendChild(fill);
2905
+ row.appendChild(track);
2906
+ row.appendChild(mkEl('span','bar-value',String(count)));
2907
+ barsEl.appendChild(row);
2908
+ }
2909
+
2910
+ // Agent list
2911
+ const agents = {};
2912
+ for (const e of [...spawns,...completes]) if(e.agent) agents[e.agent]=(agents[e.agent]||0)+1;
2913
+ const agentEl = document.getElementById('agentList');
2914
+ agentEl.textContent = '';
2915
+ for (const [agent,count] of Object.entries(agents).sort((a,b)=>b[1]-a[1]).slice(0,8)) {
2916
+ const row = mkEl('div','bar-row');
2917
+ row.appendChild(mkEl('span','bar-label',agent));
2918
+ const val = mkEl('span','bar-value',String(count));
2919
+ val.style.color = 'var(--teal)';
2920
+ row.appendChild(val);
2921
+ agentEl.appendChild(row);
2922
+ }
2923
+ }
2924
+
2925
+ function connect() {
2926
+ const es = new EventSource('/stream');
2927
+ es.onmessage = function(e) {
2928
+ const data = JSON.parse(e.data);
2929
+ if (data.type==='initial') {
2930
+ allEvents = data.events||[];
2931
+ document.getElementById('eventList').textContent = '';
2932
+ if (allEvents.length===0) showEmpty();
2933
+ else for (const ev of allEvents.slice(-100)) addEvent(ev);
2934
+ updateStats();
2935
+ } else {
2936
+ allEvents.push(data);
2937
+ addEvent(data);
2938
+ updateStats();
2939
+ }
2940
+ };
2941
+ es.onopen = function() {
2942
+ document.getElementById('statusDot').style.background='var(--green)';
2943
+ document.getElementById('statusText').textContent='Connected';
2944
+ };
2945
+ es.onerror = function() {
2946
+ document.getElementById('statusDot').style.background='var(--red)';
2947
+ document.getElementById('statusText').textContent='Reconnecting...';
2948
+ es.close();
2949
+ setTimeout(connect,3000);
2950
+ };
2951
+ }
2952
+ connect();
2953
+ </script>
2954
+ </body>
2955
+ </html>`;
2956
+ }
2957
+ function startVizServer(port = 3737) {
2958
+ mkdirSync2(ARCANEA_DIR, { recursive: true });
2959
+ let lastSize = 0;
2960
+ try {
2961
+ lastSize = existsSync2(EVENTS_FILE) ? statSync(EVENTS_FILE).size : 0;
2962
+ } catch {}
2963
+ const server = createServer((req, res) => {
2964
+ if (req.url === "/stream") {
2965
+ handleSSE(req, res);
2966
+ } else if (req.url === "/api/events") {
2967
+ handleAPI(req, res);
2968
+ } else if (req.url === "/api/test-event" && req.method === "POST") {
2969
+ let body = "";
2970
+ req.on("data", (chunk) => {
2971
+ body += chunk.toString();
2972
+ });
2973
+ req.on("end", () => {
2974
+ try {
2975
+ const event = JSON.parse(body);
2976
+ event.timestamp = event.timestamp || Date.now();
2977
+ logEvent(event);
2978
+ res.writeHead(200, { "Content-Type": "application/json" });
2979
+ res.end(JSON.stringify({ ok: true }));
2980
+ } catch {
2981
+ res.writeHead(400);
2982
+ res.end("Invalid JSON");
2983
+ }
2984
+ });
2985
+ } else {
2986
+ res.writeHead(200, { "Content-Type": "text/html" });
2987
+ res.end(getDashboardHTML());
2988
+ }
2989
+ });
2990
+ const pollInterval = setInterval(() => {
2991
+ try {
2992
+ if (!existsSync2(EVENTS_FILE))
2993
+ return;
2994
+ const currentSize = statSync(EVENTS_FILE).size;
2995
+ if (currentSize > lastSize) {
2996
+ const content = readFileSync2(EVENTS_FILE, "utf-8");
2997
+ const newContent = content.slice(lastSize);
2998
+ lastSize = currentSize;
2999
+ for (const line of newContent.trim().split(`
3000
+ `)) {
3001
+ if (!line)
3002
+ continue;
3003
+ try {
3004
+ broadcast(JSON.parse(line));
3005
+ } catch {}
3006
+ }
3007
+ }
3008
+ } catch {}
3009
+ }, 500);
3010
+ server.on("close", () => clearInterval(pollInterval));
3011
+ server.listen(port, () => {
3012
+ console.log(import_picocolors2.default.cyan(`
3013
+ Arcanea Swarm Viz v${VERSION}`));
3014
+ console.log(import_picocolors2.default.green(`Dashboard: http://localhost:${port}`));
3015
+ console.log(import_picocolors2.default.dim(`Events log: ${EVENTS_FILE}`));
3016
+ console.log(import_picocolors2.default.dim(`SSE stream: http://localhost:${port}/stream`));
3017
+ console.log(import_picocolors2.default.dim(`Press Ctrl+C to stop
3018
+ `));
3019
+ openBrowser(`http://localhost:${port}`);
3020
+ });
3021
+ }
3022
+
3023
+ // src/cli/index.ts
3024
+ import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
3025
+ import { join as join3 } from "path";
3026
+ function countMdFiles(dir) {
3027
+ let count = 0;
3028
+ for (const entry of readdirSync(dir)) {
3029
+ const full = join3(dir, entry);
3030
+ try {
3031
+ if (statSync2(full).isDirectory()) {
3032
+ count += countMdFiles(full);
3033
+ } else if (entry.endsWith(".md")) {
3034
+ count++;
3035
+ }
3036
+ } catch {}
3037
+ }
3038
+ return count;
3039
+ }
2589
3040
  var program2 = new Command;
2590
3041
  program2.name(NAME).description(`${ORCHESTRATOR} - The Creative Intelligence Platform`).version(VERSION);
2591
3042
  program2.command("install").description("Initialize Arcanea in current project").option("-f, --force", "Overwrite existing configuration").option("--claude-code", "Install only for Claude Code").option("--opencode", "Install only for OpenCode").option("--codex", "Install only for Codex").option("--gemini", "Install only for Gemini CLI").option("--cursor", "Install only for Cursor").option("--all", "Install for all supported platforms").option("--skip-mcp", "Skip MCP configuration").action(async (options) => {
@@ -2610,90 +3061,90 @@ program2.command("install").description("Initialize Arcanea in current project")
2610
3061
  });
2611
3062
  });
2612
3063
  program2.command("detect").description("Detect available AI coding platforms").action(() => {
2613
- console.log(import_picocolors2.default.cyan(`
3064
+ console.log(import_picocolors3.default.cyan(`
2614
3065
  ${ORCHESTRATOR} Platform Detection
2615
3066
  `));
2616
3067
  const platforms = detectPlatforms();
2617
3068
  if (platforms.length === 0) {
2618
- console.log(import_picocolors2.default.yellow("No platforms detected. Will install for Claude Code and OpenCode by default."));
3069
+ console.log(import_picocolors3.default.yellow("No platforms detected. Will install for Claude Code and OpenCode by default."));
2619
3070
  } else {
2620
- console.log(import_picocolors2.default.bold("Detected platforms:"));
3071
+ console.log(import_picocolors3.default.bold("Detected platforms:"));
2621
3072
  for (const platform of platforms) {
2622
- console.log(import_picocolors2.default.green(` ✓ ${platform}`));
3073
+ console.log(import_picocolors3.default.green(` ✓ ${platform}`));
2623
3074
  }
2624
3075
  }
2625
3076
  console.log();
2626
3077
  });
2627
3078
  program2.command("agents").description("List available agent teams").option("-t, --team <team>", "Show specific team details").action((options) => {
2628
- console.log(import_picocolors2.default.cyan(`
3079
+ console.log(import_picocolors3.default.cyan(`
2629
3080
  ${ORCHESTRATOR}'s Agent Teams
2630
3081
  `));
2631
3082
  if (options.team) {
2632
3083
  const team = AGENT_TEAMS[options.team];
2633
3084
  if (team) {
2634
- console.log(import_picocolors2.default.bold(team.name));
2635
- console.log(import_picocolors2.default.dim(team.description));
3085
+ console.log(import_picocolors3.default.bold(team.name));
3086
+ console.log(import_picocolors3.default.dim(team.description));
2636
3087
  console.log();
2637
3088
  console.log(" Agents:", team.agents.join(", "));
2638
3089
  } else {
2639
- console.log(import_picocolors2.default.red(`Unknown team: ${options.team}`));
3090
+ console.log(import_picocolors3.default.red(`Unknown team: ${options.team}`));
2640
3091
  console.log("Available teams:", Object.keys(AGENT_TEAMS).join(", "));
2641
3092
  }
2642
3093
  return;
2643
3094
  }
2644
3095
  for (const [key, team] of Object.entries(AGENT_TEAMS)) {
2645
3096
  const colors = {
2646
- creative: import_picocolors2.default.blue,
2647
- writing: import_picocolors2.default.green,
2648
- production: import_picocolors2.default.magenta,
2649
- research: import_picocolors2.default.yellow,
2650
- development: import_picocolors2.default.cyan,
2651
- teacher: import_picocolors2.default.dim,
2652
- visionary: import_picocolors2.default.dim
3097
+ creative: import_picocolors3.default.blue,
3098
+ writing: import_picocolors3.default.green,
3099
+ production: import_picocolors3.default.magenta,
3100
+ research: import_picocolors3.default.yellow,
3101
+ development: import_picocolors3.default.cyan,
3102
+ teacher: import_picocolors3.default.dim,
3103
+ visionary: import_picocolors3.default.dim
2653
3104
  };
2654
- const colorFn = colors[key] || import_picocolors2.default.white;
2655
- console.log(colorFn(import_picocolors2.default.bold(team.name + ":")));
3105
+ const colorFn = colors[key] || import_picocolors3.default.white;
3106
+ console.log(colorFn(import_picocolors3.default.bold(team.name + ":")));
2656
3107
  console.log(` ${team.agents.join(", ")}`);
2657
3108
  console.log();
2658
3109
  }
2659
3110
  });
2660
3111
  program2.command("luminors").description("Show the Seven Luminors").action(() => {
2661
- console.log(import_picocolors2.default.cyan(`
3112
+ console.log(import_picocolors3.default.cyan(`
2662
3113
  The Seven Luminors
2663
3114
  `));
2664
- console.log(import_picocolors2.default.dim(`Aspects of creative consciousness itself
3115
+ console.log(import_picocolors3.default.dim(`Aspects of creative consciousness itself
2665
3116
  `));
2666
3117
  for (const [_, luminor] of Object.entries(LUMINORS)) {
2667
- console.log(import_picocolors2.default.bold(import_picocolors2.default.yellow(`${luminor.name}`)) + ` - ${luminor.domain}`);
2668
- console.log(import_picocolors2.default.dim(` When: ${luminor.when}`));
3118
+ console.log(import_picocolors3.default.bold(import_picocolors3.default.yellow(`${luminor.name}`)) + ` - ${luminor.domain}`);
3119
+ console.log(import_picocolors3.default.dim(` When: ${luminor.when}`));
2669
3120
  console.log();
2670
3121
  }
2671
- console.log(import_picocolors2.default.dim("Channel a Luminor: /luminor [name] [challenge]"));
3122
+ console.log(import_picocolors3.default.dim("Channel a Luminor: /luminor [name] [challenge]"));
2672
3123
  console.log();
2673
3124
  });
2674
3125
  program2.command("magic").description("Show magic words and their effects").action(() => {
2675
- console.log(import_picocolors2.default.cyan(`
3126
+ console.log(import_picocolors3.default.cyan(`
2676
3127
  Magic Words
2677
3128
  `));
2678
- console.log(import_picocolors2.default.bold("Creative Magic:"));
2679
- console.log(import_picocolors2.default.bold(import_picocolors2.default.cyan(" ultraworld")) + " (or ulw) — Fire ALL world-building agents in parallel");
2680
- console.log(import_picocolors2.default.bold(import_picocolors2.default.green(" ultrawrite")) + " (or ulwr) — Fire ALL writing/editing agents in parallel");
2681
- console.log(import_picocolors2.default.bold(import_picocolors2.default.magenta(" ultrabook")) + " (or ulb) — Complete book pipeline end-to-end");
3129
+ console.log(import_picocolors3.default.bold("Creative Magic:"));
3130
+ console.log(import_picocolors3.default.bold(import_picocolors3.default.cyan(" ultraworld")) + " (or ulw) — Fire ALL world-building agents in parallel");
3131
+ console.log(import_picocolors3.default.bold(import_picocolors3.default.green(" ultrawrite")) + " (or ulwr) — Fire ALL writing/editing agents in parallel");
3132
+ console.log(import_picocolors3.default.bold(import_picocolors3.default.magenta(" ultrabook")) + " (or ulb) — Complete book pipeline end-to-end");
2682
3133
  console.log();
2683
- console.log(import_picocolors2.default.bold("Technical Magic:"));
2684
- console.log(import_picocolors2.default.bold(import_picocolors2.default.yellow(" ultracode")) + " (or ulc) — Fire ALL coding agents (architect + coder + reviewer)");
2685
- console.log(import_picocolors2.default.bold(import_picocolors2.default.cyan(" ultrawork")) + " (or ulwk) — Maximum parallel execution for ANY task");
3134
+ console.log(import_picocolors3.default.bold("Technical Magic:"));
3135
+ console.log(import_picocolors3.default.bold(import_picocolors3.default.yellow(" ultracode")) + " (or ulc) — Fire ALL coding agents (architect + coder + reviewer)");
3136
+ console.log(import_picocolors3.default.bold(import_picocolors3.default.cyan(" ultrawork")) + " (or ulwk) — Maximum parallel execution for ANY task");
2686
3137
  console.log();
2687
- console.log(import_picocolors2.default.bold("Prefix Triggers:"));
2688
- console.log(import_picocolors2.default.dim(" arcanea: [task]") + " — Invoke Arcanea's highest intelligence mode");
2689
- console.log(import_picocolors2.default.dim(" luminor: [task]") + " — Apply Luminor wisdom to the task");
3138
+ console.log(import_picocolors3.default.bold("Prefix Triggers:"));
3139
+ console.log(import_picocolors3.default.dim(" arcanea: [task]") + " — Invoke Arcanea's highest intelligence mode");
3140
+ console.log(import_picocolors3.default.dim(" luminor: [task]") + " — Apply Luminor wisdom to the task");
2690
3141
  console.log();
2691
- console.log(import_picocolors2.default.dim("Include any magic word in your prompt to activate!"));
3142
+ console.log(import_picocolors3.default.dim("Include any magic word in your prompt to activate!"));
2692
3143
  console.log();
2693
3144
  });
2694
3145
  program2.command("status").description("Check Arcanea installation status").action(() => {
2695
3146
  const cwd = process.cwd();
2696
- console.log(import_picocolors2.default.cyan(`
3147
+ console.log(import_picocolors3.default.cyan(`
2697
3148
  ${ORCHESTRATOR} Status
2698
3149
  `));
2699
3150
  const platformChecks = [
@@ -2703,32 +3154,32 @@ ${ORCHESTRATOR} Status
2703
3154
  { path: ".codex", name: "Codex" },
2704
3155
  { path: ".gemini", name: "Gemini CLI" }
2705
3156
  ];
2706
- console.log(import_picocolors2.default.bold("Platform installations:"));
3157
+ console.log(import_picocolors3.default.bold("Platform installations:"));
2707
3158
  for (const check of platformChecks) {
2708
- const agentsPath = join2(cwd, check.path, "agents");
2709
- const exists = existsSync2(agentsPath);
2710
- const status = exists ? import_picocolors2.default.green("✓") : import_picocolors2.default.dim("○");
3159
+ const agentsPath = join3(cwd, check.path, "agents");
3160
+ const exists = existsSync3(agentsPath);
3161
+ const status = exists ? import_picocolors3.default.green("✓") : import_picocolors3.default.dim("○");
2711
3162
  console.log(` ${status} ${check.name}`);
2712
3163
  }
2713
3164
  console.log();
2714
- console.log(import_picocolors2.default.bold("Configuration:"));
3165
+ console.log(import_picocolors3.default.bold("Configuration:"));
2715
3166
  const configChecks = [
2716
3167
  { path: "arcanea.json", name: "Arcanea config" },
2717
3168
  { path: ".mcp.json", name: "MCP config" }
2718
3169
  ];
2719
3170
  let allGood = true;
2720
3171
  for (const check of configChecks) {
2721
- const exists = existsSync2(join2(cwd, check.path));
2722
- const status = exists ? import_picocolors2.default.green("✓") : import_picocolors2.default.red("✗");
3172
+ const exists = existsSync3(join3(cwd, check.path));
3173
+ const status = exists ? import_picocolors3.default.green("✓") : import_picocolors3.default.red("✗");
2723
3174
  console.log(` ${status} ${check.name}`);
2724
3175
  if (!exists)
2725
3176
  allGood = false;
2726
3177
  }
2727
3178
  console.log();
2728
3179
  if (allGood) {
2729
- console.log(import_picocolors2.default.green("Arcanea is ready!"));
3180
+ console.log(import_picocolors3.default.green("Arcanea is ready!"));
2730
3181
  } else {
2731
- console.log(import_picocolors2.default.yellow("Run 'arcanea install' to complete setup."));
3182
+ console.log(import_picocolors3.default.yellow("Run 'arcanea install' to complete setup."));
2732
3183
  }
2733
3184
  console.log();
2734
3185
  });
@@ -2736,87 +3187,97 @@ program2.command("doctor").description("Diagnose Arcanea installation health").a
2736
3187
  const cwd = process.cwd();
2737
3188
  let issues = 0;
2738
3189
  let ok = 0;
2739
- console.log(import_picocolors2.default.cyan(`
3190
+ console.log(import_picocolors3.default.cyan(`
2740
3191
  ${ORCHESTRATOR} Doctor (v${VERSION})
2741
3192
  `));
2742
- console.log(import_picocolors2.default.bold(`Checking installation health...
3193
+ console.log(import_picocolors3.default.bold(`Checking installation health...
2743
3194
  `));
2744
3195
  const claudePaths = [
2745
- join2(cwd, ".claude", "CLAUDE.md"),
2746
- join2(cwd, ".opencode", "CLAUDE.md"),
2747
- join2(cwd, "CLAUDE.md")
3196
+ join3(cwd, ".claude", "CLAUDE.md"),
3197
+ join3(cwd, ".opencode", "CLAUDE.md"),
3198
+ join3(cwd, "CLAUDE.md")
2748
3199
  ];
2749
- const hasClaudeMd = claudePaths.some((p) => existsSync2(p));
3200
+ const hasClaudeMd = claudePaths.some((p) => existsSync3(p));
2750
3201
  if (hasClaudeMd) {
2751
- console.log(import_picocolors2.default.green(" ✓ CLAUDE.md found (Arcanea identity active)"));
3202
+ console.log(import_picocolors3.default.green(" ✓ CLAUDE.md found (Arcanea identity active)"));
2752
3203
  ok++;
2753
3204
  } else {
2754
- console.log(import_picocolors2.default.red(" ✗ No CLAUDE.md found — run 'arcanea install' to fix"));
3205
+ console.log(import_picocolors3.default.red(" ✗ No CLAUDE.md found — run 'arcanea install' to fix"));
2755
3206
  issues++;
2756
3207
  }
2757
3208
  const agentPaths = [".claude/agents", ".opencode/agents"];
2758
3209
  const hasAgents = agentPaths.some((p) => {
2759
- const full = join2(cwd, p);
2760
- return existsSync2(full) && readdirSync(full).length > 0;
3210
+ const full = join3(cwd, p);
3211
+ return existsSync3(full) && readdirSync(full).length > 0;
2761
3212
  });
2762
3213
  if (hasAgents) {
2763
- const agentDir = agentPaths.find((p) => existsSync2(join2(cwd, p)));
2764
- const count = readdirSync(join2(cwd, agentDir)).filter((f) => f.endsWith(".md")).length;
2765
- console.log(import_picocolors2.default.green(` ✓ ${count} agent definitions installed`));
3214
+ const agentDir = agentPaths.find((p) => existsSync3(join3(cwd, p)));
3215
+ const count = countMdFiles(join3(cwd, agentDir));
3216
+ console.log(import_picocolors3.default.green(` ✓ ${count} agent definitions installed`));
2766
3217
  ok++;
2767
3218
  } else {
2768
- console.log(import_picocolors2.default.red(" ✗ No agents installed — run 'arcanea install --force'"));
3219
+ console.log(import_picocolors3.default.red(" ✗ No agents installed — run 'arcanea install --force'"));
2769
3220
  issues++;
2770
3221
  }
2771
3222
  const skillPaths = [".claude/skills", ".opencode/skills"];
2772
3223
  const hasSkills = skillPaths.some((p) => {
2773
- const full = join2(cwd, p);
2774
- return existsSync2(full) && readdirSync(full).length > 0;
3224
+ const full = join3(cwd, p);
3225
+ return existsSync3(full) && readdirSync(full).length > 0;
2775
3226
  });
2776
3227
  if (hasSkills) {
2777
- console.log(import_picocolors2.default.green(" ✓ Skills installed"));
3228
+ console.log(import_picocolors3.default.green(" ✓ Skills installed"));
2778
3229
  ok++;
2779
3230
  } else {
2780
- console.log(import_picocolors2.default.red(" ✗ No skills installed — run 'arcanea install --force'"));
3231
+ console.log(import_picocolors3.default.red(" ✗ No skills installed — run 'arcanea install --force'"));
2781
3232
  issues++;
2782
3233
  }
2783
- const mcpPath = join2(cwd, ".mcp.json");
2784
- if (existsSync2(mcpPath)) {
3234
+ const mcpPath = join3(cwd, ".mcp.json");
3235
+ if (existsSync3(mcpPath)) {
2785
3236
  try {
2786
- const mcp = JSON.parse(readFileSync2(mcpPath, "utf-8"));
3237
+ const mcp = JSON.parse(readFileSync3(mcpPath, "utf-8"));
2787
3238
  const servers = Object.keys(mcp.mcpServers || {});
2788
3239
  const hasArcanea = servers.includes("arcanea");
2789
- console.log(import_picocolors2.default.green(` ✓ MCP config: ${servers.length} servers configured`));
3240
+ console.log(import_picocolors3.default.green(` ✓ MCP config: ${servers.length} servers configured`));
2790
3241
  if (!hasArcanea) {
2791
- console.log(import_picocolors2.default.yellow(" ⚠ Arcanea MCP server not configured — run 'arcanea install --force'"));
3242
+ console.log(import_picocolors3.default.yellow(" ⚠ Arcanea MCP server not configured — run 'arcanea install --force'"));
2792
3243
  }
2793
3244
  ok++;
2794
3245
  } catch {
2795
- console.log(import_picocolors2.default.red(" ✗ .mcp.json is invalid JSON"));
3246
+ console.log(import_picocolors3.default.red(" ✗ .mcp.json is invalid JSON"));
2796
3247
  issues++;
2797
3248
  }
2798
3249
  } else {
2799
- console.log(import_picocolors2.default.red(" ✗ No .mcp.json — run 'arcanea install'"));
3250
+ console.log(import_picocolors3.default.red(" ✗ No .mcp.json — run 'arcanea install'"));
2800
3251
  issues++;
2801
3252
  }
2802
- if (existsSync2(join2(cwd, "arcanea.json"))) {
2803
- console.log(import_picocolors2.default.green(" ✓ arcanea.json config exists"));
3253
+ if (existsSync3(join3(cwd, "arcanea.json"))) {
3254
+ console.log(import_picocolors3.default.green(" ✓ arcanea.json config exists"));
2804
3255
  ok++;
2805
3256
  } else {
2806
- console.log(import_picocolors2.default.yellow(" ○ No arcanea.json (optional)"));
3257
+ console.log(import_picocolors3.default.yellow(" ○ No arcanea.json (optional)"));
2807
3258
  }
2808
- if (existsSync2(join2(cwd, ".cursorrules"))) {
2809
- console.log(import_picocolors2.default.green(".cursorrules configured for Cursor"));
2810
- ok++;
3259
+ const platformFiles = [
3260
+ { path: ".cursorrules", name: "Cursor (.cursorrules)" },
3261
+ { path: "codex.md", name: "Codex CLI (codex.md)" },
3262
+ { path: "GEMINI.md", name: "Gemini CLI (GEMINI.md)" }
3263
+ ];
3264
+ for (const pf of platformFiles) {
3265
+ if (existsSync3(join3(cwd, pf.path))) {
3266
+ console.log(import_picocolors3.default.green(` ✓ ${pf.name} configured`));
3267
+ ok++;
3268
+ }
2811
3269
  }
2812
3270
  console.log();
2813
3271
  if (issues === 0) {
2814
- console.log(import_picocolors2.default.green(import_picocolors2.default.bold(`Health: ${ok} checks passed, 0 issues`)));
2815
- console.log(import_picocolors2.default.green("Arcanea is fully operational!"));
3272
+ console.log(import_picocolors3.default.green(import_picocolors3.default.bold(`Health: ${ok} checks passed, 0 issues`)));
3273
+ console.log(import_picocolors3.default.green("Arcanea is fully operational!"));
2816
3274
  } else {
2817
- console.log(import_picocolors2.default.yellow(import_picocolors2.default.bold(`Health: ${ok} passed, ${issues} issues found`)));
2818
- console.log(import_picocolors2.default.dim("Run 'arcanea install --force' to fix issues."));
3275
+ console.log(import_picocolors3.default.yellow(import_picocolors3.default.bold(`Health: ${ok} passed, ${issues} issues found`)));
3276
+ console.log(import_picocolors3.default.dim("Run 'arcanea install --force' to fix issues."));
2819
3277
  }
2820
3278
  console.log();
2821
3279
  });
3280
+ program2.command("viz").description("Launch real-time swarm visualization dashboard").option("-p, --port <port>", "Server port", "3737").option("--no-open", "Don't auto-open browser").action((options) => {
3281
+ startVizServer(parseInt(options.port, 10));
3282
+ });
2822
3283
  program2.parse();
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const VERSION = "3.2.0";
1
+ export declare const VERSION = "3.4.0";
2
2
  export declare const NAME = "arcanea";
3
3
  export declare const ORCHESTRATOR = "Arcanea";
4
4
  export type Platform = "claude-code" | "opencode" | "codex" | "gemini" | "cursor" | "unknown";
package/dist/index.js CHANGED
@@ -199,11 +199,17 @@ async function installForPlatform(targetDir, packageRoot, platform, force) {
199
199
  await installClaudeCodeSettings(platformPath, force);
200
200
  } else if (platform === "cursor") {
201
201
  await installCursorRules(targetDir, packageRoot, force);
202
+ } else if (platform === "codex") {
203
+ await installCodexConfig(targetDir, packageRoot, force);
204
+ } else if (platform === "gemini") {
205
+ await installGeminiConfig(targetDir, packageRoot, force);
202
206
  }
203
207
  }
204
208
  async function installClaudeCodeSettings(platformPath, force) {
205
209
  const settingsPath = join(platformPath, "settings.json");
206
210
  if (!existsSync(settingsPath) || force) {
211
+ const eventsDir = join(process.env.HOME || process.env.USERPROFILE || "~", ".arcanea").replace(/\\/g, "/");
212
+ const logScript = `mkdir -p "${eventsDir}" && echo '{"type":"agent-spawn","agent":"'$(echo "$TOOL_INPUT" 2>/dev/null | node -e "try{const d=JSON.parse(require('fs').readFileSync(0,'utf8'));process.stdout.write((d.subagent_type||'unknown')+'","description":"'+(d.description||'').replace(/"/g,'')+'","team":"'+(d.subagent_type||''))}catch{process.stdout.write('unknown","description":"","team":"')}" 2>/dev/null)","timestamp":'$(date +%s000)'}' >> "${eventsDir}/swarm-events.jsonl"`;
207
213
  const settings = {
208
214
  hooks: {
209
215
  UserPromptSubmit: [
@@ -242,6 +248,15 @@ async function installClaudeCodeSettings(platformPath, force) {
242
248
  command: "echo '[ARCANEA_MODE=ultrawork] Maximum parallel execution. Spawn all relevant agents simultaneously using Task tool with run_in_background=true.'"
243
249
  }]
244
250
  }
251
+ ],
252
+ PreToolUse: [
253
+ {
254
+ matcher: "Task",
255
+ hooks: [{
256
+ type: "command",
257
+ command: logScript
258
+ }]
259
+ }
245
260
  ]
246
261
  }
247
262
  };
@@ -263,6 +278,64 @@ ${claudeContent}`;
263
278
  }
264
279
  }
265
280
  }
281
+ async function installCodexConfig(targetDir, packageRoot, force) {
282
+ const codexMdPath = join(targetDir, "codex.md");
283
+ if (!existsSync(codexMdPath) || force) {
284
+ const claudeMdSource = join(packageRoot, "CLAUDE.md");
285
+ if (existsSync(claudeMdSource)) {
286
+ const content = readFileSync(claudeMdSource, "utf-8");
287
+ const codexMd = [
288
+ `# Codex Instructions — Generated by Arcanea v${VERSION}`,
289
+ "",
290
+ "> These instructions transform Codex into Arcanea, the Creative Intelligence Platform.",
291
+ "> Agent definitions: `.codex/agents/` | Skills: `.codex/skills/` | Commands: `.codex/commands/`",
292
+ "",
293
+ content,
294
+ "",
295
+ "## Codex-Specific Notes",
296
+ "",
297
+ "- Read agent definitions from `.codex/agents/` for available specialist agents",
298
+ "- Read skill definitions from `.codex/skills/` for creative and technical skills",
299
+ "- Read command definitions from `.codex/commands/` for slash commands",
300
+ "- MCP servers are configured in `.mcp.json`",
301
+ "- When magic words (ultraworld, ultracode, etc.) are used, read the relevant agent files and apply their instructions",
302
+ ""
303
+ ].join(`
304
+ `);
305
+ writeFileSync(codexMdPath, codexMd);
306
+ console.log(import_picocolors.default.green(" ✓ Created codex.md (Arcanea instructions for Codex CLI)"));
307
+ }
308
+ }
309
+ }
310
+ async function installGeminiConfig(targetDir, packageRoot, force) {
311
+ const geminiMdPath = join(targetDir, "GEMINI.md");
312
+ if (!existsSync(geminiMdPath) || force) {
313
+ const claudeMdSource = join(packageRoot, "CLAUDE.md");
314
+ if (existsSync(claudeMdSource)) {
315
+ const content = readFileSync(claudeMdSource, "utf-8");
316
+ const geminiMd = [
317
+ `# Gemini Instructions — Generated by Arcanea v${VERSION}`,
318
+ "",
319
+ "> These instructions transform Gemini into Arcanea, the Creative Intelligence Platform.",
320
+ "> Agent definitions: `.gemini/agents/` | Skills: `.gemini/skills/` | Commands: `.gemini/commands/`",
321
+ "",
322
+ content,
323
+ "",
324
+ "## Gemini-Specific Notes",
325
+ "",
326
+ "- Read agent definitions from `.gemini/agents/` for available specialist agents",
327
+ "- Read skill definitions from `.gemini/skills/` for creative and technical skills",
328
+ "- Read command definitions from `.gemini/commands/` for slash commands",
329
+ "- MCP servers are configured in `.mcp.json`",
330
+ "- When magic words (ultraworld, ultracode, etc.) are used, read the relevant agent files and apply their instructions",
331
+ ""
332
+ ].join(`
333
+ `);
334
+ writeFileSync(geminiMdPath, geminiMd);
335
+ console.log(import_picocolors.default.green(" ✓ Created GEMINI.md (Arcanea instructions for Gemini CLI)"));
336
+ }
337
+ }
338
+ }
266
339
  async function installMcpConfig(targetDir, force) {
267
340
  const mcpPath = join(targetDir, ".mcp.json");
268
341
  console.log(import_picocolors.default.blue(`
@@ -342,7 +415,7 @@ function printSuccessMessage(platforms) {
342
415
  }
343
416
 
344
417
  // src/index.ts
345
- var VERSION = "3.2.0";
418
+ var VERSION = "3.4.0";
346
419
  var NAME = "arcanea";
347
420
  var ORCHESTRATOR = "Arcanea";
348
421
  var defaultConfig = {
@@ -0,0 +1,13 @@
1
+ export interface SwarmEvent {
2
+ type: "agent-spawn" | "agent-complete" | "agent-error" | "magic-word" | "session-start";
3
+ agent?: string;
4
+ team?: string;
5
+ description?: string;
6
+ status?: "running" | "complete" | "error";
7
+ durationMs?: number;
8
+ timestamp: number;
9
+ meta?: Record<string, unknown>;
10
+ }
11
+ export declare function logEvent(event: SwarmEvent): void;
12
+ export declare function startVizServer(port?: number): void;
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/viz/index.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,aAAa,GAAG,gBAAgB,GAAG,aAAa,GAAG,YAAY,GAAG,eAAe,CAAC;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAGhD;AA2RD,wBAAgB,cAAc,CAAC,IAAI,GAAE,MAAa,GAAG,IAAI,CA2DxD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arcanea",
3
- "version": "3.2.0",
3
+ "version": "3.4.0",
4
4
  "description": "Arcanea - The Creative Intelligence Platform. Skills, agents, and tools for AI-human co-creation.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,3 +1,16 @@
1
+ ---
2
+ name: arcanea-ai-symbiosis
3
+ description: Frameworks for productive human-AI co-creation - the orchestra model, creative partnerships, and symbiotic workflows
4
+ version: 2.0.0
5
+ author: Arcanea
6
+ tags: [ai, collaboration, co-creation, symbiosis, creativity]
7
+ triggers:
8
+ - ai collaboration
9
+ - human ai
10
+ - co-creation
11
+ - ai partner
12
+ ---
13
+
1
14
  # AI Symbiosis - The Art of Human-AI Co-Creation
2
15
 
3
16
  > *"The AI is not replacing the creator. The AI is expanding what creation can be. The question is not 'human or machine?' but 'what can we become together?'"*
@@ -1,3 +1,11 @@
1
+ ---
2
+ name: arcanea-anti-trope
3
+ description: Anti-trope and naming protocol - banned AI cliches, forbidden words, and better alternatives for authentic Arcanean prose
4
+ version: 2.0.0
5
+ author: Arcanea
6
+ tags: [writing, style, voice, anti-cliche, prose-quality]
7
+ ---
8
+
1
9
  # Arcanea Anti-Trope & Naming Protocol
2
10
 
3
11
  > *"We do not 'unleash' potential; we cultivate it. We do not weave 'tapestries' of fate; we forge chains of consequence. Speak clearly, or do not speak at all."*
@@ -1,3 +1,18 @@
1
+ ---
2
+ name: arcanea-luminor-council
3
+ description: The Seven Luminors - aspects of creative consciousness providing guidance through archetypical wisdom for any creative challenge
4
+ version: 2.0.0
5
+ author: Arcanea
6
+ tags: [luminors, wisdom, guidance, creative-consciousness, archetypes]
7
+ triggers:
8
+ - luminor
9
+ - council
10
+ - wisdom
11
+ - guidance
12
+ - stuck
13
+ - advice
14
+ ---
15
+
1
16
  # Luminor Council - The Seven Guides of Creation
2
17
 
3
18
  > *"The Luminors are not characters in a story. They are aspects of creative consciousness itself - archetypes that have guided creators since the first dream became the first work."*
@@ -1,3 +1,17 @@
1
+ ---
2
+ name: arcanea-character-alchemist
3
+ description: Character development through psychological depth - wounds, desires, contradictions, and authentic character voices
4
+ version: 2.0.0
5
+ author: Arcanea
6
+ tags: [characters, psychology, writing, development, voice]
7
+ triggers:
8
+ - character
9
+ - character development
10
+ - character voice
11
+ - protagonist
12
+ - antagonist
13
+ ---
14
+
1
15
  # Character Alchemist - Transmuting Ideas into Living Beings
2
16
 
3
17
  > *"A character is not a collection of traits. A character is a wound that walks, talks, and wants."*
@@ -1,3 +1,17 @@
1
+ ---
2
+ name: arcanea-creative-bestiary
3
+ description: Navigate creative blocks using the taxonomy of psychological obstacles - naming rituals and protocols for each creature type
4
+ version: 2.0.0
5
+ author: Arcanea
6
+ tags: [creative-blocks, psychology, productivity, obstacles, mindset]
7
+ triggers:
8
+ - stuck
9
+ - blocked
10
+ - procrastinating
11
+ - afraid
12
+ - burned out
13
+ ---
14
+
1
15
  # Creative Bestiary - Navigating the Creatures of the Mind
2
16
 
3
17
  > *"The creative life is inhabited by creatures—not physical beings, but psychological presences that every creator encounters. Know them by name, and you can negotiate with them. Ignore them, and they will ambush you."*
@@ -1,3 +1,17 @@
1
+ ---
2
+ name: arcanea-story-weaver
3
+ description: Master narrative craft - story structure, scene design, dramatic tension, and meaning-making through storytelling
4
+ version: 2.0.0
5
+ author: Arcanea
6
+ tags: [story, narrative, writing, structure, craft]
7
+ triggers:
8
+ - story
9
+ - narrative
10
+ - plot
11
+ - scene
12
+ - story structure
13
+ ---
14
+
1
15
  # Story Weaver - The Master Craft of Narrative
2
16
 
3
17
  > *"Story is not what happens. Story is the meaning we make from what happens. Your job is not to tell events - it is to transmit understanding."*
@@ -1,3 +1,17 @@
1
+ ---
2
+ name: arcanea-world-architect
3
+ description: Universe creation and world-building - geography, history, belief systems, cultures, and living ecologies of meaning
4
+ version: 2.0.0
5
+ author: Arcanea
6
+ tags: [world-building, fantasy, sci-fi, universe, creation]
7
+ triggers:
8
+ - world
9
+ - world-building
10
+ - universe
11
+ - setting
12
+ - geography
13
+ ---
14
+
1
15
  # World Architect - The Art of Universe Creation
2
16
 
3
17
  > *"A world is not built. It is grown. You plant seeds - a geography, a history, a belief - and you tend them until they become a living ecology of meaning."*