@askexenow/exe-os 0.9.7 → 0.9.8

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 (95) hide show
  1. package/dist/bin/backfill-conversations.js +754 -79
  2. package/dist/bin/backfill-responses.js +752 -77
  3. package/dist/bin/backfill-vectors.js +752 -77
  4. package/dist/bin/cleanup-stale-review-tasks.js +657 -35
  5. package/dist/bin/cli.js +1388 -605
  6. package/dist/bin/exe-agent-config.js +123 -95
  7. package/dist/bin/exe-agent.js +41 -25
  8. package/dist/bin/exe-assign.js +732 -57
  9. package/dist/bin/exe-boot.js +784 -153
  10. package/dist/bin/exe-call.js +209 -138
  11. package/dist/bin/exe-cloud.js +35 -12
  12. package/dist/bin/exe-dispatch.js +692 -70
  13. package/dist/bin/exe-doctor.js +648 -26
  14. package/dist/bin/exe-export-behaviors.js +650 -20
  15. package/dist/bin/exe-forget.js +635 -13
  16. package/dist/bin/exe-gateway.js +1053 -271
  17. package/dist/bin/exe-heartbeat.js +665 -43
  18. package/dist/bin/exe-kill.js +646 -16
  19. package/dist/bin/exe-launch-agent.js +887 -97
  20. package/dist/bin/exe-link.js +658 -43
  21. package/dist/bin/exe-new-employee.js +378 -177
  22. package/dist/bin/exe-pending-messages.js +656 -34
  23. package/dist/bin/exe-pending-notifications.js +635 -13
  24. package/dist/bin/exe-pending-reviews.js +659 -37
  25. package/dist/bin/exe-rename.js +645 -30
  26. package/dist/bin/exe-review.js +635 -13
  27. package/dist/bin/exe-search.js +771 -88
  28. package/dist/bin/exe-session-cleanup.js +834 -150
  29. package/dist/bin/exe-settings.js +127 -91
  30. package/dist/bin/exe-start-codex.js +729 -94
  31. package/dist/bin/exe-start-opencode.js +717 -82
  32. package/dist/bin/exe-status.js +657 -35
  33. package/dist/bin/exe-team.js +635 -13
  34. package/dist/bin/git-sweep.js +720 -89
  35. package/dist/bin/graph-backfill.js +643 -13
  36. package/dist/bin/graph-export.js +646 -16
  37. package/dist/bin/install.js +596 -193
  38. package/dist/bin/scan-tasks.js +724 -93
  39. package/dist/bin/setup.js +1038 -210
  40. package/dist/bin/shard-migrate.js +645 -15
  41. package/dist/bin/wiki-sync.js +646 -16
  42. package/dist/gateway/index.js +1027 -245
  43. package/dist/hooks/bug-report-worker.js +891 -170
  44. package/dist/hooks/commit-complete.js +718 -87
  45. package/dist/hooks/error-recall.js +776 -93
  46. package/dist/hooks/exe-heartbeat-hook.js +85 -71
  47. package/dist/hooks/ingest-worker.js +840 -156
  48. package/dist/hooks/ingest.js +90 -73
  49. package/dist/hooks/instructions-loaded.js +669 -38
  50. package/dist/hooks/notification.js +661 -30
  51. package/dist/hooks/post-compact.js +674 -43
  52. package/dist/hooks/pre-compact.js +718 -87
  53. package/dist/hooks/pre-tool-use.js +872 -125
  54. package/dist/hooks/prompt-ingest-worker.js +758 -83
  55. package/dist/hooks/prompt-submit.js +1060 -319
  56. package/dist/hooks/response-ingest-worker.js +758 -83
  57. package/dist/hooks/session-end.js +721 -90
  58. package/dist/hooks/session-start.js +1031 -207
  59. package/dist/hooks/stop.js +680 -49
  60. package/dist/hooks/subagent-stop.js +674 -43
  61. package/dist/hooks/summary-worker.js +816 -132
  62. package/dist/index.js +1015 -232
  63. package/dist/lib/cloud-sync.js +663 -48
  64. package/dist/lib/consolidation.js +26 -3
  65. package/dist/lib/database.js +626 -18
  66. package/dist/lib/db.js +2261 -0
  67. package/dist/lib/device-registry.js +640 -25
  68. package/dist/lib/embedder.js +96 -43
  69. package/dist/lib/employee-templates.js +16 -0
  70. package/dist/lib/employees.js +259 -83
  71. package/dist/lib/exe-daemon-client.js +101 -63
  72. package/dist/lib/exe-daemon.js +894 -162
  73. package/dist/lib/hybrid-search.js +771 -88
  74. package/dist/lib/identity.js +27 -7
  75. package/dist/lib/messaging.js +55 -28
  76. package/dist/lib/reminders.js +21 -1
  77. package/dist/lib/schedules.js +636 -14
  78. package/dist/lib/skill-learning.js +21 -1
  79. package/dist/lib/store.js +643 -13
  80. package/dist/lib/task-router.js +82 -71
  81. package/dist/lib/tasks.js +98 -71
  82. package/dist/lib/tmux-routing.js +87 -60
  83. package/dist/lib/token-spend.js +26 -6
  84. package/dist/mcp/server.js +1784 -458
  85. package/dist/mcp/tools/complete-reminder.js +21 -1
  86. package/dist/mcp/tools/create-reminder.js +21 -1
  87. package/dist/mcp/tools/create-task.js +290 -164
  88. package/dist/mcp/tools/deactivate-behavior.js +24 -4
  89. package/dist/mcp/tools/list-reminders.js +21 -1
  90. package/dist/mcp/tools/list-tasks.js +195 -38
  91. package/dist/mcp/tools/send-message.js +58 -31
  92. package/dist/mcp/tools/update-task.js +75 -48
  93. package/dist/runtime/index.js +720 -89
  94. package/dist/tui/App.js +853 -123
  95. package/package.json +3 -2
@@ -1,6 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
5
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
6
+ }) : x)(function(x) {
7
+ if (typeof require !== "undefined") return require.apply(this, arguments);
8
+ throw Error('Dynamic require of "' + x + '" is not supported');
9
+ });
4
10
  var __esm = (fn, res) => function __init() {
5
11
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
12
  };
@@ -100,6 +106,118 @@ var init_config = __esm({
100
106
  }
101
107
  });
102
108
 
