@askexenow/exe-os 0.9.20 → 0.9.22

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.
Files changed (62) hide show
  1. package/LICENSE +24 -15
  2. package/dist/bin/backfill-conversations.js +17 -4
  3. package/dist/bin/backfill-responses.js +17 -4
  4. package/dist/bin/backfill-vectors.js +2 -2
  5. package/dist/bin/cleanup-stale-review-tasks.js +17 -4
  6. package/dist/bin/cli.js +420 -180
  7. package/dist/bin/exe-assign.js +17 -4
  8. package/dist/bin/exe-boot.js +2 -2
  9. package/dist/bin/exe-dispatch.js +17 -4
  10. package/dist/bin/exe-doctor.js +2 -2
  11. package/dist/bin/exe-export-behaviors.js +17 -4
  12. package/dist/bin/exe-forget.js +17 -4
  13. package/dist/bin/exe-gateway.js +17 -4
  14. package/dist/bin/exe-heartbeat.js +17 -4
  15. package/dist/bin/exe-kill.js +17 -4
  16. package/dist/bin/exe-launch-agent.js +17 -4
  17. package/dist/bin/exe-new-employee.js +42 -18
  18. package/dist/bin/exe-pending-messages.js +17 -4
  19. package/dist/bin/exe-pending-notifications.js +17 -4
  20. package/dist/bin/exe-pending-reviews.js +17 -4
  21. package/dist/bin/exe-review.js +17 -4
  22. package/dist/bin/exe-search.js +23 -8
  23. package/dist/bin/exe-session-cleanup.js +17 -4
  24. package/dist/bin/exe-start-codex.js +209 -32
  25. package/dist/bin/exe-start-opencode.js +17 -4
  26. package/dist/bin/exe-status.js +17 -4
  27. package/dist/bin/exe-team.js +17 -4
  28. package/dist/bin/git-sweep.js +17 -4
  29. package/dist/bin/graph-backfill.js +17 -4
  30. package/dist/bin/graph-export.js +17 -4
  31. package/dist/bin/install.js +84 -18
  32. package/dist/bin/intercom-check.js +17 -4
  33. package/dist/bin/scan-tasks.js +17 -4
  34. package/dist/bin/shard-migrate.js +17 -4
  35. package/dist/bin/update.js +187 -42
  36. package/dist/gateway/index.js +17 -4
  37. package/dist/hooks/bug-report-worker.js +793 -150
  38. package/dist/hooks/codex-stop-task-finalizer.js +3020 -2375
  39. package/dist/hooks/commit-complete.js +156 -6
  40. package/dist/hooks/error-recall.js +23 -8
  41. package/dist/hooks/ingest.js +17 -4
  42. package/dist/hooks/instructions-loaded.js +17 -4
  43. package/dist/hooks/notification.js +17 -4
  44. package/dist/hooks/post-compact.js +17 -4
  45. package/dist/hooks/post-tool-combined.js +23 -8
  46. package/dist/hooks/pre-compact.js +156 -8
  47. package/dist/hooks/pre-tool-use.js +21 -12
  48. package/dist/hooks/prompt-submit.js +23 -8
  49. package/dist/hooks/session-end.js +156 -8
  50. package/dist/hooks/session-start.js +23 -8
  51. package/dist/hooks/stop.js +306 -9
  52. package/dist/hooks/subagent-stop.js +306 -9
  53. package/dist/hooks/summary-worker.js +2 -2
  54. package/dist/index.js +17 -4
  55. package/dist/lib/exe-daemon.js +17 -4
  56. package/dist/lib/hybrid-search.js +23 -8
  57. package/dist/lib/schedules.js +2 -2
  58. package/dist/lib/store.js +17 -4
  59. package/dist/mcp/server.js +36 -10
  60. package/dist/runtime/index.js +17 -4
  61. package/dist/tui/App.js +17 -4
  62. package/package.json +2 -2
package/dist/bin/cli.js CHANGED
@@ -917,18 +917,21 @@ async function registerMcpServer(packageRoot, homeDir = os5.homedir()) {
917
917
  args: [path6.join(packageRoot, "dist", "mcp", "server.js")],
918
918
  env: {}
919
919
  };
