@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
@@ -106,12 +106,133 @@ var init_config = __esm({
106
106
  }
107
107
  });
108
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 readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
150
+ import path3 from "path";
151
+ function loadAgentConfig() {
152
+ if (!existsSync3(AGENT_CONFIG_PATH)) return {};
153
+ try {
154
+ return JSON.parse(readFileSync3(AGENT_CONFIG_PATH, "utf-8"));
155
+ } catch {
156
+ return {};
157
+ }
158
+ }
159
+ function saveAgentConfig(config) {
160
+ const dir = path3.dirname(AGENT_CONFIG_PATH);
161
+ if (!existsSync3(dir)) mkdirSync2(dir, { recursive: true });
162
+ writeFileSync2(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 = path3.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
+
109
221
  // src/lib/employees.ts
110
222
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
111
- import { existsSync as existsSync3, symlinkSync, readlinkSync, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "fs";
223
+ import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync4, renameSync as renameSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "fs";
112
224
  import { execSync } from "child_process";
113
- import path3 from "path";
225
+ import path4 from "path";
114
226
  import os2 from "os";
227
+ function normalizeRole(role) {
228
+ return (role ?? "").trim().toLowerCase();
229
+ }
230
+ function isCoordinatorRole(role) {
231
+ return normalizeRole(role) === normalizeRole(COORDINATOR_ROLE);
232
+ }
233
+ function getCoordinatorEmployee(employees) {
234
+ return employees.find((e) => isCoordinatorRole(e.role));
235
+ }
115
236
  function validateEmployeeName(name) {
116
237
  if (!name) {
117
238
  return { valid: false, error: "Name is required" };
@@ -128,7 +249,7 @@ function validateEmployeeName(name) {
128
249
  return { valid: true };
129
250
  }
130
251
  async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
131
- if (!existsSync3(employeesPath)) {
252
+ if (!existsSync4(employeesPath)) {
132
253
  return [];
133
254
  }
134
255
  const raw = await readFile2(employeesPath, "utf-8");
@@ -139,9 +260,17 @@ async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
139
260
  }
140
261
  }
141
262
  async function saveEmployees(employees, employeesPath = EMPLOYEES_PATH) {
142
- await mkdir2(path3.dirname(employeesPath), { recursive: true });
263
+ await mkdir2(path4.dirname(employeesPath), { recursive: true });
143
264
  await writeFile2(employeesPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
144
265
  }
266
+ function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
267
+ if (!existsSync4(employeesPath)) return [];
268
+ try {
269
+ return JSON.parse(readFileSync4(employeesPath, "utf-8"));
270
+ } catch {
271
+ return [];
272
+ }
273
+ }
145
274
  function addEmployee(employees, employee) {
146
275
  const normalized = { ...employee, name: employee.name.toLowerCase() };
147
276
  if (employees.some((e) => e.name.toLowerCase() === normalized.name)) {
@@ -149,6 +278,52 @@ function addEmployee(employees, employee) {
149
278
  }
150
279
  return [...employees, normalized];
151
280
  }
281
+ function appendToCoordinatorTeam(employee) {
282
+ const coordinator = getCoordinatorEmployee(loadEmployeesSync());
283
+ if (!coordinator) return;
284
+ const idPath = path4.join(IDENTITY_DIR, `${coordinator.name}.md`);
285
+ if (!existsSync4(idPath)) return;
286
+ const content = readFileSync4(idPath, "utf-8");
287
+ if (content.includes(`**${capitalize(employee.name)}`)) return;
288
+ const teamMatch = content.match(TEAM_SECTION_RE);
289
+ if (!teamMatch || teamMatch.index === void 0) return;
290
+ const afterTeam = content.slice(teamMatch.index + teamMatch[0].length);
291
+ const nextHeading = afterTeam.match(/\n## /);
292
+ const entry = `
293
+ **${capitalize(employee.name)} (${employee.role}):** Newly hired. Update this description as the role develops.
294
+ `;
295
+ let updated;
296
+ if (nextHeading && nextHeading.index !== void 0) {
297
+ const insertAt = teamMatch.index + teamMatch[0].length + nextHeading.index;
298
+ updated = content.slice(0, insertAt) + entry + content.slice(insertAt);
299
+ } else {
300
+ updated = content.trimEnd() + "\n" + entry;
301
+ }
302
+ writeFileSync3(idPath, updated, "utf-8");
303
+ }
304
+ function capitalize(s) {
305
+ return s.charAt(0).toUpperCase() + s.slice(1);
306
+ }
307
+ async function hireEmployee(employee) {
308
+ const employees = await loadEmployees();
309
+ const updated = addEmployee(employees, employee);
310
+ await saveEmployees(updated);
311
+ try {
312
+ appendToCoordinatorTeam(employee);
313
+ } catch {
314
+ }
315
+ try {
316
+ const { loadAgentConfig: loadAgentConfig2, saveAgentConfig: saveAgentConfig2 } = await Promise.resolve().then(() => (init_agent_config(), agent_config_exports));
317
+ const config = loadAgentConfig2();
318
+ const name = employee.name.toLowerCase();
319
+ if (!config[name] && config["default"]) {
320
+ config[name] = { ...config["default"] };
321
+ saveAgentConfig2(config);
322
+ }
323
+ } catch {
324
+ }
325
+ return updated;
326
+ }
152
327
  function findExeBin() {
153
328
  try {
154
329
  return execSync(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
@@ -165,7 +340,7 @@ function registerBinSymlinks(name) {
165
340
  errors.push("Could not find 'exe-os' in PATH");
166
341
  return { created, skipped, errors };
167
342
  }
168
- const binDir = path3.dirname(exeBinPath);
343
+ const binDir = path4.dirname(exeBinPath);
169
344
  let target;
170
345
  try {
171
346
  target = readlinkSync(exeBinPath);
@@ -175,8 +350,8 @@ function registerBinSymlinks(name) {
175
350
  }
176
351
  for (const suffix of ["", "-opencode"]) {
177
352
  const linkName = `${name}${suffix}`;
178
- const linkPath = path3.join(binDir, linkName);
179
- if (existsSync3(linkPath)) {
353
+ const linkPath = path4.join(binDir, linkName);
354
+ if (existsSync4(linkPath)) {
180
355
  skipped.push(linkName);
181
356
  continue;
182
357
  }
@@ -189,12 +364,15 @@ function registerBinSymlinks(name) {
189
364
  }
190
365
  return { created, skipped, errors };
191
366
  }
192
- var EMPLOYEES_PATH;
367
+ var EMPLOYEES_PATH, COORDINATOR_ROLE, IDENTITY_DIR, TEAM_SECTION_RE;
193
368
  var init_employees = __esm({
194
369
  "src/lib/employees.ts"() {
195
370
  "use strict";
196
371
  init_config();
197
- EMPLOYEES_PATH = path3.join(EXE_AI_DIR, "exe-employees.json");
372
+ EMPLOYEES_PATH = path4.join(EXE_AI_DIR, "exe-employees.json");
373
+ COORDINATOR_ROLE = "COO";
374
+ IDENTITY_DIR = path4.join(EXE_AI_DIR, "identity");
375
+ TEAM_SECTION_RE = /^## Team\b.*$/m;
198
376
  }
199
377
  });
200
378
 
@@ -205,12 +383,36 @@ var init_db_retry = __esm({
205
383
  }
206
384
  });
207
385
 
386
+ // src/lib/database-adapter.ts
387
+ import os3 from "os";
388
+ import path5 from "path";
389
+ import { createRequire } from "module";
390
+ import { pathToFileURL } from "url";
391
+ var BOOLEAN_COLUMNS_BY_TABLE, BOOLEAN_COLUMN_NAMES;
392
+ var init_database_adapter = __esm({
393
+ "src/lib/database-adapter.ts"() {
394
+ "use strict";
395
+ BOOLEAN_COLUMNS_BY_TABLE = {
396
+ memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
397
+ behaviors: /* @__PURE__ */ new Set(["active"]),
398
+ notifications: /* @__PURE__ */ new Set(["read"]),
399
+ users: /* @__PURE__ */ new Set(["has_personal_memory"])
400
+ };
401
+ BOOLEAN_COLUMN_NAMES = new Set(
402
+ Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
403
+ );
404
+ }
405
+ });
406
+
208
407
  // src/lib/database.ts
209
408
  import { createClient } from "@libsql/client";
210
409
  function getClient() {
211
- if (!_resilientClient) {
410
+ if (!_adapterClient) {
212
411
  throw new Error("Database client not initialized. Call initDatabase() first.");
213
412
  }
413
+ if (process.env.DATABASE_URL) {
414
+ return _adapterClient;
415
+ }
214
416
  if (process.env.EXE_IS_DAEMON === "1") {
215
417
  return _resilientClient;
216
418
  }
@@ -219,14 +421,16 @@ function getClient() {
219
421
  }
220
422
  return _resilientClient;
221
423
  }
222
- var _resilientClient, _daemonClient;
424
+ var _resilientClient, _daemonClient, _adapterClient;
223
425
  var init_database = __esm({
224
426
  "src/lib/database.ts"() {
225
427
  "use strict";
226
428
  init_db_retry();
227
429
  init_employees();
430
+ init_database_adapter();
228
431
  _resilientClient = null;
229
432
  _daemonClient = null;
433
+ _adapterClient = null;
230
434
  }
231
435
  });
232
436
 
@@ -780,17 +984,17 @@ __export(identity_exports, {
780
984
  listIdentities: () => listIdentities,
781
985
  updateIdentity: () => updateIdentity
782
986
  });
783
- import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
987
+ import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
784
988
  import { readdirSync as readdirSync2 } from "fs";
785
- import path6 from "path";
989
+ import path8 from "path";
786
990
  import { createHash } from "crypto";
787
991
  function ensureDir() {
788
- if (!existsSync6(IDENTITY_DIR)) {
789
- mkdirSync3(IDENTITY_DIR, { recursive: true });
992
+ if (!existsSync7(IDENTITY_DIR2)) {
993
+ mkdirSync4(IDENTITY_DIR2, { recursive: true });
790
994
  }
791
995
  }
792
996
  function identityPath(agentId) {
793
- return path6.join(IDENTITY_DIR, `${agentId}.md`);
997
+ return path8.join(IDENTITY_DIR2, `${agentId}.md`);
794
998
  }
795
999
  function parseFrontmatter(raw) {
796
1000
  const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
@@ -831,8 +1035,8 @@ function contentHash(content) {
831
1035
  }
832
1036
  function getIdentity(agentId) {
833
1037
  const filePath = identityPath(agentId);
834
- if (!existsSync6(filePath)) return null;
835
- const raw = readFileSync6(filePath, "utf-8");
1038
+ if (!existsSync7(filePath)) return null;
1039
+ const raw = readFileSync7(filePath, "utf-8");
836
1040
  const { frontmatter, body } = parseFrontmatter(raw);
837
1041
  return {
838
1042
  agentId,
@@ -846,7 +1050,7 @@ async function updateIdentity(agentId, content, updatedBy) {
846
1050
  ensureDir();
847
1051
  const filePath = identityPath(agentId);
848
1052
  const hash = contentHash(content);
849
- writeFileSync4(filePath, content, "utf-8");
1053
+ writeFileSync5(filePath, content, "utf-8");
850
1054
  try {
851
1055
  const client = getClient();
852
1056
  await client.execute({
@@ -863,7 +1067,7 @@ async function updateIdentity(agentId, content, updatedBy) {
863
1067
  }
864
1068
  function listIdentities() {
865
1069
  ensureDir();
866
- const files = readdirSync2(IDENTITY_DIR).filter((f) => f.endsWith(".md"));
1070
+ const files = readdirSync2(IDENTITY_DIR2).filter((f) => f.endsWith(".md"));
867
1071
  const results = [];
868
1072
  for (const file of files) {
869
1073
  const agentId = file.replace(".md", "");
@@ -896,40 +1100,40 @@ ${teamLines.join("\n")}`);
896
1100
  }
897
1101
  return parts.join("\n\n");
898
1102
  }
899
- var IDENTITY_DIR;
1103
+ var IDENTITY_DIR2;
900
1104
  var init_identity = __esm({
901
1105
  "src/lib/identity.ts"() {
902
1106
  "use strict";
903
1107
  init_config();
904
1108
  init_database();
905
- IDENTITY_DIR = path6.join(EXE_AI_DIR, "identity");
1109
+ IDENTITY_DIR2 = path8.join(EXE_AI_DIR, "identity");
906
1110
  }
907
1111
  });
908
1112
 
909
1113
  // src/lib/agent-symlinks.ts
910
- import os3 from "os";
911
- import path7 from "path";
1114
+ import os4 from "os";
1115
+ import path9 from "path";
912
1116
  import {
913
- existsSync as existsSync7,
1117
+ existsSync as existsSync8,
914
1118
  lstatSync,
915
- mkdirSync as mkdirSync4,
1119
+ mkdirSync as mkdirSync5,
916
1120
  readlinkSync as readlinkSync2,
917
1121
  symlinkSync as symlinkSync2
918
1122
  } from "fs";
919
1123
  function claudeAgentsDir(homeDir) {
920
- return path7.join(homeDir, ".claude", "agents");
1124
+ return path9.join(homeDir, ".claude", "agents");
921
1125
  }
922
1126
  function identitySourcePath(homeDir, agentId) {
923
- return path7.join(homeDir, ".exe-os", "identity", `${agentId}.md`);
1127
+ return path9.join(homeDir, ".exe-os", "identity", `${agentId}.md`);
924
1128
  }
925
1129
  function claudeAgentLinkPath(homeDir, agentId) {
926
- return path7.join(claudeAgentsDir(homeDir), `${agentId}.md`);
1130
+ return path9.join(claudeAgentsDir(homeDir), `${agentId}.md`);
927
1131
  }
928
- function ensureAgentSymlink(agentId, homeDir = os3.homedir()) {
1132
+ function ensureAgentSymlink(agentId, homeDir = os4.homedir()) {
929
1133
  const target = identitySourcePath(homeDir, agentId);
930
1134
  const link = claudeAgentLinkPath(homeDir, agentId);
931
- mkdirSync4(claudeAgentsDir(homeDir), { recursive: true });
932
- if (existsSync7(link)) {
1135
+ mkdirSync5(claudeAgentsDir(homeDir), { recursive: true });
1136
+ if (existsSync8(link)) {
933
1137
  let stat;
934
1138
  try {
935
1139
  stat = lstatSync(link);
@@ -963,7 +1167,7 @@ function ensureAgentSymlink(agentId, homeDir = os3.homedir()) {
963
1167
  }
964
1168
  return { agentId, action: "created", target, link };
965
1169
  }
966
- async function ensureAllAgentSymlinks(homeDir = os3.homedir()) {
1170
+ async function ensureAllAgentSymlinks(homeDir = os4.homedir()) {
967
1171
  const employees = await loadEmployees();
968
1172
  return employees.map((emp) => ensureAgentSymlink(emp.name, homeDir));
969
1173
  }
@@ -998,14 +1202,14 @@ var init_mcp_prefix = __esm({
998
1202
  });
999
1203
 
1000
1204
  // src/lib/preferences.ts
1001
- import { existsSync as existsSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
1002
- import path8 from "path";
1003
- import os4 from "os";
1004
- function loadPreferences(homeDir = os4.homedir()) {
1005
- const configPath = path8.join(homeDir, ".exe-os", "config.json");
1006
- if (!existsSync8(configPath)) return {};
1205
+ import { existsSync as existsSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6 } from "fs";
1206
+ import path10 from "path";
1207
+ import os5 from "os";
1208
+ function loadPreferences(homeDir = os5.homedir()) {
1209
+ const configPath = path10.join(homeDir, ".exe-os", "config.json");
1210
+ if (!existsSync9(configPath)) return {};
1007
1211
  try {
1008
- const config = JSON.parse(readFileSync7(configPath, "utf-8"));
1212
+ const config = JSON.parse(readFileSync8(configPath, "utf-8"));
1009
1213
  return config.preferences ?? {};
1010
1214
  } catch {
1011
1215
  return {};
@@ -1031,52 +1235,52 @@ __export(installer_exports, {
1031
1235
  setupTmux: () => setupTmux
1032
1236
  });
1033
1237
  import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, readdir } from "fs/promises";
1034
- import { existsSync as existsSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync6, copyFileSync, mkdirSync as mkdirSync6 } from "fs";
1035
- import path9 from "path";
1036
- import os5 from "os";
1238
+ import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync7, copyFileSync, mkdirSync as mkdirSync7 } from "fs";
1239
+ import path11 from "path";
1240
+ import os6 from "os";
1037
1241
  import { execSync as execSync2 } from "child_process";
1038
1242
  import { fileURLToPath as fileURLToPath2 } from "url";
1039
1243
  function resolvePackageRoot() {
1040
1244
  const thisFile = fileURLToPath2(import.meta.url);
1041
- let dir = path9.dirname(thisFile);
1042
- const root = path9.parse(dir).root;
1245
+ let dir = path11.dirname(thisFile);
1246
+ const root = path11.parse(dir).root;
1043
1247
  while (dir !== root) {
1044
- const pkgPath = path9.join(dir, "package.json");
1045
- if (existsSync9(pkgPath)) {
1248
+ const pkgPath = path11.join(dir, "package.json");
1249
+ if (existsSync10(pkgPath)) {
1046
1250
  try {
1047
- const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
1251
+ const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
1048
1252
  if (pkg.name === "@askexenow/exe-os" || pkg.name === "exe-os") return dir;
1049
1253
  } catch {
1050
1254
  }
1051
1255
  }
1052
- dir = path9.dirname(dir);
1256
+ dir = path11.dirname(dir);
1053
1257
  }
1054
- return path9.resolve(path9.dirname(thisFile), "..", "..", "..");
1258
+ return path11.resolve(path11.dirname(thisFile), "..", "..", "..");
1055
1259
  }
1056
- async function copySlashCommands(packageRoot, homeDir = os5.homedir()) {
1260
+ async function copySlashCommands(packageRoot, homeDir = os6.homedir()) {
1057
1261
  let copied = 0;
1058
1262
  let skipped = 0;
1059
- const skillsBase = path9.join(homeDir, ".claude", "skills");
1060
- const exeDir = path9.join(packageRoot, "src", "commands", "exe");
1061
- if (existsSync9(exeDir)) {
1263
+ const skillsBase = path11.join(homeDir, ".claude", "skills");
1264
+ const exeDir = path11.join(packageRoot, "src", "commands", "exe");
1265
+ if (existsSync10(exeDir)) {
1062
1266
  const entries = await readdir(exeDir);
1063
1267
  const mdFiles = entries.filter((f) => f.endsWith(".md"));
1064
1268
  for (const file of mdFiles) {
1065
1269
  const name = file.replace(".md", "");
1066
- const destDir = path9.join(skillsBase, `exe-${name}`);
1270
+ const destDir = path11.join(skillsBase, `exe-${name}`);
1067
1271
  await mkdir3(destDir, { recursive: true });
1068
- const srcPath = path9.join(exeDir, file);
1069
- const destPath = path9.join(destDir, "SKILL.md");
1272
+ const srcPath = path11.join(exeDir, file);
1273
+ const destPath = path11.join(destDir, "SKILL.md");
1070
1274
  const result = await copyAsSkill(srcPath, destPath, `exe-${name}`);
1071
1275
  if (result) copied++;
1072
1276
  else skipped++;
1073
1277
  }
1074
1278
  }
1075
- const topLevelSrc = path9.join(packageRoot, "src", "commands", "exe.md");
1076
- if (existsSync9(topLevelSrc)) {
1077
- const destDir = path9.join(skillsBase, "exe");
1279
+ const topLevelSrc = path11.join(packageRoot, "src", "commands", "exe.md");
1280
+ if (existsSync10(topLevelSrc)) {
1281
+ const destDir = path11.join(skillsBase, "exe");
1078
1282
  await mkdir3(destDir, { recursive: true });
1079
- const destPath = path9.join(destDir, "SKILL.md");
1283
+ const destPath = path11.join(destDir, "SKILL.md");
1080
1284
  const result = await copyAsSkill(topLevelSrc, destPath, "exe");
1081
1285
  if (result) copied++;
1082
1286
  else skipped++;
@@ -1099,17 +1303,17 @@ name: ${skillName}
1099
1303
  `);
1100
1304
  }
1101
1305
  }
1102
- if (existsSync9(destPath)) {
1306
+ if (existsSync10(destPath)) {
1103
1307
  const existing = await readFile3(destPath, "utf-8");
1104
1308
  if (existing === content) return false;
1105
1309
  }
1106
1310
  await writeFile3(destPath, content);
1107
1311
  return true;
1108
1312
  }
1109
- async function registerMcpServer(packageRoot, homeDir = os5.homedir()) {
1110
- const claudeJsonPath = path9.join(homeDir, ".claude.json");
1313
+ async function registerMcpServer(packageRoot, homeDir = os6.homedir()) {
1314
+ const claudeJsonPath = path11.join(homeDir, ".claude.json");
1111
1315
  let claudeJson = {};
1112
- if (existsSync9(claudeJsonPath)) {
1316
+ if (existsSync10(claudeJsonPath)) {
1113
1317
  try {
1114
1318
  claudeJson = JSON.parse(await readFile3(claudeJsonPath, "utf-8"));
1115
1319
  } catch {
@@ -1122,7 +1326,7 @@ async function registerMcpServer(packageRoot, homeDir = os5.homedir()) {
1122
1326
  const newEntry = {
1123
1327
  type: "stdio",
1124
1328
  command: "node",
1125
- args: [path9.join(packageRoot, "dist", "mcp", "server.js")],
1329
+ args: [path11.join(packageRoot, "dist", "mcp", "server.js")],
1126
1330
  env: {}
1127
1331
  };
1128
1332
  const currentMem = claudeJson.mcpServers[MCP_LEGACY_KEY];
@@ -1130,17 +1334,17 @@ async function registerMcpServer(packageRoot, homeDir = os5.homedir()) {
1130
1334
  const memMatches = currentMem && JSON.stringify(currentMem) === JSON.stringify(newEntry);
1131
1335
  const osMatches = currentOs && JSON.stringify(currentOs) === JSON.stringify(newEntry);
1132
1336
  if (memMatches && osMatches) {
1133
- await cleanSettingsJsonMcp(path9.join(homeDir, ".claude", "settings.json"));
1337
+ await cleanSettingsJsonMcp(path11.join(homeDir, ".claude", "settings.json"));
1134
1338
  return false;
1135
1339
  }
1136
1340
  claudeJson.mcpServers[MCP_LEGACY_KEY] = newEntry;
1137
1341
  claudeJson.mcpServers[MCP_PRIMARY_KEY] = newEntry;
1138
1342
  await writeFile3(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
1139
- await cleanSettingsJsonMcp(path9.join(homeDir, ".claude", "settings.json"));
1343
+ await cleanSettingsJsonMcp(path11.join(homeDir, ".claude", "settings.json"));
1140
1344
  return true;
1141
1345
  }
1142
1346
  async function cleanSettingsJsonMcp(settingsPath) {
1143
- if (!existsSync9(settingsPath)) return;
1347
+ if (!existsSync10(settingsPath)) return;
1144
1348
  try {
1145
1349
  const settings = JSON.parse(await readFile3(settingsPath, "utf-8"));
1146
1350
  const servers = settings.mcpServers;
@@ -1160,14 +1364,14 @@ async function cleanSettingsJsonMcp(settingsPath) {
1160
1364
  } catch {
1161
1365
  }
1162
1366
  }
1163
- async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1164
- const settingsPath = path9.join(homeDir, ".claude", "settings.json");
1165
- const logsDir = path9.join(homeDir, ".exe-os", "logs");
1166
- const hookLogPath = path9.join(logsDir, "hooks.log");
1367
+ async function mergeHooks(packageRoot, homeDir = os6.homedir()) {
1368
+ const settingsPath = path11.join(homeDir, ".claude", "settings.json");
1369
+ const logsDir = path11.join(homeDir, ".exe-os", "logs");
1370
+ const hookLogPath = path11.join(logsDir, "hooks.log");
1167
1371
  const logSuffix = ` 2>> "${hookLogPath}"`;
1168
1372
  await mkdir3(logsDir, { recursive: true });
1169
1373
  let settings = {};
1170
- if (existsSync9(settingsPath)) {
1374
+ if (existsSync10(settingsPath)) {
1171
1375
  try {
1172
1376
  settings = JSON.parse(await readFile3(settingsPath, "utf-8"));
1173
1377
  } catch {
@@ -1189,11 +1393,11 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1189
1393
  hooks: [
1190
1394
  {
1191
1395
  type: "command",
1192
- command: `node "${path9.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
1396
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
1193
1397
  },
1194
1398
  {
1195
1399
  type: "command",
1196
- command: `node "${path9.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
1400
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
1197
1401
  }
1198
1402
  ]
1199
1403
  },
@@ -1205,7 +1409,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1205
1409
  hooks: [
1206
1410
  {
1207
1411
  type: "command",
1208
- command: `node "${path9.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
1412
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
1209
1413
  timeout: 1e4
1210
1414
  }
1211
1415
  ]
@@ -1218,7 +1422,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1218
1422
  hooks: [
1219
1423
  {
1220
1424
  type: "command",
1221
- command: `node "${path9.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
1425
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
1222
1426
  }
1223
1427
  ]
1224
1428
  },
@@ -1230,7 +1434,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1230
1434
  hooks: [
1231
1435
  {
1232
1436
  type: "command",
1233
- command: `node "${path9.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
1437
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
1234
1438
  timeout: 5e3
1235
1439
  }
1236
1440
  ]
@@ -1243,7 +1447,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1243
1447
  hooks: [
1244
1448
  {
1245
1449
  type: "command",
1246
- command: `node "${path9.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
1450
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
1247
1451
  }
1248
1452
  ]
1249
1453
  },
@@ -1256,7 +1460,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1256
1460
  hooks: [
1257
1461
  {
1258
1462
  type: "command",
1259
- command: `node "${path9.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
1463
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
1260
1464
  }
1261
1465
  ]
1262
1466
  },
@@ -1268,7 +1472,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1268
1472
  hooks: [
1269
1473
  {
1270
1474
  type: "command",
1271
- command: `node "${path9.join(packageRoot, "dist", "hooks", "subagent-stop.js")}"${logSuffix}`
1475
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "subagent-stop.js")}"${logSuffix}`
1272
1476
  }
1273
1477
  ]
1274
1478
  },
@@ -1280,7 +1484,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1280
1484
  hooks: [
1281
1485
  {
1282
1486
  type: "command",
1283
- command: `node "${path9.join(packageRoot, "dist", "hooks", "pre-compact.js")}"${logSuffix}`,
1487
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "pre-compact.js")}"${logSuffix}`,
1284
1488
  timeout: 1e4
1285
1489
  }
1286
1490
  ]
@@ -1293,7 +1497,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1293
1497
  hooks: [
1294
1498
  {
1295
1499
  type: "command",
1296
- command: `node "${path9.join(packageRoot, "dist", "hooks", "session-end.js")}"${logSuffix}`
1500
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "session-end.js")}"${logSuffix}`
1297
1501
  }
1298
1502
  ]
1299
1503
  },
@@ -1305,7 +1509,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1305
1509
  hooks: [
1306
1510
  {
1307
1511
  type: "command",
1308
- command: `node "${path9.join(packageRoot, "dist", "hooks", "notification.js")}"${logSuffix}`
1512
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "notification.js")}"${logSuffix}`
1309
1513
  }
1310
1514
  ]
1311
1515
  },
@@ -1317,7 +1521,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1317
1521
  hooks: [
1318
1522
  {
1319
1523
  type: "command",
1320
- command: `node "${path9.join(packageRoot, "dist", "hooks", "post-compact.js")}"${logSuffix}`,
1524
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "post-compact.js")}"${logSuffix}`,
1321
1525
  timeout: 1e4
1322
1526
  }
1323
1527
  ]
@@ -1330,7 +1534,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1330
1534
  hooks: [
1331
1535
  {
1332
1536
  type: "command",
1333
- command: `node "${path9.join(packageRoot, "dist", "hooks", "instructions-loaded.js")}"${logSuffix}`
1537
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "instructions-loaded.js")}"${logSuffix}`
1334
1538
  }
1335
1539
  ]
1336
1540
  },
@@ -1429,13 +1633,13 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1429
1633
  allowList.push(tool);
1430
1634
  }
1431
1635
  }
1432
- await mkdir3(path9.dirname(settingsPath), { recursive: true });
1636
+ await mkdir3(path11.dirname(settingsPath), { recursive: true });
1433
1637
  await writeFile3(settingsPath, JSON.stringify(settings, null, 2) + "\n");
1434
1638
  return { added, skipped };
1435
1639
  }
1436
- async function cleanOldShellFunctions(homeDir = os5.homedir()) {
1437
- const rosterPath = path9.join(homeDir, ".exe-os", "exe-employees.json");
1438
- if (!existsSync9(rosterPath)) return 0;
1640
+ async function cleanOldShellFunctions(homeDir = os6.homedir()) {
1641
+ const rosterPath = path11.join(homeDir, ".exe-os", "exe-employees.json");
1642
+ if (!existsSync10(rosterPath)) return 0;
1439
1643
  let employees;
1440
1644
  try {
1441
1645
  employees = JSON.parse(await readFile3(rosterPath, "utf-8"));
@@ -1450,13 +1654,13 @@ async function cleanOldShellFunctions(homeDir = os5.homedir()) {
1450
1654
  return { name: n, funcDef, forLoop };
1451
1655
  });
1452
1656
  const rcFiles = [
1453
- path9.join(homeDir, ".zshrc"),
1454
- path9.join(homeDir, ".bashrc")
1657
+ path11.join(homeDir, ".zshrc"),
1658
+ path11.join(homeDir, ".bashrc")
1455
1659
  ];
1456
1660
  const REMOVED_MARKER = "# Removed by exe-os \u2014 wrappers now at ~/.exe-os/bin/";
1457
1661
  let totalRemoved = 0;
1458
1662
  for (const rcPath of rcFiles) {
1459
- if (!existsSync9(rcPath)) continue;
1663
+ if (!existsSync10(rcPath)) continue;
1460
1664
  let content;
1461
1665
  try {
1462
1666
  content = await readFile3(rcPath, "utf-8");
@@ -1560,8 +1764,8 @@ function escapeRegExp(s) {
1560
1764
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1561
1765
  }
1562
1766
  async function injectOrchestrationRules(homeDir) {
1563
- const claudeDir = path9.join(homeDir, ".claude");
1564
- const claudeMdPath = path9.join(claudeDir, "CLAUDE.md");
1767
+ const claudeDir = path11.join(homeDir, ".claude");
1768
+ const claudeMdPath = path11.join(claudeDir, "CLAUDE.md");
1565
1769
  await mkdir3(claudeDir, { recursive: true });
1566
1770
  let existing = "";
1567
1771
  try {
@@ -1583,19 +1787,19 @@ async function injectOrchestrationRules(homeDir) {
1583
1787
  await writeFile3(claudeMdPath, existing + separator + ORCHESTRATION_RULES + "\n", "utf-8");
1584
1788
  return "injected";
1585
1789
  }
1586
- async function installStatusLine(packageRoot, homeDir = os5.homedir()) {
1790
+ async function installStatusLine(packageRoot, homeDir = os6.homedir()) {
1587
1791
  const prefs = loadPreferences(homeDir);
1588
1792
  if (prefs.ccStatusLine === false) return "opted-out";
1589
- const claudeDir = path9.join(homeDir, ".claude");
1793
+ const claudeDir = path11.join(homeDir, ".claude");
1590
1794
  await mkdir3(claudeDir, { recursive: true });
1591
- const assetPath = path9.join(packageRoot, "dist", "assets", "statusline-command.sh");
1592
- if (!existsSync9(assetPath)) return "asset-missing";
1593
- const destScript = path9.join(claudeDir, "statusline-command.sh");
1795
+ const assetPath = path11.join(packageRoot, "dist", "assets", "statusline-command.sh");
1796
+ if (!existsSync10(assetPath)) return "asset-missing";
1797
+ const destScript = path11.join(claudeDir, "statusline-command.sh");
1594
1798
  const assetContent = await readFile3(assetPath, "utf-8");
1595
1799
  await writeFile3(destScript, assetContent, { mode: 493 });
1596
- const settingsPath = path9.join(claudeDir, "settings.json");
1800
+ const settingsPath = path11.join(claudeDir, "settings.json");
1597
1801
  let settings = {};
1598
- if (existsSync9(settingsPath)) {
1802
+ if (existsSync10(settingsPath)) {
1599
1803
  try {
1600
1804
  settings = JSON.parse(await readFile3(settingsPath, "utf-8"));
1601
1805
  } catch {
@@ -1632,13 +1836,13 @@ async function runInstaller(homeDir) {
1632
1836
  `Hooks: ${hookResult.added} added, ${hookResult.skipped} unchanged
1633
1837
  `
1634
1838
  );
1635
- const resolvedHome = homeDir ?? os5.homedir();
1636
- const exeWorkspace = path9.join(resolvedHome, "exe");
1637
- if (!existsSync9(exeWorkspace)) {
1839
+ const resolvedHome = homeDir ?? os6.homedir();
1840
+ const exeWorkspace = path11.join(resolvedHome, "exe");
1841
+ if (!existsSync10(exeWorkspace)) {
1638
1842
  try {
1639
- await mkdir3(path9.join(exeWorkspace, "content"), { recursive: true });
1640
- await mkdir3(path9.join(exeWorkspace, "operations"), { recursive: true });
1641
- await mkdir3(path9.join(exeWorkspace, "output"), { recursive: true });
1843
+ await mkdir3(path11.join(exeWorkspace, "content"), { recursive: true });
1844
+ await mkdir3(path11.join(exeWorkspace, "operations"), { recursive: true });
1845
+ await mkdir3(path11.join(exeWorkspace, "output"), { recursive: true });
1642
1846
  process.stderr.write(
1643
1847
  `Created ~/exe/ \u2014 your automation workspace for non-code projects
1644
1848
  `
@@ -1673,34 +1877,34 @@ exe-os installed successfully.
1673
1877
  `);
1674
1878
  }
1675
1879
  function setupTmux(home) {
1676
- const homeDir = home ?? os5.homedir();
1677
- const exeDir = path9.join(homeDir, ".exe-os");
1678
- const exeTmuxConf = path9.join(exeDir, "tmux.conf");
1679
- const userTmuxConf = path9.join(homeDir, ".tmux.conf");
1680
- const backupPath = path9.join(homeDir, ".tmux.conf.backup");
1880
+ const homeDir = home ?? os6.homedir();
1881
+ const exeDir = path11.join(homeDir, ".exe-os");
1882
+ const exeTmuxConf = path11.join(exeDir, "tmux.conf");
1883
+ const userTmuxConf = path11.join(homeDir, ".tmux.conf");
1884
+ const backupPath = path11.join(homeDir, ".tmux.conf.backup");
1681
1885
  const sourceLine = "source-file ~/.exe-os/tmux.conf";
1682
1886
  const pkgRoot = resolvePackageRoot();
1683
- const assetPath = path9.join(pkgRoot, "dist", "assets", "tmux.conf");
1684
- if (!existsSync9(assetPath)) {
1887
+ const assetPath = path11.join(pkgRoot, "dist", "assets", "tmux.conf");
1888
+ if (!existsSync10(assetPath)) {
1685
1889
  process.stderr.write(`exe-os: tmux.conf asset not found at ${assetPath} \u2014 skipping tmux setup
1686
1890
  `);
1687
1891
  return;
1688
1892
  }
1689
- mkdirSync6(exeDir, { recursive: true });
1893
+ mkdirSync7(exeDir, { recursive: true });
1690
1894
  copyFileSync(assetPath, exeTmuxConf);
1691
- if (existsSync9(userTmuxConf)) {
1692
- const existing = readFileSync8(userTmuxConf, "utf8");
1895
+ if (existsSync10(userTmuxConf)) {
1896
+ const existing = readFileSync9(userTmuxConf, "utf8");
1693
1897
  if (!existing.includes(sourceLine)) {
1694
- if (!existsSync9(backupPath)) {
1898
+ if (!existsSync10(backupPath)) {
1695
1899
  copyFileSync(userTmuxConf, backupPath);
1696
1900
  process.stderr.write(`exe-os: backed up existing tmux config to ${backupPath}
1697
1901
  `);
1698
1902
  }
1699
- writeFileSync6(userTmuxConf, `${sourceLine}
1903
+ writeFileSync7(userTmuxConf, `${sourceLine}
1700
1904
  ${existing}`);
1701
1905
  }
1702
1906
  } else {
1703
- writeFileSync6(userTmuxConf, `# Exe OS tmux defaults \u2014 remove this line to use your own config
1907
+ writeFileSync7(userTmuxConf, `# Exe OS tmux defaults \u2014 remove this line to use your own config
1704
1908
  ${sourceLine}
1705
1909
  `);
1706
1910
  }
@@ -1711,10 +1915,10 @@ ${sourceLine}
1711
1915
  process.stderr.write("exe-os: tmux config installed\n");
1712
1916
  }
1713
1917
  function setupGhostty(home) {
1714
- const homeDir = home ?? os5.homedir();
1715
- const xdgConfig = path9.join(homeDir, ".config", "ghostty");
1716
- const macConfig = path9.join(homeDir, "Library", "Application Support", "com.mitchellh.ghostty");
1717
- const ghosttyInstalled = existsSync9(xdgConfig) || existsSync9(macConfig) || (() => {
1918
+ const homeDir = home ?? os6.homedir();
1919
+ const xdgConfig = path11.join(homeDir, ".config", "ghostty");
1920
+ const macConfig = path11.join(homeDir, "Library", "Application Support", "com.mitchellh.ghostty");
1921
+ const ghosttyInstalled = existsSync10(xdgConfig) || existsSync10(macConfig) || (() => {
1718
1922
  try {
1719
1923
  execSync2("which ghostty 2>/dev/null");
1720
1924
  return true;
@@ -1726,47 +1930,47 @@ function setupGhostty(home) {
1726
1930
  return;
1727
1931
  }
1728
1932
  const pkgRoot = resolvePackageRoot();
1729
- const assetPath = path9.join(pkgRoot, "dist", "assets", "ghostty.conf");
1730
- if (!existsSync9(assetPath)) {
1933
+ const assetPath = path11.join(pkgRoot, "dist", "assets", "ghostty.conf");
1934
+ if (!existsSync10(assetPath)) {
1731
1935
  process.stderr.write("exe-os: ghostty.conf asset not found \u2014 skipping Ghostty setup\n");
1732
1936
  return;
1733
1937
  }
1734
1938
  const configDir = xdgConfig;
1735
- const configPath = path9.join(configDir, "config");
1736
- const backupPath = path9.join(configDir, "config.backup");
1737
- mkdirSync6(configDir, { recursive: true });
1939
+ const configPath = path11.join(configDir, "config");
1940
+ const backupPath = path11.join(configDir, "config.backup");
1941
+ mkdirSync7(configDir, { recursive: true });
1738
1942
  const START_MARKER = "# \u2500\u2500 exe-os:ghostty-start \u2500\u2500";
1739
1943
  const END_MARKER = "# \u2500\u2500 exe-os:ghostty-end \u2500\u2500";
1740
- const assetContent = readFileSync8(assetPath, "utf8").trim();
1944
+ const assetContent = readFileSync9(assetPath, "utf8").trim();
1741
1945
  const markedSection = `${START_MARKER}
1742
1946
  ${assetContent}
1743
1947
  ${END_MARKER}`;
1744
- if (existsSync9(configPath)) {
1745
- const existing = readFileSync8(configPath, "utf8");
1948
+ if (existsSync10(configPath)) {
1949
+ const existing = readFileSync9(configPath, "utf8");
1746
1950
  if (existing.includes(START_MARKER) && existing.includes(END_MARKER)) {
1747
1951
  const before = existing.slice(0, existing.indexOf(START_MARKER));
1748
1952
  const after = existing.slice(existing.indexOf(END_MARKER) + END_MARKER.length);
1749
- writeFileSync6(configPath, `${before}${markedSection}${after}`);
1953
+ writeFileSync7(configPath, `${before}${markedSection}${after}`);
1750
1954
  } else if (existing.includes("Exe OS")) {
1751
- if (!existsSync9(backupPath)) {
1955
+ if (!existsSync10(backupPath)) {
1752
1956
  copyFileSync(configPath, backupPath);
1753
1957
  process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
1754
1958
  `);
1755
1959
  }
1756
- writeFileSync6(configPath, `${markedSection}
1960
+ writeFileSync7(configPath, `${markedSection}
1757
1961
  `);
1758
1962
  } else {
1759
- if (!existsSync9(backupPath)) {
1963
+ if (!existsSync10(backupPath)) {
1760
1964
  copyFileSync(configPath, backupPath);
1761
1965
  process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
1762
1966
  `);
1763
1967
  }
1764
- writeFileSync6(configPath, `${markedSection}
1968
+ writeFileSync7(configPath, `${markedSection}
1765
1969
 
1766
1970
  ${existing}`);
1767
1971
  }
1768
1972
  } else {
1769
- writeFileSync6(configPath, `${markedSection}
1973
+ writeFileSync7(configPath, `${markedSection}
1770
1974
  `);
1771
1975
  }
1772
1976
  process.stderr.write("exe-os: Ghostty config installed\n");
@@ -1807,8 +2011,8 @@ ${EXE_SECTION_END}`;
1807
2011
  });
1808
2012
 
1809
2013
  // src/bin/exe-new-employee.ts
1810
- import { existsSync as existsSync10, mkdirSync as mkdirSync7 } from "fs";
1811
- import path10 from "path";
2014
+ import { existsSync as existsSync11, mkdirSync as mkdirSync8 } from "fs";
2015
+ import path12 from "path";
1812
2016
 
1813
2017
  // src/lib/session-wrappers.ts
1814
2018
  import {
@@ -2400,18 +2604,18 @@ function isMainModule(importMetaUrl) {
2400
2604
  // src/lib/plan-limits.ts
2401
2605
  init_database();
2402
2606
  init_employees();
2403
- import { readFileSync as readFileSync5, existsSync as existsSync5 } from "fs";
2404
- import path5 from "path";
2607
+ import { readFileSync as readFileSync6, existsSync as existsSync6 } from "fs";
2608
+ import path7 from "path";
2405
2609
 
2406
2610
  // src/lib/license.ts
2407
2611
  init_config();
2408
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync4, mkdirSync as mkdirSync2 } from "fs";
2612
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
2409
2613
  import { randomUUID as randomUUID2 } from "crypto";
2410
- import path4 from "path";
2614
+ import path6 from "path";
2411
2615
  import { jwtVerify, importSPKI } from "jose";
2412
- var LICENSE_PATH = path4.join(EXE_AI_DIR, "license.key");
2413
- var CACHE_PATH = path4.join(EXE_AI_DIR, "license-cache.json");
2414
- var DEVICE_ID_PATH = path4.join(EXE_AI_DIR, "device-id");
2616
+ var LICENSE_PATH = path6.join(EXE_AI_DIR, "license.key");
2617
+ var CACHE_PATH = path6.join(EXE_AI_DIR, "license-cache.json");
2618
+ var DEVICE_ID_PATH = path6.join(EXE_AI_DIR, "device-id");
2415
2619
  var API_BASE = "https://askexe.com/cloud";
2416
2620
  var RETRY_DELAY_MS = 500;
2417
2621
  async function fetchRetry(url, init) {
@@ -2444,37 +2648,37 @@ var FREE_LICENSE = {
2444
2648
  memoryLimit: 5e3
2445
2649
  };
2446
2650
  function loadDeviceId() {
2447
- const deviceJsonPath = path4.join(EXE_AI_DIR, "device.json");
2651
+ const deviceJsonPath = path6.join(EXE_AI_DIR, "device.json");
2448
2652
  try {
2449
- if (existsSync4(deviceJsonPath)) {
2450
- const data = JSON.parse(readFileSync4(deviceJsonPath, "utf8"));
2653
+ if (existsSync5(deviceJsonPath)) {
2654
+ const data = JSON.parse(readFileSync5(deviceJsonPath, "utf8"));
2451
2655
  if (data.deviceId) return data.deviceId;
2452
2656
  }
2453
2657
  } catch {
2454
2658
  }
2455
2659
  try {
2456
- if (existsSync4(DEVICE_ID_PATH)) {
2457
- const id2 = readFileSync4(DEVICE_ID_PATH, "utf8").trim();
2660
+ if (existsSync5(DEVICE_ID_PATH)) {
2661
+ const id2 = readFileSync5(DEVICE_ID_PATH, "utf8").trim();
2458
2662
  if (id2) return id2;
2459
2663
  }
2460
2664
  } catch {
2461
2665
  }
2462
2666
  const id = randomUUID2();
2463
- mkdirSync2(EXE_AI_DIR, { recursive: true });
2464
- writeFileSync3(DEVICE_ID_PATH, id, "utf8");
2667
+ mkdirSync3(EXE_AI_DIR, { recursive: true });
2668
+ writeFileSync4(DEVICE_ID_PATH, id, "utf8");
2465
2669
  return id;
2466
2670
  }
2467
2671
  function loadLicense() {
2468
2672
  try {
2469
- if (!existsSync4(LICENSE_PATH)) return null;
2470
- return readFileSync4(LICENSE_PATH, "utf8").trim();
2673
+ if (!existsSync5(LICENSE_PATH)) return null;
2674
+ return readFileSync5(LICENSE_PATH, "utf8").trim();
2471
2675
  } catch {
2472
2676
  return null;
2473
2677
  }
2474
2678
  }
2475
2679
  function saveLicense(apiKey) {
2476
- mkdirSync2(EXE_AI_DIR, { recursive: true });
2477
- writeFileSync3(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
2680
+ mkdirSync3(EXE_AI_DIR, { recursive: true });
2681
+ writeFileSync4(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
2478
2682
  }
2479
2683
  async function verifyLicenseJwt(token) {
2480
2684
  try {
@@ -2500,8 +2704,8 @@ async function verifyLicenseJwt(token) {
2500
2704
  }
2501
2705
  async function getCachedLicense() {
2502
2706
  try {
2503
- if (!existsSync4(CACHE_PATH)) return null;
2504
- const raw = JSON.parse(readFileSync4(CACHE_PATH, "utf8"));
2707
+ if (!existsSync5(CACHE_PATH)) return null;
2708
+ const raw = JSON.parse(readFileSync5(CACHE_PATH, "utf8"));
2505
2709
  if (!raw.token || typeof raw.token !== "string") return null;
2506
2710
  return await verifyLicenseJwt(raw.token);
2507
2711
  } catch {
@@ -2510,8 +2714,8 @@ async function getCachedLicense() {
2510
2714
  }
2511
2715
  function readCachedToken() {
2512
2716
  try {
2513
- if (!existsSync4(CACHE_PATH)) return null;
2514
- const raw = JSON.parse(readFileSync4(CACHE_PATH, "utf8"));
2717
+ if (!existsSync5(CACHE_PATH)) return null;
2718
+ const raw = JSON.parse(readFileSync5(CACHE_PATH, "utf8"));
2515
2719
  return typeof raw.token === "string" ? raw.token : null;
2516
2720
  } catch {
2517
2721
  return null;
@@ -2545,7 +2749,7 @@ function getRawCachedPlan() {
2545
2749
  }
2546
2750
  function cacheResponse(token) {
2547
2751
  try {
2548
- writeFileSync3(CACHE_PATH, JSON.stringify({ token }), "utf8");
2752
+ writeFileSync4(CACHE_PATH, JSON.stringify({ token }), "utf8");
2549
2753
  } catch {
2550
2754
  }
2551
2755
  }
@@ -2610,9 +2814,9 @@ async function checkLicense() {
2610
2814
  let key = loadLicense();
2611
2815
  if (!key) {
2612
2816
  try {
2613
- const configPath = path4.join(EXE_AI_DIR, "config.json");
2614
- if (existsSync4(configPath)) {
2615
- const raw = JSON.parse(readFileSync4(configPath, "utf8"));
2817
+ const configPath = path6.join(EXE_AI_DIR, "config.json");
2818
+ if (existsSync5(configPath)) {
2819
+ const raw = JSON.parse(readFileSync5(configPath, "utf8"));
2616
2820
  const cloud = raw.cloud;
2617
2821
  if (cloud?.apiKey) {
2618
2822
  key = cloud.apiKey;
@@ -2637,7 +2841,7 @@ var PlanLimitError = class extends Error {
2637
2841
  this.name = "PlanLimitError";
2638
2842
  }
2639
2843
  };
2640
- var CACHE_PATH2 = path5.join(EXE_AI_DIR, "license-cache.json");
2844
+ var CACHE_PATH2 = path7.join(EXE_AI_DIR, "license-cache.json");
2641
2845
  async function assertEmployeeLimit(license, rosterPath) {
2642
2846
  const lic = license ?? await checkLicense();
2643
2847
  if (lic.employeeLimit < 0) return;
@@ -2671,7 +2875,6 @@ async function main() {
2671
2875
  console.error(`Invalid name: ${validation.error}`);
2672
2876
  process.exit(1);
2673
2877
  }
2674
- const employees = await loadEmployees();
2675
2878
  let newEmployee;
2676
2879
  const effectiveTemplate = templateName ?? name;
2677
2880
  const template = getTemplate(effectiveTemplate);
@@ -2709,14 +2912,12 @@ async function main() {
2709
2912
  }
2710
2913
  throw err;
2711
2914
  }
2712
- let updated;
2713
2915
  try {
2714
- updated = addEmployee(employees, newEmployee);
2916
+ await hireEmployee(newEmployee);
2715
2917
  } catch (err) {
2716
2918
  console.error(err instanceof Error ? err.message : String(err));
2717
2919
  process.exit(1);
2718
2920
  }
2719
- await saveEmployees(updated);
2720
2921
  try {
2721
2922
  const { getTemplate: getIdentityTemplate } = await Promise.resolve().then(() => (init_identity_templates(), identity_templates_exports));
2722
2923
  const { identityPath: identityPath2 } = await Promise.resolve().then(() => (init_identity(), identity_exports));
@@ -2733,7 +2934,7 @@ async function main() {
2733
2934
  const identityTemplate = templateKey ? getIdentityTemplate(templateKey) : null;
2734
2935
  if (identityTemplate) {
2735
2936
  const idPath = identityPath2(name);
2736
- const dir = path10.dirname(idPath);
2937
+ const dir = path12.dirname(idPath);
2737
2938
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
2738
2939
  const content = identityTemplate.replace(/^agent_id: \w+/m, `agent_id: ${name}`);
2739
2940
  fs.writeFileSync(idPath, content, "utf-8");
@@ -2741,9 +2942,9 @@ async function main() {
2741
2942
  }
2742
2943
  } catch {
2743
2944
  }
2744
- const taskDir = path10.join(process.cwd(), "exe", name);
2745
- if (!existsSync10(taskDir)) {
2746
- mkdirSync7(taskDir, { recursive: true });
2945
+ const taskDir = path12.join(process.cwd(), "exe", name);
2946
+ if (!existsSync11(taskDir)) {
2947
+ mkdirSync8(taskDir, { recursive: true });
2747
2948
  }
2748
2949
  const bins = registerBinSymlinks(newEmployee.name);
2749
2950
  if (bins.created.length > 0) {