buildwithnexus 0.3.1 → 0.3.2

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/bin.js CHANGED
@@ -363,7 +363,7 @@ __export(qemu_exports, {
363
363
  import fs3 from "fs";
364
364
  import net from "net";
365
365
  import path3 from "path";
366
- import { execa } from "execa";
366
+ import { execa, execaSync } from "execa";
367
367
  import { select } from "@inquirer/prompts";
368
368
  import chalk5 from "chalk";
369
369
  async function isQemuInstalled(platform) {
@@ -378,10 +378,16 @@ async function installQemu(platform) {
378
378
  if (platform.os === "mac") {
379
379
  await execa("brew", ["install", "qemu", "cdrtools"], { stdio: "inherit", env: scrubEnv() });
380
380
  } else if (platform.os === "linux") {
381
+ let hasApt = false;
381
382
  try {
383
+ await execa("which", ["apt-get"], { env: scrubEnv() });
384
+ hasApt = true;
385
+ } catch {
386
+ }
387
+ if (hasApt) {
382
388
  await execa("sudo", ["apt-get", "update"], { stdio: "inherit", env: scrubEnv() });
383
389
  await execa("sudo", ["apt-get", "install", "-y", "qemu-system", "qemu-utils", "genisoimage"], { stdio: "inherit", env: scrubEnv() });
384
- } catch {
390
+ } else {
385
391
  await execa("sudo", ["yum", "install", "-y", "qemu-system-arm", "qemu-system-x86", "qemu-img", "genisoimage"], { stdio: "inherit", env: scrubEnv() });
386
392
  }
387
393
  } else {
@@ -392,7 +398,7 @@ async function downloadImage(platform) {
392
398
  const imagePath = path3.join(IMAGES_DIR, platform.ubuntuImage);
393
399
  if (fs3.existsSync(imagePath)) return imagePath;
394
400
  const url = `${UBUNTU_BASE_URL}/${platform.ubuntuImage}`;
395
- await execa("curl", ["-L", "-o", imagePath, "--progress-bar", url], { stdio: "inherit", env: scrubEnv() });
401
+ await execa("curl", ["-L", "-C", "-", "-o", imagePath, "--progress-bar", url], { stdio: "inherit", env: scrubEnv() });
396
402
  return imagePath;
397
403
  }
398
404
  async function createDisk(basePath, sizeGb) {
@@ -490,38 +496,36 @@ async function resolvePortConflicts(ports) {
490
496
  return resolved;
491
497
  }
492
498
  async function launchVm(platform, diskPath, initIsoPath, ram, cpus, ports) {
493
- const machineArg = platform.os === "mac" ? "-machine virt,gic-version=3" : "-machine pc";
499
+ const machineArgs = platform.os === "mac" ? ["-machine", "virt,gic-version=3"] : ["-machine", "pc"];
494
500
  const biosArgs = fs3.existsSync(platform.biosPath) ? ["-bios", platform.biosPath] : [];
495
- function buildArgs(cpuFlag) {
496
- return [
497
- ...machineArg.split(" "),
498
- ...cpuFlag.split(" "),
499
- "-m",
500
- `${ram}G`,
501
- "-smp",
502
- `${cpus}`,
503
- "-drive",
504
- `file=${diskPath},if=virtio,cache=writethrough`,
505
- "-drive",
506
- `file=${initIsoPath},if=virtio,format=raw,cache=writethrough`,
507
- "-display",
508
- "none",
509
- "-serial",
510
- "none",
511
- "-net",
512
- "nic,model=virtio",
513
- "-net",
514
- `user,hostfwd=tcp::${ports.ssh}-:22,hostfwd=tcp::${ports.http}-:4200,hostfwd=tcp::${ports.https}-:443`,
515
- ...biosArgs,
516
- "-pidfile",
517
- PID_FILE,
518
- "-daemonize"
519
- ];
520
- }
501
+ const buildArgs = (cpuArgs) => [
502
+ ...machineArgs,
503
+ ...cpuArgs,
504
+ "-m",
505
+ `${ram}G`,
506
+ "-smp",
507
+ `${cpus}`,
508
+ "-drive",
509
+ `file=${diskPath},if=virtio,cache=writethrough`,
510
+ "-drive",
511
+ `file=${initIsoPath},if=virtio,format=raw,cache=writethrough`,
512
+ "-display",
513
+ "none",
514
+ "-serial",
515
+ "none",
516
+ "-net",
517
+ "nic,model=virtio",
518
+ "-net",
519
+ `user,hostfwd=tcp::${ports.ssh}-:22,hostfwd=tcp::${ports.http}-:4200,hostfwd=tcp::${ports.https}-:443`,
520
+ ...biosArgs,
521
+ "-pidfile",
522
+ PID_FILE,
523
+ "-daemonize"
524
+ ];
521
525
  try {
522
- await execa(platform.qemuBinary, buildArgs(platform.qemuCpuFlag), { env: scrubEnv() });
526
+ await execa(platform.qemuBinary, buildArgs(platform.qemuCpuFlag.split(" ")), { env: scrubEnv() });
523
527
  } catch {
524
- const fallbackCpu = platform.os === "mac" ? "-cpu max" : "-cpu qemu64";
528
+ const fallbackCpu = platform.os === "mac" ? ["-cpu", "max"] : ["-cpu", "qemu64"];
525
529
  await execa(platform.qemuBinary, buildArgs(fallbackCpu), { env: scrubEnv() });
526
530
  }
527
531
  return ports;
@@ -533,6 +537,14 @@ function readValidPid() {
533
537
  if (!Number.isInteger(pid) || pid <= 1 || pid > 4194304) return null;
534
538
  return pid;
535
539
  }
540
+ function isQemuPid(pid) {
541
+ try {
542
+ const { stdout } = execaSync("ps", ["-p", String(pid), "-o", "comm="], { env: scrubEnv() });
543
+ return stdout.trim().toLowerCase().includes("qemu");
544
+ } catch {
545
+ return false;
546
+ }
547
+ }
536
548
  function isVmRunning() {
537
549
  const pid = readValidPid();
538
550
  if (!pid) return false;
@@ -546,6 +558,13 @@ function isVmRunning() {
546
558
  function stopVm() {
547
559
  const pid = readValidPid();
548
560
  if (!pid) return;
561
+ if (!isQemuPid(pid)) {
562
+ try {
563
+ fs3.unlinkSync(PID_FILE);
564
+ } catch {
565
+ }
566
+ return;
567
+ }
549
568
  try {
550
569
  process.kill(pid, "SIGTERM");
551
570
  } catch {
@@ -722,6 +741,7 @@ import { Command as Command14 } from "commander";
722
741
  // src/commands/init.ts
723
742
  init_banner();
724
743
  import { Command } from "commander";
744
+ import chalk6 from "chalk";
725
745
 
726
746
  // src/ui/spinner.ts
727
747
  import ora from "ora";
@@ -928,69 +948,65 @@ async function createCloudInitIso(userDataPath) {
928
948
  fs5.writeFileSync(metaDataPath, "instance-id: nexus-vm-1\nlocal-hostname: nexus-vm\n", { mode: 384 });
929
949
  const isoPath = path5.join(IMAGES_DIR2, "init.iso");
930
950
  const env = scrubEnv();
931
- let created = false;
932
951
  try {
933
- await execa3("mkisofs", [
934
- "-output",
935
- isoPath,
936
- "-volid",
937
- "cidata",
938
- "-joliet",
939
- "-rock",
940
- userDataPath,
941
- metaDataPath
942
- ], { env });
943
- created = true;
944
- } catch {
945
- }
946
- if (!created) {
952
+ let created = false;
953
+ for (const tool of ["mkisofs", "genisoimage"]) {
954
+ if (created) break;
955
+ try {
956
+ await execa3(tool, [
957
+ "-output",
958
+ isoPath,
959
+ "-volid",
960
+ "cidata",
961
+ "-joliet",
962
+ "-rock",
963
+ userDataPath,
964
+ metaDataPath
965
+ ], { env });
966
+ created = true;
967
+ } catch {
968
+ }
969
+ }
970
+ if (!created) {
971
+ try {
972
+ const stagingDir = path5.join(CONFIGS_DIR, "cidata-staging");
973
+ fs5.mkdirSync(stagingDir, { recursive: true, mode: 448 });
974
+ fs5.copyFileSync(userDataPath, path5.join(stagingDir, "user-data"));
975
+ fs5.copyFileSync(metaDataPath, path5.join(stagingDir, "meta-data"));
976
+ await execa3("hdiutil", [
977
+ "makehybrid",
978
+ "-o",
979
+ isoPath,
980
+ "-joliet",
981
+ "-iso",
982
+ "-default-volume-name",
983
+ "cidata",
984
+ stagingDir
985
+ ], { env });
986
+ fs5.rmSync(stagingDir, { recursive: true, force: true });
987
+ created = true;
988
+ } catch {
989
+ }
990
+ }
991
+ if (!created) {
992
+ throw new Error(
993
+ "Cannot create cloud-init ISO: none of mkisofs, genisoimage, or hdiutil are available. On macOS, install cdrtools: brew install cdrtools. On Linux: sudo apt install genisoimage"
994
+ );
995
+ }
996
+ fs5.chmodSync(isoPath, 384);
997
+ audit("cloudinit_iso_created", "init.iso created");
998
+ return isoPath;
999
+ } finally {
947
1000
  try {
948
- await execa3("genisoimage", [
949
- "-output",
950
- isoPath,
951
- "-volid",
952
- "cidata",
953
- "-joliet",
954
- "-rock",
955
- userDataPath,
956
- metaDataPath
957
- ], { env });
958
- created = true;
1001
+ fs5.unlinkSync(userDataPath);
959
1002
  } catch {
960
1003
  }
961
- }
962
- if (!created) {
963
1004
  try {
964
- const stagingDir = path5.join(CONFIGS_DIR, "cidata-staging");
965
- fs5.mkdirSync(stagingDir, { recursive: true, mode: 448 });
966
- fs5.copyFileSync(userDataPath, path5.join(stagingDir, "user-data"));
967
- fs5.copyFileSync(metaDataPath, path5.join(stagingDir, "meta-data"));
968
- await execa3("hdiutil", [
969
- "makehybrid",
970
- "-o",
971
- isoPath,
972
- "-joliet",
973
- "-iso",
974
- "-default-volume-name",
975
- "cidata",
976
- stagingDir
977
- ], { env });
978
- fs5.rmSync(stagingDir, { recursive: true, force: true });
979
- created = true;
1005
+ fs5.unlinkSync(metaDataPath);
980
1006
  } catch {
981
1007
  }
1008
+ audit("cloudinit_plaintext_deleted", "user-data.yaml and meta-data.yaml removed");
982
1009
  }
983
- if (!created) {
984
- throw new Error(
985
- "Cannot create cloud-init ISO: none of mkisofs, genisoimage, or hdiutil are available. On macOS, install cdrtools: brew install cdrtools. On Linux: sudo apt install genisoimage"
986
- );
987
- }
988
- fs5.chmodSync(isoPath, 384);
989
- fs5.unlinkSync(userDataPath);
990
- fs5.unlinkSync(metaDataPath);
991
- audit("cloudinit_plaintext_deleted", "user-data.yaml and meta-data.yaml removed");
992
- audit("cloudinit_iso_created", "init.iso created");
993
- return isoPath;
994
1010
  }
995
1011
 
996
1012
  // src/core/health.ts
@@ -1029,27 +1045,51 @@ async function checkHealth(port, vmRunning) {
1029
1045
  }
1030
1046
  return status;
1031
1047
  }
1032
- async function waitForServer(port, timeoutMs = 6e5) {
1048
+ async function waitForServer(port, timeoutMs = 9e5) {
1033
1049
  const start = Date.now();
1050
+ let lastLog = 0;
1034
1051
  while (Date.now() - start < timeoutMs) {
1035
1052
  try {
1036
1053
  const { stdout, code } = await sshExec(port, "curl -sf http://localhost:4200/health");
1037
1054
  if (code === 0 && stdout.includes("ok")) return true;
1038
1055
  } catch {
1039
1056
  }
1040
- await new Promise((r) => setTimeout(r, 1e4));
1057
+ const elapsed = Date.now() - start;
1058
+ if (elapsed - lastLog >= 3e4) {
1059
+ lastLog = elapsed;
1060
+ try {
1061
+ const { stdout } = await sshExec(port, "systemctl is-active nexus 2>/dev/null || echo 'starting...'");
1062
+ process.stderr.write(`
1063
+ [server ${Math.round(elapsed / 1e3)}s] ${stdout.trim().slice(0, 120)}
1064
+ `);
1065
+ } catch {
1066
+ }
1067
+ }
1068
+ await new Promise((r) => setTimeout(r, 5e3));
1041
1069
  }
1042
1070
  return false;
1043
1071
  }
1044
- async function waitForCloudInit(port, timeoutMs = 9e5) {
1072
+ async function waitForCloudInit(port, timeoutMs = 18e5) {
1045
1073
  const start = Date.now();
1074
+ let lastLog = 0;
1046
1075
  while (Date.now() - start < timeoutMs) {
1047
1076
  try {
1048
1077
  const { code } = await sshExec(port, "test -f /var/lib/cloud/instance/boot-finished");
1049
1078
  if (code === 0) return true;
1050
1079
  } catch {
1051
1080
  }
1052
- await new Promise((r) => setTimeout(r, 1e4));
1081
+ const elapsed = Date.now() - start;
1082
+ if (elapsed - lastLog >= 6e4) {
1083
+ lastLog = elapsed;
1084
+ try {
1085
+ const { stdout } = await sshExec(port, "tail -1 /var/log/cloud-init-output.log 2>/dev/null || echo 'waiting...'");
1086
+ process.stderr.write(`
1087
+ [cloud-init ${Math.round(elapsed / 1e3)}s] ${stdout.trim().slice(0, 120)}
1088
+ `);
1089
+ } catch {
1090
+ }
1091
+ }
1092
+ await new Promise((r) => setTimeout(r, 2e4));
1053
1093
  }
1054
1094
  return false;
1055
1095
  }
@@ -1076,17 +1116,19 @@ async function installCloudflared(sshPort, arch) {
1076
1116
  }
1077
1117
  async function startTunnel(sshPort) {
1078
1118
  await sshExec(sshPort, [
1079
- "nohup cloudflared tunnel --url http://localhost:4200",
1080
- "> /tmp/tunnel.log 2>&1 &",
1119
+ "install -m 600 /dev/null /home/nexus/.nexus/tunnel.log",
1120
+ "&& nohup cloudflared tunnel --no-autoupdate --url http://localhost:4200",
1121
+ "> /home/nexus/.nexus/tunnel.log 2>&1 &",
1081
1122
  "disown"
1082
1123
  ].join(" "));
1083
1124
  const start = Date.now();
1084
- while (Date.now() - start < 3e4) {
1125
+ while (Date.now() - start < 6e4) {
1085
1126
  try {
1086
- const { stdout } = await sshExec(sshPort, "grep -o 'https://[^ ]*\\.trycloudflare\\.com' /tmp/tunnel.log 2>/dev/null | head -1");
1127
+ const { stdout } = await sshExec(sshPort, "grep -oE 'https://[a-z0-9-]+\\.trycloudflare\\.com' /home/nexus/.nexus/tunnel.log 2>/dev/null | head -1");
1087
1128
  if (stdout.includes("https://")) {
1088
1129
  const url = stdout.trim();
1089
1130
  if (!/^https:\/\/[a-z0-9-]+\.trycloudflare\.com$/.test(url)) {
1131
+ audit("tunnel_url_rejected", `Invalid URL format: ${url.slice(0, 80)}`);
1090
1132
  return null;
1091
1133
  }
1092
1134
  await sshExec(sshPort, shellCommand`printf '%s\n' ${url} > /home/nexus/.nexus/tunnel-url.txt && chmod 600 /home/nexus/.nexus/tunnel-url.txt`);
@@ -1119,176 +1161,281 @@ function getReleaseTarball() {
1119
1161
  if (fs6.existsSync(rootPath)) return rootPath;
1120
1162
  throw new Error("nexus-release.tar.gz not found. Run: npm run bundle");
1121
1163
  }
1122
- var TOTAL_PHASES = 10;
1123
1164
  function getCloudInitTemplate() {
1124
1165
  const dir = path6.dirname(fileURLToPath(import.meta.url));
1125
1166
  const templatePath = path6.join(dir, "templates", "cloud-init.yaml.ejs");
1126
- if (fs6.existsSync(templatePath)) {
1127
- return fs6.readFileSync(templatePath, "utf-8");
1128
- }
1167
+ if (fs6.existsSync(templatePath)) return fs6.readFileSync(templatePath, "utf-8");
1129
1168
  const srcPath = path6.resolve(dir, "..", "src", "templates", "cloud-init.yaml.ejs");
1130
1169
  return fs6.readFileSync(srcPath, "utf-8");
1131
1170
  }
1132
- var initCommand = new Command("init").description("Scaffold and launch a new NEXUS runtime").action(async () => {
1133
- try {
1134
- showBanner();
1135
- showPhase(1, TOTAL_PHASES, "Configuration");
1136
- const platform = detectPlatform();
1137
- log.detail("Platform", `${platform.os} ${platform.arch}`);
1138
- log.detail("QEMU", platform.qemuBinary);
1139
- const userConfig = await promptInitConfig();
1140
- ensureHome();
1141
- const masterSecret = generateMasterSecret();
1142
- const config = {
1143
- vmRam: userConfig.vmRam,
1144
- vmCpus: userConfig.vmCpus,
1145
- vmDisk: userConfig.vmDisk,
1146
- enableTunnel: userConfig.enableTunnel,
1147
- sshPort: 2222,
1148
- httpPort: 4200,
1149
- httpsPort: 8443,
1150
- masterSecret
1151
- };
1152
- const keys = {
1153
- ANTHROPIC_API_KEY: userConfig.anthropicKey,
1154
- OPENAI_API_KEY: userConfig.openaiKey || void 0,
1155
- GOOGLE_API_KEY: userConfig.googleKey || void 0,
1156
- NEXUS_MASTER_SECRET: masterSecret
1157
- };
1158
- const violations = validateAllKeys(keys);
1159
- if (violations.length > 0) {
1160
- for (const v of violations) log.error(v);
1161
- process.exit(1);
1171
+ async function withSpinner(spinner, label, fn) {
1172
+ spinner.text = label;
1173
+ spinner.start();
1174
+ const result = await fn();
1175
+ succeed(spinner, label);
1176
+ return result;
1177
+ }
1178
+ var phases = [
1179
+ // Phase 1 — Configuration
1180
+ {
1181
+ name: "Configuration",
1182
+ run: async (ctx) => {
1183
+ showBanner();
1184
+ const platform = detectPlatform();
1185
+ log.detail("Platform", `${platform.os} ${platform.arch}`);
1186
+ log.detail("QEMU", platform.qemuBinary);
1187
+ const userConfig = await promptInitConfig();
1188
+ ensureHome();
1189
+ const masterSecret = generateMasterSecret();
1190
+ const config = {
1191
+ vmRam: userConfig.vmRam,
1192
+ vmCpus: userConfig.vmCpus,
1193
+ vmDisk: userConfig.vmDisk,
1194
+ enableTunnel: userConfig.enableTunnel,
1195
+ sshPort: 2222,
1196
+ httpPort: 4200,
1197
+ httpsPort: 8443,
1198
+ masterSecret
1199
+ };
1200
+ const keys = {
1201
+ ANTHROPIC_API_KEY: userConfig.anthropicKey,
1202
+ OPENAI_API_KEY: userConfig.openaiKey || void 0,
1203
+ GOOGLE_API_KEY: userConfig.googleKey || void 0,
1204
+ NEXUS_MASTER_SECRET: masterSecret
1205
+ };
1206
+ const violations = validateAllKeys(keys);
1207
+ if (violations.length > 0) {
1208
+ for (const v of violations) log.error(v);
1209
+ process.exit(1);
1210
+ }
1211
+ saveConfig(config);
1212
+ saveKeys(keys);
1213
+ log.success("Configuration saved");
1214
+ ctx.platform = platform;
1215
+ ctx.config = config;
1216
+ ctx.keys = keys;
1162
1217
  }
1163
- saveConfig(config);
1164
- saveKeys(keys);
1165
- log.success("Configuration saved");
1166
- showPhase(2, TOTAL_PHASES, "QEMU Installation");
1167
- let spinner = createSpinner("Checking QEMU...");
1168
- spinner.start();
1169
- const hasQemu = await isQemuInstalled(platform);
1170
- if (hasQemu) {
1171
- succeed(spinner, "QEMU already installed");
1172
- } else {
1173
- spinner.text = "Installing QEMU...";
1174
- await installQemu(platform);
1175
- succeed(spinner, "QEMU installed");
1218
+ },
1219
+ // Phase 2 — QEMU
1220
+ {
1221
+ name: "QEMU Installation",
1222
+ run: async (ctx, spinner) => {
1223
+ const { platform } = ctx;
1224
+ await withSpinner(spinner, "Checking QEMU...", async () => {
1225
+ const hasQemu = await isQemuInstalled(platform);
1226
+ if (!hasQemu) {
1227
+ spinner.text = "Installing QEMU...";
1228
+ await installQemu(platform);
1229
+ }
1230
+ });
1231
+ succeed(spinner, hasQemuLabel(await isQemuInstalled(ctx.platform)));
1176
1232
  }
1177
- showPhase(3, TOTAL_PHASES, "SSH Key Setup");
1178
- spinner = createSpinner("Generating SSH key...");
1179
- spinner.start();
1180
- await generateSshKey();
1181
- addSshConfig(config.sshPort);
1182
- succeed(spinner, "SSH key ready (ed25519)");
1183
- showPhase(4, TOTAL_PHASES, "VM Image Download");
1184
- spinner = createSpinner(`Downloading Ubuntu 24.04 (${platform.ubuntuImage})...`);
1185
- spinner.start();
1186
- const imagePath = await downloadImage(platform);
1187
- succeed(spinner, "Ubuntu image ready");
1188
- showPhase(5, TOTAL_PHASES, "Cloud-Init Generation");
1189
- spinner = createSpinner("Locating release tarball...");
1190
- spinner.start();
1191
- const tarballPath = getReleaseTarball();
1192
- succeed(spinner, `Release tarball found (${path6.basename(tarballPath)})`);
1193
- spinner = createSpinner("Rendering cloud-init...");
1194
- spinner.start();
1195
- const pubKey = getPubKey();
1196
- const template = getCloudInitTemplate();
1197
- const userDataPath = await renderCloudInit({ sshPubKey: pubKey, keys, config }, template);
1198
- const isoPath = await createCloudInitIso(userDataPath);
1199
- succeed(spinner, "Cloud-init ISO created");
1200
- showPhase(6, TOTAL_PHASES, "VM Launch");
1201
- spinner = createSpinner("Checking port availability...");
1202
- spinner.start();
1203
- const requestedPorts = { ssh: config.sshPort, http: config.httpPort, https: config.httpsPort };
1204
- spinner.stop();
1205
- spinner.clear();
1206
- const resolvedPorts = await resolvePortConflicts(requestedPorts);
1207
- spinner = createSpinner("Creating disk and launching VM...");
1208
- spinner.start();
1209
- const diskPath = await createDisk(imagePath, config.vmDisk);
1210
- await launchVm(platform, diskPath, isoPath, config.vmRam, config.vmCpus, resolvedPorts);
1211
- config.sshPort = resolvedPorts.ssh;
1212
- config.httpPort = resolvedPorts.http;
1213
- config.httpsPort = resolvedPorts.https;
1214
- saveConfig(config);
1215
- const portNote = resolvedPorts.ssh !== 2222 || resolvedPorts.http !== 4200 || resolvedPorts.https !== 8443 ? ` (ports: SSH=${resolvedPorts.ssh}, HTTP=${resolvedPorts.http}, HTTPS=${resolvedPorts.https})` : "";
1216
- succeed(spinner, `VM launched (daemonized)${portNote}`);
1217
- showPhase(7, TOTAL_PHASES, "VM Provisioning");
1218
- spinner = createSpinner("Waiting for SSH...");
1219
- spinner.start();
1220
- const sshReady = await waitForSsh(config.sshPort);
1221
- if (!sshReady) {
1222
- fail(spinner, "SSH connection timed out");
1223
- process.exit(1);
1233
+ },
1234
+ // Phase 3 SSH Keys
1235
+ {
1236
+ name: "SSH Key Setup",
1237
+ run: async (ctx, spinner) => {
1238
+ const { config } = ctx;
1239
+ await withSpinner(spinner, "Generating SSH key...", async () => {
1240
+ await generateSshKey();
1241
+ addSshConfig(config.sshPort);
1242
+ });
1224
1243
  }
1225
- succeed(spinner, "SSH connected");
1226
- spinner = createSpinner("Uploading NEXUS release tarball...");
1227
- spinner.start();
1228
- await sshUploadFile(config.sshPort, tarballPath, "/tmp/nexus-release.tar.gz");
1229
- succeed(spinner, "Tarball uploaded");
1230
- spinner = createSpinner("Staging API keys...");
1231
- spinner.start();
1232
- const keysContent = Object.entries(keys).filter(([, v]) => v).map(([k, v]) => `${k}=${v}`).join("\n") + "\n";
1233
- const tmpKeysPath = path6.join(os2.tmpdir(), `.nexus-keys-${crypto4.randomBytes(8).toString("hex")}`);
1234
- fs6.writeFileSync(tmpKeysPath, keysContent, { mode: 384 });
1235
- try {
1236
- await sshUploadFile(config.sshPort, tmpKeysPath, "/tmp/.nexus-env-keys");
1237
- await sshExec(config.sshPort, "chmod 600 /tmp/.nexus-env-keys");
1238
- } finally {
1239
- try {
1240
- fs6.writeFileSync(tmpKeysPath, "0".repeat(keysContent.length));
1241
- fs6.unlinkSync(tmpKeysPath);
1242
- } catch {
1243
- }
1244
+ },
1245
+ // Phase 4 Ubuntu Image
1246
+ {
1247
+ name: "VM Image Download",
1248
+ run: async (ctx, spinner) => {
1249
+ const { platform } = ctx;
1250
+ const imagePath = await withSpinner(
1251
+ spinner,
1252
+ `Downloading Ubuntu 24.04 (${platform.ubuntuImage})...`,
1253
+ () => downloadImage(platform)
1254
+ );
1255
+ ctx.imagePath = imagePath;
1244
1256
  }
1245
- succeed(spinner, "API keys staged");
1246
- spinner = createSpinner("Cloud-init provisioning (extracting NEXUS, building Docker, installing deps)...");
1247
- spinner.start();
1248
- const cloudInitDone = await waitForCloudInit(config.sshPort);
1249
- if (!cloudInitDone) {
1250
- fail(spinner, "Cloud-init timed out");
1251
- log.warn("You can check progress with: buildwithnexus ssh then: tail -f /var/log/cloud-init-output.log");
1252
- process.exit(1);
1257
+ },
1258
+ // Phase 5 — Cloud-Init
1259
+ {
1260
+ name: "Cloud-Init Generation",
1261
+ run: async (ctx, spinner) => {
1262
+ const { keys, config } = ctx;
1263
+ const tarballPath = await withSpinner(spinner, "Locating release tarball...", async () => {
1264
+ return getReleaseTarball();
1265
+ });
1266
+ ctx.tarballPath = tarballPath;
1267
+ const isoPath = await withSpinner(spinner, "Rendering cloud-init...", async () => {
1268
+ const pubKey = getPubKey();
1269
+ const template = getCloudInitTemplate();
1270
+ const userDataPath = await renderCloudInit({ sshPubKey: pubKey, keys, config }, template);
1271
+ return createCloudInitIso(userDataPath);
1272
+ });
1273
+ ctx.isoPath = isoPath;
1253
1274
  }
1254
- succeed(spinner, "VM fully provisioned");
1255
- spinner = createSpinner("Delivering API keys...");
1256
- spinner.start();
1257
- await sshExec(config.sshPort, "mkdir -p /home/nexus/.nexus && mv /tmp/.nexus-env-keys /home/nexus/.nexus/.env.keys && chown -R nexus:nexus /home/nexus/.nexus && chmod 600 /home/nexus/.nexus/.env.keys");
1258
- succeed(spinner, "API keys delivered securely");
1259
- showPhase(8, TOTAL_PHASES, "NEXUS Server Startup");
1260
- spinner = createSpinner("Waiting for NEXUS server...");
1261
- spinner.start();
1262
- const serverReady = await waitForServer(config.sshPort);
1263
- if (!serverReady) {
1264
- fail(spinner, "Server failed to start");
1265
- log.warn("Check logs: buildwithnexus logs");
1266
- process.exit(1);
1275
+ },
1276
+ // Phase 6 VM Boot
1277
+ {
1278
+ name: "VM Launch",
1279
+ run: async (ctx, spinner) => {
1280
+ const { platform, imagePath, isoPath, config } = ctx;
1281
+ spinner.text = "Checking port availability...";
1282
+ spinner.start();
1283
+ spinner.stop();
1284
+ spinner.clear();
1285
+ const requestedPorts = { ssh: config.sshPort, http: config.httpPort, https: config.httpsPort };
1286
+ const resolvedPorts = await resolvePortConflicts(requestedPorts);
1287
+ const diskPath = await withSpinner(spinner, "Creating disk and launching VM...", async () => {
1288
+ const disk = await createDisk(imagePath, config.vmDisk);
1289
+ await launchVm(platform, disk, isoPath, config.vmRam, config.vmCpus, resolvedPorts);
1290
+ return disk;
1291
+ });
1292
+ config.sshPort = resolvedPorts.ssh;
1293
+ config.httpPort = resolvedPorts.http;
1294
+ config.httpsPort = resolvedPorts.https;
1295
+ saveConfig(config);
1296
+ const portNote = resolvedPorts.ssh !== 2222 || resolvedPorts.http !== 4200 || resolvedPorts.https !== 8443 ? ` (ports: SSH=${resolvedPorts.ssh}, HTTP=${resolvedPorts.http}, HTTPS=${resolvedPorts.https})` : "";
1297
+ succeed(spinner, `VM launched (daemonized)${portNote}`);
1298
+ ctx.diskPath = diskPath;
1299
+ ctx.resolvedPorts = resolvedPorts;
1300
+ ctx.vmLaunched = true;
1267
1301
  }
1268
- succeed(spinner, "NEXUS server healthy on port 4200");
1269
- let tunnelUrl;
1270
- if (config.enableTunnel) {
1271
- showPhase(9, TOTAL_PHASES, "Cloudflare Tunnel");
1272
- spinner = createSpinner("Installing cloudflared...");
1302
+ },
1303
+ // Phase 7 — VM Provisioning
1304
+ {
1305
+ name: "VM Provisioning",
1306
+ run: async (ctx, spinner) => {
1307
+ const { config, keys, tarballPath } = ctx;
1308
+ spinner.text = "Waiting for SSH...";
1309
+ spinner.start();
1310
+ const sshReady = await waitForSsh(config.sshPort);
1311
+ if (!sshReady) {
1312
+ fail(spinner, "SSH connection timed out");
1313
+ throw new Error("SSH connection timed out");
1314
+ }
1315
+ succeed(spinner, "SSH connected");
1316
+ await withSpinner(
1317
+ spinner,
1318
+ "Uploading NEXUS release tarball...",
1319
+ () => sshUploadFile(config.sshPort, tarballPath, "/tmp/nexus-release.tar.gz")
1320
+ );
1321
+ await withSpinner(spinner, "Staging API keys...", async () => {
1322
+ const keysContent = Object.entries(keys).filter(([, v]) => v).map(([k, v]) => `${k}=${v}`).join("\n") + "\n";
1323
+ const tmpKeysPath = path6.join(os2.tmpdir(), `.nexus-keys-${crypto4.randomBytes(8).toString("hex")}`);
1324
+ fs6.writeFileSync(tmpKeysPath, keysContent, { mode: 384 });
1325
+ try {
1326
+ await sshUploadFile(config.sshPort, tmpKeysPath, "/tmp/.nexus-env-keys");
1327
+ await sshExec(config.sshPort, "chmod 600 /tmp/.nexus-env-keys");
1328
+ } finally {
1329
+ try {
1330
+ fs6.writeFileSync(tmpKeysPath, "0".repeat(keysContent.length));
1331
+ fs6.unlinkSync(tmpKeysPath);
1332
+ } catch {
1333
+ }
1334
+ }
1335
+ });
1336
+ spinner.text = "Cloud-init provisioning \u2014 this takes 10-20 min (extracting NEXUS, building Docker, installing deps)...";
1337
+ spinner.start();
1338
+ const cloudInitDone = await waitForCloudInit(config.sshPort);
1339
+ if (!cloudInitDone) {
1340
+ fail(spinner, "Cloud-init timed out after 30 minutes");
1341
+ log.warn("Check progress: buildwithnexus ssh \u2192 tail -f /var/log/cloud-init-output.log");
1342
+ throw new Error("Cloud-init timed out");
1343
+ }
1344
+ succeed(spinner, "VM fully provisioned");
1345
+ await withSpinner(
1346
+ spinner,
1347
+ "Delivering API keys...",
1348
+ () => sshExec(
1349
+ config.sshPort,
1350
+ "mkdir -p /home/nexus/.nexus && mv /tmp/.nexus-env-keys /home/nexus/.nexus/.env.keys && chown -R nexus:nexus /home/nexus/.nexus && chmod 600 /home/nexus/.nexus/.env.keys"
1351
+ )
1352
+ );
1353
+ }
1354
+ },
1355
+ // Phase 8 — Server Health
1356
+ {
1357
+ name: "NEXUS Server Startup",
1358
+ run: async (ctx, spinner) => {
1359
+ const { config } = ctx;
1360
+ spinner.text = "Waiting for NEXUS server...";
1273
1361
  spinner.start();
1274
- await installCloudflared(config.sshPort, platform.arch);
1362
+ const serverReady = await waitForServer(config.sshPort);
1363
+ if (!serverReady) {
1364
+ fail(spinner, "Server failed to start");
1365
+ log.warn("Check logs: buildwithnexus logs");
1366
+ throw new Error("NEXUS server failed to start");
1367
+ }
1368
+ succeed(spinner, "NEXUS server healthy on port 4200");
1369
+ }
1370
+ },
1371
+ // Phase 9 — Cloudflare Tunnel
1372
+ {
1373
+ name: "Cloudflare Tunnel",
1374
+ run: async (ctx, spinner) => {
1375
+ const { config, platform } = ctx;
1376
+ if (!config.enableTunnel) {
1377
+ log.dim("Skipped (not enabled)");
1378
+ return;
1379
+ }
1380
+ await withSpinner(
1381
+ spinner,
1382
+ "Installing cloudflared...",
1383
+ () => installCloudflared(config.sshPort, platform.arch)
1384
+ );
1275
1385
  spinner.text = "Starting tunnel...";
1386
+ spinner.start();
1276
1387
  const url = await startTunnel(config.sshPort);
1277
1388
  if (url) {
1278
- tunnelUrl = url;
1389
+ ctx.tunnelUrl = url;
1279
1390
  succeed(spinner, `Tunnel active: ${url}`);
1280
1391
  } else {
1281
1392
  fail(spinner, "Tunnel failed to start (server still accessible locally)");
1282
1393
  }
1283
- } else {
1284
- showPhase(9, TOTAL_PHASES, "Cloudflare Tunnel");
1285
- log.dim("Skipped (not enabled)");
1286
1394
  }
1287
- showPhase(10, TOTAL_PHASES, "Complete");
1288
- showCompletion({
1289
- remote: tunnelUrl,
1290
- ssh: "buildwithnexus ssh"
1291
- });
1395
+ },
1396
+ // Phase 10 — Complete
1397
+ {
1398
+ name: "Complete",
1399
+ run: async (ctx) => {
1400
+ showCompletion({ remote: ctx.tunnelUrl, ssh: "buildwithnexus ssh" });
1401
+ }
1402
+ }
1403
+ ];
1404
+ function hasQemuLabel(installed) {
1405
+ return installed ? "QEMU ready" : "QEMU installed";
1406
+ }
1407
+ var TOTAL_PHASES = phases.length;
1408
+ async function runInit() {
1409
+ const ctx = { vmLaunched: false, tunnelUrl: void 0 };
1410
+ const spinner = createSpinner("");
1411
+ for (let i = 0; i < phases.length; i++) {
1412
+ const phase = phases[i];
1413
+ showPhase(i + 1, TOTAL_PHASES, phase.name);
1414
+ if (phase.skip?.(ctx)) {
1415
+ log.dim("Skipped");
1416
+ continue;
1417
+ }
1418
+ try {
1419
+ await phase.run(ctx, spinner);
1420
+ } catch (err) {
1421
+ try {
1422
+ spinner.stop();
1423
+ } catch {
1424
+ }
1425
+ if (ctx.vmLaunched) {
1426
+ process.stderr.write(chalk6.dim("\n Stopping VM due to init failure...\n"));
1427
+ try {
1428
+ stopVm();
1429
+ } catch {
1430
+ }
1431
+ }
1432
+ throw err;
1433
+ }
1434
+ }
1435
+ }
1436
+ var initCommand = new Command("init").description("Scaffold and launch a new NEXUS runtime").action(async () => {
1437
+ try {
1438
+ await runInit();
1292
1439
  } catch (err) {
1293
1440
  const safeErr = redactError(err);
1294
1441
  log.error(`Init failed: ${safeErr.message}`);
@@ -1394,7 +1541,7 @@ var stopCommand = new Command3("stop").description("Gracefully shut down the NEX
1394
1541
 
1395
1542
  // src/commands/status.ts
1396
1543
  import { Command as Command4 } from "commander";
1397
- import chalk6 from "chalk";
1544
+ import chalk7 from "chalk";
1398
1545
  init_secrets();
1399
1546
  init_qemu();
1400
1547
  var statusCommand = new Command4("status").description("Check NEXUS runtime health").option("--json", "Output as JSON").action(async (opts) => {
@@ -1409,15 +1556,15 @@ var statusCommand = new Command4("status").description("Check NEXUS runtime heal
1409
1556
  console.log(JSON.stringify({ ...health, pid: getVmPid(), ports: { ssh: config.sshPort, http: config.httpPort, https: config.httpsPort } }, null, 2));
1410
1557
  return;
1411
1558
  }
1412
- const check = (ok) => ok ? chalk6.green("\u25CF") : chalk6.red("\u25CB");
1559
+ const check = (ok) => ok ? chalk7.green("\u25CF") : chalk7.red("\u25CB");
1413
1560
  console.log("");
1414
- console.log(chalk6.bold(" NEXUS Runtime Status"));
1561
+ console.log(chalk7.bold(" NEXUS Runtime Status"));
1415
1562
  console.log("");
1416
- console.log(` ${check(health.vmRunning)} VM ${health.vmRunning ? chalk6.green("running") + chalk6.dim(` (PID ${getVmPid()})`) : chalk6.red("stopped")}`);
1417
- console.log(` ${check(health.sshReady)} SSH ${health.sshReady ? chalk6.green("connected") + chalk6.dim(` (port ${config.sshPort})`) : chalk6.red("unreachable")}`);
1418
- console.log(` ${check(health.dockerReady)} Docker ${health.dockerReady ? chalk6.green("ready") : chalk6.red("not ready")}`);
1419
- console.log(` ${check(health.serverHealthy)} Server ${health.serverHealthy ? chalk6.green("healthy") + chalk6.dim(` (port ${config.httpPort})`) : chalk6.red("unhealthy")}`);
1420
- console.log(` ${check(!!health.tunnelUrl)} Tunnel ${health.tunnelUrl ? chalk6.green(health.tunnelUrl) : chalk6.dim("not active")}`);
1563
+ console.log(` ${check(health.vmRunning)} VM ${health.vmRunning ? chalk7.green("running") + chalk7.dim(` (PID ${getVmPid()})`) : chalk7.red("stopped")}`);
1564
+ console.log(` ${check(health.sshReady)} SSH ${health.sshReady ? chalk7.green("connected") + chalk7.dim(` (port ${config.sshPort})`) : chalk7.red("unreachable")}`);
1565
+ console.log(` ${check(health.dockerReady)} Docker ${health.dockerReady ? chalk7.green("ready") : chalk7.red("not ready")}`);
1566
+ console.log(` ${check(health.serverHealthy)} Server ${health.serverHealthy ? chalk7.green("healthy") + chalk7.dim(` (port ${config.httpPort})`) : chalk7.red("unhealthy")}`);
1567
+ console.log(` ${check(!!health.tunnelUrl)} Tunnel ${health.tunnelUrl ? chalk7.green(health.tunnelUrl) : chalk7.dim("not active")}`);
1421
1568
  console.log("");
1422
1569
  if (health.serverHealthy) {
1423
1570
  log.success(`NEXUS CLI ready \u2014 connect via: buildwithnexus ssh`);
@@ -1426,7 +1573,7 @@ var statusCommand = new Command4("status").description("Check NEXUS runtime heal
1426
1573
 
1427
1574
  // src/commands/doctor.ts
1428
1575
  import { Command as Command5 } from "commander";
1429
- import chalk7 from "chalk";
1576
+ import chalk8 from "chalk";
1430
1577
  import fs7 from "fs";
1431
1578
  init_qemu();
1432
1579
  init_secrets();
@@ -1434,12 +1581,12 @@ import path8 from "path";
1434
1581
  import { execa as execa4 } from "execa";
1435
1582
  var doctorCommand = new Command5("doctor").description("Diagnose NEXUS runtime environment").action(async () => {
1436
1583
  const platform = detectPlatform();
1437
- const check = (ok) => ok ? chalk7.green("\u2713") : chalk7.red("\u2717");
1584
+ const check = (ok) => ok ? chalk8.green("\u2713") : chalk8.red("\u2717");
1438
1585
  console.log("");
1439
- console.log(chalk7.bold(" NEXUS Doctor"));
1586
+ console.log(chalk8.bold(" NEXUS Doctor"));
1440
1587
  console.log("");
1441
1588
  const nodeOk = Number(process.versions.node.split(".")[0]) >= 18;
1442
- console.log(` ${check(nodeOk)} Node.js ${process.versions.node} ${nodeOk ? "" : chalk7.red("(need >= 18)")}`);
1589
+ console.log(` ${check(nodeOk)} Node.js ${process.versions.node} ${nodeOk ? "" : chalk8.red("(need >= 18)")}`);
1443
1590
  console.log(` ${check(true)} Platform: ${platform.os} ${platform.arch}`);
1444
1591
  const qemuOk = await isQemuInstalled(platform);
1445
1592
  if (qemuOk) {
@@ -1479,14 +1626,14 @@ var doctorCommand = new Command5("doctor").description("Diagnose NEXUS runtime e
1479
1626
  });
1480
1627
  server.listen(port);
1481
1628
  });
1482
- console.log(` ${check(available)} Port ${port} (${name}) ${available ? "available" : chalk7.red("in use")}`);
1629
+ console.log(` ${check(available)} Port ${port} (${name}) ${available ? "available" : chalk8.red("in use")}`);
1483
1630
  } catch {
1484
1631
  console.log(` ${check(false)} Port ${port} (${name}) \u2014 check failed`);
1485
1632
  }
1486
1633
  }
1487
1634
  }
1488
1635
  const biosOk = fs7.existsSync(platform.biosPath);
1489
- console.log(` ${check(biosOk)} UEFI firmware ${biosOk ? "" : chalk7.dim(platform.biosPath)}`);
1636
+ console.log(` ${check(biosOk)} UEFI firmware ${biosOk ? "" : chalk8.dim(platform.biosPath)}`);
1490
1637
  console.log("");
1491
1638
  if (qemuOk && isoTool && biosOk) {
1492
1639
  log.success("Environment ready for NEXUS");
@@ -1597,7 +1744,7 @@ var updateCommand = new Command7("update").description("Update NEXUS to the late
1597
1744
 
1598
1745
  // src/commands/destroy.ts
1599
1746
  import { Command as Command8 } from "commander";
1600
- import chalk8 from "chalk";
1747
+ import chalk9 from "chalk";
1601
1748
  import fs9 from "fs";
1602
1749
  import { input as input2 } from "@inquirer/prompts";
1603
1750
  init_secrets();
@@ -1607,11 +1754,11 @@ var destroyCommand = new Command8("destroy").description("Remove NEXUS VM and al
1607
1754
  const config = loadConfig();
1608
1755
  if (!opts.force) {
1609
1756
  console.log("");
1610
- console.log(chalk8.red.bold(" This will permanently delete:"));
1611
- console.log(chalk8.red(" - NEXUS VM and all data inside it"));
1612
- console.log(chalk8.red(" - VM disk images"));
1613
- console.log(chalk8.red(" - SSH keys"));
1614
- console.log(chalk8.red(" - Configuration and API keys"));
1757
+ console.log(chalk9.red.bold(" This will permanently delete:"));
1758
+ console.log(chalk9.red(" - NEXUS VM and all data inside it"));
1759
+ console.log(chalk9.red(" - VM disk images"));
1760
+ console.log(chalk9.red(" - SSH keys"));
1761
+ console.log(chalk9.red(" - Configuration and API keys"));
1615
1762
  console.log("");
1616
1763
  const confirm2 = await input2({
1617
1764
  message: 'Type "destroy" to confirm:'
@@ -1655,7 +1802,7 @@ var destroyCommand = new Command8("destroy").description("Remove NEXUS VM and al
1655
1802
  // src/commands/keys.ts
1656
1803
  import { Command as Command9 } from "commander";
1657
1804
  import { password as password2 } from "@inquirer/prompts";
1658
- import chalk9 from "chalk";
1805
+ import chalk10 from "chalk";
1659
1806
  init_secrets();
1660
1807
  init_dlp();
1661
1808
  var keysCommand = new Command9("keys").description("Manage API keys");
@@ -1665,10 +1812,10 @@ keysCommand.command("list").description("Show configured API keys (masked)").act
1665
1812
  log.error("No keys configured. Run: buildwithnexus init");
1666
1813
  process.exit(1);
1667
1814
  }
1668
- console.log(chalk9.bold("\n Configured Keys\n"));
1815
+ console.log(chalk10.bold("\n Configured Keys\n"));
1669
1816
  for (const [name, value] of Object.entries(keys)) {
1670
1817
  if (value) {
1671
- console.log(` ${chalk9.cyan(name.padEnd(24))} ${maskKey(value)}`);
1818
+ console.log(` ${chalk10.cyan(name.padEnd(24))} ${maskKey(value)}`);
1672
1819
  }
1673
1820
  }
1674
1821
  console.log("");
@@ -1733,18 +1880,18 @@ var sshCommand = new Command10("ssh").description("Open an SSH session into the
1733
1880
 
1734
1881
  // src/commands/brainstorm.ts
1735
1882
  import { Command as Command11 } from "commander";
1736
- import chalk10 from "chalk";
1883
+ import chalk11 from "chalk";
1737
1884
  import { input as input3 } from "@inquirer/prompts";
1738
1885
  init_secrets();
1739
1886
  init_qemu();
1740
1887
  init_ssh();
1741
1888
  init_dlp();
1742
- var COS_PREFIX = chalk10.bold.cyan(" Chief of Staff");
1743
- var YOU_PREFIX = chalk10.bold.white(" You");
1744
- var DIVIDER = chalk10.dim(" " + "\u2500".repeat(56));
1889
+ var COS_PREFIX = chalk11.bold.cyan(" Chief of Staff");
1890
+ var YOU_PREFIX = chalk11.bold.white(" You");
1891
+ var DIVIDER = chalk11.dim(" " + "\u2500".repeat(56));
1745
1892
  function formatResponse(text) {
1746
1893
  const lines = text.split("\n");
1747
- return lines.map((line) => chalk10.white(" " + line)).join("\n");
1894
+ return lines.map((line) => chalk11.white(" " + line)).join("\n");
1748
1895
  }
1749
1896
  async function sendMessage(sshPort, message, source) {
1750
1897
  const payload = JSON.stringify({ message, source });
@@ -1787,13 +1934,13 @@ var brainstormCommand = new Command11("brainstorm").description("Brainstorm an i
1787
1934
  }
1788
1935
  succeed(spinner, "Connected to NEXUS");
1789
1936
  console.log("");
1790
- console.log(chalk10.bold(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
1791
- console.log(chalk10.bold(" \u2551 ") + chalk10.bold.cyan("NEXUS Brainstorm Session") + chalk10.bold(" \u2551"));
1792
- console.log(chalk10.bold(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
1793
- console.log(chalk10.bold(" \u2551 ") + chalk10.dim("The Chief of Staff will discuss your idea with the".padEnd(55)) + chalk10.bold("\u2551"));
1794
- console.log(chalk10.bold(" \u2551 ") + chalk10.dim("NEXUS team and share their recommendations.".padEnd(55)) + chalk10.bold("\u2551"));
1795
- console.log(chalk10.bold(" \u2551 ") + chalk10.dim("Type 'exit' or 'quit' to end the session.".padEnd(55)) + chalk10.bold("\u2551"));
1796
- console.log(chalk10.bold(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
1937
+ console.log(chalk11.bold(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
1938
+ console.log(chalk11.bold(" \u2551 ") + chalk11.bold.cyan("NEXUS Brainstorm Session") + chalk11.bold(" \u2551"));
1939
+ console.log(chalk11.bold(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
1940
+ console.log(chalk11.bold(" \u2551 ") + chalk11.dim("The Chief of Staff will discuss your idea with the".padEnd(55)) + chalk11.bold("\u2551"));
1941
+ console.log(chalk11.bold(" \u2551 ") + chalk11.dim("NEXUS team and share their recommendations.".padEnd(55)) + chalk11.bold("\u2551"));
1942
+ console.log(chalk11.bold(" \u2551 ") + chalk11.dim("Type 'exit' or 'quit' to end the session.".padEnd(55)) + chalk11.bold("\u2551"));
1943
+ console.log(chalk11.bold(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
1797
1944
  console.log("");
1798
1945
  let idea = ideaWords.length > 0 ? ideaWords.join(" ") : "";
1799
1946
  if (!idea) {
@@ -1810,7 +1957,7 @@ var brainstormCommand = new Command11("brainstorm").description("Brainstorm an i
1810
1957
  while (true) {
1811
1958
  turn++;
1812
1959
  if (turn === 1) {
1813
- console.log(`${YOU_PREFIX}: ${chalk10.white(idea)}`);
1960
+ console.log(`${YOU_PREFIX}: ${chalk11.white(idea)}`);
1814
1961
  }
1815
1962
  console.log(DIVIDER);
1816
1963
  const thinking = createSpinner(
@@ -1828,17 +1975,17 @@ var brainstormCommand = new Command11("brainstorm").description("Brainstorm an i
1828
1975
  console.log(formatResponse(redact(response)));
1829
1976
  console.log(DIVIDER);
1830
1977
  const followUp = await input3({
1831
- message: chalk10.bold("You:")
1978
+ message: chalk11.bold("You:")
1832
1979
  });
1833
1980
  const trimmed = followUp.trim().toLowerCase();
1834
1981
  if (!trimmed || trimmed === "exit" || trimmed === "quit" || trimmed === "q") {
1835
1982
  console.log("");
1836
1983
  log.success("Brainstorm session ended");
1837
- console.log(chalk10.dim(" Run again anytime: buildwithnexus brainstorm"));
1984
+ console.log(chalk11.dim(" Run again anytime: buildwithnexus brainstorm"));
1838
1985
  console.log("");
1839
1986
  return;
1840
1987
  }
1841
- console.log(`${YOU_PREFIX}: ${chalk10.white(followUp)}`);
1988
+ console.log(`${YOU_PREFIX}: ${chalk11.white(followUp)}`);
1842
1989
  currentMessage = `[BRAINSTORM FOLLOW-UP] The CEO responds: ${followUp}`;
1843
1990
  }
1844
1991
  } catch (err) {
@@ -1855,18 +2002,18 @@ var brainstormCommand = new Command11("brainstorm").description("Brainstorm an i
1855
2002
 
1856
2003
  // src/commands/ninety-nine.ts
1857
2004
  import { Command as Command12 } from "commander";
1858
- import chalk11 from "chalk";
2005
+ import chalk12 from "chalk";
1859
2006
  import { input as input4 } from "@inquirer/prompts";
1860
2007
  init_secrets();
1861
2008
  init_qemu();
1862
2009
  init_ssh();
1863
2010
  init_dlp();
1864
- var AGENT_PREFIX = chalk11.bold.green(" 99 \u276F");
1865
- var YOU_PREFIX2 = chalk11.bold.white(" You");
1866
- var DIVIDER2 = chalk11.dim(" " + "\u2500".repeat(56));
2011
+ var AGENT_PREFIX = chalk12.bold.green(" 99 \u276F");
2012
+ var YOU_PREFIX2 = chalk12.bold.white(" You");
2013
+ var DIVIDER2 = chalk12.dim(" " + "\u2500".repeat(56));
1867
2014
  function formatAgentActivity(text) {
1868
2015
  const lines = text.split("\n");
1869
- return lines.map((line) => chalk11.white(" " + line)).join("\n");
2016
+ return lines.map((line) => chalk12.white(" " + line)).join("\n");
1870
2017
  }
1871
2018
  function parsePrefixes(instruction) {
1872
2019
  const files = [];
@@ -1930,14 +2077,14 @@ var ninetyNineCommand = new Command12("99").description("AI pair-programming ses
1930
2077
  }
1931
2078
  succeed(spinner, "Connected to NEXUS");
1932
2079
  console.log("");
1933
- console.log(chalk11.bold(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
1934
- console.log(chalk11.bold(" \u2551 ") + chalk11.bold.green("/99 Pair Programming") + chalk11.dim(" \u2014 powered by NEXUS") + chalk11.bold(" \u2551"));
1935
- console.log(chalk11.bold(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
1936
- console.log(chalk11.bold(" \u2551 ") + chalk11.dim("Describe what you want changed. NEXUS engineers".padEnd(55)) + chalk11.bold("\u2551"));
1937
- console.log(chalk11.bold(" \u2551 ") + chalk11.dim("analyze and modify your code in real time.".padEnd(55)) + chalk11.bold("\u2551"));
1938
- console.log(chalk11.bold(" \u2551 ") + chalk11.dim("Use @file to attach context, #rule to load rules.".padEnd(55)) + chalk11.bold("\u2551"));
1939
- console.log(chalk11.bold(" \u2551 ") + chalk11.dim("Type 'exit' or 'quit' to end the session.".padEnd(55)) + chalk11.bold("\u2551"));
1940
- console.log(chalk11.bold(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2080
+ console.log(chalk12.bold(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2081
+ console.log(chalk12.bold(" \u2551 ") + chalk12.bold.green("/99 Pair Programming") + chalk12.dim(" \u2014 powered by NEXUS") + chalk12.bold(" \u2551"));
2082
+ console.log(chalk12.bold(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
2083
+ console.log(chalk12.bold(" \u2551 ") + chalk12.dim("Describe what you want changed. NEXUS engineers".padEnd(55)) + chalk12.bold("\u2551"));
2084
+ console.log(chalk12.bold(" \u2551 ") + chalk12.dim("analyze and modify your code in real time.".padEnd(55)) + chalk12.bold("\u2551"));
2085
+ console.log(chalk12.bold(" \u2551 ") + chalk12.dim("Use @file to attach context, #rule to load rules.".padEnd(55)) + chalk12.bold("\u2551"));
2086
+ console.log(chalk12.bold(" \u2551 ") + chalk12.dim("Type 'exit' or 'quit' to end the session.".padEnd(55)) + chalk12.bold("\u2551"));
2087
+ console.log(chalk12.bold(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
1941
2088
  console.log("");
1942
2089
  const cwd = process.cwd();
1943
2090
  if (opts.edit) {
@@ -1946,7 +2093,7 @@ var ninetyNineCommand = new Command12("99").description("AI pair-programming ses
1946
2093
  });
1947
2094
  const { cleaned, files, rules } = parsePrefixes(instruction);
1948
2095
  const fullInstruction = `Edit file ${opts.edit}: ${cleaned}`;
1949
- console.log(`${YOU_PREFIX2}: ${chalk11.white(fullInstruction)}`);
2096
+ console.log(`${YOU_PREFIX2}: ${chalk12.white(fullInstruction)}`);
1950
2097
  console.log(DIVIDER2);
1951
2098
  const thinking = createSpinner("NEXUS engineers analyzing the file...");
1952
2099
  thinking.start();
@@ -1960,7 +2107,7 @@ var ninetyNineCommand = new Command12("99").description("AI pair-programming ses
1960
2107
  }
1961
2108
  if (opts.search) {
1962
2109
  const fullInstruction = `Search the codebase for: ${opts.search}`;
1963
- console.log(`${YOU_PREFIX2}: ${chalk11.white(fullInstruction)}`);
2110
+ console.log(`${YOU_PREFIX2}: ${chalk12.white(fullInstruction)}`);
1964
2111
  console.log(DIVIDER2);
1965
2112
  const thinking = createSpinner("Searching with NEXUS context...");
1966
2113
  thinking.start();
@@ -1974,7 +2121,7 @@ var ninetyNineCommand = new Command12("99").description("AI pair-programming ses
1974
2121
  }
1975
2122
  if (opts.debug) {
1976
2123
  const fullInstruction = "Debug the current issue \u2014 analyze recent errors, identify the root cause, and propose a fix";
1977
- console.log(`${YOU_PREFIX2}: ${chalk11.white(fullInstruction)}`);
2124
+ console.log(`${YOU_PREFIX2}: ${chalk12.white(fullInstruction)}`);
1978
2125
  console.log(DIVIDER2);
1979
2126
  const thinking = createSpinner("NEXUS debugger agent analyzing...");
1980
2127
  thinking.start();
@@ -1989,7 +2136,7 @@ var ninetyNineCommand = new Command12("99").description("AI pair-programming ses
1989
2136
  let initialInstruction = instructionWords.length > 0 ? instructionWords.join(" ") : "";
1990
2137
  if (!initialInstruction) {
1991
2138
  initialInstruction = await input4({
1992
- message: chalk11.green("99 \u276F")
2139
+ message: chalk12.green("99 \u276F")
1993
2140
  });
1994
2141
  if (!initialInstruction.trim()) {
1995
2142
  log.warn("No instruction provided");
@@ -2004,13 +2151,13 @@ var ninetyNineCommand = new Command12("99").description("AI pair-programming ses
2004
2151
  const display = currentInstruction;
2005
2152
  const nexusInstruction = cleaned || currentInstruction;
2006
2153
  if (turn === 1) {
2007
- console.log(`${YOU_PREFIX2}: ${chalk11.white(display)}`);
2154
+ console.log(`${YOU_PREFIX2}: ${chalk12.white(display)}`);
2008
2155
  }
2009
2156
  if (files.length > 0) {
2010
- console.log(chalk11.dim(` Attaching: ${files.join(", ")}`));
2157
+ console.log(chalk12.dim(` Attaching: ${files.join(", ")}`));
2011
2158
  }
2012
2159
  if (rules.length > 0) {
2013
- console.log(chalk11.dim(` Rules: ${rules.join(", ")}`));
2160
+ console.log(chalk12.dim(` Rules: ${rules.join(", ")}`));
2014
2161
  }
2015
2162
  console.log(DIVIDER2);
2016
2163
  const thinking = createSpinner(
@@ -2024,17 +2171,17 @@ var ninetyNineCommand = new Command12("99").description("AI pair-programming ses
2024
2171
  console.log(formatAgentActivity(redact(response)));
2025
2172
  console.log(DIVIDER2);
2026
2173
  const followUp = await input4({
2027
- message: chalk11.green("99 \u276F")
2174
+ message: chalk12.green("99 \u276F")
2028
2175
  });
2029
2176
  const trimmed = followUp.trim().toLowerCase();
2030
2177
  if (!trimmed || trimmed === "exit" || trimmed === "quit" || trimmed === "q") {
2031
2178
  console.log("");
2032
2179
  log.success("/99 session ended");
2033
- console.log(chalk11.dim(" Run again: buildwithnexus 99"));
2180
+ console.log(chalk12.dim(" Run again: buildwithnexus 99"));
2034
2181
  console.log("");
2035
2182
  return;
2036
2183
  }
2037
- console.log(`${YOU_PREFIX2}: ${chalk11.white(followUp)}`);
2184
+ console.log(`${YOU_PREFIX2}: ${chalk12.white(followUp)}`);
2038
2185
  currentInstruction = followUp;
2039
2186
  }
2040
2187
  } catch (err) {
@@ -2051,7 +2198,7 @@ var ninetyNineCommand = new Command12("99").description("AI pair-programming ses
2051
2198
 
2052
2199
  // src/commands/shell.ts
2053
2200
  import { Command as Command13 } from "commander";
2054
- import chalk14 from "chalk";
2201
+ import chalk15 from "chalk";
2055
2202
  init_secrets();
2056
2203
  init_qemu();
2057
2204
  init_ssh();
@@ -2062,7 +2209,7 @@ init_secrets();
2062
2209
  import readline from "readline";
2063
2210
  import fs10 from "fs";
2064
2211
  import path11 from "path";
2065
- import chalk12 from "chalk";
2212
+ import chalk13 from "chalk";
2066
2213
  var HISTORY_FILE = path11.join(NEXUS_HOME2, "shell_history");
2067
2214
  var MAX_HISTORY = 1e3;
2068
2215
  var Repl = class {
@@ -2097,7 +2244,7 @@ var Repl = class {
2097
2244
  this.rl = readline.createInterface({
2098
2245
  input: process.stdin,
2099
2246
  output: process.stdout,
2100
- prompt: chalk12.bold.cyan("nexus") + chalk12.dim(" \u276F "),
2247
+ prompt: chalk13.bold.cyan("nexus") + chalk13.dim(" \u276F "),
2101
2248
  history: this.history,
2102
2249
  historySize: MAX_HISTORY,
2103
2250
  terminal: true
@@ -2127,25 +2274,25 @@ var Repl = class {
2127
2274
  try {
2128
2275
  await cmd.handler();
2129
2276
  } catch (err) {
2130
- console.log(chalk12.red(` \u2717 Command failed: ${err.message}`));
2277
+ console.log(chalk13.red(` \u2717 Command failed: ${err.message}`));
2131
2278
  }
2132
2279
  this.rl?.prompt();
2133
2280
  return;
2134
2281
  }
2135
- console.log(chalk12.yellow(` Unknown command: /${cmdName}. Type /help for available commands.`));
2282
+ console.log(chalk13.yellow(` Unknown command: /${cmdName}. Type /help for available commands.`));
2136
2283
  this.rl?.prompt();
2137
2284
  return;
2138
2285
  }
2139
2286
  try {
2140
2287
  await this.onMessage(trimmed);
2141
2288
  } catch (err) {
2142
- console.log(chalk12.red(` \u2717 ${err.message}`));
2289
+ console.log(chalk13.red(` \u2717 ${err.message}`));
2143
2290
  }
2144
2291
  this.rl?.prompt();
2145
2292
  });
2146
2293
  this.rl.on("close", () => {
2147
2294
  this.saveHistory();
2148
- console.log(chalk12.dim("\n Session ended."));
2295
+ console.log(chalk13.dim("\n Session ended."));
2149
2296
  process.exit(0);
2150
2297
  });
2151
2298
  this.rl.on("SIGINT", () => {
@@ -2154,15 +2301,15 @@ var Repl = class {
2154
2301
  }
2155
2302
  showHelp() {
2156
2303
  console.log("");
2157
- console.log(chalk12.bold(" Available Commands:"));
2158
- console.log(chalk12.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2304
+ console.log(chalk13.bold(" Available Commands:"));
2305
+ console.log(chalk13.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2159
2306
  for (const [name, cmd] of this.commands) {
2160
- console.log(` ${chalk12.cyan("/" + name.padEnd(14))} ${chalk12.dim(cmd.description)}`);
2307
+ console.log(` ${chalk13.cyan("/" + name.padEnd(14))} ${chalk13.dim(cmd.description)}`);
2161
2308
  }
2162
- console.log(` ${chalk12.cyan("/help".padEnd(15))} ${chalk12.dim("Show this help message")}`);
2163
- console.log(` ${chalk12.cyan("/exit".padEnd(15))} ${chalk12.dim("Exit the shell")}`);
2164
- console.log(chalk12.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2165
- console.log(chalk12.dim(" Type anything else to chat with NEXUS"));
2309
+ console.log(` ${chalk13.cyan("/help".padEnd(15))} ${chalk13.dim("Show this help message")}`);
2310
+ console.log(` ${chalk13.cyan("/exit".padEnd(15))} ${chalk13.dim("Exit the shell")}`);
2311
+ console.log(chalk13.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2312
+ console.log(chalk13.dim(" Type anything else to chat with NEXUS"));
2166
2313
  console.log("");
2167
2314
  }
2168
2315
  write(text) {
@@ -2188,17 +2335,17 @@ var Repl = class {
2188
2335
  init_ssh();
2189
2336
  init_secrets();
2190
2337
  init_dlp();
2191
- import chalk13 from "chalk";
2338
+ import chalk14 from "chalk";
2192
2339
  var ROLE_COLORS = {
2193
- "Chief of Staff": chalk13.bold.cyan,
2194
- "VP Engineering": chalk13.bold.blue,
2195
- "VP Product": chalk13.bold.magenta,
2196
- "Senior Engineer": chalk13.bold.green,
2197
- "Engineer": chalk13.green,
2198
- "QA Lead": chalk13.bold.yellow,
2199
- "Security Engineer": chalk13.bold.red,
2200
- "DevOps Engineer": chalk13.bold.hex("#FF8C00"),
2201
- "default": chalk13.bold.white
2340
+ "Chief of Staff": chalk14.bold.cyan,
2341
+ "VP Engineering": chalk14.bold.blue,
2342
+ "VP Product": chalk14.bold.magenta,
2343
+ "Senior Engineer": chalk14.bold.green,
2344
+ "Engineer": chalk14.green,
2345
+ "QA Lead": chalk14.bold.yellow,
2346
+ "Security Engineer": chalk14.bold.red,
2347
+ "DevOps Engineer": chalk14.bold.hex("#FF8C00"),
2348
+ "default": chalk14.bold.white
2202
2349
  };
2203
2350
  function getColor(role) {
2204
2351
  if (!role) return ROLE_COLORS["default"];
@@ -2209,15 +2356,15 @@ function formatEvent(event) {
2209
2356
  const prefix = event.role ? color(` [${event.role}]`) : "";
2210
2357
  switch (event.type) {
2211
2358
  case "agent_thinking":
2212
- return `${prefix} ${chalk13.dim("thinking...")}`;
2359
+ return `${prefix} ${chalk14.dim("thinking...")}`;
2213
2360
  case "agent_response":
2214
2361
  return `${prefix} ${redact(event.content ?? "")}`;
2215
2362
  case "task_delegated":
2216
- return `${prefix} ${chalk13.dim("\u2192")} delegated to ${chalk13.bold(event.target ?? "agent")}`;
2363
+ return `${prefix} ${chalk14.dim("\u2192")} delegated to ${chalk14.bold(event.target ?? "agent")}`;
2217
2364
  case "agent_complete":
2218
- return `${prefix} ${chalk13.green("\u2713")} ${chalk13.dim("complete")}`;
2365
+ return `${prefix} ${chalk14.green("\u2713")} ${chalk14.dim("complete")}`;
2219
2366
  case "error":
2220
- return ` ${chalk13.red("\u2717")} ${redact(event.content ?? "Unknown error")}`;
2367
+ return ` ${chalk14.red("\u2717")} ${redact(event.content ?? "Unknown error")}`;
2221
2368
  case "heartbeat":
2222
2369
  return null;
2223
2370
  default:
@@ -2300,19 +2447,19 @@ async function sendMessage2(sshPort, message) {
2300
2447
  }
2301
2448
  }
2302
2449
  function showShellBanner(health) {
2303
- const check = chalk14.green("\u2713");
2304
- const cross = chalk14.red("\u2717");
2450
+ const check = chalk15.green("\u2713");
2451
+ const cross = chalk15.red("\u2717");
2305
2452
  console.log("");
2306
- console.log(chalk14.bold(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2307
- console.log(chalk14.bold(" \u2551 ") + chalk14.bold.cyan("NEXUS Interactive Shell") + chalk14.bold(" \u2551"));
2308
- console.log(chalk14.bold(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
2309
- console.log(chalk14.bold(" \u2551 ") + `${health.vmRunning ? check : cross} VM ${health.sshReady ? check : cross} SSH ${health.dockerReady ? check : cross} Docker ${health.serverHealthy ? check : cross} Engine`.padEnd(55) + chalk14.bold("\u2551"));
2453
+ console.log(chalk15.bold(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2454
+ console.log(chalk15.bold(" \u2551 ") + chalk15.bold.cyan("NEXUS Interactive Shell") + chalk15.bold(" \u2551"));
2455
+ console.log(chalk15.bold(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
2456
+ console.log(chalk15.bold(" \u2551 ") + `${health.vmRunning ? check : cross} VM ${health.sshReady ? check : cross} SSH ${health.dockerReady ? check : cross} Docker ${health.serverHealthy ? check : cross} Engine`.padEnd(55) + chalk15.bold("\u2551"));
2310
2457
  if (health.tunnelUrl) {
2311
- console.log(chalk14.bold(" \u2551 ") + chalk14.dim(`Tunnel: ${health.tunnelUrl}`.padEnd(55)) + chalk14.bold("\u2551"));
2458
+ console.log(chalk15.bold(" \u2551 ") + chalk15.dim(`Tunnel: ${health.tunnelUrl}`.padEnd(55)) + chalk15.bold("\u2551"));
2312
2459
  }
2313
- console.log(chalk14.bold(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
2314
- console.log(chalk14.bold(" \u2551 ") + chalk14.dim("Type naturally to chat \xB7 /help for commands".padEnd(55)) + chalk14.bold("\u2551"));
2315
- console.log(chalk14.bold(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2460
+ console.log(chalk15.bold(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
2461
+ console.log(chalk15.bold(" \u2551 ") + chalk15.dim("Type naturally to chat \xB7 /help for commands".padEnd(55)) + chalk15.bold("\u2551"));
2462
+ console.log(chalk15.bold(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2316
2463
  console.log("");
2317
2464
  }
2318
2465
  async function getAgentList(sshPort) {
@@ -2322,13 +2469,13 @@ async function getAgentList(sshPort) {
2322
2469
  const agents = JSON.parse(stdout);
2323
2470
  if (!Array.isArray(agents)) return stdout;
2324
2471
  const lines = [""];
2325
- lines.push(chalk14.bold(" Registered Agents:"));
2326
- lines.push(chalk14.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2472
+ lines.push(chalk15.bold(" Registered Agents:"));
2473
+ lines.push(chalk15.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2327
2474
  for (const agent of agents) {
2328
2475
  const name = agent.name ?? agent.id ?? "unknown";
2329
2476
  const role = agent.role ?? "";
2330
- const status = agent.status === "active" ? chalk14.green("\u25CF") : chalk14.dim("\u25CB");
2331
- lines.push(` ${status} ${chalk14.bold(name.padEnd(24))} ${chalk14.dim(role)}`);
2477
+ const status = agent.status === "active" ? chalk15.green("\u25CF") : chalk15.dim("\u25CB");
2478
+ lines.push(` ${status} ${chalk15.bold(name.padEnd(24))} ${chalk15.dim(role)}`);
2332
2479
  }
2333
2480
  lines.push("");
2334
2481
  return lines.join("\n");
@@ -2340,11 +2487,11 @@ async function getStatus(sshPort) {
2340
2487
  try {
2341
2488
  const vmRunning = isVmRunning();
2342
2489
  const health = await checkHealth(sshPort, vmRunning);
2343
- const check = chalk14.green("\u2713");
2344
- const cross = chalk14.red("\u2717");
2490
+ const check = chalk15.green("\u2713");
2491
+ const cross = chalk15.red("\u2717");
2345
2492
  const lines = [""];
2346
- lines.push(chalk14.bold(" System Status:"));
2347
- lines.push(chalk14.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2493
+ lines.push(chalk15.bold(" System Status:"));
2494
+ lines.push(chalk15.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2348
2495
  lines.push(` ${health.vmRunning ? check : cross} Virtual Machine`);
2349
2496
  lines.push(` ${health.sshReady ? check : cross} SSH Connection`);
2350
2497
  lines.push(` ${health.dockerReady ? check : cross} Docker Engine`);
@@ -2366,17 +2513,17 @@ async function getCost(sshPort) {
2366
2513
  if (code !== 0) return " Could not retrieve cost data";
2367
2514
  const data = JSON.parse(stdout);
2368
2515
  const lines = [""];
2369
- lines.push(chalk14.bold(" Token Costs:"));
2370
- lines.push(chalk14.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2516
+ lines.push(chalk15.bold(" Token Costs:"));
2517
+ lines.push(chalk15.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2371
2518
  if (data.total !== void 0) {
2372
- lines.push(` Total: ${chalk14.bold.green("$" + Number(data.total).toFixed(4))}`);
2519
+ lines.push(` Total: ${chalk15.bold.green("$" + Number(data.total).toFixed(4))}`);
2373
2520
  }
2374
2521
  if (data.today !== void 0) {
2375
- lines.push(` Today: ${chalk14.bold("$" + Number(data.today).toFixed(4))}`);
2522
+ lines.push(` Today: ${chalk15.bold("$" + Number(data.today).toFixed(4))}`);
2376
2523
  }
2377
2524
  if (data.by_agent && typeof data.by_agent === "object") {
2378
2525
  lines.push("");
2379
- lines.push(chalk14.dim(" By Agent:"));
2526
+ lines.push(chalk15.dim(" By Agent:"));
2380
2527
  for (const [agent, cost] of Object.entries(data.by_agent)) {
2381
2528
  lines.push(` ${agent.padEnd(20)} $${Number(cost).toFixed(4)}`);
2382
2529
  }
@@ -2421,10 +2568,10 @@ var shellCommand2 = new Command13("shell").description("Launch the interactive N
2421
2568
  thinkingSpinner.stop();
2422
2569
  thinkingSpinner.clear();
2423
2570
  console.log("");
2424
- console.log(chalk14.bold.cyan(" Chief of Staff:"));
2571
+ console.log(chalk15.bold.cyan(" Chief of Staff:"));
2425
2572
  const lines = redact(response).split("\n");
2426
2573
  for (const line of lines) {
2427
- console.log(chalk14.white(" " + line));
2574
+ console.log(chalk15.white(" " + line));
2428
2575
  }
2429
2576
  console.log("");
2430
2577
  } catch (err) {
@@ -2438,14 +2585,14 @@ var shellCommand2 = new Command13("shell").description("Launch the interactive N
2438
2585
  description: "Brainstorm with the full NEXUS org (led by Chief of Staff)",
2439
2586
  handler: async () => {
2440
2587
  console.log("");
2441
- console.log(chalk14.bold(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2442
- console.log(chalk14.bold(" \u2551 ") + chalk14.bold.cyan("NEXUS Brainstorm Session") + chalk14.bold(" \u2551"));
2443
- console.log(chalk14.bold(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
2444
- console.log(chalk14.bold(" \u2551 ") + chalk14.dim("The Chief of Staff will facilitate a discussion with".padEnd(55)) + chalk14.bold("\u2551"));
2445
- console.log(chalk14.bold(" \u2551 ") + chalk14.dim("the full NEXUS org to refine your idea. When ready,".padEnd(55)) + chalk14.bold("\u2551"));
2446
- console.log(chalk14.bold(" \u2551 ") + chalk14.dim("NEXUS will draft an execution plan for your review.".padEnd(55)) + chalk14.bold("\u2551"));
2447
- console.log(chalk14.bold(" \u2551 ") + chalk14.dim("Type 'exit' to end brainstorm. Type 'plan' to hand off.".padEnd(55)) + chalk14.bold("\u2551"));
2448
- console.log(chalk14.bold(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2588
+ console.log(chalk15.bold(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2589
+ console.log(chalk15.bold(" \u2551 ") + chalk15.bold.cyan("NEXUS Brainstorm Session") + chalk15.bold(" \u2551"));
2590
+ console.log(chalk15.bold(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
2591
+ console.log(chalk15.bold(" \u2551 ") + chalk15.dim("The Chief of Staff will facilitate a discussion with".padEnd(55)) + chalk15.bold("\u2551"));
2592
+ console.log(chalk15.bold(" \u2551 ") + chalk15.dim("the full NEXUS org to refine your idea. When ready,".padEnd(55)) + chalk15.bold("\u2551"));
2593
+ console.log(chalk15.bold(" \u2551 ") + chalk15.dim("NEXUS will draft an execution plan for your review.".padEnd(55)) + chalk15.bold("\u2551"));
2594
+ console.log(chalk15.bold(" \u2551 ") + chalk15.dim("Type 'exit' to end brainstorm. Type 'plan' to hand off.".padEnd(55)) + chalk15.bold("\u2551"));
2595
+ console.log(chalk15.bold(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2449
2596
  console.log("");
2450
2597
  const { input: input5 } = await import("@inquirer/prompts");
2451
2598
  const idea = await input5({ message: "What would you like to brainstorm?" });
@@ -2458,12 +2605,12 @@ var shellCommand2 = new Command13("shell").description("Launch the interactive N
2458
2605
  brainstormSpinner.stop();
2459
2606
  brainstormSpinner.clear();
2460
2607
  console.log("");
2461
- console.log(chalk14.bold.cyan(" Chief of Staff:"));
2608
+ console.log(chalk15.bold.cyan(" Chief of Staff:"));
2462
2609
  for (const line of redact(response).split("\n")) {
2463
- console.log(chalk14.white(" " + line));
2610
+ console.log(chalk15.white(" " + line));
2464
2611
  }
2465
2612
  console.log("");
2466
- const followUp = await input5({ message: chalk14.bold("You:") });
2613
+ const followUp = await input5({ message: chalk15.bold("You:") });
2467
2614
  const trimmed = followUp.trim().toLowerCase();
2468
2615
  if (!trimmed || trimmed === "exit" || trimmed === "quit") {
2469
2616
  console.log("");
@@ -2477,9 +2624,9 @@ var shellCommand2 = new Command13("shell").description("Launch the interactive N
2477
2624
  planSpinner.stop();
2478
2625
  planSpinner.clear();
2479
2626
  console.log("");
2480
- console.log(chalk14.bold.green(" Execution Plan:"));
2627
+ console.log(chalk15.bold.green(" Execution Plan:"));
2481
2628
  for (const line of redact(planResponse).split("\n")) {
2482
- console.log(chalk14.white(" " + line));
2629
+ console.log(chalk15.white(" " + line));
2483
2630
  }
2484
2631
  console.log("");
2485
2632
  log.success("Plan drafted. Use the shell to refine or approve.");
@@ -2519,10 +2666,10 @@ var shellCommand2 = new Command13("shell").description("Launch the interactive N
2519
2666
  handler: async () => {
2520
2667
  const { stdout } = await sshExec(config.sshPort, "tail -30 /home/nexus/.nexus/logs/server.log 2>/dev/null");
2521
2668
  console.log("");
2522
- console.log(chalk14.bold(" Recent Logs:"));
2523
- console.log(chalk14.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2669
+ console.log(chalk15.bold(" Recent Logs:"));
2670
+ console.log(chalk15.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2524
2671
  for (const line of redact(stdout).split("\n")) {
2525
- console.log(chalk14.dim(" " + line));
2672
+ console.log(chalk15.dim(" " + line));
2526
2673
  }
2527
2674
  console.log("");
2528
2675
  }
@@ -2542,24 +2689,24 @@ var shellCommand2 = new Command13("shell").description("Launch the interactive N
2542
2689
  description: "Display the NEXUS organizational hierarchy",
2543
2690
  handler: async () => {
2544
2691
  console.log("");
2545
- console.log(chalk14.bold(" NEXUS Organizational Hierarchy"));
2546
- console.log(chalk14.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2547
- console.log(` ${chalk14.bold.white("You")} ${chalk14.dim("(CEO)")}`);
2548
- console.log(` \u2514\u2500\u2500 ${chalk14.bold.cyan("Chief of Staff")} ${chalk14.dim("\u2014 orchestrates all work, your direct interface")}`);
2549
- console.log(` \u251C\u2500\u2500 ${chalk14.bold.blue("VP Engineering")} ${chalk14.dim("\u2014 owns technical execution")}`);
2550
- console.log(` \u2502 \u251C\u2500\u2500 ${chalk14.green("Senior Engineer")} ${chalk14.dim("\xD7 8 \u2014 implementation, refactoring")}`);
2551
- console.log(` \u2502 \u251C\u2500\u2500 ${chalk14.green("Engineer")} ${chalk14.dim("\xD7 12 \u2014 feature work, bug fixes")}`);
2552
- console.log(` \u2502 \u2514\u2500\u2500 ${chalk14.hex("#FF8C00")("DevOps Engineer")} ${chalk14.dim("\xD7 4 \u2014 CI/CD, Docker, infra")}`);
2553
- console.log(` \u251C\u2500\u2500 ${chalk14.bold.magenta("VP Product")} ${chalk14.dim("\u2014 owns roadmap and priorities")}`);
2554
- console.log(` \u2502 \u251C\u2500\u2500 ${chalk14.magenta("Product Manager")} ${chalk14.dim("\xD7 3 \u2014 specs, requirements")}`);
2555
- console.log(` \u2502 \u2514\u2500\u2500 ${chalk14.magenta("Designer")} ${chalk14.dim("\xD7 2 \u2014 UI/UX, prototyping")}`);
2556
- console.log(` \u251C\u2500\u2500 ${chalk14.bold.yellow("QA Lead")} ${chalk14.dim("\u2014 owns quality assurance")}`);
2557
- console.log(` \u2502 \u2514\u2500\u2500 ${chalk14.yellow("QA Engineer")} ${chalk14.dim("\xD7 6 \u2014 testing, coverage, validation")}`);
2558
- console.log(` \u251C\u2500\u2500 ${chalk14.bold.red("Security Engineer")} ${chalk14.dim("\xD7 4 \u2014 auth, scanning, compliance")}`);
2559
- console.log(` \u2514\u2500\u2500 ${chalk14.bold.white("Knowledge Manager")} ${chalk14.dim("\u2014 RAG, documentation, learning")}`);
2692
+ console.log(chalk15.bold(" NEXUS Organizational Hierarchy"));
2693
+ console.log(chalk15.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2694
+ console.log(` ${chalk15.bold.white("You")} ${chalk15.dim("(CEO)")}`);
2695
+ console.log(` \u2514\u2500\u2500 ${chalk15.bold.cyan("Chief of Staff")} ${chalk15.dim("\u2014 orchestrates all work, your direct interface")}`);
2696
+ console.log(` \u251C\u2500\u2500 ${chalk15.bold.blue("VP Engineering")} ${chalk15.dim("\u2014 owns technical execution")}`);
2697
+ console.log(` \u2502 \u251C\u2500\u2500 ${chalk15.green("Senior Engineer")} ${chalk15.dim("\xD7 8 \u2014 implementation, refactoring")}`);
2698
+ console.log(` \u2502 \u251C\u2500\u2500 ${chalk15.green("Engineer")} ${chalk15.dim("\xD7 12 \u2014 feature work, bug fixes")}`);
2699
+ console.log(` \u2502 \u2514\u2500\u2500 ${chalk15.hex("#FF8C00")("DevOps Engineer")} ${chalk15.dim("\xD7 4 \u2014 CI/CD, Docker, infra")}`);
2700
+ console.log(` \u251C\u2500\u2500 ${chalk15.bold.magenta("VP Product")} ${chalk15.dim("\u2014 owns roadmap and priorities")}`);
2701
+ console.log(` \u2502 \u251C\u2500\u2500 ${chalk15.magenta("Product Manager")} ${chalk15.dim("\xD7 3 \u2014 specs, requirements")}`);
2702
+ console.log(` \u2502 \u2514\u2500\u2500 ${chalk15.magenta("Designer")} ${chalk15.dim("\xD7 2 \u2014 UI/UX, prototyping")}`);
2703
+ console.log(` \u251C\u2500\u2500 ${chalk15.bold.yellow("QA Lead")} ${chalk15.dim("\u2014 owns quality assurance")}`);
2704
+ console.log(` \u2502 \u2514\u2500\u2500 ${chalk15.yellow("QA Engineer")} ${chalk15.dim("\xD7 6 \u2014 testing, coverage, validation")}`);
2705
+ console.log(` \u251C\u2500\u2500 ${chalk15.bold.red("Security Engineer")} ${chalk15.dim("\xD7 4 \u2014 auth, scanning, compliance")}`);
2706
+ console.log(` \u2514\u2500\u2500 ${chalk15.bold.white("Knowledge Manager")} ${chalk15.dim("\u2014 RAG, documentation, learning")}`);
2560
2707
  console.log("");
2561
- console.log(chalk14.dim(" 56 agents total \xB7 Self-learning ML pipeline"));
2562
- console.log(chalk14.dim(" Full details: https://buildwithnexus.dev/overview"));
2708
+ console.log(chalk15.dim(" 56 agents total \xB7 Self-learning ML pipeline"));
2709
+ console.log(chalk15.dim(" Full details: https://buildwithnexus.dev/overview"));
2563
2710
  console.log("");
2564
2711
  }
2565
2712
  });
@@ -2648,14 +2795,14 @@ var shellCommand2 = new Command13("shell").description("Launch the interactive N
2648
2795
  for (let i = 0; i < steps.length; i++) {
2649
2796
  const step = steps[i];
2650
2797
  console.log("");
2651
- console.log(chalk14.bold(` \u2500\u2500 ${chalk14.cyan(`Step ${i + 1}/${steps.length}`)} \u2500\u2500 ${step.title} \u2500\u2500`));
2798
+ console.log(chalk15.bold(` \u2500\u2500 ${chalk15.cyan(`Step ${i + 1}/${steps.length}`)} \u2500\u2500 ${step.title} \u2500\u2500`));
2652
2799
  console.log("");
2653
2800
  for (const line of step.content) {
2654
- console.log(chalk14.white(" " + line));
2801
+ console.log(chalk15.white(" " + line));
2655
2802
  }
2656
2803
  console.log("");
2657
2804
  if (i < steps.length - 1) {
2658
- const next = await input5({ message: chalk14.dim("Press Enter to continue (or 'skip' to exit)") });
2805
+ const next = await input5({ message: chalk15.dim("Press Enter to continue (or 'skip' to exit)") });
2659
2806
  if (next.trim().toLowerCase() === "skip") {
2660
2807
  log.success("Tutorial ended. Type /help to see all commands.");
2661
2808
  return;
@@ -2702,9 +2849,9 @@ cli.addCommand(shellCommand2);
2702
2849
  cli.action(async () => {
2703
2850
  try {
2704
2851
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_secrets(), secrets_exports));
2705
- const { isVmRunning: isVmRunning3 } = await Promise.resolve().then(() => (init_qemu(), qemu_exports));
2852
+ const { isVmRunning: isVmRunning2 } = await Promise.resolve().then(() => (init_qemu(), qemu_exports));
2706
2853
  const config = loadConfig2();
2707
- if (config && isVmRunning3()) {
2854
+ if (config && isVmRunning2()) {
2708
2855
  await shellCommand2.parseAsync([], { from: "user" });
2709
2856
  return;
2710
2857
  }
@@ -2718,7 +2865,7 @@ import fs11 from "fs";
2718
2865
  import path12 from "path";
2719
2866
  import os3 from "os";
2720
2867
  import https from "https";
2721
- import chalk15 from "chalk";
2868
+ import chalk16 from "chalk";
2722
2869
  var PACKAGE_NAME = "buildwithnexus";
2723
2870
  var CHECK_INTERVAL_MS = 4 * 60 * 60 * 1e3;
2724
2871
  var STATE_DIR = path12.join(os3.homedir(), ".buildwithnexus");
@@ -2799,8 +2946,8 @@ async function checkForUpdates(currentVersion) {
2799
2946
  function printUpdateBanner(current, latest) {
2800
2947
  const msg = [
2801
2948
  "",
2802
- chalk15.yellow(` Update available: ${current} \u2192 ${latest}`),
2803
- chalk15.cyan(` Run: npm update -g buildwithnexus`),
2949
+ chalk16.yellow(` Update available: ${current} \u2192 ${latest}`),
2950
+ chalk16.cyan(` Run: npm update -g buildwithnexus`),
2804
2951
  ""
2805
2952
  ].join("\n");
2806
2953
  process.stderr.write(msg + "\n");