920
- const currentMem = claudeJson.mcpServers[MCP_LEGACY_KEY];
921
- const memMatches = currentMem && JSON.stringify(currentMem) === JSON.stringify(newEntry);
922
- if (claudeJson.mcpServers[MCP_PRIMARY_KEY]) {
923
- delete claudeJson.mcpServers[MCP_PRIMARY_KEY];
920
+ if (claudeJson.mcpServers[MCP_LEGACY_KEY]) {
921
+ delete claudeJson.mcpServers[MCP_LEGACY_KEY];
922
+ process.stderr.write("exe-os: migrated MCP server key exe-mem \u2192 exe-os\n");
924
923
  }
925
- if (memMatches && !claudeJson.mcpServers[MCP_PRIMARY_KEY]) {
924
+ const currentOs = claudeJson.mcpServers[MCP_PRIMARY_KEY];
925
+ const osMatches = currentOs && JSON.stringify(currentOs) === JSON.stringify(newEntry);
926
+ if (osMatches) {
926
927
  await cleanSettingsJsonMcp(path6.join(homeDir, ".claude", "settings.json"));
928
+ await migratePermissionsToExeOs(path6.join(homeDir, ".claude", "settings.json"));
927
929
  return false;
928
930
  }
929
- claudeJson.mcpServers[MCP_LEGACY_KEY] = newEntry;
931
+ claudeJson.mcpServers[MCP_PRIMARY_KEY] = newEntry;
930
932
  await writeFile3(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
931
933
  await cleanSettingsJsonMcp(path6.join(homeDir, ".claude", "settings.json"));
934
+ await migratePermissionsToExeOs(path6.join(homeDir, ".claude", "settings.json"));
932
935
  return true;
933
936
  }
934
937
  async function cleanSettingsJsonMcp(settingsPath) {
@@ -952,6 +955,35 @@ async function cleanSettingsJsonMcp(settingsPath) {
952
955
  } catch {
953
956
  }
954
957
  }
958
+ async function migratePermissionsToExeOs(settingsPath) {
959
+ if (!existsSync7(settingsPath)) return;
960
+ try {
961
+ const settings = JSON.parse(await readFile3(settingsPath, "utf-8"));
962
+ const permissions = settings.permissions;
963
+ if (!permissions || !Array.isArray(permissions.allow)) return;
964
+ const allow = permissions.allow;
965
+ let migrated = 0;
966
+ for (let i = 0; i < allow.length; i++) {
967
+ if (allow[i].startsWith("mcp__exe-mem__")) {
968
+ const newName = allow[i].replace("mcp__exe-mem__", "mcp__exe-os__");
969
+ if (!allow.includes(newName)) {
970
+ allow[i] = newName;
971
+ } else {
972
+ allow[i] = "__REMOVE__";
973
+ }
974
+ migrated++;
975
+ }
976
+ }
977
+ if (migrated > 0) {
978
+ permissions.allow = allow.filter((e) => e !== "__REMOVE__");
979
+ permissions.allow = [...new Set(permissions.allow)];
980
+ await writeFile3(settingsPath, JSON.stringify(settings, null, 2) + "\n");
981
+ process.stderr.write(`exe-os: migrated ${migrated} permission(s) from exe-mem \u2192 exe-os
982
+ `);
983
+ }
984
+ } catch {
985
+ }
986
+ }
955
987
  async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
956
988
  const settingsPath = path6.join(homeDir, ".claude", "settings.json");
957
989
  const logsDir = path6.join(homeDir, ".exe-os", "logs");
@@ -1212,9 +1244,10 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1212
1244
  "deploy_client"
1213
1245
  ];
1214
1246
  const allowList = permissions.allow;
1215
- for (const tool of expandDualPrefixTools(toolNames)) {
1216
- if (!allowList.includes(tool)) {
1217
- allowList.push(tool);
1247
+ for (const name of toolNames) {
1248
+ const fullName = `mcp__${MCP_PRIMARY_KEY}__${name}`;
1249
+ if (!allowList.includes(fullName)) {
1250
+ allowList.push(fullName);
1218
1251
  }
1219
1252
  }
1220
1253
  await mkdir3(path6.dirname(settingsPath), { recursive: true });
@@ -5952,9 +5985,9 @@ async function cloudPullGraphRAG(config) {
5952
5985
  pulled += stmts.length;
5953
5986
  }
5954
5987
  if (blob.relationship_memories.length > 0) {
5955
- const stmts = blob.relationship_memories.map((rm) => ({
5988
+ const stmts = blob.relationship_memories.map((rm2) => ({
5956
5989
  sql: `INSERT OR IGNORE INTO relationship_memories (relationship_id, memory_id) VALUES (?, ?)`,
5957
- args: [sqlSafe(rm.relationship_id), sqlSafe(rm.memory_id)]
5990
+ args: [sqlSafe(rm2.relationship_id), sqlSafe(rm2.memory_id)]
5958
5991
  }));
5959
5992
  await client.batch(stmts, "write");
5960
5993
  pulled += stmts.length;
@@ -6471,8 +6504,8 @@ function getShardClient(projectName) {
6471
6504
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
6472
6505
  }
6473
6506
  const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
6474
- if (!safeName) {
6475
- throw new Error(`Invalid project name for shard: "${projectName}"`);
6507
+ if (!safeName || safeName === "unknown") {
6508
+ throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
6476
6509
  }
6477
6510
  const cached = _shards.get(safeName);
6478
6511
  if (cached) {
@@ -7341,19 +7374,32 @@ async function flushBatch() {
7341
7374
  const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
7342
7375
  if (isShardingEnabled2()) {
7343
7376
  const byProject = /* @__PURE__ */ new Map();
7377
+ let skippedUnknown = 0;
7344
7378
  for (const row of batch) {
7345
- const proj = row.project_name || "unknown";
7379
+ const proj = row.project_name?.trim();
7380
+ if (!proj) {
7381
+ skippedUnknown++;
7382
+ continue;
7383
+ }
7346
7384
  if (!byProject.has(proj)) byProject.set(proj, []);
7347
7385
  byProject.get(proj).push(row);
7348
7386
  }
7387
+ if (skippedUnknown > 0) {
7388
+ process.stderr.write(
7389
+ `[store] Shard skip: ${skippedUnknown} record(s) with empty project_name (kept in main DB only)
7390
+ `
7391
+ );
7392
+ }
7349
7393
  for (const [project, rows] of byProject) {
7350
7394
  try {
7351
7395
  const shardClient = await getReadyShardClient2(project);
7352
7396
  const shardStmts = rows.map(buildStmt);
7353
7397
  await shardClient.batch(shardStmts, "write");
7354
7398
  } catch (err) {
7399
+ const fullError = err instanceof Error ? `${err.name}: ${err.message}${err.stack ? `
7400
+ ${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
7355
7401
  process.stderr.write(
7356
- `[store] Shard write failed for ${project}: ${err instanceof Error ? err.message : String(err)}
7402
+ `[store] Shard write failed for ${project} (${rows.length} records): ${fullError}
7357
7403
  `
7358
7404
  );
7359
7405
  }
@@ -8381,9 +8427,9 @@ Unclassified: ${unclassified}
8381
8427
  }
8382
8428
  async function exportBatches(options) {
8383
8429
  const fs8 = await import("fs");
8384
- const path46 = await import("path");
8430
+ const path47 = await import("path");
8385
8431
  const client = getClient();
8386
- const outDir = path46.join(process.cwd(), "exe/output/classifications/input");
8432
+ const outDir = path47.join(process.cwd(), "exe/output/classifications/input");
8387
8433
  fs8.mkdirSync(outDir, { recursive: true });
8388
8434
  const countResult = await client.execute({
8389
8435
  sql: "SELECT COUNT(*) as cnt FROM memories WHERE intent IS NULL AND outcome IS NULL AND domain IS NULL",
@@ -8407,7 +8453,7 @@ async function exportBatches(options) {
8407
8453
  const text = String(row.text || "").replace(/\n/g, " ");
8408
8454
  return JSON.stringify({ id: row.id, text });
8409
8455
  });
8410
- const batchFile = path46.join(outDir, `batch-${String(batchNum).padStart(4, "0")}.jsonl`);
8456
+ const batchFile = path47.join(outDir, `batch-${String(batchNum).padStart(4, "0")}.jsonl`);
8411
8457
  fs8.writeFileSync(batchFile, lines.join("\n") + "\n");
8412
8458
  exported += batch.rows.length;
8413
8459
  offset += options.batchSize;
@@ -8423,7 +8469,7 @@ async function exportBatches(options) {
8423
8469
  }
8424
8470
  async function importClassifications(importDir) {
8425
8471
  const fs8 = await import("fs");
8426
- const path46 = await import("path");
8472
+ const path47 = await import("path");
8427
8473
  const client = getClient();
8428
8474
  const files = fs8.readdirSync(importDir).filter((f) => f.endsWith(".jsonl")).sort();
8429
8475
  process.stderr.write(`[backfill-metadata] Found ${files.length} JSONL files to import from ${importDir}
@@ -8431,7 +8477,7 @@ async function importClassifications(importDir) {
8431
8477
  let imported = 0;
8432
8478
  let invalid = 0;
8433
8479
  for (const file of files) {
8434
- const lines = fs8.readFileSync(path46.join(importDir, file), "utf-8").split("\n").filter(Boolean);
8480
+ const lines = fs8.readFileSync(path47.join(importDir, file), "utf-8").split("\n").filter(Boolean);
8435
8481
  for (const line of lines) {
8436
8482
  try {
8437
8483
  const rec = JSON.parse(line);
@@ -11064,10 +11110,10 @@ async function disposeEmbedder() {
11064
11110
  async function embedDirect(text) {
11065
11111
  const llamaCpp = await import("node-llama-cpp");
11066
11112
  const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
11067
- const { existsSync: existsSync32 } = await import("fs");
11068
- const path46 = await import("path");
11069
- const modelPath = path46.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
11070
- if (!existsSync32(modelPath)) {
11113
+ const { existsSync: existsSync33 } = await import("fs");
11114
+ const path47 = await import("path");
11115
+ const modelPath = path47.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
11116
+ if (!existsSync33(modelPath)) {
11071
11117
  throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
11072
11118
  }
11073
11119
  const llama = await llamaCpp.getLlama();
@@ -15482,12 +15528,108 @@ var init_setup_wizard = __esm({
15482
15528
  }
15483
15529
  });
15484
15530
 
15531
+ // src/lib/update-backup.ts
15532
+ import { copyFile, readFile as readFile6, readdir as readdir3, writeFile as writeFile7, rm, mkdir as mkdir7, cp } from "fs/promises";
15533
+ import { existsSync as existsSync28 } from "fs";
15534
+ import path34 from "path";
15535
+ import os17 from "os";
15536
+ function resolveDataDir2() {
15537
+ if (process.env.EXE_OS_DIR) return process.env.EXE_OS_DIR;
15538
+ if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
15539
+ return path34.join(os17.homedir(), ".exe-os");
15540
+ }
15541
+ async function createUpdateBackup(currentVersion, dataDir) {
15542
+ const dir = dataDir ?? resolveDataDir2();
15543
+ const backupDir = path34.join(dir, BACKUP_DIR_NAME);
15544
+ if (existsSync28(backupDir)) {
15545
+ await rm(backupDir, { recursive: true, force: true });
15546
+ }
15547
+ await mkdir7(backupDir, { recursive: true });
15548
+ const backedUpFiles = [];
15549
+ for (const target of BACKUP_TARGETS) {
15550
+ const src = path34.join(dir, target.name);
15551
+ if (!existsSync28(src)) continue;
15552
+ const dest = path34.join(backupDir, target.name);
15553
+ if (target.type === "file") {
15554
+ await copyFile(src, dest);
15555
+ } else {
15556
+ await cp(src, dest, { recursive: true });
15557
+ }
15558
+ backedUpFiles.push(target.name);
15559
+ }
15560
+ const entries = await readdir3(dir, { withFileTypes: true });
15561
+ for (const entry of entries) {
15562
+ if (entry.isFile() && entry.name.endsWith(".db") && entry.name !== BACKUP_DIR_NAME) {
15563
+ const src = path34.join(dir, entry.name);
15564
+ const dest = path34.join(backupDir, entry.name);
15565
+ await copyFile(src, dest);
15566
+ backedUpFiles.push(entry.name);
15567
+ }
15568
+ }
15569
+ const manifest = {
15570
+ version: currentVersion,
15571
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
15572
+ files: backedUpFiles
15573
+ };
15574
+ await writeFile7(
15575
+ path34.join(backupDir, "manifest.json"),
15576
+ JSON.stringify(manifest, null, 2) + "\n"
15577
+ );
15578
+ return manifest;
15579
+ }
15580
+ async function restoreFromBackup(dataDir) {
15581
+ const dir = dataDir ?? resolveDataDir2();
15582
+ const backupDir = path34.join(dir, BACKUP_DIR_NAME);
15583
+ const manifestPath = path34.join(backupDir, "manifest.json");
15584
+ if (!existsSync28(manifestPath)) {
15585
+ throw new Error(
15586
+ `No backup found at ${backupDir}. Nothing to restore.`
15587
+ );
15588
+ }
15589
+ const manifest = JSON.parse(
15590
+ await readFile6(manifestPath, "utf-8")
15591
+ );
15592
+ for (const fileName of manifest.files) {
15593
+ const src = path34.join(backupDir, fileName);
15594
+ const dest = path34.join(dir, fileName);
15595
+ if (!existsSync28(src)) continue;
15596
+ const stat2 = await import("fs/promises").then((m) => m.stat(src));
15597
+ if (stat2.isDirectory()) {
15598
+ await cp(src, dest, { recursive: true, force: true });
15599
+ } else {
15600
+ await copyFile(src, dest);
15601
+ }
15602
+ }
15603
+ return manifest;
15604
+ }
15605
+ async function deleteBackup(dataDir) {
15606
+ const dir = dataDir ?? resolveDataDir2();
15607
+ const backupDir = path34.join(dir, BACKUP_DIR_NAME);
15608
+ if (existsSync28(backupDir)) {
15609
+ await rm(backupDir, { recursive: true, force: true });
15610
+ }
15611
+ }
15612
+ var BACKUP_DIR_NAME, BACKUP_TARGETS;
15613
+ var init_update_backup = __esm({
15614
+ "src/lib/update-backup.ts"() {
15615
+ "use strict";
15616
+ BACKUP_DIR_NAME = ".update-backup";
15617
+ BACKUP_TARGETS = [
15618
+ { name: "config.json", type: "file" },
15619
+ { name: "exe-employees.json", type: "file" },
15620
+ { name: "master.key", type: "file" },
15621
+ { name: "identity", type: "dir" }
15622
+ // All .db files (SQLCipher databases) — matched dynamically
15623
+ ];
15624
+ }
15625
+ });
15626
+
15485
15627
  // src/lib/update-check.ts
15486
15628
  import { execSync as execSync11 } from "child_process";
15487
15629
  import { readFileSync as readFileSync24 } from "fs";
15488
- import path34 from "path";
15630
+ import path35 from "path";
15489
15631
  function getLocalVersion(packageRoot) {
15490
- const pkgPath = path34.join(packageRoot, "package.json");
15632
+ const pkgPath = path35.join(packageRoot, "package.json");
15491
15633
  const pkg = JSON.parse(readFileSync24(pkgPath, "utf-8"));
15492
15634
  return pkg.version;
15493
15635
  }
@@ -15534,10 +15676,47 @@ __export(update_exports, {
15534
15676
  });
15535
15677
  import { execSync as execSync12 } from "child_process";
15536
15678
  import { createInterface as createInterface4 } from "readline";
15679
+ async function runRestore() {
15680
+ console.log("\n\u{1F504} Restoring from update backup...");
15681
+ try {
15682
+ const manifest = await restoreFromBackup();
15683
+ console.log(` Restored ${manifest.files.length} file(s) from v${manifest.version} backup.`);
15684
+ console.log(` Backup was created at ${manifest.timestamp}`);
15685
+ console.log(`
15686
+ \u{1F4E5} Reinstalling @askexenow/exe-os@${manifest.version}...`);
15687
+ try {
15688
+ execSync12(`npm install -g @askexenow/exe-os@${manifest.version}`, {
15689
+ stdio: ["pipe", "pipe", "inherit"],
15690
+ timeout: 3e5
15691
+ });
15692
+ console.log(`
15693
+ \u2705 Restored to v${manifest.version}`);
15694
+ } catch {
15695
+ console.error(`
15696
+ \u26A0\uFE0F Could not reinstall v${manifest.version} via npm.`);
15697
+ console.error(` Your data files have been restored. Try manually:`);
15698
+ console.error(` npm install -g @askexenow/exe-os@${manifest.version}`);
15699
+ }
15700
+ try {
15701
+ await deleteBackup();
15702
+ } catch {
15703
+ }
15704
+ console.log("\n\u{1F680} Restore complete. Restart your sessions.\n");
15705
+ } catch (err) {
15706
+ console.error("\u274C Restore failed.");
15707
+ if (err instanceof Error) console.error(` ${err.message}`);
15708
+ process.exit(1);
15709
+ }
15710
+ }
15537
15711
  async function runUpdate(cliArgs) {
15538
15712
  const args2 = cliArgs ?? process.argv.slice(2);
15539
15713
  const autoMode = args2.includes("--auto") || args2.includes("-y");
15540
15714
  const checkOnly = args2.includes("--check");
15715
+ const restoreMode = args2.includes("--restore");
15716
+ if (restoreMode) {
15717
+ await runRestore();
15718
+ return;
15719
+ }
15541
15720
  const packageRoot = new URL("../..", import.meta.url).pathname;
15542
15721
  const result = checkForUpdate(packageRoot);
15543
15722
  if (result.error) {
@@ -15572,7 +15751,16 @@ async function runUpdate(cliArgs) {
15572
15751
  console.log("Update skipped.");
15573
15752
  process.exit(0);
15574
15753
  }
15575
- console.log("\n\u{1F9F9} Clearing npm cache...");
15754
+ console.log("\n\u{1F4BE} Backing up customer data...");
15755
+ try {
15756
+ const backupResult = await createUpdateBackup(result.localVersion);
15757
+ console.log(` Backed up ${backupResult.files.length} file(s) to ${BACKUP_DIR_NAME}/`);
15758
+ } catch (err) {
15759
+ console.error("\u274C Backup failed \u2014 aborting update to protect your data.");
15760
+ if (err instanceof Error) console.error(` ${err.message}`);
15761
+ process.exit(1);
15762
+ }
15763
+ console.log("\u{1F9F9} Clearing npm cache...");
15576
15764
  try {
15577
15765
  execSync12("npm cache clean --force", { stdio: "pipe" });
15578
15766
  console.log(" Done");
@@ -15587,8 +15775,9 @@ async function runUpdate(cliArgs) {
15587
15775
  timeout: 3e5
15588
15776
  });
15589
15777
  } catch (err) {
15590
- console.error("\n\u274C Update failed.");
15591
- console.error(" Try manually: npm install -g @askexenow/exe-os@latest");
15778
+ console.error("\n\u274C Update failed. Your backup is preserved.");
15779
+ console.error(` Restore with: exe-os update --restore`);
15780
+ console.error(" Or try manually: npm install -g @askexenow/exe-os@latest");
15592
15781
  if (err instanceof Error && err.message) {
15593
15782
  console.error(` Error: ${err.message.split("\n")[0]}`);
15594
15783
  }
@@ -15607,30 +15796,38 @@ async function runUpdate(cliArgs) {
15607
15796
  }
15608
15797
  }
15609
15798
  const remoteVersion = result.remoteVersion;
15799
+ const updateSucceeded = newVersion !== result.localVersion;
15610
15800
  if (newVersion === remoteVersion) {
15611
15801
  console.log(`
15612
15802
  \u2705 Updated to v${newVersion}`);
15613
- } else if (newVersion !== result.localVersion) {
15803
+ } else if (updateSucceeded) {
15614
15804
  console.log(`
15615
15805
  \u2705 Updated to v${newVersion} (latest: v${remoteVersion})`);
15616
15806
  } else {
15617
15807
  console.log(`
15618
15808
  \u26A0\uFE0F Version unchanged (v${newVersion}). npm cache may be stale.`);
15809
+ console.log(" Backup preserved. Restore with: exe-os update --restore");
15619
15810
  console.log(" Try: npm cache clean --force && npm install -g @askexenow/exe-os@latest");
15620
15811
  }
15812
+ if (updateSucceeded) {
15813
+ try {
15814
+ await deleteBackup();
15815
+ } catch {
15816
+ }
15817
+ }
15621
15818
  console.log(" Hooks re-wired, daemon restarted automatically.");
15622
15819
  console.log("");
15623
15820
  console.log(" \x1B[33m\u26A1 Run /mcp in each active Claude Code session to pick up new tools.\x1B[0m");
15624
15821
  console.log(" \x1B[2m(MCP servers can't hot-reload \u2014 Claude Code needs to reconnect them.)\x1B[0m");
15625
15822
  try {
15626
- const { existsSync: exists, readFileSync: readFile8 } = await import("fs");
15823
+ const { existsSync: exists, readFileSync: readFile9 } = await import("fs");
15627
15824
  const p = await import("path");
15628
15825
  const { homedir: home } = await import("os");
15629
15826
  const exeDir = p.default.join(home(), ".exe-os");
15630
15827
  const licKeyPath = p.default.join(exeDir, "license.key");
15631
15828
  const configPath = p.default.join(exeDir, "config.json");
15632
15829
  if (!exists(licKeyPath) && exists(configPath)) {
15633
- const cfg = JSON.parse(readFile8(configPath, "utf8"));
15830
+ const cfg = JSON.parse(readFile9(configPath, "utf8"));
15634
15831
  const cloud = cfg.cloud;
15635
15832
  if (cloud?.apiKey) {
15636
15833
  const { mirrorLicenseKey: mirrorLicenseKey2 } = await Promise.resolve().then(() => (init_license(), license_exports));
@@ -15646,6 +15843,7 @@ var init_update = __esm({
15646
15843
  "src/bin/update.ts"() {
15647
15844
  "use strict";
15648
15845
  init_is_main();
15846
+ init_update_backup();
15649
15847
  init_update_check();
15650
15848
  init_update_check();
15651
15849
  if (isMainModule(import.meta.url) && process.argv[1]?.includes("update")) {
@@ -20015,8 +20213,8 @@ var init_ErrorOverview = __esm({
20015
20213
  "use strict";
20016
20214
  init_Box();
20017
20215
  init_Text();
20018
- cleanupPath = (path46) => {
20019
- return path46?.replace(`file://${cwd()}/`, "");
20216
+ cleanupPath = (path47) => {
20217
+ return path47?.replace(`file://${cwd()}/`, "");
20020
20218
  };
20021
20219
  stackUtils = new StackUtils({
20022
20220
  cwd: cwd(),
@@ -21434,8 +21632,8 @@ var init_parse_keypress = __esm({
21434
21632
  57453: "isoLevel3Shift",
21435
21633
  57454: "isoLevel5Shift"
21436
21634
  };
21437
- isValidCodepoint = (cp) => cp >= 0 && cp <= 1114111 && !(cp >= 55296 && cp <= 57343);
21438
- safeFromCodePoint = (cp) => isValidCodepoint(cp) ? String.fromCodePoint(cp) : "?";
21635
+ isValidCodepoint = (cp2) => cp2 >= 0 && cp2 <= 1114111 && !(cp2 >= 55296 && cp2 <= 57343);
21636
+ safeFromCodePoint = (cp2) => isValidCodepoint(cp2) ? String.fromCodePoint(cp2) : "?";
21439
21637
  parseKittyKeypress = (s) => {
21440
21638
  const match = kittyKeyRe.exec(s);
21441
21639
  if (!match)
@@ -21449,7 +21647,7 @@ var init_parse_keypress = __esm({
21449
21647
  }
21450
21648
  let text;
21451
21649
  if (textField) {
21452
- text = textField.split(":").map((cp) => safeFromCodePoint(parseInt(cp, 10))).join("");
21650
+ text = textField.split(":").map((cp2) => safeFromCodePoint(parseInt(cp2, 10))).join("");
21453
21651
  }
21454
21652
  let name;
21455
21653
  let isPrintable;
@@ -22424,11 +22622,11 @@ function Footer() {
22424
22622
  } catch {
22425
22623
  }
22426
22624
  try {
22427
- const { existsSync: existsSync32 } = await import("fs");
22625
+ const { existsSync: existsSync33 } = await import("fs");
22428
22626
  const { join } = await import("path");
22429
22627
  const home = process.env.HOME ?? "";
22430
22628
  const pidPath = join(home, ".exe-os", "exed.pid");
22431
- setDaemon(existsSync32(pidPath) ? "running" : "stopped");
22629
+ setDaemon(existsSync33(pidPath) ? "running" : "stopped");
22432
22630
  } catch {
22433
22631
  setDaemon("unknown");
22434
22632
  }
@@ -24479,10 +24677,10 @@ var init_hooks = __esm({
24479
24677
  });
24480
24678
 
24481
24679
  // src/runtime/safety-checks.ts
24482
- import path35 from "path";
24483
- import os17 from "os";
24680
+ import path36 from "path";
24681
+ import os18 from "os";
24484
24682
  function checkPathSafety(filePath) {
24485
- const resolved = path35.resolve(filePath);
24683
+ const resolved = path36.resolve(filePath);
24486
24684
  for (const { pattern, reason } of BYPASS_IMMUNE_PATTERNS) {
24487
24685
  const matches = typeof pattern === "function" ? pattern(resolved) : pattern.test(resolved);
24488
24686
  if (matches) {
@@ -24492,7 +24690,7 @@ function checkPathSafety(filePath) {
24492
24690
  return { safe: true, bypassImmune: true };
24493
24691
  }
24494
24692
  function checkReadPathSafety(filePath) {
24495
- const resolved = path35.resolve(filePath);
24693
+ const resolved = path36.resolve(filePath);
24496
24694
  const credPatterns = BYPASS_IMMUNE_PATTERNS.filter(
24497
24695
  (p) => typeof p.pattern !== "function" && (p.reason.includes("secrets") || p.reason.includes("Private key") || p.reason.includes("Credential"))
24498
24696
  );
@@ -24507,7 +24705,7 @@ var HOME, BYPASS_IMMUNE_PATTERNS;
24507
24705
  var init_safety_checks = __esm({
24508
24706
  "src/runtime/safety-checks.ts"() {
24509
24707
  "use strict";
24510
- HOME = os17.homedir();
24708
+ HOME = os18.homedir();
24511
24709
  BYPASS_IMMUNE_PATTERNS = [
24512
24710
  {
24513
24711
  pattern: /\/\.git\/hooks\//,
@@ -24518,11 +24716,11 @@ var init_safety_checks = __esm({
24518
24716
  reason: "Git config can set hooks and command execution"
24519
24717
  },
24520
24718
  {
24521
- pattern: (p) => p.startsWith(path35.join(HOME, ".claude")),
24719
+ pattern: (p) => p.startsWith(path36.join(HOME, ".claude")),
24522
24720
  reason: "Claude configuration files are protected"
24523
24721
  },
24524
24722
  {
24525
- pattern: (p) => p.startsWith(path35.join(HOME, ".exe-os")),
24723
+ pattern: (p) => p.startsWith(path36.join(HOME, ".exe-os")),
24526
24724
  reason: "exe-os configuration files are protected"
24527
24725
  },
24528
24726
  {
@@ -24539,7 +24737,7 @@ var init_safety_checks = __esm({
24539
24737
  },
24540
24738
  {
24541
24739
  pattern: (p) => {
24542
- const name = path35.basename(p);
24740
+ const name = path36.basename(p);
24543
24741
  return [".bashrc", ".zshrc", ".profile", ".bash_profile", ".zprofile", ".zshenv"].includes(name);
24544
24742
  },
24545
24743
  reason: "Shell configuration files can execute arbitrary code on login"
@@ -24566,7 +24764,7 @@ __export(file_read_exports, {
24566
24764
  FileReadTool: () => FileReadTool
24567
24765
  });
24568
24766
  import fs3 from "fs/promises";
24569
- import path36 from "path";
24767
+ import path37 from "path";
24570
24768
  import { z } from "zod";
24571
24769
  function isBinary(buf) {
24572
24770
  for (let i = 0; i < buf.length; i++) {
@@ -24602,7 +24800,7 @@ var init_file_read = __esm({
24602
24800
  return { behavior: "allow" };
24603
24801
  },
24604
24802
  async call(input, context) {
24605
- const filePath = path36.isAbsolute(input.file_path) ? input.file_path : path36.resolve(context.cwd, input.file_path);
24803
+ const filePath = path37.isAbsolute(input.file_path) ? input.file_path : path37.resolve(context.cwd, input.file_path);
24606
24804
  let stat2;
24607
24805
  try {
24608
24806
  stat2 = await fs3.stat(filePath);
@@ -24642,7 +24840,7 @@ __export(glob_exports, {
24642
24840
  GlobTool: () => GlobTool
24643
24841
  });
24644
24842
  import fs4 from "fs/promises";
24645
- import path37 from "path";
24843
+ import path38 from "path";
24646
24844
  import { z as z2 } from "zod";
24647
24845
  async function walkDir(dir, maxDepth = 10) {
24648
24846
  const results = [];
@@ -24658,7 +24856,7 @@ async function walkDir(dir, maxDepth = 10) {
24658
24856
  if (entry.isDirectory() && (entry.name === "node_modules" || entry.name === ".git")) {
24659
24857
  continue;
24660
24858
  }
24661
- const fullPath = path37.join(current, entry.name);
24859
+ const fullPath = path38.join(current, entry.name);
24662
24860
  if (entry.isDirectory()) {
24663
24861
  await walk(fullPath, depth + 1);
24664
24862
  } else {
@@ -24692,11 +24890,11 @@ var init_glob = __esm({
24692
24890
  inputSchema: inputSchema2,
24693
24891
  isReadOnly: true,
24694
24892
  async call(input, context) {
24695
- const baseDir = input.path ? path37.isAbsolute(input.path) ? input.path : path37.resolve(context.cwd, input.path) : context.cwd;
24893
+ const baseDir = input.path ? path38.isAbsolute(input.path) ? input.path : path38.resolve(context.cwd, input.path) : context.cwd;
24696
24894
  try {
24697
24895
  const entries = await walkDir(baseDir);
24698
24896
  const matched = entries.filter(
24699
- (e) => simpleGlobMatch(path37.relative(baseDir, e.path), input.pattern)
24897
+ (e) => simpleGlobMatch(path38.relative(baseDir, e.path), input.pattern)
24700
24898
  );
24701
24899
  matched.sort((a, b) => b.mtime - a.mtime);
24702
24900
  if (matched.length === 0) {
@@ -24722,7 +24920,7 @@ __export(grep_exports, {
24722
24920
  });
24723
24921
  import { spawn as spawn2 } from "child_process";
24724
24922
  import fs5 from "fs/promises";
24725
- import path38 from "path";
24923
+ import path39 from "path";
24726
24924
  import { z as z3 } from "zod";
24727
24925
  function runRipgrep(input, searchPath, context) {
24728
24926
  return new Promise((resolve, reject) => {
@@ -24776,7 +24974,7 @@ async function nodeGrep(input, searchPath) {
24776
24974
  }
24777
24975
  for (const entry of entries) {
24778
24976
  if (entry.name === "node_modules" || entry.name === ".git") continue;
24779
- const fullPath = path38.join(dir, entry.name);
24977
+ const fullPath = path39.join(dir, entry.name);
24780
24978
  if (entry.isDirectory()) {
24781
24979
  await walk(fullPath);
24782
24980
  } else {
@@ -24822,7 +25020,7 @@ var init_grep = __esm({
24822
25020
  inputSchema: inputSchema3,
24823
25021
  isReadOnly: true,
24824
25022
  async call(input, context) {
24825
- const searchPath = input.path ? path38.isAbsolute(input.path) ? input.path : path38.resolve(context.cwd, input.path) : context.cwd;
25023
+ const searchPath = input.path ? path39.isAbsolute(input.path) ? input.path : path39.resolve(context.cwd, input.path) : context.cwd;
24826
25024
  try {
24827
25025
  const result = await runRipgrep(input, searchPath, context);
24828
25026
  return result;
@@ -24847,7 +25045,7 @@ __export(file_write_exports, {
24847
25045
  FileWriteTool: () => FileWriteTool
24848
25046
  });
24849
25047
  import fs6 from "fs/promises";
24850
- import path39 from "path";
25048
+ import path40 from "path";
24851
25049
  import { z as z4 } from "zod";
24852
25050
  var inputSchema4, FileWriteTool;
24853
25051
  var init_file_write = __esm({
@@ -24875,8 +25073,8 @@ var init_file_write = __esm({
24875
25073
  return { behavior: "allow" };
24876
25074
  },
24877
25075
  async call(input, context) {
24878
- const filePath = path39.isAbsolute(input.file_path) ? input.file_path : path39.resolve(context.cwd, input.file_path);
24879
- const dir = path39.dirname(filePath);
25076
+ const filePath = path40.isAbsolute(input.file_path) ? input.file_path : path40.resolve(context.cwd, input.file_path);
25077
+ const dir = path40.dirname(filePath);
24880
25078
  await fs6.mkdir(dir, { recursive: true });
24881
25079
  await fs6.writeFile(filePath, input.content, "utf-8");
24882
25080
  return {
@@ -24894,7 +25092,7 @@ __export(file_edit_exports, {
24894
25092
  FileEditTool: () => FileEditTool
24895
25093
  });
24896
25094
  import fs7 from "fs/promises";
24897
- import path40 from "path";
25095
+ import path41 from "path";
24898
25096
  import { z as z5 } from "zod";
24899
25097
  function countOccurrences(haystack, needle) {
24900
25098
  let count = 0;
@@ -24935,7 +25133,7 @@ var init_file_edit = __esm({
24935
25133
  return { behavior: "allow" };
24936
25134
  },
24937
25135
  async call(input, context) {
24938
- const filePath = path40.isAbsolute(input.file_path) ? input.file_path : path40.resolve(context.cwd, input.file_path);
25136
+ const filePath = path41.isAbsolute(input.file_path) ? input.file_path : path41.resolve(context.cwd, input.file_path);
24939
25137
  let content;
24940
25138
  try {
24941
25139
  content = await fs7.readFile(filePath, "utf-8");
@@ -25177,7 +25375,7 @@ var init_bash = __esm({
25177
25375
  // src/tui/views/CommandCenter.tsx
25178
25376
  import { useState as useState6, useEffect as useEffect8, useMemo as useMemo4, useCallback as useCallback4, useRef as useRef4 } from "react";
25179
25377
  import TextInput from "ink-text-input";
25180
- import path41 from "path";
25378
+ import path42 from "path";
25181
25379
  import { homedir as homedir6 } from "os";
25182
25380
  import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
25183
25381
  function CommandCenterView({
@@ -25212,13 +25410,13 @@ function CommandCenterView({
25212
25410
  const { createPermissionsFromPreset: createPermissionsFromPreset2, EMPLOYEE_PERMISSIONS: EMPLOYEE_PERMISSIONS2 } = await Promise.resolve().then(() => (init_permissions(), permissions_exports));
25213
25411
  const { getPresetByRole: getPresetByRole2 } = await Promise.resolve().then(() => (init_permission_presets(), permission_presets_exports));
25214
25412
  const { createDefaultHooks: createDefaultHooks2 } = await Promise.resolve().then(() => (init_hooks(), hooks_exports));
25215
- const { readFileSync: readFileSync28, existsSync: existsSync32 } = await import("fs");
25413
+ const { readFileSync: readFileSync28, existsSync: existsSync33 } = await import("fs");
25216
25414
  const { join } = await import("path");
25217
25415
  const { homedir: homedir8 } = await import("os");
25218
25416
  const configPath = join(homedir8(), ".exe-os", "config.json");
25219
25417
  let failoverChain = ["anthropic", "opencode", "gemini", "openai"];
25220
25418
  let providerConfigs = {};
25221
- if (existsSync32(configPath)) {
25419
+ if (existsSync33(configPath)) {
25222
25420
  try {
25223
25421
  const raw = JSON.parse(readFileSync28(configPath, "utf8"));
25224
25422
  if (Array.isArray(raw.failoverChain)) failoverChain = raw.failoverChain;
@@ -25426,7 +25624,7 @@ function CommandCenterView({
25426
25624
  const demoEntries = DEMO_PROJECTS.map((p) => ({
25427
25625
  projectName: p.projectName,
25428
25626
  exeSession: p.exeSession,
25429
- projectDir: path41.join(homedir6(), p.projectName),
25627
+ projectDir: path42.join(homedir6(), p.projectName),
25430
25628
  employeeCount: p.employees.length,
25431
25629
  activeCount: p.employees.filter((e) => e.status === "active").length,
25432
25630
  memoryCount: p.employees.length * 4e3,
@@ -25464,7 +25662,7 @@ function CommandCenterView({
25464
25662
  const { listSessions: listSessions2 } = await Promise.resolve().then(() => (init_session_registry(), session_registry_exports));
25465
25663
  const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
25466
25664
  const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
25467
- const { existsSync: existsSync32 } = await import("fs");
25665
+ const { existsSync: existsSync33 } = await import("fs");
25468
25666
  const { join } = await import("path");
25469
25667
  const client = getClient2();
25470
25668
  if (!client) {
@@ -25535,7 +25733,7 @@ function CommandCenterView({
25535
25733
  }
25536
25734
  const memoryCount = memoryCounts.get(name) ?? 0;
25537
25735
  const openTaskCount = openTaskCounts.get(name) ?? 0;
25538
- const hasGit = projectDir ? existsSync32(join(projectDir, ".git")) : false;
25736
+ const hasGit = projectDir ? existsSync33(join(projectDir, ".git")) : false;
25539
25737
  const type = hasGit ? "code" : memoryCount > 0 ? "code" : "automation";
25540
25738
  projectList.push({
25541
25739
  projectName: name,
@@ -25560,7 +25758,7 @@ function CommandCenterView({
25560
25758
  setHealth((h) => ({ ...h, memories: Number(totalResult.rows[0]?.cnt ?? 0) }));
25561
25759
  try {
25562
25760
  const pidPath = join(process.env.HOME ?? "", ".exe-os", "exed.pid");
25563
- setHealth((h) => ({ ...h, daemon: existsSync32(pidPath) ? "running" : "stopped" }));
25761
+ setHealth((h) => ({ ...h, daemon: existsSync33(pidPath) ? "running" : "stopped" }));
25564
25762
  } catch {
25565
25763
  }
25566
25764
  const activityResult = await client.execute(
@@ -26430,7 +26628,7 @@ var init_useOrchestrator = __esm({
26430
26628
 
26431
26629
  // src/tui/views/Sessions.tsx
26432
26630
  import React19, { useState as useState9, useEffect as useEffect11, useCallback as useCallback6 } from "react";
26433
- import path42 from "path";
26631
+ import path43 from "path";
26434
26632
  import { homedir as homedir7 } from "os";
26435
26633
  import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
26436
26634
  function isCoordinatorEntry(entry) {
@@ -26468,7 +26666,7 @@ function SessionsView({
26468
26666
  if (demo) {
26469
26667
  setProjects(DEMO_PROJECTS.map((p) => ({
26470
26668
  ...p,
26471
- projectDir: path42.join(homedir7(), p.projectName),
26669
+ projectDir: path43.join(homedir7(), p.projectName),
26472
26670
  employees: p.employees.map((e) => ({ ...e, attached: e.status === "active" }))
26473
26671
  })));
26474
26672
  return;
@@ -27683,11 +27881,11 @@ async function loadGatewayConfig() {
27683
27881
  state.running = false;
27684
27882
  }
27685
27883
  try {
27686
- const { existsSync: existsSync32, readFileSync: readFileSync28 } = await import("fs");
27884
+ const { existsSync: existsSync33, readFileSync: readFileSync28 } = await import("fs");
27687
27885
  const { join } = await import("path");
27688
27886
  const home = process.env.HOME ?? "";
27689
27887
  const configPath = join(home, ".exe-os", "gateway.json");
27690
- if (existsSync32(configPath)) {
27888
+ if (existsSync33(configPath)) {
27691
27889
  const raw = JSON.parse(readFileSync28(configPath, "utf8"));
27692
27890
  state.port = raw.port ?? 3100;
27693
27891
  state.gatewayUrl = raw.gatewayUrl ?? "";
@@ -28286,11 +28484,11 @@ function TeamView({ onBack, onViewSessions }) {
28286
28484
  setMembers(teamData);
28287
28485
  setDbError(null);
28288
28486
  try {
28289
- const { existsSync: existsSync32, readFileSync: readFileSync28 } = await import("fs");
28487
+ const { existsSync: existsSync33, readFileSync: readFileSync28 } = await import("fs");
28290
28488
  const { join } = await import("path");
28291
28489
  const home = process.env.HOME ?? "";
28292
28490
  const gatewayConfig = join(home, ".exe-os", "gateway.json");
28293
- if (existsSync32(gatewayConfig)) {
28491
+ if (existsSync33(gatewayConfig)) {
28294
28492
  const raw = JSON.parse(readFileSync28(gatewayConfig, "utf8"));
28295
28493
  if (raw.agents && raw.agents.length > 0) {
28296
28494
  setExternals(raw.agents.map((a) => ({
@@ -28471,8 +28669,8 @@ __export(wiki_client_exports, {
28471
28669
  listDocuments: () => listDocuments,
28472
28670
  listWorkspaces: () => listWorkspaces
28473
28671
  });
28474
- async function wikiFetch(config, path46, method = "GET", body) {
28475
- const url = `${config.baseUrl}/api/v1${path46}`;
28672
+ async function wikiFetch(config, path47, method = "GET", body) {
28673
+ const url = `${config.baseUrl}/api/v1${path47}`;
28476
28674
  const headers = {
28477
28675
  Authorization: `Bearer ${config.apiKey}`,
28478
28676
  "Content-Type": "application/json"
@@ -28505,7 +28703,7 @@ async function wikiFetch(config, path46, method = "GET", body) {
28505
28703
  }
28506
28704
  }
28507
28705
  if (!response.ok) {
28508
- throw new Error(`Wiki API ${method} ${path46}: ${response.status} ${response.statusText}`);
28706
+ throw new Error(`Wiki API ${method} ${path47}: ${response.status} ${response.statusText}`);
28509
28707
  }
28510
28708
  return response.json();
28511
28709
  } finally {
@@ -29099,12 +29297,12 @@ function SettingsView({ onBack }) {
29099
29297
  }
29100
29298
  setProviders(providerList);
29101
29299
  try {
29102
- const { existsSync: existsSync32 } = await import("fs");
29300
+ const { existsSync: existsSync33 } = await import("fs");
29103
29301
  const { join } = await import("path");
29104
29302
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
29105
29303
  const cfg = await loadConfig2();
29106
29304
  const home = process.env.HOME ?? "";
29107
- const hasKey = existsSync32(join(home, ".exe-os", "master.key"));
29305
+ const hasKey = existsSync33(join(home, ".exe-os", "master.key"));
29108
29306
  if (cfg.cloud) {
29109
29307
  setCloud({
29110
29308
  configured: true,
@@ -29117,7 +29315,7 @@ function SettingsView({ onBack }) {
29117
29315
  const pidPath = join(home, ".exe-os", "exed.pid");
29118
29316
  let daemon = "unknown";
29119
29317
  try {
29120
- daemon = existsSync32(pidPath) ? "running" : "stopped";
29318
+ daemon = existsSync33(pidPath) ? "running" : "stopped";
29121
29319
  } catch {
29122
29320
  }
29123
29321
  let version = "unknown";
@@ -29932,18 +30130,18 @@ __export(installer_exports2, {
29932
30130
  runOpenCodeInstaller: () => runOpenCodeInstaller,
29933
30131
  verifyOpenCodeHooks: () => verifyOpenCodeHooks
29934
30132
  });
29935
- import { readFile as readFile6, writeFile as writeFile7, mkdir as mkdir7 } from "fs/promises";
29936
- import { existsSync as existsSync29, readFileSync as readFileSync26 } from "fs";
29937
- import path43 from "path";
29938
- import os18 from "os";
29939
- async function registerOpenCodeMcp(packageRoot, homeDir = os18.homedir()) {
29940
- const configDir = path43.join(homeDir, ".config", "opencode");
29941
- const configPath = path43.join(configDir, "opencode.json");
29942
- await mkdir7(configDir, { recursive: true });
30133
+ import { readFile as readFile7, writeFile as writeFile8, mkdir as mkdir8 } from "fs/promises";
30134
+ import { existsSync as existsSync30, readFileSync as readFileSync26 } from "fs";
30135
+ import path44 from "path";
30136
+ import os19 from "os";
30137
+ async function registerOpenCodeMcp(packageRoot, homeDir = os19.homedir()) {
30138
+ const configDir = path44.join(homeDir, ".config", "opencode");
30139
+ const configPath = path44.join(configDir, "opencode.json");
30140
+ await mkdir8(configDir, { recursive: true });
29943
30141
  let config = {};
29944
- if (existsSync29(configPath)) {
30142
+ if (existsSync30(configPath)) {
29945
30143
  try {
29946
- config = JSON.parse(await readFile6(configPath, "utf-8"));
30144
+ config = JSON.parse(await readFile7(configPath, "utf-8"));
29947
30145
  } catch {
29948
30146
  config = {};
29949
30147
  }
@@ -29953,7 +30151,7 @@ async function registerOpenCodeMcp(packageRoot, homeDir = os18.homedir()) {
29953
30151
  }
29954
30152
  const newEntry = {
29955
30153
  type: "local",
29956
- command: ["node", path43.join(packageRoot, "dist", "mcp", "server.js")],
30154
+ command: ["node", path44.join(packageRoot, "dist", "mcp", "server.js")],
29957
30155
  enabled: true
29958
30156
  };
29959
30157
  const current = config.mcp["exe-os"];
@@ -29964,37 +30162,37 @@ async function registerOpenCodeMcp(packageRoot, homeDir = os18.homedir()) {
29964
30162
  if (!config.$schema) {
29965
30163
  config.$schema = "https://opencode.ai/config.json";
29966
30164
  }
29967
- await writeFile7(configPath, JSON.stringify(config, null, 2) + "\n");
30165
+ await writeFile8(configPath, JSON.stringify(config, null, 2) + "\n");
29968
30166
  return true;
29969
30167
  }
29970
- async function installOpenCodePlugin(packageRoot, homeDir = os18.homedir()) {
29971
- const pluginDir = path43.join(homeDir, ".config", "opencode", "plugins");
29972
- const pluginPath = path43.join(pluginDir, "exe-os.mjs");
29973
- await mkdir7(pluginDir, { recursive: true });
30168
+ async function installOpenCodePlugin(packageRoot, homeDir = os19.homedir()) {
30169
+ const pluginDir = path44.join(homeDir, ".config", "opencode", "plugins");
30170
+ const pluginPath = path44.join(pluginDir, "exe-os.mjs");
30171
+ await mkdir8(pluginDir, { recursive: true });
29974
30172
  const pluginContent = PLUGIN_TEMPLATE.replace(
29975
30173
  /__PACKAGE_ROOT__/g,
29976
30174
  packageRoot.replace(/\\/g, "\\\\")
29977
30175
  );
29978
- if (existsSync29(pluginPath)) {
29979
- const existing = await readFile6(pluginPath, "utf-8");
30176
+ if (existsSync30(pluginPath)) {
30177
+ const existing = await readFile7(pluginPath, "utf-8");
29980
30178
  if (existing === pluginContent) {
29981
30179
  return false;
29982
30180
  }
29983
30181
  }
29984
- await writeFile7(pluginPath, pluginContent);
30182
+ await writeFile8(pluginPath, pluginContent);
29985
30183
  return true;
29986
30184
  }
29987
- function verifyOpenCodeHooks(homeDir = os18.homedir()) {
29988
- const configPath = path43.join(homeDir, ".config", "opencode", "opencode.json");
29989
- const pluginPath = path43.join(homeDir, ".config", "opencode", "plugins", "exe-os.mjs");
29990
- if (!existsSync29(configPath)) return false;
30185
+ function verifyOpenCodeHooks(homeDir = os19.homedir()) {
30186
+ const configPath = path44.join(homeDir, ".config", "opencode", "opencode.json");
30187
+ const pluginPath = path44.join(homeDir, ".config", "opencode", "plugins", "exe-os.mjs");
30188
+ if (!existsSync30(configPath)) return false;
29991
30189
  try {
29992
30190
  const config = JSON.parse(readFileSync26(configPath, "utf-8"));
29993
30191
  if (!config.mcp?.["exe-os"]?.enabled) return false;
29994
30192
  } catch {
29995
30193
  return false;
29996
30194
  }
29997
- if (!existsSync29(pluginPath)) return false;
30195
+ if (!existsSync30(pluginPath)) return false;
29998
30196
  return true;
29999
30197
  }
30000
30198
  async function runOpenCodeInstaller(homeDir) {
@@ -30023,25 +30221,26 @@ var installer_exports3 = {};
30023
30221
  __export(installer_exports3, {
30024
30222
  installCodexStatusLine: () => installCodexStatusLine,
30025
30223
  mergeCodexHooks: () => mergeCodexHooks,
30224
+ registerCodexMcpServer: () => registerCodexMcpServer,
30026
30225
  runCodexInstaller: () => runCodexInstaller,
30027
30226
  verifyCodexHooks: () => verifyCodexHooks
30028
30227
  });
30029
- import { readFile as readFile7, writeFile as writeFile8, mkdir as mkdir8 } from "fs/promises";
30030
- import { existsSync as existsSync30 } from "fs";
30031
- import path44 from "path";
30032
- import os19 from "os";
30033
- async function mergeCodexHooks(packageRoot, homeDir = os19.homedir()) {
30034
- const codexDir = path44.join(homeDir, ".codex");
30035
- const hooksPath = path44.join(codexDir, "hooks.json");
30036
- const logsDir = path44.join(homeDir, ".exe-os", "logs");
30037
- const hookLogPath = path44.join(logsDir, "hooks.log");
30228
+ import { readFile as readFile8, writeFile as writeFile9, mkdir as mkdir9 } from "fs/promises";
30229
+ import { existsSync as existsSync31 } from "fs";
30230
+ import path45 from "path";
30231
+ import os20 from "os";
30232
+ async function mergeCodexHooks(packageRoot, homeDir = os20.homedir()) {
30233
+ const codexDir = path45.join(homeDir, ".codex");
30234
+ const hooksPath = path45.join(codexDir, "hooks.json");
30235
+ const logsDir = path45.join(homeDir, ".exe-os", "logs");
30236
+ const hookLogPath = path45.join(logsDir, "hooks.log");
30038
30237
  const logSuffix = ` 2>> "${hookLogPath}"`;
30039
- await mkdir8(codexDir, { recursive: true });
30040
- await mkdir8(logsDir, { recursive: true });
30238
+ await mkdir9(codexDir, { recursive: true });
30239
+ await mkdir9(logsDir, { recursive: true });
30041
30240
  let hooksJson = {};
30042
- if (existsSync30(hooksPath)) {
30241
+ if (existsSync31(hooksPath)) {
30043
30242
  try {
30044
- hooksJson = JSON.parse(await readFile7(hooksPath, "utf-8"));
30243
+ hooksJson = JSON.parse(await readFile8(hooksPath, "utf-8"));
30045
30244
  } catch {
30046
30245
  hooksJson = {};
30047
30246
  }
@@ -30056,7 +30255,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os19.homedir()) {
30056
30255
  hooks: [
30057
30256
  {
30058
30257
  type: "command",
30059
- command: `node "${path44.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
30258
+ command: `node "${path45.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
30060
30259
  timeout: 30,
30061
30260
  statusMessage: "exe-os: loading memory brief"
30062
30261
  }
@@ -30071,11 +30270,11 @@ async function mergeCodexHooks(packageRoot, homeDir = os19.homedir()) {
30071
30270
  hooks: [
30072
30271
  {
30073
30272
  type: "command",
30074
- command: `node "${path44.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
30273
+ command: `node "${path45.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
30075
30274
  },
30076
30275
  {
30077
30276
  type: "command",
30078
- command: `node "${path44.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
30277
+ command: `node "${path45.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
30079
30278
  }
30080
30279
  ]
30081
30280
  },
@@ -30087,11 +30286,11 @@ async function mergeCodexHooks(packageRoot, homeDir = os19.homedir()) {
30087
30286
  hooks: [
30088
30287
  {
30089
30288
  type: "command",
30090
- command: `node "${path44.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
30289
+ command: `node "${path45.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
30091
30290
  },
30092
30291
  {
30093
30292
  type: "command",
30094
- command: `node "${path44.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
30293
+ command: `node "${path45.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
30095
30294
  timeout: 5
30096
30295
  }
30097
30296
  ]
@@ -30104,7 +30303,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os19.homedir()) {
30104
30303
  hooks: [
30105
30304
  {
30106
30305
  type: "command",
30107
- command: `node "${path44.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
30306
+ command: `node "${path45.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
30108
30307
  }
30109
30308
  ]
30110
30309
  },
@@ -30117,7 +30316,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os19.homedir()) {
30117
30316
  hooks: [
30118
30317
  {
30119
30318
  type: "command",
30120
- command: `node "${path44.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
30319
+ command: `node "${path45.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
30121
30320
  }
30122
30321
  ]
30123
30322
  },
@@ -30145,12 +30344,12 @@ async function mergeCodexHooks(packageRoot, homeDir = os19.homedir()) {
30145
30344
  added++;
30146
30345
  }
30147
30346
  }
30148
- await writeFile8(hooksPath, JSON.stringify(hooksJson, null, 2) + "\n");
30347
+ await writeFile9(hooksPath, JSON.stringify(hooksJson, null, 2) + "\n");
30149
30348
  return { added, skipped };
30150
30349
  }
30151
- function verifyCodexHooks(homeDir = os19.homedir()) {
30152
- const hooksPath = path44.join(homeDir, ".codex", "hooks.json");
30153
- if (!existsSync30(hooksPath)) return false;
30350
+ function verifyCodexHooks(homeDir = os20.homedir()) {
30351
+ const hooksPath = path45.join(homeDir, ".codex", "hooks.json");
30352
+ if (!existsSync31(hooksPath)) return false;
30154
30353
  try {
30155
30354
  const hooksJson = JSON.parse(
30156
30355
  __require("fs").readFileSync(hooksPath, "utf-8")
@@ -30170,15 +30369,15 @@ function verifyCodexHooks(homeDir = os19.homedir()) {
30170
30369
  return false;
30171
30370
  }
30172
30371
  }
30173
- async function installCodexStatusLine(homeDir = os19.homedir()) {
30372
+ async function installCodexStatusLine(homeDir = os20.homedir()) {
30174
30373
  const prefs = loadPreferences(homeDir);
30175
30374
  if (prefs.codexStatusLine === false) return "opted-out";
30176
- const codexDir = path44.join(homeDir, ".codex");
30177
- const configPath = path44.join(codexDir, "config.toml");
30178
- await mkdir8(codexDir, { recursive: true });
30375
+ const codexDir = path45.join(homeDir, ".codex");
30376
+ const configPath = path45.join(codexDir, "config.toml");
30377
+ await mkdir9(codexDir, { recursive: true });
30179
30378
  let content = "";
30180
- if (existsSync30(configPath)) {
30181
- content = await readFile7(configPath, "utf-8");
30379
+ if (existsSync31(configPath)) {
30380
+ content = await readFile8(configPath, "utf-8");
30182
30381
  if (/\[tui\][\s\S]*?status_line\s*=/.test(content)) {
30183
30382
  return "already-configured";
30184
30383
  }
@@ -30191,14 +30390,55 @@ status_line = [${DEFAULT_CODEX_STATUS_LINE.map((s) => `"${s}"`).join(", ")}]`;
30191
30390
  const separator = content.length > 0 && !content.endsWith("\n") ? "\n\n" : content.length > 0 ? "\n" : "";
30192
30391
  content = content + separator + statusLineToml + "\n";
30193
30392
  }
30194
- await writeFile8(configPath, content);
30393
+ await writeFile9(configPath, content);
30195
30394
  return "installed";
30196
30395
  }
30396
+ async function registerCodexMcpServer(packageRoot, homeDir = os20.homedir()) {
30397
+ const codexDir = path45.join(homeDir, ".codex");
30398
+ const configPath = path45.join(codexDir, "config.toml");
30399
+ const serverJsPath = path45.join(packageRoot, "dist", "mcp", "server.js");
30400
+ await mkdir9(codexDir, { recursive: true });
30401
+ let content = "";
30402
+ if (existsSync31(configPath)) {
30403
+ content = await readFile8(configPath, "utf-8");
30404
+ }
30405
+ const sectionHeader = "[mcp_servers.exe-os]";
30406
+ const headerIndex = content.indexOf(sectionHeader);
30407
+ if (headerIndex !== -1) {
30408
+ const afterHeader = content.slice(headerIndex + sectionHeader.length);
30409
+ const nextSectionMatch = afterHeader.match(/\n\[(?!mcp_servers\.exe-os)/);
30410
+ const sectionEnd = nextSectionMatch ? headerIndex + sectionHeader.length + nextSectionMatch.index : content.length;
30411
+ const sectionContent = content.slice(headerIndex, sectionEnd);
30412
+ if (sectionContent.includes(serverJsPath)) {
30413
+ return "already-registered";
30414
+ }
30415
+ const newSection2 = `${sectionHeader}
30416
+ command = "node"
30417
+ args = ["${serverJsPath}"]
30418
+ `;
30419
+ content = content.slice(0, headerIndex) + newSection2 + content.slice(sectionEnd);
30420
+ await writeFile9(configPath, content);
30421
+ return "updated";
30422
+ }
30423
+ const newSection = `[mcp_servers.exe-os]
30424
+ command = "node"
30425
+ args = ["${serverJsPath}"]
30426
+ `;
30427
+ const separator = content.length > 0 && !content.endsWith("\n") ? "\n\n" : content.length > 0 ? "\n" : "";
30428
+ content = content + separator + newSection;
30429
+ await writeFile9(configPath, content);
30430
+ return "registered";
30431
+ }
30197
30432
  async function runCodexInstaller(homeDir) {
30198
30433
  const packageRoot = resolvePackageRoot();
30199
30434
  const result = await mergeCodexHooks(packageRoot, homeDir);
30200
30435
  process.stderr.write(
30201
30436
  `[exe-os] Codex hooks: ${result.added} added, ${result.skipped} unchanged
30437
+ `
30438
+ );
30439
+ const mcpResult = await registerCodexMcpServer(packageRoot, homeDir);
30440
+ process.stderr.write(
30441
+ `[exe-os] Codex MCP server: ${mcpResult}
30202
30442
  `
30203
30443
  );
30204
30444
  const statusResult = await installCodexStatusLine(homeDir);
@@ -30225,13 +30465,13 @@ var init_installer3 = __esm({
30225
30465
  });
30226
30466
 
30227
30467
  // src/bin/cli.ts
30228
- import { existsSync as existsSync31, readFileSync as readFileSync27, writeFileSync as writeFileSync20, readdirSync as readdirSync9, rmSync } from "fs";
30229
- import path45 from "path";
30230
- import os20 from "os";
30468
+ import { existsSync as existsSync32, readFileSync as readFileSync27, writeFileSync as writeFileSync20, readdirSync as readdirSync9, rmSync } from "fs";
30469
+ import path46 from "path";
30470
+ import os21 from "os";
30231
30471
  var args = process.argv.slice(2);
30232
30472
  if (args.includes("--version") || args.includes("-v")) {
30233
30473
  try {
30234
- const pkgPath = path45.join(path45.dirname(new URL(import.meta.url).pathname), "..", "..", "package.json");
30474
+ const pkgPath = path46.join(path46.dirname(new URL(import.meta.url).pathname), "..", "..", "package.json");
30235
30475
  const pkg = JSON.parse(readFileSync27(pkgPath, "utf8"));
30236
30476
  console.log(pkg.version);
30237
30477
  } catch {
@@ -30396,9 +30636,9 @@ ID: ${result.id}`);
30396
30636
  });
30397
30637
  await init_App2().then(() => App_exports);
30398
30638
  } else {
30399
- const claudeDir = path45.join(os20.homedir(), ".claude");
30400
- const settingsPath = path45.join(claudeDir, "settings.json");
30401
- const hasClaudeCode = existsSync31(settingsPath) && (() => {
30639
+ const claudeDir = path46.join(os21.homedir(), ".claude");
30640
+ const settingsPath = path46.join(claudeDir, "settings.json");
30641
+ const hasClaudeCode = existsSync32(settingsPath) && (() => {
30402
30642
  try {
30403
30643
  const raw = readFileSync27(settingsPath, "utf8");
30404
30644
  return raw.includes("exe-os") || raw.includes("exe-mem");
@@ -30410,8 +30650,8 @@ ID: ${result.id}`);
30410
30650
  const { DEFAULT_COORDINATOR_TEMPLATE_NAME: DEFAULT_COORDINATOR_TEMPLATE_NAME2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
30411
30651
  let cooName = DEFAULT_COORDINATOR_TEMPLATE_NAME2;
30412
30652
  try {
30413
- const rosterPath = path45.join(os20.homedir(), ".exe-os", "exe-employees.json");
30414
- if (existsSync31(rosterPath)) {
30653
+ const rosterPath = path46.join(os21.homedir(), ".exe-os", "exe-employees.json");
30654
+ if (existsSync32(rosterPath)) {
30415
30655
  const roster = JSON.parse(readFileSync27(rosterPath, "utf8"));
30416
30656
  const coo = roster.find((e) => e.role === "COO");
30417
30657
  if (coo) cooName = coo.name;
@@ -30476,11 +30716,11 @@ async function runCodexInstall() {
30476
30716
  }
30477
30717
  }
30478
30718
  async function runClaudeCheck() {
30479
- const claudeDir = path45.join(os20.homedir(), ".claude");
30480
- const settingsPath = path45.join(claudeDir, "settings.json");
30481
- const claudeJsonPath = path45.join(os20.homedir(), ".claude.json");
30719
+ const claudeDir = path46.join(os21.homedir(), ".claude");
30720
+ const settingsPath = path46.join(claudeDir, "settings.json");
30721
+ const claudeJsonPath = path46.join(os21.homedir(), ".claude.json");
30482
30722
  let ok = true;
30483
- if (existsSync31(settingsPath)) {
30723
+ if (existsSync32(settingsPath)) {
30484
30724
  let settings;
30485
30725
  try {
30486
30726
  settings = JSON.parse(readFileSync27(settingsPath, "utf8"));
@@ -30509,7 +30749,7 @@ async function runClaudeCheck() {
30509
30749
  console.log("\x1B[31m\u2717\x1B[0m settings.json not found");
30510
30750
  ok = false;
30511
30751
  }
30512
- if (existsSync31(claudeJsonPath)) {
30752
+ if (existsSync32(claudeJsonPath)) {
30513
30753
  let claudeJson;
30514
30754
  try {
30515
30755
  claudeJson = JSON.parse(readFileSync27(claudeJsonPath, "utf8"));
@@ -30531,8 +30771,8 @@ async function runClaudeCheck() {
30531
30771
  console.log("\x1B[31m\u2717\x1B[0m claude.json not found");
30532
30772
  ok = false;
30533
30773
  }
30534
- const skillsDir = path45.join(claudeDir, "skills");
30535
- if (existsSync31(skillsDir)) {
30774
+ const skillsDir = path46.join(claudeDir, "skills");
30775
+ if (existsSync32(skillsDir)) {
30536
30776
  console.log("\x1B[32m\u2713\x1B[0m Slash skills directory exists");
30537
30777
  } else {
30538
30778
  console.log("\x1B[31m\u2717\x1B[0m Slash skills directory missing");
@@ -30548,15 +30788,15 @@ async function runClaudeCheck() {
30548
30788
  async function runClaudeUninstall(flags = []) {
30549
30789
  const dryRun = flags.includes("--dry-run");
30550
30790
  const purge = flags.includes("--purge");
30551
- const homeDir = os20.homedir();
30552
- const claudeDir = path45.join(homeDir, ".claude");
30553
- const settingsPath = path45.join(claudeDir, "settings.json");
30554
- const claudeJsonPath = path45.join(homeDir, ".claude.json");
30555
- const exeOsDir = path45.join(homeDir, ".exe-os");
30791
+ const homeDir = os21.homedir();
30792
+ const claudeDir = path46.join(homeDir, ".claude");
30793
+ const settingsPath = path46.join(claudeDir, "settings.json");
30794
+ const claudeJsonPath = path46.join(homeDir, ".claude.json");
30795
+ const exeOsDir = path46.join(homeDir, ".exe-os");
30556
30796
  let removed = 0;
30557
30797
  const log = (msg) => console.log(dryRun ? `[dry-run] ${msg}` : msg);
30558
30798
  let settings = {};
30559
- if (existsSync31(settingsPath)) {
30799
+ if (existsSync32(settingsPath)) {
30560
30800
  try {
30561
30801
  settings = JSON.parse(readFileSync27(settingsPath, "utf8"));
30562
30802
  } catch {
@@ -30603,7 +30843,7 @@ async function runClaudeUninstall(flags = []) {
30603
30843
  removed++;
30604
30844
  }
30605
30845
  }
30606
- if (existsSync31(claudeJsonPath)) {
30846
+ if (existsSync32(claudeJsonPath)) {
30607
30847
  const raw = readFileSync27(claudeJsonPath, "utf8");
30608
30848
  if (raw.length > 1e6) {
30609
30849
  console.error("claude.json exceeds 1 MB \u2014 skipping parse.");
@@ -30633,14 +30873,14 @@ async function runClaudeUninstall(flags = []) {
30633
30873
  }
30634
30874
  }
30635
30875
  }
30636
- const skillsDir = path45.join(claudeDir, "skills");
30637
- if (existsSync31(skillsDir)) {
30876
+ const skillsDir = path46.join(claudeDir, "skills");
30877
+ if (existsSync32(skillsDir)) {
30638
30878
  let skillCount = 0;
30639
30879
  try {
30640
30880
  const entries = readdirSync9(skillsDir);
30641
30881
  for (const entry of entries) {
30642
30882
  if (entry.startsWith("exe")) {
30643
- const fullPath = path45.join(skillsDir, entry);
30883
+ const fullPath = path46.join(skillsDir, entry);
30644
30884
  if (!dryRun) rmSync(fullPath, { recursive: true, force: true });
30645
30885
  skillCount++;
30646
30886
  }
@@ -30652,8 +30892,8 @@ async function runClaudeUninstall(flags = []) {
30652
30892
  removed++;
30653
30893
  }
30654
30894
  }
30655
- const claudeMdPath = path45.join(claudeDir, "CLAUDE.md");
30656
- if (existsSync31(claudeMdPath)) {
30895
+ const claudeMdPath = path46.join(claudeDir, "CLAUDE.md");
30896
+ if (existsSync32(claudeMdPath)) {
30657
30897
  const content = readFileSync27(claudeMdPath, "utf8");
30658
30898
  const startMarker = "<!-- exe-os:orchestration-start -->";
30659
30899
  const endMarker = "<!-- exe-os:orchestration-end -->";
@@ -30666,14 +30906,14 @@ async function runClaudeUninstall(flags = []) {
30666
30906
  removed++;
30667
30907
  }
30668
30908
  }
30669
- const agentsDir = path45.join(claudeDir, "agents");
30670
- if (existsSync31(agentsDir)) {
30909
+ const agentsDir = path46.join(claudeDir, "agents");
30910
+ if (existsSync32(agentsDir)) {
30671
30911
  let agentCount = 0;
30672
30912
  try {
30673
30913
  const entries = readdirSync9(agentsDir).filter((f) => f.endsWith(".md"));
30674
30914
  let knownNames = /* @__PURE__ */ new Set();
30675
- const rosterPath = path45.join(exeOsDir, "exe-employees.json");
30676
- if (existsSync31(rosterPath)) {
30915
+ const rosterPath = path46.join(exeOsDir, "exe-employees.json");
30916
+ if (existsSync32(rosterPath)) {
30677
30917
  try {
30678
30918
  const roster = JSON.parse(readFileSync27(rosterPath, "utf8"));
30679
30919
  knownNames = new Set(roster.map((e) => e.name));
@@ -30683,7 +30923,7 @@ async function runClaudeUninstall(flags = []) {
30683
30923
  for (const entry of entries) {
30684
30924
  const name = entry.replace(/\.md$/, "");
30685
30925
  if (knownNames.has(name)) {
30686
- if (!dryRun) rmSync(path45.join(agentsDir, entry), { force: true });
30926
+ if (!dryRun) rmSync(path46.join(agentsDir, entry), { force: true });
30687
30927
  agentCount++;
30688
30928
  }
30689
30929
  }
@@ -30694,14 +30934,14 @@ async function runClaudeUninstall(flags = []) {
30694
30934
  removed++;
30695
30935
  }
30696
30936
  }
30697
- const projectsDir = path45.join(claudeDir, "projects");
30698
- if (existsSync31(projectsDir)) {
30937
+ const projectsDir = path46.join(claudeDir, "projects");
30938
+ if (existsSync32(projectsDir)) {
30699
30939
  let projectCount = 0;
30700
30940
  try {
30701
30941
  const projects = readdirSync9(projectsDir);
30702
30942
  for (const proj of projects) {
30703
- const projSettings = path45.join(projectsDir, proj, "settings.json");
30704
- if (!existsSync31(projSettings)) continue;
30943
+ const projSettings = path46.join(projectsDir, proj, "settings.json");
30944
+ if (!existsSync32(projSettings)) continue;
30705
30945
  try {
30706
30946
  const pSettings = JSON.parse(readFileSync27(projSettings, "utf8"));
30707
30947
  let changed = false;
@@ -30737,18 +30977,18 @@ async function runClaudeUninstall(flags = []) {
30737
30977
  };
30738
30978
  const exeBinPath = findExeBin3();
30739
30979
  if (!exeBinPath) throw new Error("exe-os not found in PATH");
30740
- const binDir = path45.dirname(exeBinPath);
30980
+ const binDir = path46.dirname(exeBinPath);
30741
30981
  let symlinkCount = 0;
30742
- const rosterPath = path45.join(exeOsDir, "exe-employees.json");
30743
- if (existsSync31(rosterPath)) {
30982
+ const rosterPath = path46.join(exeOsDir, "exe-employees.json");
30983
+ if (existsSync32(rosterPath)) {
30744
30984
  const roster = JSON.parse(readFileSync27(rosterPath, "utf8"));
30745
30985
  const { DEFAULT_COORDINATOR_TEMPLATE_NAME: DEFAULT_COORDINATOR_TEMPLATE_NAME2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
30746
30986
  const coordinatorName = roster.find((e) => e.role?.toLowerCase() === "coo")?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME2;
30747
30987
  for (const emp of roster) {
30748
30988
  if (emp.name === coordinatorName) continue;
30749
30989
  for (const suffix of ["", "-opencode"]) {
30750
- const linkPath = path45.join(binDir, `${emp.name}${suffix}`);
30751
- if (existsSync31(linkPath)) {
30990
+ const linkPath = path46.join(binDir, `${emp.name}${suffix}`);
30991
+ if (existsSync32(linkPath)) {
30752
30992
  if (!dryRun) rmSync(linkPath, { force: true });
30753
30993
  symlinkCount++;
30754
30994
  }
@@ -30761,7 +31001,7 @@ async function runClaudeUninstall(flags = []) {
30761
31001
  }
30762
31002
  } catch {
30763
31003
  }
30764
- if (purge && existsSync31(exeOsDir)) {
31004
+ if (purge && existsSync32(exeOsDir)) {
30765
31005
  if (!dryRun) {
30766
31006
  process.stdout.write("\x1B[33m\u26A0 This will delete all memories, identities, and agent data.\x1B[0m\n");
30767
31007
  process.stdout.write(" Removing ~/.exe-os...\n");
@@ -30786,7 +31026,7 @@ async function checkForUpdateOnBoot() {
30786
31026
  const config = await loadConfig2();
30787
31027
  if (!config.autoUpdate.checkOnBoot) return;
30788
31028
  const { checkForUpdate: checkForUpdate2 } = await Promise.resolve().then(() => (init_update(), update_exports));
30789
- const packageRoot = path45.resolve(
31029
+ const packageRoot = path46.resolve(
30790
31030
  new URL("../..", import.meta.url).pathname
30791
31031
  );
30792
31032
  const result = checkForUpdate2(packageRoot);
@@ -30846,7 +31086,7 @@ async function runActivate(key) {
30846
31086
  const idTemplate = getIdentityTemplate(identityKey);
30847
31087
  if (idTemplate) {
30848
31088
  const idPath = identityPath2(name);
30849
- const dir = path45.dirname(idPath);
31089
+ const dir = path46.dirname(idPath);
30850
31090
  if (!fs8.existsSync(dir)) fs8.mkdirSync(dir, { recursive: true });
30851
31091
  fs8.writeFileSync(idPath, idTemplate.replace(/^agent_id: \w+/m, `agent_id: ${name}`), "utf-8");
30852
31092
  }