109
+ // src/lib/runtime-table.ts
110
+ var RUNTIME_TABLE, DEFAULT_RUNTIME;
111
+ var init_runtime_table = __esm({
112
+ "src/lib/runtime-table.ts"() {
113
+ "use strict";
114
+ RUNTIME_TABLE = {
115
+ codex: {
116
+ binary: "codex",
117
+ launchMode: "interactive",
118
+ autoApproveFlag: "--dangerously-bypass-approvals-and-sandbox",
119
+ inlineFlag: "--no-alt-screen",
120
+ apiKeyEnv: "OPENAI_API_KEY",
121
+ defaultModel: "gpt-5.4"
122
+ },
123
+ opencode: {
124
+ binary: "opencode",
125
+ launchMode: "exec",
126
+ autoApproveFlag: "--dangerously-skip-permissions",
127
+ inlineFlag: "",
128
+ apiKeyEnv: "ANTHROPIC_API_KEY",
129
+ defaultModel: "anthropic/claude-sonnet-4-6"
130
+ }
131
+ };
132
+ DEFAULT_RUNTIME = "claude";
133
+ }
134
+ });
135
+
136
+ // src/lib/agent-config.ts
137
+ var agent_config_exports = {};
138
+ __export(agent_config_exports, {
139
+ AGENT_CONFIG_PATH: () => AGENT_CONFIG_PATH,
140
+ DEFAULT_MODELS: () => DEFAULT_MODELS,
141
+ KNOWN_RUNTIMES: () => KNOWN_RUNTIMES,
142
+ RUNTIME_LABELS: () => RUNTIME_LABELS,
143
+ clearAgentRuntime: () => clearAgentRuntime,
144
+ getAgentRuntime: () => getAgentRuntime,
145
+ loadAgentConfig: () => loadAgentConfig,
146
+ saveAgentConfig: () => saveAgentConfig,
147
+ setAgentRuntime: () => setAgentRuntime
148
+ });
149
+ import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2, mkdirSync } from "fs";
150
+ import path2 from "path";
151
+ function loadAgentConfig() {
152
+ if (!existsSync2(AGENT_CONFIG_PATH)) return {};
153
+ try {
154
+ return JSON.parse(readFileSync2(AGENT_CONFIG_PATH, "utf-8"));
155
+ } catch {
156
+ return {};
157
+ }
158
+ }
159
+ function saveAgentConfig(config) {
160
+ const dir = path2.dirname(AGENT_CONFIG_PATH);
161
+ if (!existsSync2(dir)) mkdirSync(dir, { recursive: true });
162
+ writeFileSync(AGENT_CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
163
+ }
164
+ function getAgentRuntime(agentId) {
165
+ const config = loadAgentConfig();
166
+ const entry = config[agentId];
167
+ if (entry) return entry;
168
+ const orgDefault = config["default"];
169
+ if (orgDefault) return orgDefault;
170
+ return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
171
+ }
172
+ function setAgentRuntime(agentId, runtime, model) {
173
+ const knownModels = KNOWN_RUNTIMES[runtime];
174
+ if (!knownModels) {
175
+ return {
176
+ ok: false,
177
+ error: `Unknown runtime "${runtime}". Valid: ${Object.keys(KNOWN_RUNTIMES).join(", ")}`
178
+ };
179
+ }
180
+ if (!knownModels.includes(model)) {
181
+ return {
182
+ ok: false,
183
+ error: `Unknown model "${model}" for runtime "${runtime}". Valid: ${knownModels.join(", ")}`
184
+ };
185
+ }
186
+ const config = loadAgentConfig();
187
+ config[agentId] = { runtime, model };
188
+ saveAgentConfig(config);
189
+ return { ok: true };
190
+ }
191
+ function clearAgentRuntime(agentId) {
192
+ const config = loadAgentConfig();
193
+ delete config[agentId];
194
+ saveAgentConfig(config);
195
+ }
196
+ var AGENT_CONFIG_PATH, KNOWN_RUNTIMES, RUNTIME_LABELS, DEFAULT_MODELS;
197
+ var init_agent_config = __esm({
198
+ "src/lib/agent-config.ts"() {
199
+ "use strict";
200
+ init_config();
201
+ init_runtime_table();
202
+ AGENT_CONFIG_PATH = path2.join(EXE_AI_DIR, "agent-config.json");
203
+ KNOWN_RUNTIMES = {
204
+ claude: ["claude-opus-4", "claude-sonnet-4", "claude-haiku-4.5"],
205
+ codex: ["gpt-5.4", "gpt-5.5", "gpt-5.3-codex-spark", "o3", "o4-mini"],
206
+ opencode: ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4", "google/gemini-2.5-pro", "deepseek/deepseek-r3", "minimax/minimax-m2.5"]
207
+ };
208
+ RUNTIME_LABELS = {
209
+ claude: "Claude Code (Anthropic)",
210
+ codex: "Codex (OpenAI)",
211
+ opencode: "OpenCode (open source)"
212
+ };
213
+ DEFAULT_MODELS = {
214
+ claude: "claude-opus-4",
215
+ codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
216
+ opencode: RUNTIME_TABLE.opencode?.defaultModel ?? "anthropic/claude-sonnet-4-6"
217
+ };
218
+ }
219
+ });
220
+
103
221
  // src/lib/employees.ts
104
222
  var employees_exports = {};
105
223
  __export(employees_exports, {
@@ -115,6 +233,7 @@ __export(employees_exports, {
115
233
  getEmployeeByRole: () => getEmployeeByRole,
116
234
  getEmployeeNamesByRole: () => getEmployeeNamesByRole,
117
235
  hasRole: () => hasRole,
236
+ hireEmployee: () => hireEmployee,
118
237
  isCoordinatorName: () => isCoordinatorName,
119
238
  isCoordinatorRole: () => isCoordinatorRole,
120
239
  isMultiInstance: () => isMultiInstance,
@@ -127,9 +246,9 @@ __export(employees_exports, {
127
246
  validateEmployeeName: () => validateEmployeeName
128
247
  });
129
248
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
130
- import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
249
+ import { existsSync as existsSync3, symlinkSync, readlinkSync, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
131
250
  import { execSync } from "child_process";
132
- import path2 from "path";
251
+ import path3 from "path";
133
252
  import os2 from "os";
134
253
  function normalizeRole(role) {
135
254
  return (role ?? "").trim().toLowerCase();
@@ -166,7 +285,7 @@ function validateEmployeeName(name) {
166
285
  return { valid: true };
167
286
  }
168
287
  async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
169
- if (!existsSync2(employeesPath)) {
288
+ if (!existsSync3(employeesPath)) {
170
289
  return [];
171
290
  }
172
291
  const raw = await readFile2(employeesPath, "utf-8");
@@ -177,13 +296,13 @@ async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
177
296
  }
178
297
  }
179
298
  async function saveEmployees(employees, employeesPath = EMPLOYEES_PATH) {
180
- await mkdir2(path2.dirname(employeesPath), { recursive: true });
299
+ await mkdir2(path3.dirname(employeesPath), { recursive: true });
181
300
  await writeFile2(employeesPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
182
301
  }
183
302
  function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
184
- if (!existsSync2(employeesPath)) return [];
303
+ if (!existsSync3(employeesPath)) return [];
185
304
  try {
186
- return JSON.parse(readFileSync2(employeesPath, "utf-8"));
305
+ return JSON.parse(readFileSync3(employeesPath, "utf-8"));
187
306
  } catch {
188
307
  return [];
189
308
  }
@@ -225,6 +344,52 @@ function addEmployee(employees, employee) {
225
344
  }
226
345
  return [...employees, normalized];
227
346
  }
347
+ function appendToCoordinatorTeam(employee) {
348
+ const coordinator = getCoordinatorEmployee(loadEmployeesSync());
349
+ if (!coordinator) return;
350
+ const idPath = path3.join(IDENTITY_DIR, `${coordinator.name}.md`);
351
+ if (!existsSync3(idPath)) return;
352
+ const content = readFileSync3(idPath, "utf-8");
353
+ if (content.includes(`**${capitalize(employee.name)}`)) return;
354
+ const teamMatch = content.match(TEAM_SECTION_RE);
355
+ if (!teamMatch || teamMatch.index === void 0) return;
356
+ const afterTeam = content.slice(teamMatch.index + teamMatch[0].length);
357
+ const nextHeading = afterTeam.match(/\n## /);
358
+ const entry = `
359
+ **${capitalize(employee.name)} (${employee.role}):** Newly hired. Update this description as the role develops.
360
+ `;
361
+ let updated;
362
+ if (nextHeading && nextHeading.index !== void 0) {
363
+ const insertAt = teamMatch.index + teamMatch[0].length + nextHeading.index;
364
+ updated = content.slice(0, insertAt) + entry + content.slice(insertAt);
365
+ } else {
366
+ updated = content.trimEnd() + "\n" + entry;
367
+ }
368
+ writeFileSync2(idPath, updated, "utf-8");
369
+ }
370
+ function capitalize(s) {
371
+ return s.charAt(0).toUpperCase() + s.slice(1);
372
+ }
373
+ async function hireEmployee(employee) {
374
+ const employees = await loadEmployees();
375
+ const updated = addEmployee(employees, employee);
376
+ await saveEmployees(updated);
377
+ try {
378
+ appendToCoordinatorTeam(employee);
379
+ } catch {
380
+ }
381
+ try {
382
+ const { loadAgentConfig: loadAgentConfig2, saveAgentConfig: saveAgentConfig2 } = await Promise.resolve().then(() => (init_agent_config(), agent_config_exports));
383
+ const config = loadAgentConfig2();
384
+ const name = employee.name.toLowerCase();
385
+ if (!config[name] && config["default"]) {
386
+ config[name] = { ...config["default"] };
387
+ saveAgentConfig2(config);
388
+ }
389
+ } catch {
390
+ }
391
+ return updated;
392
+ }
228
393
  async function normalizeRosterCase(rosterPath) {
229
394
  const employees = await loadEmployees(rosterPath);
230
395
  let changed = false;
@@ -234,14 +399,14 @@ async function normalizeRosterCase(rosterPath) {
234
399
  emp.name = emp.name.toLowerCase();
235
400
  changed = true;
236
401
  try {
237
- const identityDir = path2.join(os2.homedir(), ".exe-os", "identity");
238
- const oldPath = path2.join(identityDir, `${oldName}.md`);
239
- const newPath = path2.join(identityDir, `${emp.name}.md`);
240
- if (existsSync2(oldPath) && !existsSync2(newPath)) {
402
+ const identityDir = path3.join(os2.homedir(), ".exe-os", "identity");
403
+ const oldPath = path3.join(identityDir, `${oldName}.md`);
404
+ const newPath = path3.join(identityDir, `${emp.name}.md`);
405
+ if (existsSync3(oldPath) && !existsSync3(newPath)) {
241
406
  renameSync2(oldPath, newPath);
242
- } else if (existsSync2(oldPath) && oldPath !== newPath) {
243
- const content = readFileSync2(oldPath, "utf-8");
244
- writeFileSync(newPath, content, "utf-8");
407
+ } else if (existsSync3(oldPath) && oldPath !== newPath) {
408
+ const content = readFileSync3(oldPath, "utf-8");
409
+ writeFileSync2(newPath, content, "utf-8");
245
410
  if (oldPath.toLowerCase() !== newPath.toLowerCase()) {
246
411
  unlinkSync(oldPath);
247
412
  }
@@ -271,7 +436,7 @@ function registerBinSymlinks(name) {
271
436
  errors.push("Could not find 'exe-os' in PATH");
272
437
  return { created, skipped, errors };
273
438
  }
274
- const binDir = path2.dirname(exeBinPath);
439
+ const binDir = path3.dirname(exeBinPath);
275
440
  let target;
276
441
  try {
277
442
  target = readlinkSync(exeBinPath);
@@ -281,8 +446,8 @@ function registerBinSymlinks(name) {
281
446
  }
282
447
  for (const suffix of ["", "-opencode"]) {
283
448
  const linkName = `${name}${suffix}`;
284
- const linkPath = path2.join(binDir, linkName);
285
- if (existsSync2(linkPath)) {
449
+ const linkPath = path3.join(binDir, linkName);
450
+ if (existsSync3(linkPath)) {
286
451
  skipped.push(linkName);
287
452
  continue;
288
453
  }
@@ -295,51 +460,44 @@ function registerBinSymlinks(name) {
295
460
  }
296
461
  return { created, skipped, errors };
297
462
  }
298
- var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, MULTI_INSTANCE_ROLES;
463
+ var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, MULTI_INSTANCE_ROLES, IDENTITY_DIR, TEAM_SECTION_RE;
299
464
  var init_employees = __esm({
300
465
  "src/lib/employees.ts"() {
301
466
  "use strict";
302
467
  init_config();
303
- EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
468
+ EMPLOYEES_PATH = path3.join(EXE_AI_DIR, "exe-employees.json");
304
469
  DEFAULT_COORDINATOR_TEMPLATE_NAME = "exe";
305
470
  COORDINATOR_ROLE = "COO";
306
471
  MULTI_INSTANCE_ROLES = /* @__PURE__ */ new Set(["principal engineer", "content production specialist", "staff code reviewer"]);
472
+ IDENTITY_DIR = path3.join(EXE_AI_DIR, "identity");
473
+ TEAM_SECTION_RE = /^## Team\b.*$/m;
307
474
  }
308
475
  });
309
476
 
310
- // src/adapters/claude/installer.ts
311
- import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, readdir } from "fs/promises";
312
- import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3, copyFileSync, mkdirSync as mkdirSync3 } from "fs";
313
- import path5 from "path";
314
- import os5 from "os";
315
- import { execSync as execSync2 } from "child_process";
316
- import { fileURLToPath } from "url";
317
-
318
477
  // src/lib/agent-symlinks.ts
319
- init_employees();
320
478
  import os3 from "os";
321
- import path3 from "path";
479
+ import path4 from "path";
322
480
  import {
323
- existsSync as existsSync3,
481
+ existsSync as existsSync4,
324
482
  lstatSync,
325
- mkdirSync,
483
+ mkdirSync as mkdirSync2,
326
484
  readlinkSync as readlinkSync2,
327
485
  symlinkSync as symlinkSync2
328
486
  } from "fs";
329
487
  function claudeAgentsDir(homeDir) {
330
- return path3.join(homeDir, ".claude", "agents");
488
+ return path4.join(homeDir, ".claude", "agents");
331
489
  }
332
490
  function identitySourcePath(homeDir, agentId) {
333
- return path3.join(homeDir, ".exe-os", "identity", `${agentId}.md`);
491
+ return path4.join(homeDir, ".exe-os", "identity", `${agentId}.md`);
334
492
  }
335
493
  function claudeAgentLinkPath(homeDir, agentId) {
336
- return path3.join(claudeAgentsDir(homeDir), `${agentId}.md`);
494
+ return path4.join(claudeAgentsDir(homeDir), `${agentId}.md`);
337
495
  }
338
496
  function ensureAgentSymlink(agentId, homeDir = os3.homedir()) {
339
497
  const target = identitySourcePath(homeDir, agentId);
340
498
  const link = claudeAgentLinkPath(homeDir, agentId);
341
- mkdirSync(claudeAgentsDir(homeDir), { recursive: true });
342
- if (existsSync3(link)) {
499
+ mkdirSync2(claudeAgentsDir(homeDir), { recursive: true });
500
+ if (existsSync4(link)) {
343
501
  let stat;
344
502
  try {
345
503
  stat = lstatSync(link);
@@ -377,14 +535,14 @@ async function ensureAllAgentSymlinks(homeDir = os3.homedir()) {
377
535
  const employees = await loadEmployees();
378
536
  return employees.map((emp) => ensureAgentSymlink(emp.name, homeDir));
379
537
  }
538
+ var init_agent_symlinks = __esm({
539
+ "src/lib/agent-symlinks.ts"() {
540
+ "use strict";
541
+ init_employees();
542
+ }
543
+ });
380
544
 
381
545
  // src/lib/mcp-prefix.ts
382
- var MCP_PRIMARY_KEY = "exe-os";
383
- var MCP_LEGACY_KEY = "exe-mem";
384
- var MCP_TOOL_PREFIXES = [
385
- `mcp__${MCP_PRIMARY_KEY}__`,
386
- `mcp__${MCP_LEGACY_KEY}__`
387
- ];
388
546
  function expandDualPrefixTools(shortNames) {
389
547
  const out = [];
390
548
  for (const name of shortNames) {
@@ -394,64 +552,87 @@ function expandDualPrefixTools(shortNames) {
394
552
  }
395
553
  return out;
396
554
  }
555
+ var MCP_PRIMARY_KEY, MCP_LEGACY_KEY, MCP_TOOL_PREFIXES;
556
+ var init_mcp_prefix = __esm({
557
+ "src/lib/mcp-prefix.ts"() {
558
+ "use strict";
559
+ MCP_PRIMARY_KEY = "exe-os";
560
+ MCP_LEGACY_KEY = "exe-mem";
561
+ MCP_TOOL_PREFIXES = [
562
+ `mcp__${MCP_PRIMARY_KEY}__`,
563
+ `mcp__${MCP_LEGACY_KEY}__`
564
+ ];
565
+ }
566
+ });
397
567
 
398
568
  // src/lib/preferences.ts
399
- import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
400
- import path4 from "path";
569
+ import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
570
+ import path5 from "path";
401
571
  import os4 from "os";
402
572
  function loadPreferences(homeDir = os4.homedir()) {
403
- const configPath = path4.join(homeDir, ".exe-os", "config.json");
404
- if (!existsSync4(configPath)) return {};
573
+ const configPath = path5.join(homeDir, ".exe-os", "config.json");
574
+ if (!existsSync5(configPath)) return {};
405
575
  try {
406
- const config = JSON.parse(readFileSync3(configPath, "utf-8"));
576
+ const config = JSON.parse(readFileSync4(configPath, "utf-8"));
407
577
  return config.preferences ?? {};
408
578
  } catch {
409
579
  return {};
410
580
  }
411
581
  }
582
+ var init_preferences = __esm({
583
+ "src/lib/preferences.ts"() {
584
+ "use strict";
585
+ }
586
+ });
412
587
 
413
588
  // src/adapters/claude/installer.ts
589
+ 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";
591
+ import path6 from "path";
592
+ import os5 from "os";
593
+ import { execSync as execSync2 } from "child_process";
594
+ import { fileURLToPath } from "url";
414
595
  function resolvePackageRoot() {
415
596
  const thisFile = fileURLToPath(import.meta.url);
416
- let dir = path5.dirname(thisFile);
417
- const root = path5.parse(dir).root;
597
+ let dir = path6.dirname(thisFile);
598
+ const root = path6.parse(dir).root;
418
599
  while (dir !== root) {
419
- const pkgPath = path5.join(dir, "package.json");
420
- if (existsSync5(pkgPath)) {
600
+ const pkgPath = path6.join(dir, "package.json");
601
+ if (existsSync6(pkgPath)) {
421
602
  try {
422
- const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
603
+ const pkg = JSON.parse(readFileSync5(pkgPath, "utf-8"));
423
604
  if (pkg.name === "@askexenow/exe-os" || pkg.name === "exe-os") return dir;
424
605
  } catch {
425
606
  }
426
607
  }
427
- dir = path5.dirname(dir);
608
+ dir = path6.dirname(dir);
428
609
  }
429
- return path5.resolve(path5.dirname(thisFile), "..", "..", "..");
610
+ return path6.resolve(path6.dirname(thisFile), "..", "..", "..");
430
611
  }
431
612
  async function copySlashCommands(packageRoot, homeDir = os5.homedir()) {
432
613
  let copied = 0;
433
614
  let skipped = 0;
434
- const skillsBase = path5.join(homeDir, ".claude", "skills");
435
- const exeDir = path5.join(packageRoot, "src", "commands", "exe");
436
- if (existsSync5(exeDir)) {
615
+ const skillsBase = path6.join(homeDir, ".claude", "skills");
616
+ const exeDir = path6.join(packageRoot, "src", "commands", "exe");
617
+ if (existsSync6(exeDir)) {
437
618
  const entries = await readdir(exeDir);
438
619
  const mdFiles = entries.filter((f) => f.endsWith(".md"));
439
620
  for (const file of mdFiles) {
440
621
  const name = file.replace(".md", "");
441
- const destDir = path5.join(skillsBase, `exe-${name}`);
622
+ const destDir = path6.join(skillsBase, `exe-${name}`);
442
623
  await mkdir3(destDir, { recursive: true });
443
- const srcPath = path5.join(exeDir, file);
444
- const destPath = path5.join(destDir, "SKILL.md");
624
+ const srcPath = path6.join(exeDir, file);
625
+ const destPath = path6.join(destDir, "SKILL.md");
445
626
  const result = await copyAsSkill(srcPath, destPath, `exe-${name}`);
446
627
  if (result) copied++;
447
628
  else skipped++;
448
629
  }
449
630
  }
450
- const topLevelSrc = path5.join(packageRoot, "src", "commands", "exe.md");
451
- if (existsSync5(topLevelSrc)) {
452
- const destDir = path5.join(skillsBase, "exe");
631
+ const topLevelSrc = path6.join(packageRoot, "src", "commands", "exe.md");
632
+ if (existsSync6(topLevelSrc)) {
633
+ const destDir = path6.join(skillsBase, "exe");
453
634
  await mkdir3(destDir, { recursive: true });
454
- const destPath = path5.join(destDir, "SKILL.md");
635
+ const destPath = path6.join(destDir, "SKILL.md");
455
636
  const result = await copyAsSkill(topLevelSrc, destPath, "exe");
456
637
  if (result) copied++;
457
638
  else skipped++;
@@ -474,7 +655,7 @@ name: ${skillName}
474
655
  `);
475
656
  }
476
657
  }
477
- if (existsSync5(destPath)) {
658
+ if (existsSync6(destPath)) {
478
659
  const existing = await readFile3(destPath, "utf-8");
479
660
  if (existing === content) return false;
480
661
  }
@@ -482,9 +663,9 @@ name: ${skillName}
482
663
  return true;
483
664
  }
484
665
  async function registerMcpServer(packageRoot, homeDir = os5.homedir()) {
485
- const claudeJsonPath = path5.join(homeDir, ".claude.json");
666
+ const claudeJsonPath = path6.join(homeDir, ".claude.json");
486
667
  let claudeJson = {};
487
- if (existsSync5(claudeJsonPath)) {
668
+ if (existsSync6(claudeJsonPath)) {
488
669
  try {
489
670
  claudeJson = JSON.parse(await readFile3(claudeJsonPath, "utf-8"));
490
671
  } catch {
@@ -497,7 +678,7 @@ async function registerMcpServer(packageRoot, homeDir = os5.homedir()) {
497
678
  const newEntry = {
498
679
  type: "stdio",
499
680
  command: "node",
500
- args: [path5.join(packageRoot, "dist", "mcp", "server.js")],
681
+ args: [path6.join(packageRoot, "dist", "mcp", "server.js")],
501
682
  env: {}
502
683
  };
503
684
  const currentMem = claudeJson.mcpServers[MCP_LEGACY_KEY];
@@ -505,17 +686,17 @@ async function registerMcpServer(packageRoot, homeDir = os5.homedir()) {
505
686
  const memMatches = currentMem && JSON.stringify(currentMem) === JSON.stringify(newEntry);
506
687
  const osMatches = currentOs && JSON.stringify(currentOs) === JSON.stringify(newEntry);
507
688
  if (memMatches && osMatches) {
508
- await cleanSettingsJsonMcp(path5.join(homeDir, ".claude", "settings.json"));
689
+ await cleanSettingsJsonMcp(path6.join(homeDir, ".claude", "settings.json"));
509
690
  return false;
510
691
  }
511
692
  claudeJson.mcpServers[MCP_LEGACY_KEY] = newEntry;
512
693
  claudeJson.mcpServers[MCP_PRIMARY_KEY] = newEntry;
513
694
  await writeFile3(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
514
- await cleanSettingsJsonMcp(path5.join(homeDir, ".claude", "settings.json"));
695
+ await cleanSettingsJsonMcp(path6.join(homeDir, ".claude", "settings.json"));
515
696
  return true;
516
697
  }
517
698
  async function cleanSettingsJsonMcp(settingsPath) {
518
- if (!existsSync5(settingsPath)) return;
699
+ if (!existsSync6(settingsPath)) return;
519
700
  try {
520
701
  const settings = JSON.parse(await readFile3(settingsPath, "utf-8"));
521
702
  const servers = settings.mcpServers;
@@ -536,13 +717,13 @@ async function cleanSettingsJsonMcp(settingsPath) {
536
717
  }
537
718
  }
538
719
  async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
539
- const settingsPath = path5.join(homeDir, ".claude", "settings.json");
540
- const logsDir = path5.join(homeDir, ".exe-os", "logs");
541
- const hookLogPath = path5.join(logsDir, "hooks.log");
720
+ const settingsPath = path6.join(homeDir, ".claude", "settings.json");
721
+ const logsDir = path6.join(homeDir, ".exe-os", "logs");
722
+ const hookLogPath = path6.join(logsDir, "hooks.log");
542
723
  const logSuffix = ` 2>> "${hookLogPath}"`;
543
724
  await mkdir3(logsDir, { recursive: true });
544
725
  let settings = {};
545
- if (existsSync5(settingsPath)) {
726
+ if (existsSync6(settingsPath)) {
546
727
  try {
547
728
  settings = JSON.parse(await readFile3(settingsPath, "utf-8"));
548
729
  } catch {
@@ -564,11 +745,11 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
564
745
  hooks: [
565
746
  {
566
747
  type: "command",
567
- command: `node "${path5.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
748
+ command: `node "${path6.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
568
749
  },
569
750
  {
570
751
  type: "command",
571
- command: `node "${path5.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
752
+ command: `node "${path6.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
572
753
  }
573
754
  ]
574
755
  },
@@ -580,7 +761,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
580
761
  hooks: [
581
762
  {
582
763
  type: "command",
583
- command: `node "${path5.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
764
+ command: `node "${path6.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
584
765
  timeout: 1e4
585
766
  }
586
767
  ]
@@ -593,7 +774,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
593
774
  hooks: [
594
775
  {
595
776
  type: "command",
596
- command: `node "${path5.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
777
+ command: `node "${path6.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
597
778
  }
598
779
  ]
599
780
  },
@@ -605,7 +786,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
605
786
  hooks: [
606
787
  {
607
788
  type: "command",
608
- command: `node "${path5.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
789
+ command: `node "${path6.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
609
790
  timeout: 5e3
610
791
  }
611
792
  ]
@@ -618,7 +799,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
618
799
  hooks: [
619
800
  {
620
801
  type: "command",
621
- command: `node "${path5.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
802
+ command: `node "${path6.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
622
803
  }
623
804
  ]
624
805
  },
@@ -631,7 +812,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
631
812
  hooks: [
632
813
  {
633
814
  type: "command",
634
- command: `node "${path5.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
815
+ command: `node "${path6.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
635
816
  }
636
817
  ]
637
818
  },
@@ -643,7 +824,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
643
824
  hooks: [
644
825
  {
645
826
  type: "command",
646
- command: `node "${path5.join(packageRoot, "dist", "hooks", "subagent-stop.js")}"${logSuffix}`
827
+ command: `node "${path6.join(packageRoot, "dist", "hooks", "subagent-stop.js")}"${logSuffix}`
647
828
  }
648
829
  ]
649
830
  },
@@ -655,7 +836,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
655
836
  hooks: [
656
837
  {
657
838
  type: "command",
658
- command: `node "${path5.join(packageRoot, "dist", "hooks", "pre-compact.js")}"${logSuffix}`,
839
+ command: `node "${path6.join(packageRoot, "dist", "hooks", "pre-compact.js")}"${logSuffix}`,
659
840
  timeout: 1e4
660
841
  }
661
842
  ]
@@ -668,7 +849,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
668
849
  hooks: [
669
850
  {
670
851
  type: "command",
671
- command: `node "${path5.join(packageRoot, "dist", "hooks", "session-end.js")}"${logSuffix}`
852
+ command: `node "${path6.join(packageRoot, "dist", "hooks", "session-end.js")}"${logSuffix}`
672
853
  }
673
854
  ]
674
855
  },
@@ -680,7 +861,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
680
861
  hooks: [
681
862
  {
682
863
  type: "command",
683
- command: `node "${path5.join(packageRoot, "dist", "hooks", "notification.js")}"${logSuffix}`
864
+ command: `node "${path6.join(packageRoot, "dist", "hooks", "notification.js")}"${logSuffix}`
684
865
  }
685
866
  ]
686
867
  },
@@ -692,7 +873,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
692
873
  hooks: [
693
874
  {
694
875
  type: "command",
695
- command: `node "${path5.join(packageRoot, "dist", "hooks", "post-compact.js")}"${logSuffix}`,
876
+ command: `node "${path6.join(packageRoot, "dist", "hooks", "post-compact.js")}"${logSuffix}`,
696
877
  timeout: 1e4
697
878
  }
698
879
  ]
@@ -705,7 +886,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
705
886
  hooks: [
706
887
  {
707
888
  type: "command",
708
- command: `node "${path5.join(packageRoot, "dist", "hooks", "instructions-loaded.js")}"${logSuffix}`
889
+ command: `node "${path6.join(packageRoot, "dist", "hooks", "instructions-loaded.js")}"${logSuffix}`
709
890
  }
710
891
  ]
711
892
  },
@@ -804,13 +985,13 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
804
985
  allowList.push(tool);
805
986
  }
806
987
  }
807
- await mkdir3(path5.dirname(settingsPath), { recursive: true });
988
+ await mkdir3(path6.dirname(settingsPath), { recursive: true });
808
989
  await writeFile3(settingsPath, JSON.stringify(settings, null, 2) + "\n");
809
990
  return { added, skipped };
810
991
  }
811
992
  async function cleanOldShellFunctions(homeDir = os5.homedir()) {
812
- const rosterPath = path5.join(homeDir, ".exe-os", "exe-employees.json");
813
- if (!existsSync5(rosterPath)) return 0;
993
+ const rosterPath = path6.join(homeDir, ".exe-os", "exe-employees.json");
994
+ if (!existsSync6(rosterPath)) return 0;
814
995
  let employees;
815
996
  try {
816
997
  employees = JSON.parse(await readFile3(rosterPath, "utf-8"));
@@ -825,13 +1006,13 @@ async function cleanOldShellFunctions(homeDir = os5.homedir()) {
825
1006
  return { name: n, funcDef, forLoop };
826
1007
  });
827
1008
  const rcFiles = [
828
- path5.join(homeDir, ".zshrc"),
829
- path5.join(homeDir, ".bashrc")
1009
+ path6.join(homeDir, ".zshrc"),
1010
+ path6.join(homeDir, ".bashrc")
830
1011
  ];
831
1012
  const REMOVED_MARKER = "# Removed by exe-os \u2014 wrappers now at ~/.exe-os/bin/";
832
1013
  let totalRemoved = 0;
833
1014
  for (const rcPath of rcFiles) {
834
- if (!existsSync5(rcPath)) continue;
1015
+ if (!existsSync6(rcPath)) continue;
835
1016
  let content;
836
1017
  try {
837
1018
  content = await readFile3(rcPath, "utf-8");
@@ -934,22 +1115,9 @@ async function cleanOldShellFunctions(homeDir = os5.homedir()) {
934
1115
  function escapeRegExp(s) {
935
1116
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
936
1117
  }
937
- var EXE_SECTION_START = "<!-- exe-os:orchestration-start -->";
938
- var EXE_SECTION_END = "<!-- exe-os:orchestration-end -->";
939
- var ORCHESTRATION_RULES = `${EXE_SECTION_START}
940
- ## exe-os Multi-Agent Orchestration (auto-managed \u2014 do not edit)
941
-
942
- These rules are injected by exe-os and override default behavior for multi-agent coordination.
943
-
944
- - **Session routing is deterministic.** When working in a coordinator session, ALL employee sessions use that same coordinator-session suffix. NEVER reference, consider, or dispatch to employee sessions from other project sessions. This is not a choice \u2014 it is a hard constraint.
945
- - **Always use create_task to assign work.** Never use messages, tmux send-keys, or ad-hoc instructions as a substitute for tasks.
946
- - **Never modify another agent's in-progress task.** Create a new task instead. Modifying active tasks causes race conditions.
947
- - **Chain of command:** founder -> COO -> managers -> specialists. The COO does not bypass managers for specialist work.
948
- - **Verify dispatch.** After every create_task, confirm the employee received and started the task via tmux capture-pane.
949
- ${EXE_SECTION_END}`;
950
1118
  async function injectOrchestrationRules(homeDir) {
951
- const claudeDir = path5.join(homeDir, ".claude");
952
- const claudeMdPath = path5.join(claudeDir, "CLAUDE.md");
1119
+ const claudeDir = path6.join(homeDir, ".claude");
1120
+ const claudeMdPath = path6.join(claudeDir, "CLAUDE.md");
953
1121
  await mkdir3(claudeDir, { recursive: true });
954
1122
  let existing = "";
955
1123
  try {
@@ -974,16 +1142,16 @@ async function injectOrchestrationRules(homeDir) {
974
1142
  async function installStatusLine(packageRoot, homeDir = os5.homedir()) {
975
1143
  const prefs = loadPreferences(homeDir);
976
1144
  if (prefs.ccStatusLine === false) return "opted-out";
977
- const claudeDir = path5.join(homeDir, ".claude");
1145
+ const claudeDir = path6.join(homeDir, ".claude");
978
1146
  await mkdir3(claudeDir, { recursive: true });
979
- const assetPath = path5.join(packageRoot, "dist", "assets", "statusline-command.sh");
980
- if (!existsSync5(assetPath)) return "asset-missing";
981
- const destScript = path5.join(claudeDir, "statusline-command.sh");
1147
+ const assetPath = path6.join(packageRoot, "dist", "assets", "statusline-command.sh");
1148
+ if (!existsSync6(assetPath)) return "asset-missing";
1149
+ const destScript = path6.join(claudeDir, "statusline-command.sh");
982
1150
  const assetContent = await readFile3(assetPath, "utf-8");
983
1151
  await writeFile3(destScript, assetContent, { mode: 493 });
984
- const settingsPath = path5.join(claudeDir, "settings.json");
1152
+ const settingsPath = path6.join(claudeDir, "settings.json");
985
1153
  let settings = {};
986
- if (existsSync5(settingsPath)) {
1154
+ if (existsSync6(settingsPath)) {
987
1155
  try {
988
1156
  settings = JSON.parse(await readFile3(settingsPath, "utf-8"));
989
1157
  } catch {
@@ -1021,12 +1189,12 @@ async function runInstaller(homeDir) {
1021
1189
  `
1022
1190
  );
1023
1191
  const resolvedHome = homeDir ?? os5.homedir();
1024
- const exeWorkspace = path5.join(resolvedHome, "exe");
1025
- if (!existsSync5(exeWorkspace)) {
1192
+ const exeWorkspace = path6.join(resolvedHome, "exe");
1193
+ if (!existsSync6(exeWorkspace)) {
1026
1194
  try {
1027
- await mkdir3(path5.join(exeWorkspace, "content"), { recursive: true });
1028
- await mkdir3(path5.join(exeWorkspace, "operations"), { recursive: true });
1029
- await mkdir3(path5.join(exeWorkspace, "output"), { recursive: true });
1195
+ await mkdir3(path6.join(exeWorkspace, "content"), { recursive: true });
1196
+ await mkdir3(path6.join(exeWorkspace, "operations"), { recursive: true });
1197
+ await mkdir3(path6.join(exeWorkspace, "output"), { recursive: true });
1030
1198
  process.stderr.write(
1031
1199
  `Created ~/exe/ \u2014 your automation workspace for non-code projects
1032
1200
  `
@@ -1062,33 +1230,33 @@ exe-os installed successfully.
1062
1230
  }
1063
1231
  function setupTmux(home) {
1064
1232
  const homeDir = home ?? os5.homedir();
1065
- const exeDir = path5.join(homeDir, ".exe-os");
1066
- const exeTmuxConf = path5.join(exeDir, "tmux.conf");
1067
- const userTmuxConf = path5.join(homeDir, ".tmux.conf");
1068
- const backupPath = path5.join(homeDir, ".tmux.conf.backup");
1233
+ const exeDir = path6.join(homeDir, ".exe-os");
1234
+ const exeTmuxConf = path6.join(exeDir, "tmux.conf");
1235
+ const userTmuxConf = path6.join(homeDir, ".tmux.conf");
1236
+ const backupPath = path6.join(homeDir, ".tmux.conf.backup");
1069
1237
  const sourceLine = "source-file ~/.exe-os/tmux.conf";
1070
1238
  const pkgRoot = resolvePackageRoot();
1071
- const assetPath = path5.join(pkgRoot, "dist", "assets", "tmux.conf");
1072
- if (!existsSync5(assetPath)) {
1239
+ const assetPath = path6.join(pkgRoot, "dist", "assets", "tmux.conf");
1240
+ if (!existsSync6(assetPath)) {
1073
1241
  process.stderr.write(`exe-os: tmux.conf asset not found at ${assetPath} \u2014 skipping tmux setup
1074
1242
  `);
1075
1243
  return;
1076
1244
  }
1077
- mkdirSync3(exeDir, { recursive: true });
1245
+ mkdirSync4(exeDir, { recursive: true });
1078
1246
  copyFileSync(assetPath, exeTmuxConf);
1079
- if (existsSync5(userTmuxConf)) {
1080
- const existing = readFileSync4(userTmuxConf, "utf8");
1247
+ if (existsSync6(userTmuxConf)) {
1248
+ const existing = readFileSync5(userTmuxConf, "utf8");
1081
1249
  if (!existing.includes(sourceLine)) {
1082
- if (!existsSync5(backupPath)) {
1250
+ if (!existsSync6(backupPath)) {
1083
1251
  copyFileSync(userTmuxConf, backupPath);
1084
1252
  process.stderr.write(`exe-os: backed up existing tmux config to ${backupPath}
1085
1253
  `);
1086
1254
  }
1087
- writeFileSync3(userTmuxConf, `${sourceLine}
1255
+ writeFileSync4(userTmuxConf, `${sourceLine}
1088
1256
  ${existing}`);
1089
1257
  }
1090
1258
  } else {
1091
- writeFileSync3(userTmuxConf, `# Exe OS tmux defaults \u2014 remove this line to use your own config
1259
+ writeFileSync4(userTmuxConf, `# Exe OS tmux defaults \u2014 remove this line to use your own config
1092
1260
  ${sourceLine}
1093
1261
  `);
1094
1262
  }
@@ -1100,9 +1268,9 @@ ${sourceLine}
1100
1268
  }
1101
1269
  function setupGhostty(home) {
1102
1270
  const homeDir = home ?? os5.homedir();
1103
- const xdgConfig = path5.join(homeDir, ".config", "ghostty");
1104
- const macConfig = path5.join(homeDir, "Library", "Application Support", "com.mitchellh.ghostty");
1105
- const ghosttyInstalled = existsSync5(xdgConfig) || existsSync5(macConfig) || (() => {
1271
+ const xdgConfig = path6.join(homeDir, ".config", "ghostty");
1272
+ const macConfig = path6.join(homeDir, "Library", "Application Support", "com.mitchellh.ghostty");
1273
+ const ghosttyInstalled = existsSync6(xdgConfig) || existsSync6(macConfig) || (() => {
1106
1274
  try {
1107
1275
  execSync2("which ghostty 2>/dev/null");
1108
1276
  return true;
@@ -1114,47 +1282,47 @@ function setupGhostty(home) {
1114
1282
  return;
1115
1283
  }
1116
1284
  const pkgRoot = resolvePackageRoot();
1117
- const assetPath = path5.join(pkgRoot, "dist", "assets", "ghostty.conf");
1118
- if (!existsSync5(assetPath)) {
1285
+ const assetPath = path6.join(pkgRoot, "dist", "assets", "ghostty.conf");
1286
+ if (!existsSync6(assetPath)) {
1119
1287
  process.stderr.write("exe-os: ghostty.conf asset not found \u2014 skipping Ghostty setup\n");
1120
1288
  return;
1121
1289
  }
1122
1290
  const configDir = xdgConfig;
1123
- const configPath = path5.join(configDir, "config");
1124
- const backupPath = path5.join(configDir, "config.backup");
1125
- mkdirSync3(configDir, { recursive: true });
1291
+ const configPath = path6.join(configDir, "config");
1292
+ const backupPath = path6.join(configDir, "config.backup");
1293
+ mkdirSync4(configDir, { recursive: true });
1126
1294
  const START_MARKER = "# \u2500\u2500 exe-os:ghostty-start \u2500\u2500";
1127
1295
  const END_MARKER = "# \u2500\u2500 exe-os:ghostty-end \u2500\u2500";
1128
- const assetContent = readFileSync4(assetPath, "utf8").trim();
1296
+ const assetContent = readFileSync5(assetPath, "utf8").trim();
1129
1297
  const markedSection = `${START_MARKER}
1130
1298
  ${assetContent}
1131
1299
  ${END_MARKER}`;
1132
- if (existsSync5(configPath)) {
1133
- const existing = readFileSync4(configPath, "utf8");
1300
+ if (existsSync6(configPath)) {
1301
+ const existing = readFileSync5(configPath, "utf8");
1134
1302
  if (existing.includes(START_MARKER) && existing.includes(END_MARKER)) {
1135
1303
  const before = existing.slice(0, existing.indexOf(START_MARKER));
1136
1304
  const after = existing.slice(existing.indexOf(END_MARKER) + END_MARKER.length);
1137
- writeFileSync3(configPath, `${before}${markedSection}${after}`);
1305
+ writeFileSync4(configPath, `${before}${markedSection}${after}`);
1138
1306
  } else if (existing.includes("Exe OS")) {
1139
- if (!existsSync5(backupPath)) {
1307
+ if (!existsSync6(backupPath)) {
1140
1308
  copyFileSync(configPath, backupPath);
1141
1309
  process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
1142
1310
  `);
1143
1311
  }
1144
- writeFileSync3(configPath, `${markedSection}
1312
+ writeFileSync4(configPath, `${markedSection}
1145
1313
  `);
1146
1314
  } else {
1147
- if (!existsSync5(backupPath)) {
1315
+ if (!existsSync6(backupPath)) {
1148
1316
  copyFileSync(configPath, backupPath);
1149
1317
  process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
1150
1318
  `);
1151
1319
  }
1152
- writeFileSync3(configPath, `${markedSection}
1320
+ writeFileSync4(configPath, `${markedSection}
1153
1321
 
1154
1322
  ${existing}`);
1155
1323
  }
1156
1324
  } else {
1157
- writeFileSync3(configPath, `${markedSection}
1325
+ writeFileSync4(configPath, `${markedSection}
1158
1326
  `);
1159
1327
  }
1160
1328
  process.stderr.write("exe-os: Ghostty config installed\n");
@@ -1171,46 +1339,275 @@ function summarizeSymlinkResults(results) {
1171
1339
  }
1172
1340
  return summary;
1173
1341
  }
1342
+ var EXE_SECTION_START, EXE_SECTION_END, ORCHESTRATION_RULES;
1343
+ var init_installer = __esm({
1344
+ "src/adapters/claude/installer.ts"() {
1345
+ "use strict";
1346
+ init_agent_symlinks();
1347
+ init_mcp_prefix();
1348
+ init_preferences();
1349
+ EXE_SECTION_START = "<!-- exe-os:orchestration-start -->";
1350
+ EXE_SECTION_END = "<!-- exe-os:orchestration-end -->";
1351
+ ORCHESTRATION_RULES = `${EXE_SECTION_START}
1352
+ ## exe-os Multi-Agent Orchestration (auto-managed \u2014 do not edit)
1353
+
1354
+ These rules are injected by exe-os and override default behavior for multi-agent coordination.
1355
+
1356
+ - **Session routing is deterministic.** When working in a coordinator session, ALL employee sessions use that same coordinator-session suffix. NEVER reference, consider, or dispatch to employee sessions from other project sessions. This is not a choice \u2014 it is a hard constraint.
1357
+ - **Always use create_task to assign work.** Never use messages, tmux send-keys, or ad-hoc instructions as a substitute for tasks.
1358
+ - **Never modify another agent's in-progress task.** Create a new task instead. Modifying active tasks causes race conditions.
1359
+ - **Chain of command:** founder -> COO -> managers -> specialists. The COO does not bypass managers for specialist work.
1360
+ - **Verify dispatch.** After every create_task, confirm the employee received and started the task via tmux capture-pane.
1361
+ ${EXE_SECTION_END}`;
1362
+ }
1363
+ });
1364
+
1365
+ // src/adapters/codex/installer.ts
1366
+ var installer_exports = {};
1367
+ __export(installer_exports, {
1368
+ installCodexStatusLine: () => installCodexStatusLine,
1369
+ mergeCodexHooks: () => mergeCodexHooks,
1370
+ runCodexInstaller: () => runCodexInstaller,
1371
+ verifyCodexHooks: () => verifyCodexHooks
1372
+ });
1373
+ import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir4 } from "fs/promises";
1374
+ import { existsSync as existsSync8 } from "fs";
1375
+ import path8 from "path";
1376
+ import os6 from "os";
1377
+ async function mergeCodexHooks(packageRoot, homeDir = os6.homedir()) {
1378
+ const codexDir = path8.join(homeDir, ".codex");
1379
+ const hooksPath = path8.join(codexDir, "hooks.json");
1380
+ const logsDir = path8.join(homeDir, ".exe-os", "logs");
1381
+ const hookLogPath = path8.join(logsDir, "hooks.log");
1382
+ const logSuffix = ` 2>> "${hookLogPath}"`;
1383
+ await mkdir4(codexDir, { recursive: true });
1384
+ await mkdir4(logsDir, { recursive: true });
1385
+ let hooksJson = {};
1386
+ if (existsSync8(hooksPath)) {
1387
+ try {
1388
+ hooksJson = JSON.parse(await readFile4(hooksPath, "utf-8"));
1389
+ } catch {
1390
+ hooksJson = {};
1391
+ }
1392
+ }
1393
+ if (!hooksJson.hooks) {
1394
+ hooksJson.hooks = {};
1395
+ }
1396
+ const hooksToRegister = [
1397
+ {
1398
+ event: "SessionStart",
1399
+ group: {
1400
+ hooks: [
1401
+ {
1402
+ type: "command",
1403
+ command: `node "${path8.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
1404
+ timeout: 30,
1405
+ statusMessage: "exe-os: loading memory brief"
1406
+ }
1407
+ ]
1408
+ },
1409
+ marker: "dist/hooks/session-start.js"
1410
+ },
1411
+ {
1412
+ event: "PostToolUse",
1413
+ group: {
1414
+ matcher: "Bash|apply_patch|Edit|Write|Read|Glob|Grep|mcp__.*",
1415
+ hooks: [
1416
+ {
1417
+ type: "command",
1418
+ command: `node "${path8.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
1419
+ },
1420
+ {
1421
+ type: "command",
1422
+ command: `node "${path8.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
1423
+ }
1424
+ ]
1425
+ },
1426
+ marker: "dist/hooks/ingest.js"
1427
+ },
1428
+ {
1429
+ event: "UserPromptSubmit",
1430
+ group: {
1431
+ hooks: [
1432
+ {
1433
+ type: "command",
1434
+ command: `node "${path8.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
1435
+ },
1436
+ {
1437
+ type: "command",
1438
+ command: `node "${path8.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
1439
+ timeout: 5
1440
+ }
1441
+ ]
1442
+ },
1443
+ marker: "dist/hooks/prompt-submit.js"
1444
+ },
1445
+ {
1446
+ event: "Stop",
1447
+ group: {
1448
+ hooks: [
1449
+ {
1450
+ type: "command",
1451
+ command: `node "${path8.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
1452
+ }
1453
+ ]
1454
+ },
1455
+ marker: "dist/hooks/stop.js"
1456
+ },
1457
+ {
1458
+ event: "PreToolUse",
1459
+ group: {
1460
+ matcher: "Bash|apply_patch",
1461
+ hooks: [
1462
+ {
1463
+ type: "command",
1464
+ command: `node "${path8.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
1465
+ }
1466
+ ]
1467
+ },
1468
+ marker: "dist/hooks/pre-tool-use.js"
1469
+ }
1470
+ ];
1471
+ let added = 0;
1472
+ let skipped = 0;
1473
+ for (const { event, group, marker } of hooksToRegister) {
1474
+ if (!hooksJson.hooks[event]) {
1475
+ hooksJson.hooks[event] = [];
1476
+ }
1477
+ const existing = hooksJson.hooks[event];
1478
+ const correctCommand = group.hooks[0]?.command ?? "";
1479
+ const alreadyCorrect = existing.some(
1480
+ (g) => g.hooks.some((h) => h.command === correctCommand)
1481
+ );
1482
+ if (alreadyCorrect) {
1483
+ skipped++;
1484
+ } else {
1485
+ hooksJson.hooks[event] = existing.filter(
1486
+ (g) => !g.hooks.some((h) => h.command.includes(marker))
1487
+ );
1488
+ hooksJson.hooks[event].push(group);
1489
+ added++;
1490
+ }
1491
+ }
1492
+ await writeFile4(hooksPath, JSON.stringify(hooksJson, null, 2) + "\n");
1493
+ return { added, skipped };
1494
+ }
1495
+ function verifyCodexHooks(homeDir = os6.homedir()) {
1496
+ const hooksPath = path8.join(homeDir, ".codex", "hooks.json");
1497
+ if (!existsSync8(hooksPath)) return false;
1498
+ try {
1499
+ const hooksJson = JSON.parse(
1500
+ __require("fs").readFileSync(hooksPath, "utf-8")
1501
+ );
1502
+ if (!hooksJson.hooks) return false;
1503
+ const required = ["SessionStart", "PostToolUse", "UserPromptSubmit", "Stop", "PreToolUse"];
1504
+ for (const event of required) {
1505
+ const groups = hooksJson.hooks[event];
1506
+ if (!groups || !groups.some(
1507
+ (g) => g.hooks.some((h) => h.command.includes("dist/hooks/"))
1508
+ )) {
1509
+ return false;
1510
+ }
1511
+ }
1512
+ return true;
1513
+ } catch {
1514
+ return false;
1515
+ }
1516
+ }
1517
+ async function installCodexStatusLine(homeDir = os6.homedir()) {
1518
+ const prefs = loadPreferences(homeDir);
1519
+ if (prefs.codexStatusLine === false) return "opted-out";
1520
+ const codexDir = path8.join(homeDir, ".codex");
1521
+ const configPath = path8.join(codexDir, "config.toml");
1522
+ await mkdir4(codexDir, { recursive: true });
1523
+ let content = "";
1524
+ if (existsSync8(configPath)) {
1525
+ content = await readFile4(configPath, "utf-8");
1526
+ if (/\[tui\][\s\S]*?status_line\s*=/.test(content)) {
1527
+ return "already-configured";
1528
+ }
1529
+ }
1530
+ const statusLineToml = `[tui]
1531
+ status_line = [${DEFAULT_CODEX_STATUS_LINE.map((s) => `"${s}"`).join(", ")}]`;
1532
+ if (content.includes("[tui]")) {
1533
+ content = content.replace(/\[tui\]/, `${statusLineToml}`);
1534
+ } else {
1535
+ const separator = content.length > 0 && !content.endsWith("\n") ? "\n\n" : content.length > 0 ? "\n" : "";
1536
+ content = content + separator + statusLineToml + "\n";
1537
+ }
1538
+ await writeFile4(configPath, content);
1539
+ return "installed";
1540
+ }
1541
+ async function runCodexInstaller(homeDir) {
1542
+ const packageRoot = resolvePackageRoot();
1543
+ const result = await mergeCodexHooks(packageRoot, homeDir);
1544
+ process.stderr.write(
1545
+ `[exe-os] Codex hooks: ${result.added} added, ${result.skipped} unchanged
1546
+ `
1547
+ );
1548
+ const statusResult = await installCodexStatusLine(homeDir);
1549
+ process.stderr.write(
1550
+ `[exe-os] Codex status line: ${statusResult}
1551
+ `
1552
+ );
1553
+ }
1554
+ var DEFAULT_CODEX_STATUS_LINE;
1555
+ var init_installer2 = __esm({
1556
+ "src/adapters/codex/installer.ts"() {
1557
+ "use strict";
1558
+ init_installer();
1559
+ init_preferences();
1560
+ DEFAULT_CODEX_STATUS_LINE = [
1561
+ "model-with-reasoning",
1562
+ "current-dir",
1563
+ "project-name",
1564
+ "git-branch",
1565
+ "run-state",
1566
+ "context-used"
1567
+ ];
1568
+ }
1569
+ });
1174
1570
 
1175
1571
  // src/bin/install.ts
1176
- import { existsSync as existsSync7, readFileSync as readFileSync6, unlinkSync as unlinkSync3, readdirSync as readdirSync2, openSync, closeSync } from "fs";
1572
+ init_installer();
1573
+ import { existsSync as existsSync9, readFileSync as readFileSync7, unlinkSync as unlinkSync3, readdirSync as readdirSync2, openSync, closeSync } from "fs";
1177
1574
  import { spawn, execSync as execSync3 } from "child_process";
1178
- import path7 from "path";
1179
- import os6 from "os";
1575
+ import path9 from "path";
1576
+ import os7 from "os";
1180
1577
 
1181
1578
  // src/lib/session-wrappers.ts
1182
1579
  import {
1183
- existsSync as existsSync6,
1184
- readFileSync as readFileSync5,
1185
- writeFileSync as writeFileSync4,
1186
- mkdirSync as mkdirSync4,
1580
+ existsSync as existsSync7,
1581
+ readFileSync as readFileSync6,
1582
+ writeFileSync as writeFileSync5,
1583
+ mkdirSync as mkdirSync5,
1187
1584
  chmodSync,
1188
1585
  readdirSync,
1189
1586
  unlinkSync as unlinkSync2
1190
1587
  } from "fs";
1191
- import path6 from "path";
1588
+ import path7 from "path";
1192
1589
  import { homedir } from "os";
1193
1590
  var MAX_N = 9;
1194
1591
  function generateSessionWrappers(packageRoot, homeDir) {
1195
1592
  const home = homeDir ?? homedir();
1196
- const binDir = path6.join(home, ".exe-os", "bin");
1197
- const rosterPath = path6.join(home, ".exe-os", "exe-employees.json");
1198
- mkdirSync4(binDir, { recursive: true });
1199
- const exeStartDst = path6.join(binDir, "exe-start");
1593
+ const binDir = path7.join(home, ".exe-os", "bin");
1594
+ const rosterPath = path7.join(home, ".exe-os", "exe-employees.json");
1595
+ mkdirSync5(binDir, { recursive: true });
1596
+ const exeStartDst = path7.join(binDir, "exe-start");
1200
1597
  const candidates = [
1201
- path6.join(packageRoot, "dist", "bin", "exe-start.sh"),
1202
- path6.join(packageRoot, "src", "bin", "exe-start.sh")
1598
+ path7.join(packageRoot, "dist", "bin", "exe-start.sh"),
1599
+ path7.join(packageRoot, "src", "bin", "exe-start.sh")
1203
1600
  ];
1204
1601
  for (const src of candidates) {
1205
- if (existsSync6(src)) {
1206
- writeFileSync4(exeStartDst, readFileSync5(src));
1602
+ if (existsSync7(src)) {
1603
+ writeFileSync5(exeStartDst, readFileSync6(src));
1207
1604
  chmodSync(exeStartDst, 493);
1208
1605
  break;
1209
1606
  }
1210
1607
  }
1211
1608
  let employees = [];
1212
1609
  try {
1213
- employees = JSON.parse(readFileSync5(rosterPath, "utf8"));
1610
+ employees = JSON.parse(readFileSync6(rosterPath, "utf8"));
1214
1611
  } catch {
1215
1612
  return { created: 0, pathConfigured: false };
1216
1613
  }
@@ -1220,9 +1617,9 @@ function generateSessionWrappers(packageRoot, homeDir) {
1220
1617
  try {
1221
1618
  for (const f of readdirSync(binDir)) {
1222
1619
  if (f === "exe-start") continue;
1223
- const fPath = path6.join(binDir, f);
1620
+ const fPath = path7.join(binDir, f);
1224
1621
  try {
1225
- const content = readFileSync5(fPath, "utf8");
1622
+ const content = readFileSync6(fPath, "utf8");
1226
1623
  if (content.includes("exe-start")) {
1227
1624
  unlinkSync2(fPath);
1228
1625
  }
@@ -1237,30 +1634,30 @@ exec "${exeStartDst}" "$0" "$@"
1237
1634
  `;
1238
1635
  for (const emp of employees) {
1239
1636
  for (let n = 1; n <= MAX_N; n++) {
1240
- const wrapperPath = path6.join(binDir, `${emp.name}${n}`);
1241
- writeFileSync4(wrapperPath, wrapperContent);
1637
+ const wrapperPath = path7.join(binDir, `${emp.name}${n}`);
1638
+ writeFileSync5(wrapperPath, wrapperContent);
1242
1639
  chmodSync(wrapperPath, 493);
1243
1640
  created++;
1244
1641
  }
1245
1642
  }
1246
1643
  const codexLauncherCandidates = [
1247
- path6.join(packageRoot, "dist", "bin", "exe-start-codex.js"),
1248
- path6.join(packageRoot, "src", "bin", "exe-start-codex.ts")
1644
+ path7.join(packageRoot, "dist", "bin", "exe-start-codex.js"),
1645
+ path7.join(packageRoot, "src", "bin", "exe-start-codex.ts")
1249
1646
  ];
1250
1647
  let codexLauncher = null;
1251
1648
  for (const c of codexLauncherCandidates) {
1252
- if (existsSync6(c)) {
1649
+ if (existsSync7(c)) {
1253
1650
  codexLauncher = c;
1254
1651
  break;
1255
1652
  }
1256
1653
  }
1257
1654
  if (codexLauncher) {
1258
1655
  for (const emp of employees) {
1259
- const wrapperPath = path6.join(binDir, `${emp.name}-codex`);
1656
+ const wrapperPath = path7.join(binDir, `${emp.name}-codex`);
1260
1657
  const content = `#!/bin/bash
1261
1658
  exec node "${codexLauncher}" --agent ${emp.name} "$@"
1262
1659
  `;
1263
- writeFileSync4(wrapperPath, content);
1660
+ writeFileSync5(wrapperPath, content);
1264
1661
  chmodSync(wrapperPath, 493);
1265
1662
  created++;
1266
1663
  }
@@ -1279,24 +1676,24 @@ export PATH="${binDir}:$PATH"
1279
1676
  const shell = process.env.SHELL ?? "/bin/bash";
1280
1677
  const profilePaths = [];
1281
1678
  if (shell.includes("zsh")) {
1282
- profilePaths.push(path6.join(home, ".zshrc"));
1679
+ profilePaths.push(path7.join(home, ".zshrc"));
1283
1680
  } else if (shell.includes("bash")) {
1284
- profilePaths.push(path6.join(home, ".bashrc"));
1285
- profilePaths.push(path6.join(home, ".bash_profile"));
1681
+ profilePaths.push(path7.join(home, ".bashrc"));
1682
+ profilePaths.push(path7.join(home, ".bash_profile"));
1286
1683
  } else {
1287
- profilePaths.push(path6.join(home, ".profile"));
1684
+ profilePaths.push(path7.join(home, ".profile"));
1288
1685
  }
1289
1686
  for (const profilePath of profilePaths) {
1290
1687
  try {
1291
1688
  let content = "";
1292
1689
  try {
1293
- content = readFileSync5(profilePath, "utf8");
1690
+ content = readFileSync6(profilePath, "utf8");
1294
1691
  } catch {
1295
1692
  }
1296
1693
  if (content.includes(".exe-os/bin")) {
1297
1694
  return false;
1298
1695
  }
1299
- writeFileSync4(profilePath, content + exportLine);
1696
+ writeFileSync5(profilePath, content + exportLine);
1300
1697
  return true;
1301
1698
  } catch {
1302
1699
  continue;
@@ -1306,14 +1703,14 @@ export PATH="${binDir}:$PATH"
1306
1703
  }
1307
1704
 
1308
1705
  // src/bin/install.ts
1309
- var homedir2 = os6.homedir;
1310
- var EXE_DIR = path7.join(homedir2(), ".exe-os");
1706
+ var homedir2 = os7.homedir;
1707
+ var EXE_DIR = path9.join(homedir2(), ".exe-os");
1311
1708
  function restartDaemon() {
1312
- const pidPath = path7.join(EXE_DIR, "exed.pid");
1313
- const sockPath = path7.join(EXE_DIR, "exed.sock");
1709
+ const pidPath = path9.join(EXE_DIR, "exed.pid");
1710
+ const sockPath = path9.join(EXE_DIR, "exed.sock");
1314
1711
  try {
1315
- if (existsSync7(pidPath)) {
1316
- const pid = parseInt(readFileSync6(pidPath, "utf8").trim(), 10);
1712
+ if (existsSync9(pidPath)) {
1713
+ const pid = parseInt(readFileSync7(pidPath, "utf8").trim(), 10);
1317
1714
  if (!isNaN(pid) && pid > 0) {
1318
1715
  try {
1319
1716
  process.kill(pid, "SIGKILL");
@@ -1354,11 +1751,11 @@ function restartDaemon() {
1354
1751
  } catch {
1355
1752
  }
1356
1753
  try {
1357
- const wpDir = path7.join(EXE_DIR, "worker-pids");
1358
- if (existsSync7(wpDir)) {
1754
+ const wpDir = path9.join(EXE_DIR, "worker-pids");
1755
+ if (existsSync9(wpDir)) {
1359
1756
  for (const f of readdirSync2(wpDir)) {
1360
1757
  try {
1361
- unlinkSync3(path7.join(wpDir, f));
1758
+ unlinkSync3(path9.join(wpDir, f));
1362
1759
  } catch {
1363
1760
  }
1364
1761
  }
@@ -1375,7 +1772,7 @@ function restartDaemon() {
1375
1772
  }
1376
1773
  } catch {
1377
1774
  }
1378
- const totalGB = os6.totalmem() / (1024 * 1024 * 1024);
1775
+ const totalGB = os7.totalmem() / (1024 * 1024 * 1024);
1379
1776
  if (totalGB <= 8) {
1380
1777
  process.stderr.write(
1381
1778
  `exe-os: ${totalGB.toFixed(0)}GB system \u2014 skipping daemon spawn (keyword search mode)
@@ -1385,13 +1782,13 @@ function restartDaemon() {
1385
1782
  }
1386
1783
  try {
1387
1784
  const pkgRoot = resolvePackageRoot();
1388
- const daemonPath = path7.join(pkgRoot, "dist", "lib", "exe-daemon.js");
1389
- if (!existsSync7(daemonPath)) {
1785
+ const daemonPath = path9.join(pkgRoot, "dist", "lib", "exe-daemon.js");
1786
+ if (!existsSync9(daemonPath)) {
1390
1787
  process.stderr.write(`exe-os: daemon not found at ${daemonPath} \u2014 skipping respawn
1391
1788
  `);
1392
1789
  return;
1393
1790
  }
1394
- const logPath = path7.join(EXE_DIR, "exed.log");
1791
+ const logPath = path9.join(EXE_DIR, "exed.log");
1395
1792
  let stderrFd = "ignore";
1396
1793
  try {
1397
1794
  stderrFd = openSync(logPath, "a");
@@ -1461,6 +1858,12 @@ if (args.includes("--commands-only")) {
1461
1858
  } catch (err) {
1462
1859
  process.stderr.write(`exe-os: session wrapper generation failed: ${err instanceof Error ? err.message : String(err)}
1463
1860
  `);
1861
+ }
1862
+ try {
1863
+ execSync3("which codex", { encoding: "utf8", timeout: 5e3 });
1864
+ const { runCodexInstaller: runCodexInstaller2 } = await Promise.resolve().then(() => (init_installer2(), installer_exports));
1865
+ await runCodexInstaller2();
1866
+ } catch {
1464
1867
  }
1465
1868
  restartDaemon();
1466
1869
  } catch (err) {