@askexenow/exe-os 0.9.8 → 0.9.9

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 (101) hide show
  1. package/dist/bin/backfill-conversations.js +222 -49
  2. package/dist/bin/backfill-responses.js +221 -48
  3. package/dist/bin/backfill-vectors.js +225 -52
  4. package/dist/bin/cleanup-stale-review-tasks.js +150 -28
  5. package/dist/bin/cli.js +1295 -856
  6. package/dist/bin/exe-agent-config.js +36 -8
  7. package/dist/bin/exe-agent.js +14 -4
  8. package/dist/bin/exe-assign.js +221 -48
  9. package/dist/bin/exe-boot.js +778 -427
  10. package/dist/bin/exe-call.js +41 -13
  11. package/dist/bin/exe-cloud.js +163 -58
  12. package/dist/bin/exe-dispatch.js +276 -139
  13. package/dist/bin/exe-doctor.js +145 -27
  14. package/dist/bin/exe-export-behaviors.js +141 -23
  15. package/dist/bin/exe-forget.js +137 -19
  16. package/dist/bin/exe-gateway.js +677 -388
  17. package/dist/bin/exe-heartbeat.js +227 -108
  18. package/dist/bin/exe-kill.js +138 -20
  19. package/dist/bin/exe-launch-agent.js +172 -39
  20. package/dist/bin/exe-link.js +291 -100
  21. package/dist/bin/exe-new-employee.js +214 -106
  22. package/dist/bin/exe-pending-messages.js +395 -33
  23. package/dist/bin/exe-pending-notifications.js +684 -99
  24. package/dist/bin/exe-pending-reviews.js +420 -74
  25. package/dist/bin/exe-rename.js +147 -49
  26. package/dist/bin/exe-review.js +138 -20
  27. package/dist/bin/exe-search.js +240 -69
  28. package/dist/bin/exe-session-cleanup.js +440 -250
  29. package/dist/bin/exe-settings.js +61 -17
  30. package/dist/bin/exe-start-codex.js +158 -39
  31. package/dist/bin/exe-start-opencode.js +157 -38
  32. package/dist/bin/exe-status.js +151 -29
  33. package/dist/bin/exe-team.js +138 -20
  34. package/dist/bin/git-sweep.js +404 -212
  35. package/dist/bin/graph-backfill.js +137 -19
  36. package/dist/bin/graph-export.js +140 -22
  37. package/dist/bin/install.js +90 -61
  38. package/dist/bin/scan-tasks.js +412 -220
  39. package/dist/bin/setup.js +564 -293
  40. package/dist/bin/shard-migrate.js +139 -21
  41. package/dist/bin/update.js +138 -49
  42. package/dist/bin/wiki-sync.js +137 -19
  43. package/dist/gateway/index.js +533 -320
  44. package/dist/hooks/bug-report-worker.js +344 -193
  45. package/dist/hooks/codex-stop-task-finalizer.js +4678 -0
  46. package/dist/hooks/commit-complete.js +402 -210
  47. package/dist/hooks/error-recall.js +245 -74
  48. package/dist/hooks/exe-heartbeat-hook.js +16 -6
  49. package/dist/hooks/ingest-worker.js +3423 -3157
  50. package/dist/hooks/ingest.js +832 -97
  51. package/dist/hooks/instructions-loaded.js +227 -54
  52. package/dist/hooks/notification.js +216 -43
  53. package/dist/hooks/post-compact.js +239 -62
  54. package/dist/hooks/pre-compact.js +408 -216
  55. package/dist/hooks/pre-tool-use.js +268 -90
  56. package/dist/hooks/prompt-ingest-worker.js +352 -102
  57. package/dist/hooks/prompt-submit.js +541 -328
  58. package/dist/hooks/response-ingest-worker.js +372 -122
  59. package/dist/hooks/session-end.js +443 -240
  60. package/dist/hooks/session-start.js +313 -127
  61. package/dist/hooks/stop.js +293 -98
  62. package/dist/hooks/subagent-stop.js +239 -62
  63. package/dist/hooks/summary-worker.js +568 -236
  64. package/dist/index.js +538 -324
  65. package/dist/lib/agent-config.js +28 -6
  66. package/dist/lib/cloud-sync.js +284 -105
  67. package/dist/lib/config.js +30 -10
  68. package/dist/lib/consolidation.js +16 -6
  69. package/dist/lib/database.js +123 -25
  70. package/dist/lib/db-daemon-client.js +73 -19
  71. package/dist/lib/db.js +123 -25
  72. package/dist/lib/device-registry.js +133 -35
  73. package/dist/lib/embedder.js +107 -32
  74. package/dist/lib/employee-templates.js +14 -4
  75. package/dist/lib/employees.js +41 -13
  76. package/dist/lib/exe-daemon-client.js +88 -22
  77. package/dist/lib/exe-daemon.js +935 -587
  78. package/dist/lib/hybrid-search.js +240 -69
  79. package/dist/lib/identity.js +18 -8
  80. package/dist/lib/license.js +133 -48
  81. package/dist/lib/messaging.js +116 -56
  82. package/dist/lib/reminders.js +14 -4
  83. package/dist/lib/schedules.js +137 -19
  84. package/dist/lib/skill-learning.js +33 -6
  85. package/dist/lib/store.js +137 -19
  86. package/dist/lib/task-router.js +14 -4
  87. package/dist/lib/tasks.js +280 -234
  88. package/dist/lib/tmux-routing.js +172 -125
  89. package/dist/lib/token-spend.js +26 -8
  90. package/dist/mcp/server.js +1326 -609
  91. package/dist/mcp/tools/complete-reminder.js +14 -4
  92. package/dist/mcp/tools/create-reminder.js +14 -4
  93. package/dist/mcp/tools/create-task.js +306 -248
  94. package/dist/mcp/tools/deactivate-behavior.js +16 -6
  95. package/dist/mcp/tools/list-reminders.js +14 -4
  96. package/dist/mcp/tools/list-tasks.js +123 -107
  97. package/dist/mcp/tools/send-message.js +75 -29
  98. package/dist/mcp/tools/update-task.js +1848 -199
  99. package/dist/runtime/index.js +441 -248
  100. package/dist/tui/App.js +761 -424
  101. package/package.json +1 -1
@@ -15,9 +15,34 @@ var __export = (target, all) => {
15
15
  __defProp(target, name, { get: all[name], enumerable: true });
16
16
  };
17
17
 
18
+ // src/lib/secure-files.ts
19
+ import { chmodSync, existsSync, mkdirSync } from "fs";
20
+ import { chmod, mkdir } from "fs/promises";
21
+ function ensurePrivateDirSync(dirPath) {
22
+ mkdirSync(dirPath, { recursive: true, mode: PRIVATE_DIR_MODE });
23
+ try {
24
+ chmodSync(dirPath, PRIVATE_DIR_MODE);
25
+ } catch {
26
+ }
27
+ }
28
+ function enforcePrivateFileSync(filePath) {
29
+ try {
30
+ if (existsSync(filePath)) chmodSync(filePath, PRIVATE_FILE_MODE);
31
+ } catch {
32
+ }
33
+ }
34
+ var PRIVATE_DIR_MODE, PRIVATE_FILE_MODE;
35
+ var init_secure_files = __esm({
36
+ "src/lib/secure-files.ts"() {
37
+ "use strict";
38
+ PRIVATE_DIR_MODE = 448;
39
+ PRIVATE_FILE_MODE = 384;
40
+ }
41
+ });
42
+
18
43
  // src/lib/config.ts
19
- import { readFile, writeFile, mkdir, chmod } from "fs/promises";
20
- import { readFileSync, existsSync, renameSync } from "fs";
44
+ import { readFile, writeFile } from "fs/promises";
45
+ import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
21
46
  import path from "path";
22
47
  import os from "os";
23
48
  function resolveDataDir() {
@@ -25,7 +50,7 @@ function resolveDataDir() {
25
50
  if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
26
51
  const newDir = path.join(os.homedir(), ".exe-os");
27
52
  const legacyDir = path.join(os.homedir(), ".exe-mem");
28
- if (!existsSync(newDir) && existsSync(legacyDir)) {
53
+ if (!existsSync2(newDir) && existsSync2(legacyDir)) {
29
54
  try {
30
55
  renameSync(legacyDir, newDir);
31
56
  process.stderr.write(`[exe-os] Migrated data directory: ~/.exe-mem \u2192 ~/.exe-os
@@ -40,6 +65,7 @@ var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CON
40
65
  var init_config = __esm({
41
66
  "src/lib/config.ts"() {
42
67
  "use strict";
68
+ init_secure_files();
43
69
  EXE_AI_DIR = resolveDataDir();
44
70
  DB_PATH = path.join(EXE_AI_DIR, "memories.db");
45
71
  MODELS_DIR = path.join(EXE_AI_DIR, "models");
@@ -146,10 +172,10 @@ __export(agent_config_exports, {
146
172
  saveAgentConfig: () => saveAgentConfig,
147
173
  setAgentRuntime: () => setAgentRuntime
148
174
  });
149
- import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2, mkdirSync } from "fs";
175
+ import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync3 } from "fs";
150
176
  import path2 from "path";
151
177
  function loadAgentConfig() {
152
- if (!existsSync2(AGENT_CONFIG_PATH)) return {};
178
+ if (!existsSync3(AGENT_CONFIG_PATH)) return {};
153
179
  try {
154
180
  return JSON.parse(readFileSync2(AGENT_CONFIG_PATH, "utf-8"));
155
181
  } catch {
@@ -158,8 +184,9 @@ function loadAgentConfig() {
158
184
  }
159
185
  function saveAgentConfig(config) {
160
186
  const dir = path2.dirname(AGENT_CONFIG_PATH);
161
- if (!existsSync2(dir)) mkdirSync(dir, { recursive: true });
187
+ ensurePrivateDirSync(dir);
162
188
  writeFileSync(AGENT_CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
189
+ enforcePrivateFileSync(AGENT_CONFIG_PATH);
163
190
  }
164
191
  function getAgentRuntime(agentId) {
165
192
  const config = loadAgentConfig();
@@ -199,6 +226,7 @@ var init_agent_config = __esm({
199
226
  "use strict";
200
227
  init_config();
201
228
  init_runtime_table();
229
+ init_secure_files();
202
230
  AGENT_CONFIG_PATH = path2.join(EXE_AI_DIR, "agent-config.json");
203
231
  KNOWN_RUNTIMES = {
204
232
  claude: ["claude-opus-4", "claude-sonnet-4", "claude-haiku-4.5"],
@@ -246,7 +274,7 @@ __export(employees_exports, {
246
274
  validateEmployeeName: () => validateEmployeeName
247
275
  });
248
276
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
249
- import { existsSync as existsSync3, symlinkSync, readlinkSync, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
277
+ import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
250
278
  import { execSync } from "child_process";
251
279
  import path3 from "path";
252
280
  import os2 from "os";
@@ -285,7 +313,7 @@ function validateEmployeeName(name) {
285
313
  return { valid: true };
286
314
  }
287
315
  async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
288
- if (!existsSync3(employeesPath)) {
316
+ if (!existsSync4(employeesPath)) {
289
317
  return [];
290
318
  }
291
319
  const raw = await readFile2(employeesPath, "utf-8");
@@ -300,7 +328,7 @@ async function saveEmployees(employees, employeesPath = EMPLOYEES_PATH) {
300
328
  await writeFile2(employeesPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
301
329
  }
302
330
  function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
303
- if (!existsSync3(employeesPath)) return [];
331
+ if (!existsSync4(employeesPath)) return [];
304
332
  try {
305
333
  return JSON.parse(readFileSync3(employeesPath, "utf-8"));
306
334
  } catch {
@@ -348,7 +376,7 @@ function appendToCoordinatorTeam(employee) {
348
376
  const coordinator = getCoordinatorEmployee(loadEmployeesSync());
349
377
  if (!coordinator) return;
350
378
  const idPath = path3.join(IDENTITY_DIR, `${coordinator.name}.md`);
351
- if (!existsSync3(idPath)) return;
379
+ if (!existsSync4(idPath)) return;
352
380
  const content = readFileSync3(idPath, "utf-8");
353
381
  if (content.includes(`**${capitalize(employee.name)}`)) return;
354
382
  const teamMatch = content.match(TEAM_SECTION_RE);
@@ -402,9 +430,9 @@ async function normalizeRosterCase(rosterPath) {
402
430
  const identityDir = path3.join(os2.homedir(), ".exe-os", "identity");
403
431
  const oldPath = path3.join(identityDir, `${oldName}.md`);
404
432
  const newPath = path3.join(identityDir, `${emp.name}.md`);
405
- if (existsSync3(oldPath) && !existsSync3(newPath)) {
433
+ if (existsSync4(oldPath) && !existsSync4(newPath)) {
406
434
  renameSync2(oldPath, newPath);
407
- } else if (existsSync3(oldPath) && oldPath !== newPath) {
435
+ } else if (existsSync4(oldPath) && oldPath !== newPath) {
408
436
  const content = readFileSync3(oldPath, "utf-8");
409
437
  writeFileSync2(newPath, content, "utf-8");
410
438
  if (oldPath.toLowerCase() !== newPath.toLowerCase()) {
@@ -447,7 +475,7 @@ function registerBinSymlinks(name) {
447
475
  for (const suffix of ["", "-opencode"]) {
448
476
  const linkName = `${name}${suffix}`;
449
477
  const linkPath = path3.join(binDir, linkName);
450
- if (existsSync3(linkPath)) {
478
+ if (existsSync4(linkPath)) {
451
479
  skipped.push(linkName);
452
480
  continue;
453
481
  }
@@ -478,7 +506,7 @@ var init_employees = __esm({
478
506
  import os3 from "os";
479
507
  import path4 from "path";
480
508
  import {
481
- existsSync as existsSync4,
509
+ existsSync as existsSync5,
482
510
  lstatSync,
483
511
  mkdirSync as mkdirSync2,
484
512
  readlinkSync as readlinkSync2,
@@ -497,7 +525,7 @@ function ensureAgentSymlink(agentId, homeDir = os3.homedir()) {
497
525
  const target = identitySourcePath(homeDir, agentId);
498
526
  const link = claudeAgentLinkPath(homeDir, agentId);
499
527
  mkdirSync2(claudeAgentsDir(homeDir), { recursive: true });
500
- if (existsSync4(link)) {
528
+ if (existsSync5(link)) {
501
529
  let stat;
502
530
  try {
503
531
  stat = lstatSync(link);
@@ -566,12 +594,12 @@ var init_mcp_prefix = __esm({
566
594
  });
567
595
 
568
596
  // src/lib/preferences.ts
569
- import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
597
+ import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
570
598
  import path5 from "path";
571
599
  import os4 from "os";
572
600
  function loadPreferences(homeDir = os4.homedir()) {
573
601
  const configPath = path5.join(homeDir, ".exe-os", "config.json");
574
- if (!existsSync5(configPath)) return {};
602
+ if (!existsSync6(configPath)) return {};
575
603
  try {
576
604
  const config = JSON.parse(readFileSync4(configPath, "utf-8"));
577
605
  return config.preferences ?? {};
@@ -582,12 +610,13 @@ function loadPreferences(homeDir = os4.homedir()) {
582
610
  var init_preferences = __esm({
583
611
  "src/lib/preferences.ts"() {
584
612
  "use strict";
613
+ init_secure_files();
585
614
  }
586
615
  });
587
616
 
588
617
  // src/adapters/claude/installer.ts
589
618
  import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, readdir } from "fs/promises";
590
- import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync4, copyFileSync, mkdirSync as mkdirSync4 } from "fs";
619
+ import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync4, copyFileSync, mkdirSync as mkdirSync3 } from "fs";
591
620
  import path6 from "path";
592
621
  import os5 from "os";
593
622
  import { execSync as execSync2 } from "child_process";
@@ -598,7 +627,7 @@ function resolvePackageRoot() {
598
627
  const root = path6.parse(dir).root;
599
628
  while (dir !== root) {
600
629
  const pkgPath = path6.join(dir, "package.json");
601
- if (existsSync6(pkgPath)) {
630
+ if (existsSync7(pkgPath)) {
602
631
  try {
603
632
  const pkg = JSON.parse(readFileSync5(pkgPath, "utf-8"));
604
633
  if (pkg.name === "@askexenow/exe-os" || pkg.name === "exe-os") return dir;
@@ -614,7 +643,7 @@ async function copySlashCommands(packageRoot, homeDir = os5.homedir()) {
614
643
  let skipped = 0;
615
644
  const skillsBase = path6.join(homeDir, ".claude", "skills");
616
645
  const exeDir = path6.join(packageRoot, "src", "commands", "exe");
617
- if (existsSync6(exeDir)) {
646
+ if (existsSync7(exeDir)) {
618
647
  const entries = await readdir(exeDir);
619
648
  const mdFiles = entries.filter((f) => f.endsWith(".md"));
620
649
  for (const file of mdFiles) {
@@ -629,7 +658,7 @@ async function copySlashCommands(packageRoot, homeDir = os5.homedir()) {
629
658
  }
630
659
  }
631
660
  const topLevelSrc = path6.join(packageRoot, "src", "commands", "exe.md");
632
- if (existsSync6(topLevelSrc)) {
661
+ if (existsSync7(topLevelSrc)) {
633
662
  const destDir = path6.join(skillsBase, "exe");
634
663
  await mkdir3(destDir, { recursive: true });
635
664
  const destPath = path6.join(destDir, "SKILL.md");
@@ -655,7 +684,7 @@ name: ${skillName}
655
684
  `);
656
685
  }
657
686
  }
658
- if (existsSync6(destPath)) {
687
+ if (existsSync7(destPath)) {
659
688
  const existing = await readFile3(destPath, "utf-8");
660
689
  if (existing === content) return false;
661
690
  }
@@ -665,7 +694,7 @@ name: ${skillName}
665
694
  async function registerMcpServer(packageRoot, homeDir = os5.homedir()) {
666
695
  const claudeJsonPath = path6.join(homeDir, ".claude.json");
667
696
  let claudeJson = {};
668
- if (existsSync6(claudeJsonPath)) {
697
+ if (existsSync7(claudeJsonPath)) {
669
698
  try {
670
699
  claudeJson = JSON.parse(await readFile3(claudeJsonPath, "utf-8"));
671
700
  } catch {
@@ -682,21 +711,21 @@ async function registerMcpServer(packageRoot, homeDir = os5.homedir()) {
682
711
  env: {}
683
712
  };
684
713
  const currentMem = claudeJson.mcpServers[MCP_LEGACY_KEY];
685
- const currentOs = claudeJson.mcpServers[MCP_PRIMARY_KEY];
686
714
  const memMatches = currentMem && JSON.stringify(currentMem) === JSON.stringify(newEntry);
687
- const osMatches = currentOs && JSON.stringify(currentOs) === JSON.stringify(newEntry);
688
- if (memMatches && osMatches) {
715
+ if (claudeJson.mcpServers[MCP_PRIMARY_KEY]) {
716
+ delete claudeJson.mcpServers[MCP_PRIMARY_KEY];
717
+ }
718
+ if (memMatches && !claudeJson.mcpServers[MCP_PRIMARY_KEY]) {
689
719
  await cleanSettingsJsonMcp(path6.join(homeDir, ".claude", "settings.json"));
690
720
  return false;
691
721
  }
692
722
  claudeJson.mcpServers[MCP_LEGACY_KEY] = newEntry;
693
- claudeJson.mcpServers[MCP_PRIMARY_KEY] = newEntry;
694
723
  await writeFile3(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
695
724
  await cleanSettingsJsonMcp(path6.join(homeDir, ".claude", "settings.json"));
696
725
  return true;
697
726
  }
698
727
  async function cleanSettingsJsonMcp(settingsPath) {
699
- if (!existsSync6(settingsPath)) return;
728
+ if (!existsSync7(settingsPath)) return;
700
729
  try {
701
730
  const settings = JSON.parse(await readFile3(settingsPath, "utf-8"));
702
731
  const servers = settings.mcpServers;
@@ -723,7 +752,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
723
752
  const logSuffix = ` 2>> "${hookLogPath}"`;
724
753
  await mkdir3(logsDir, { recursive: true });
725
754
  let settings = {};
726
- if (existsSync6(settingsPath)) {
755
+ if (existsSync7(settingsPath)) {
727
756
  try {
728
757
  settings = JSON.parse(await readFile3(settingsPath, "utf-8"));
729
758
  } catch {
@@ -991,7 +1020,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
991
1020
  }
992
1021
  async function cleanOldShellFunctions(homeDir = os5.homedir()) {
993
1022
  const rosterPath = path6.join(homeDir, ".exe-os", "exe-employees.json");
994
- if (!existsSync6(rosterPath)) return 0;
1023
+ if (!existsSync7(rosterPath)) return 0;
995
1024
  let employees;
996
1025
  try {
997
1026
  employees = JSON.parse(await readFile3(rosterPath, "utf-8"));
@@ -1012,7 +1041,7 @@ async function cleanOldShellFunctions(homeDir = os5.homedir()) {
1012
1041
  const REMOVED_MARKER = "# Removed by exe-os \u2014 wrappers now at ~/.exe-os/bin/";
1013
1042
  let totalRemoved = 0;
1014
1043
  for (const rcPath of rcFiles) {
1015
- if (!existsSync6(rcPath)) continue;
1044
+ if (!existsSync7(rcPath)) continue;
1016
1045
  let content;
1017
1046
  try {
1018
1047
  content = await readFile3(rcPath, "utf-8");
@@ -1145,13 +1174,13 @@ async function installStatusLine(packageRoot, homeDir = os5.homedir()) {
1145
1174
  const claudeDir = path6.join(homeDir, ".claude");
1146
1175
  await mkdir3(claudeDir, { recursive: true });
1147
1176
  const assetPath = path6.join(packageRoot, "dist", "assets", "statusline-command.sh");
1148
- if (!existsSync6(assetPath)) return "asset-missing";
1177
+ if (!existsSync7(assetPath)) return "asset-missing";
1149
1178
  const destScript = path6.join(claudeDir, "statusline-command.sh");
1150
1179
  const assetContent = await readFile3(assetPath, "utf-8");
1151
1180
  await writeFile3(destScript, assetContent, { mode: 493 });
1152
1181
  const settingsPath = path6.join(claudeDir, "settings.json");
1153
1182
  let settings = {};
1154
- if (existsSync6(settingsPath)) {
1183
+ if (existsSync7(settingsPath)) {
1155
1184
  try {
1156
1185
  settings = JSON.parse(await readFile3(settingsPath, "utf-8"));
1157
1186
  } catch {
@@ -1190,7 +1219,7 @@ async function runInstaller(homeDir) {
1190
1219
  );
1191
1220
  const resolvedHome = homeDir ?? os5.homedir();
1192
1221
  const exeWorkspace = path6.join(resolvedHome, "exe");
1193
- if (!existsSync6(exeWorkspace)) {
1222
+ if (!existsSync7(exeWorkspace)) {
1194
1223
  try {
1195
1224
  await mkdir3(path6.join(exeWorkspace, "content"), { recursive: true });
1196
1225
  await mkdir3(path6.join(exeWorkspace, "operations"), { recursive: true });
@@ -1237,17 +1266,17 @@ function setupTmux(home) {
1237
1266
  const sourceLine = "source-file ~/.exe-os/tmux.conf";
1238
1267
  const pkgRoot = resolvePackageRoot();
1239
1268
  const assetPath = path6.join(pkgRoot, "dist", "assets", "tmux.conf");
1240
- if (!existsSync6(assetPath)) {
1269
+ if (!existsSync7(assetPath)) {
1241
1270
  process.stderr.write(`exe-os: tmux.conf asset not found at ${assetPath} \u2014 skipping tmux setup
1242
1271
  `);
1243
1272
  return;
1244
1273
  }
1245
- mkdirSync4(exeDir, { recursive: true });
1274
+ mkdirSync3(exeDir, { recursive: true });
1246
1275
  copyFileSync(assetPath, exeTmuxConf);
1247
- if (existsSync6(userTmuxConf)) {
1276
+ if (existsSync7(userTmuxConf)) {
1248
1277
  const existing = readFileSync5(userTmuxConf, "utf8");
1249
1278
  if (!existing.includes(sourceLine)) {
1250
- if (!existsSync6(backupPath)) {
1279
+ if (!existsSync7(backupPath)) {
1251
1280
  copyFileSync(userTmuxConf, backupPath);
1252
1281
  process.stderr.write(`exe-os: backed up existing tmux config to ${backupPath}
1253
1282
  `);
@@ -1270,7 +1299,7 @@ function setupGhostty(home) {
1270
1299
  const homeDir = home ?? os5.homedir();
1271
1300
  const xdgConfig = path6.join(homeDir, ".config", "ghostty");
1272
1301
  const macConfig = path6.join(homeDir, "Library", "Application Support", "com.mitchellh.ghostty");
1273
- const ghosttyInstalled = existsSync6(xdgConfig) || existsSync6(macConfig) || (() => {
1302
+ const ghosttyInstalled = existsSync7(xdgConfig) || existsSync7(macConfig) || (() => {
1274
1303
  try {
1275
1304
  execSync2("which ghostty 2>/dev/null");
1276
1305
  return true;
@@ -1283,28 +1312,28 @@ function setupGhostty(home) {
1283
1312
  }
1284
1313
  const pkgRoot = resolvePackageRoot();
1285
1314
  const assetPath = path6.join(pkgRoot, "dist", "assets", "ghostty.conf");
1286
- if (!existsSync6(assetPath)) {
1315
+ if (!existsSync7(assetPath)) {
1287
1316
  process.stderr.write("exe-os: ghostty.conf asset not found \u2014 skipping Ghostty setup\n");
1288
1317
  return;
1289
1318
  }
1290
1319
  const configDir = xdgConfig;
1291
1320
  const configPath = path6.join(configDir, "config");
1292
1321
  const backupPath = path6.join(configDir, "config.backup");
1293
- mkdirSync4(configDir, { recursive: true });
1322
+ mkdirSync3(configDir, { recursive: true });
1294
1323
  const START_MARKER = "# \u2500\u2500 exe-os:ghostty-start \u2500\u2500";
1295
1324
  const END_MARKER = "# \u2500\u2500 exe-os:ghostty-end \u2500\u2500";
1296
1325
  const assetContent = readFileSync5(assetPath, "utf8").trim();
1297
1326
  const markedSection = `${START_MARKER}
1298
1327
  ${assetContent}
1299
1328
  ${END_MARKER}`;
1300
- if (existsSync6(configPath)) {
1329
+ if (existsSync7(configPath)) {
1301
1330
  const existing = readFileSync5(configPath, "utf8");
1302
1331
  if (existing.includes(START_MARKER) && existing.includes(END_MARKER)) {
1303
1332
  const before = existing.slice(0, existing.indexOf(START_MARKER));
1304
1333
  const after = existing.slice(existing.indexOf(END_MARKER) + END_MARKER.length);
1305
1334
  writeFileSync4(configPath, `${before}${markedSection}${after}`);
1306
1335
  } else if (existing.includes("Exe OS")) {
1307
- if (!existsSync6(backupPath)) {
1336
+ if (!existsSync7(backupPath)) {
1308
1337
  copyFileSync(configPath, backupPath);
1309
1338
  process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
1310
1339
  `);
@@ -1312,7 +1341,7 @@ ${END_MARKER}`;
1312
1341
  writeFileSync4(configPath, `${markedSection}
1313
1342
  `);
1314
1343
  } else {
1315
- if (!existsSync6(backupPath)) {
1344
+ if (!existsSync7(backupPath)) {
1316
1345
  copyFileSync(configPath, backupPath);
1317
1346
  process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
1318
1347
  `);
@@ -1371,7 +1400,7 @@ __export(installer_exports, {
1371
1400
  verifyCodexHooks: () => verifyCodexHooks
1372
1401
  });
1373
1402
  import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir4 } from "fs/promises";
1374
- import { existsSync as existsSync8 } from "fs";
1403
+ import { existsSync as existsSync9 } from "fs";
1375
1404
  import path8 from "path";
1376
1405
  import os6 from "os";
1377
1406
  async function mergeCodexHooks(packageRoot, homeDir = os6.homedir()) {
@@ -1383,7 +1412,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os6.homedir()) {
1383
1412
  await mkdir4(codexDir, { recursive: true });
1384
1413
  await mkdir4(logsDir, { recursive: true });
1385
1414
  let hooksJson = {};
1386
- if (existsSync8(hooksPath)) {
1415
+ if (existsSync9(hooksPath)) {
1387
1416
  try {
1388
1417
  hooksJson = JSON.parse(await readFile4(hooksPath, "utf-8"));
1389
1418
  } catch {
@@ -1494,7 +1523,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os6.homedir()) {
1494
1523
  }
1495
1524
  function verifyCodexHooks(homeDir = os6.homedir()) {
1496
1525
  const hooksPath = path8.join(homeDir, ".codex", "hooks.json");
1497
- if (!existsSync8(hooksPath)) return false;
1526
+ if (!existsSync9(hooksPath)) return false;
1498
1527
  try {
1499
1528
  const hooksJson = JSON.parse(
1500
1529
  __require("fs").readFileSync(hooksPath, "utf-8")
@@ -1521,7 +1550,7 @@ async function installCodexStatusLine(homeDir = os6.homedir()) {
1521
1550
  const configPath = path8.join(codexDir, "config.toml");
1522
1551
  await mkdir4(codexDir, { recursive: true });
1523
1552
  let content = "";
1524
- if (existsSync8(configPath)) {
1553
+ if (existsSync9(configPath)) {
1525
1554
  content = await readFile4(configPath, "utf-8");
1526
1555
  if (/\[tui\][\s\S]*?status_line\s*=/.test(content)) {
1527
1556
  return "already-configured";
@@ -1570,18 +1599,18 @@ var init_installer2 = __esm({
1570
1599
 
1571
1600
  // src/bin/install.ts
1572
1601
  init_installer();
1573
- import { existsSync as existsSync9, readFileSync as readFileSync7, unlinkSync as unlinkSync3, readdirSync as readdirSync2, openSync, closeSync } from "fs";
1602
+ import { existsSync as existsSync10, readFileSync as readFileSync7, unlinkSync as unlinkSync3, readdirSync as readdirSync2, openSync, closeSync } from "fs";
1574
1603
  import { spawn, execSync as execSync3 } from "child_process";
1575
1604
  import path9 from "path";
1576
1605
  import os7 from "os";
1577
1606
 
1578
1607
  // src/lib/session-wrappers.ts
1579
1608
  import {
1580
- existsSync as existsSync7,
1609
+ existsSync as existsSync8,
1581
1610
  readFileSync as readFileSync6,
1582
1611
  writeFileSync as writeFileSync5,
1583
- mkdirSync as mkdirSync5,
1584
- chmodSync,
1612
+ mkdirSync as mkdirSync4,
1613
+ chmodSync as chmodSync2,
1585
1614
  readdirSync,
1586
1615
  unlinkSync as unlinkSync2
1587
1616
  } from "fs";
@@ -1592,16 +1621,16 @@ function generateSessionWrappers(packageRoot, homeDir) {
1592
1621
  const home = homeDir ?? homedir();
1593
1622
  const binDir = path7.join(home, ".exe-os", "bin");
1594
1623
  const rosterPath = path7.join(home, ".exe-os", "exe-employees.json");
1595
- mkdirSync5(binDir, { recursive: true });
1624
+ mkdirSync4(binDir, { recursive: true });
1596
1625
  const exeStartDst = path7.join(binDir, "exe-start");
1597
1626
  const candidates = [
1598
1627
  path7.join(packageRoot, "dist", "bin", "exe-start.sh"),
1599
1628
  path7.join(packageRoot, "src", "bin", "exe-start.sh")
1600
1629
  ];
1601
1630
  for (const src of candidates) {
1602
- if (existsSync7(src)) {
1631
+ if (existsSync8(src)) {
1603
1632
  writeFileSync5(exeStartDst, readFileSync6(src));
1604
- chmodSync(exeStartDst, 493);
1633
+ chmodSync2(exeStartDst, 493);
1605
1634
  break;
1606
1635
  }
1607
1636
  }
@@ -1636,7 +1665,7 @@ exec "${exeStartDst}" "$0" "$@"
1636
1665
  for (let n = 1; n <= MAX_N; n++) {
1637
1666
  const wrapperPath = path7.join(binDir, `${emp.name}${n}`);
1638
1667
  writeFileSync5(wrapperPath, wrapperContent);
1639
- chmodSync(wrapperPath, 493);
1668
+ chmodSync2(wrapperPath, 493);
1640
1669
  created++;
1641
1670
  }
1642
1671
  }
@@ -1646,7 +1675,7 @@ exec "${exeStartDst}" "$0" "$@"
1646
1675
  ];
1647
1676
  let codexLauncher = null;
1648
1677
  for (const c of codexLauncherCandidates) {
1649
- if (existsSync7(c)) {
1678
+ if (existsSync8(c)) {
1650
1679
  codexLauncher = c;
1651
1680
  break;
1652
1681
  }
@@ -1658,7 +1687,7 @@ exec "${exeStartDst}" "$0" "$@"
1658
1687
  exec node "${codexLauncher}" --agent ${emp.name} "$@"
1659
1688
  `;
1660
1689
  writeFileSync5(wrapperPath, content);
1661
- chmodSync(wrapperPath, 493);
1690
+ chmodSync2(wrapperPath, 493);
1662
1691
  created++;
1663
1692
  }
1664
1693
  }
@@ -1709,7 +1738,7 @@ function restartDaemon() {
1709
1738
  const pidPath = path9.join(EXE_DIR, "exed.pid");
1710
1739
  const sockPath = path9.join(EXE_DIR, "exed.sock");
1711
1740
  try {
1712
- if (existsSync9(pidPath)) {
1741
+ if (existsSync10(pidPath)) {
1713
1742
  const pid = parseInt(readFileSync7(pidPath, "utf8").trim(), 10);
1714
1743
  if (!isNaN(pid) && pid > 0) {
1715
1744
  try {
@@ -1752,7 +1781,7 @@ function restartDaemon() {
1752
1781
  }
1753
1782
  try {
1754
1783
  const wpDir = path9.join(EXE_DIR, "worker-pids");
1755
- if (existsSync9(wpDir)) {
1784
+ if (existsSync10(wpDir)) {
1756
1785
  for (const f of readdirSync2(wpDir)) {
1757
1786
  try {
1758
1787
  unlinkSync3(path9.join(wpDir, f));
@@ -1783,7 +1812,7 @@ function restartDaemon() {
1783
1812
  try {
1784
1813
  const pkgRoot = resolvePackageRoot();
1785
1814
  const daemonPath = path9.join(pkgRoot, "dist", "lib", "exe-daemon.js");
1786
- if (!existsSync9(daemonPath)) {
1815
+ if (!existsSync10(daemonPath)) {
1787
1816
  process.stderr.write(`exe-os: daemon not found at ${daemonPath} \u2014 skipping respawn
1788
1817
  `);
1789
1818
  return;