@askexenow/exe-os 0.8.89 → 0.8.91

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 (44) hide show
  1. package/dist/bin/backfill-conversations.js +10 -0
  2. package/dist/bin/backfill-responses.js +10 -0
  3. package/dist/bin/backfill-vectors.js +10 -0
  4. package/dist/bin/cli.js +75 -30
  5. package/dist/bin/exe-assign.js +13 -3
  6. package/dist/bin/exe-boot.js +34 -24
  7. package/dist/bin/exe-gateway.js +36 -26
  8. package/dist/bin/exe-link.js +10 -0
  9. package/dist/bin/exe-rename.js +10 -0
  10. package/dist/bin/exe-search.js +10 -0
  11. package/dist/bin/exe-session-cleanup.js +30 -20
  12. package/dist/bin/git-sweep.js +25 -15
  13. package/dist/bin/scan-tasks.js +27 -17
  14. package/dist/bin/setup.js +52 -7
  15. package/dist/gateway/index.js +34 -24
  16. package/dist/hooks/commit-complete.js +25 -15
  17. package/dist/hooks/error-recall.js +10 -0
  18. package/dist/hooks/ingest-worker.js +30 -20
  19. package/dist/hooks/instructions-loaded.js +15 -5
  20. package/dist/hooks/notification.js +13 -3
  21. package/dist/hooks/post-compact.js +17 -7
  22. package/dist/hooks/pre-compact.js +25 -15
  23. package/dist/hooks/pre-tool-use.js +20 -10
  24. package/dist/hooks/prompt-ingest-worker.js +10 -0
  25. package/dist/hooks/prompt-submit.js +20 -10
  26. package/dist/hooks/response-ingest-worker.js +10 -0
  27. package/dist/hooks/session-end.js +26 -16
  28. package/dist/hooks/session-start.js +19 -9
  29. package/dist/hooks/stop.js +17 -7
  30. package/dist/hooks/subagent-stop.js +17 -7
  31. package/dist/hooks/summary-worker.js +23 -13
  32. package/dist/index.js +29 -19
  33. package/dist/lib/cloud-sync.js +13 -3
  34. package/dist/lib/database.js +10 -0
  35. package/dist/lib/db-daemon-client.js +10 -0
  36. package/dist/lib/device-registry.js +12 -2
  37. package/dist/lib/embedder.js +10 -0
  38. package/dist/lib/exe-daemon-client.js +10 -0
  39. package/dist/lib/exe-daemon.js +31 -21
  40. package/dist/lib/hybrid-search.js +10 -0
  41. package/dist/mcp/server.js +38 -28
  42. package/dist/runtime/index.js +25 -15
  43. package/dist/tui/App.js +27 -17
  44. package/package.json +1 -1
@@ -460,6 +460,7 @@ var init_employees = __esm({
460
460
 
461
461
  // src/lib/exe-daemon-client.ts
462
462
  import net from "net";
463
+ import os3 from "os";
463
464
  import { spawn } from "child_process";
464
465
  import { randomUUID } from "crypto";
465
466
  import { existsSync as existsSync3, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
@@ -523,6 +524,15 @@ function findPackageRoot() {
523
524
  return null;
524
525
  }
525
526
  function spawnDaemon() {
527
+ const freeGB = os3.freemem() / (1024 * 1024 * 1024);
528
+ const totalGB = os3.totalmem() / (1024 * 1024 * 1024);
529
+ if (freeGB < 1.5 && totalGB <= 8) {
530
+ process.stderr.write(
531
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
532
+ `
533
+ );
534
+ return;
535
+ }
526
536
  const pkgRoot = findPackageRoot();
527
537
  if (!pkgRoot) {
528
538
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -2488,7 +2498,7 @@ ${p.content}`).join("\n\n");
2488
2498
  // src/lib/notifications.ts
2489
2499
  import crypto2 from "crypto";
2490
2500
  import path7 from "path";
2491
- import os4 from "os";
2501
+ import os5 from "os";
2492
2502
  import {
2493
2503
  readFileSync as readFileSync4,
2494
2504
  readdirSync as readdirSync2,
@@ -2937,7 +2947,7 @@ var init_embedder = __esm({
2937
2947
  // src/lib/session-registry.ts
2938
2948
  import { readFileSync as readFileSync7, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync9 } from "fs";
2939
2949
  import path10 from "path";
2940
- import os5 from "os";
2950
+ import os6 from "os";
2941
2951
  function registerSession(entry) {
2942
2952
  const dir = path10.dirname(REGISTRY_PATH);
2943
2953
  if (!existsSync9(dir)) {
@@ -2964,7 +2974,7 @@ var REGISTRY_PATH;
2964
2974
  var init_session_registry = __esm({
2965
2975
  "src/lib/session-registry.ts"() {
2966
2976
  "use strict";
2967
- REGISTRY_PATH = path10.join(os5.homedir(), ".exe-os", "session-registry.json");
2977
+ REGISTRY_PATH = path10.join(os6.homedir(), ".exe-os", "session-registry.json");
2968
2978
  }
2969
2979
  });
2970
2980
 
@@ -3214,7 +3224,7 @@ var init_agent_config = __esm({
3214
3224
  // src/lib/intercom-queue.ts
3215
3225
  import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, renameSync as renameSync3, existsSync as existsSync11, mkdirSync as mkdirSync5 } from "fs";
3216
3226
  import path12 from "path";
3217
- import os6 from "os";
3227
+ import os7 from "os";
3218
3228
  function ensureDir() {
3219
3229
  const dir = path12.dirname(QUEUE_PATH);
3220
3230
  if (!existsSync11(dir)) mkdirSync5(dir, { recursive: true });
@@ -3254,9 +3264,9 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
3254
3264
  var init_intercom_queue = __esm({
3255
3265
  "src/lib/intercom-queue.ts"() {
3256
3266
  "use strict";
3257
- QUEUE_PATH = path12.join(os6.homedir(), ".exe-os", "intercom-queue.json");
3267
+ QUEUE_PATH = path12.join(os7.homedir(), ".exe-os", "intercom-queue.json");
3258
3268
  TTL_MS = 60 * 60 * 1e3;
3259
- INTERCOM_LOG = path12.join(os6.homedir(), ".exe-os", "intercom.log");
3269
+ INTERCOM_LOG = path12.join(os7.homedir(), ".exe-os", "intercom.log");
3260
3270
  }
3261
3271
  });
3262
3272
 
@@ -3606,7 +3616,7 @@ __export(tmux_routing_exports, {
3606
3616
  import { execFileSync as execFileSync2, execSync as execSync5 } from "child_process";
3607
3617
  import { readFileSync as readFileSync10, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6, existsSync as existsSync12, appendFileSync } from "fs";
3608
3618
  import path13 from "path";
3609
- import os7 from "os";
3619
+ import os8 from "os";
3610
3620
  import { fileURLToPath as fileURLToPath2 } from "url";
3611
3621
  import { unlinkSync as unlinkSync4 } from "fs";
3612
3622
  function spawnLockPath(sessionName) {
@@ -4020,7 +4030,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4020
4030
  const transport = getTransport();
4021
4031
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
4022
4032
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
4023
- const logDir = path13.join(os7.homedir(), ".exe-os", "session-logs");
4033
+ const logDir = path13.join(os8.homedir(), ".exe-os", "session-logs");
4024
4034
  const logFile = path13.join(logDir, `${instanceLabel}-${Date.now()}.log`);
4025
4035
  if (!existsSync12(logDir)) {
4026
4036
  mkdirSync6(logDir, { recursive: true });
@@ -4036,7 +4046,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4036
4046
  } catch {
4037
4047
  }
4038
4048
  try {
4039
- const claudeJsonPath = path13.join(os7.homedir(), ".claude.json");
4049
+ const claudeJsonPath = path13.join(os8.homedir(), ".claude.json");
4040
4050
  let claudeJson = {};
4041
4051
  try {
4042
4052
  claudeJson = JSON.parse(readFileSync10(claudeJsonPath, "utf8"));
@@ -4051,7 +4061,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4051
4061
  } catch {
4052
4062
  }
4053
4063
  try {
4054
- const settingsDir = path13.join(os7.homedir(), ".claude", "projects");
4064
+ const settingsDir = path13.join(os8.homedir(), ".claude", "projects");
4055
4065
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
4056
4066
  const projSettingsDir = path13.join(settingsDir, normalizedKey);
4057
4067
  const settingsPath = path13.join(projSettingsDir, "settings.json");
@@ -4102,7 +4112,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4102
4112
  let legacyFallbackWarned = false;
4103
4113
  if (!useExeAgent && !useBinSymlink) {
4104
4114
  const identityPath = path13.join(
4105
- os7.homedir(),
4115
+ os8.homedir(),
4106
4116
  ".exe-os",
4107
4117
  "identity",
4108
4118
  `${employeeName}.md`
@@ -4132,7 +4142,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4132
4142
  }
4133
4143
  let sessionContextFlag = "";
4134
4144
  try {
4135
- const ctxDir = path13.join(os7.homedir(), ".exe-os", "session-cache");
4145
+ const ctxDir = path13.join(os8.homedir(), ".exe-os", "session-cache");
4136
4146
  mkdirSync6(ctxDir, { recursive: true });
4137
4147
  const ctxFile = path13.join(ctxDir, `session-context-${sessionName}.md`);
4138
4148
  const ctxContent = [
@@ -4293,13 +4303,13 @@ var init_tmux_routing = __esm({
4293
4303
  init_intercom_queue();
4294
4304
  init_plan_limits();
4295
4305
  init_employees();
4296
- SPAWN_LOCK_DIR = path13.join(os7.homedir(), ".exe-os", "spawn-locks");
4297
- SESSION_CACHE = path13.join(os7.homedir(), ".exe-os", "session-cache");
4306
+ SPAWN_LOCK_DIR = path13.join(os8.homedir(), ".exe-os", "spawn-locks");
4307
+ SESSION_CACHE = path13.join(os8.homedir(), ".exe-os", "session-cache");
4298
4308
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
4299
4309
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
4300
4310
  VERIFY_PANE_LINES = 200;
4301
4311
  INTERCOM_DEBOUNCE_MS = 3e4;
4302
- INTERCOM_LOG2 = path13.join(os7.homedir(), ".exe-os", "intercom.log");
4312
+ INTERCOM_LOG2 = path13.join(os8.homedir(), ".exe-os", "intercom.log");
4303
4313
  DEBOUNCE_FILE = path13.join(SESSION_CACHE, "intercom-debounce.json");
4304
4314
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
4305
4315
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
@@ -4333,7 +4343,7 @@ var init_task_scope = __esm({
4333
4343
  // src/lib/tasks-crud.ts
4334
4344
  import crypto4 from "crypto";
4335
4345
  import path14 from "path";
4336
- import os8 from "os";
4346
+ import os9 from "os";
4337
4347
  import { execSync as execSync6 } from "child_process";
4338
4348
  import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
4339
4349
  import { existsSync as existsSync13, readFileSync as readFileSync11 } from "fs";
@@ -4548,7 +4558,7 @@ ${laneWarning}` : laneWarning;
4548
4558
  });
4549
4559
  if (input2.baseDir) {
4550
4560
  try {
4551
- const EXE_OS_DIR = path14.join(os8.homedir(), ".exe-os");
4561
+ const EXE_OS_DIR = path14.join(os9.homedir(), ".exe-os");
4552
4562
  const mdPath = path14.join(EXE_OS_DIR, taskFile);
4553
4563
  const mdDir = path14.dirname(mdPath);
4554
4564
  if (!existsSync13(mdDir)) await mkdir4(mdDir, { recursive: true });
@@ -6066,11 +6076,11 @@ import { createHash } from "crypto";
6066
6076
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
6067
6077
  import { existsSync as existsSync4 } from "fs";
6068
6078
  import path5 from "path";
6069
- import os3 from "os";
6079
+ import os4 from "os";
6070
6080
  var SERVICE = "exe-mem";
6071
6081
  var ACCOUNT = "master-key";
6072
6082
  function getKeyDir() {
6073
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path5.join(os3.homedir(), ".exe-os");
6083
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path5.join(os4.homedir(), ".exe-os");
6074
6084
  }
6075
6085
  function getKeyPath() {
6076
6086
  return path5.join(getKeyDir(), "master.key");
@@ -6096,7 +6106,7 @@ async function getMasterKey() {
6096
6106
  const keyPath = getKeyPath();
6097
6107
  if (!existsSync4(keyPath)) {
6098
6108
  process.stderr.write(
6099
- `[keychain] Key not found at ${keyPath} (HOME=${os3.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
6109
+ `[keychain] Key not found at ${keyPath} (HOME=${os4.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
6100
6110
  `
6101
6111
  );
6102
6112
  return null;
@@ -288,6 +288,7 @@ var init_db_retry = __esm({
288
288
 
289
289
  // src/lib/exe-daemon-client.ts
290
290
  import net from "net";
291
+ import os3 from "os";
291
292
  import { spawn } from "child_process";
292
293
  import { randomUUID } from "crypto";
293
294
  import { existsSync as existsSync3, unlinkSync as unlinkSync3, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
@@ -351,6 +352,15 @@ function findPackageRoot() {
351
352
  return null;
352
353
  }
353
354
  function spawnDaemon() {
355
+ const freeGB = os3.freemem() / (1024 * 1024 * 1024);
356
+ const totalGB = os3.totalmem() / (1024 * 1024 * 1024);
357
+ if (freeGB < 1.5 && totalGB <= 8) {
358
+ process.stderr.write(
359
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
360
+ `
361
+ );
362
+ return;
363
+ }
354
364
  const pkgRoot = findPackageRoot();
355
365
  if (!pkgRoot) {
356
366
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -1749,9 +1759,9 @@ var init_memory = __esm({
1749
1759
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
1750
1760
  import { existsSync as existsSync5 } from "fs";
1751
1761
  import path6 from "path";
1752
- import os3 from "os";
1762
+ import os4 from "os";
1753
1763
  function getKeyDir() {
1754
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path6.join(os3.homedir(), ".exe-os");
1764
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path6.join(os4.homedir(), ".exe-os");
1755
1765
  }
1756
1766
  function getKeyPath() {
1757
1767
  return path6.join(getKeyDir(), "master.key");
@@ -1777,7 +1787,7 @@ async function getMasterKey() {
1777
1787
  const keyPath = getKeyPath();
1778
1788
  if (!existsSync5(keyPath)) {
1779
1789
  process.stderr.write(
1780
- `[keychain] Key not found at ${keyPath} (HOME=${os3.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
1790
+ `[keychain] Key not found at ${keyPath} (HOME=${os4.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
1781
1791
  `
1782
1792
  );
1783
1793
  return null;
@@ -3136,8 +3146,8 @@ process.stdin.on("end", async () => {
3136
3146
  try {
3137
3147
  const { readFileSync: readFileSync6, existsSync: existsSync7 } = await import("fs");
3138
3148
  const { join } = await import("path");
3139
- const os4 = await import("os");
3140
- const claudeMd = join(os4.homedir(), ".claude", "CLAUDE.md");
3149
+ const os5 = await import("os");
3150
+ const claudeMd = join(os5.homedir(), ".claude", "CLAUDE.md");
3141
3151
  if (existsSync7(claudeMd)) {
3142
3152
  const content = readFileSync6(claudeMd, "utf8");
3143
3153
  const hasOrchRules = content.includes("exe-os:orchestration-start");
@@ -297,6 +297,7 @@ var init_db_retry = __esm({
297
297
 
298
298
  // src/lib/exe-daemon-client.ts
299
299
  import net from "net";
300
+ import os3 from "os";
300
301
  import { spawn } from "child_process";
301
302
  import { randomUUID } from "crypto";
302
303
  import { existsSync as existsSync3, unlinkSync as unlinkSync3, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
@@ -360,6 +361,15 @@ function findPackageRoot() {
360
361
  return null;
361
362
  }
362
363
  function spawnDaemon() {
364
+ const freeGB = os3.freemem() / (1024 * 1024 * 1024);
365
+ const totalGB = os3.totalmem() / (1024 * 1024 * 1024);
366
+ if (freeGB < 1.5 && totalGB <= 8) {
367
+ process.stderr.write(
368
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
369
+ `
370
+ );
371
+ return;
372
+ }
363
373
  const pkgRoot = findPackageRoot();
364
374
  if (!pkgRoot) {
365
375
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -1749,9 +1759,9 @@ var init_database = __esm({
1749
1759
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
1750
1760
  import { existsSync as existsSync4 } from "fs";
1751
1761
  import path5 from "path";
1752
- import os3 from "os";
1762
+ import os4 from "os";
1753
1763
  function getKeyDir() {
1754
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path5.join(os3.homedir(), ".exe-os");
1764
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path5.join(os4.homedir(), ".exe-os");
1755
1765
  }
1756
1766
  function getKeyPath() {
1757
1767
  return path5.join(getKeyDir(), "master.key");
@@ -1777,7 +1787,7 @@ async function getMasterKey() {
1777
1787
  const keyPath = getKeyPath();
1778
1788
  if (!existsSync4(keyPath)) {
1779
1789
  process.stderr.write(
1780
- `[keychain] Key not found at ${keyPath} (HOME=${os3.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
1790
+ `[keychain] Key not found at ${keyPath} (HOME=${os4.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
1781
1791
  `
1782
1792
  );
1783
1793
  return null;
@@ -531,6 +531,7 @@ var init_db_retry = __esm({
531
531
 
532
532
  // src/lib/exe-daemon-client.ts
533
533
  import net from "net";
534
+ import os5 from "os";
534
535
  import { spawn } from "child_process";
535
536
  import { randomUUID } from "crypto";
536
537
  import { existsSync as existsSync5, unlinkSync as unlinkSync3, readFileSync as readFileSync6, openSync, closeSync, statSync } from "fs";
@@ -594,6 +595,15 @@ function findPackageRoot() {
594
595
  return null;
595
596
  }
596
597
  function spawnDaemon() {
598
+ const freeGB = os5.freemem() / (1024 * 1024 * 1024);
599
+ const totalGB = os5.totalmem() / (1024 * 1024 * 1024);
600
+ if (freeGB < 1.5 && totalGB <= 8) {
601
+ process.stderr.write(
602
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
603
+ `
604
+ );
605
+ return;
606
+ }
597
607
  const pkgRoot = findPackageRoot();
598
608
  if (!pkgRoot) {
599
609
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -2013,7 +2023,7 @@ var init_plan_limits = __esm({
2013
2023
  // src/lib/tmux-routing.ts
2014
2024
  import { readFileSync as readFileSync9, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, existsSync as existsSync8, appendFileSync } from "fs";
2015
2025
  import path10 from "path";
2016
- import os5 from "os";
2026
+ import os6 from "os";
2017
2027
  import { fileURLToPath as fileURLToPath2 } from "url";
2018
2028
  function getMySession() {
2019
2029
  return getTransport().getMySession();
@@ -2060,9 +2070,9 @@ var init_tmux_routing = __esm({
2060
2070
  init_intercom_queue();
2061
2071
  init_plan_limits();
2062
2072
  init_employees();
2063
- SPAWN_LOCK_DIR = path10.join(os5.homedir(), ".exe-os", "spawn-locks");
2064
- SESSION_CACHE = path10.join(os5.homedir(), ".exe-os", "session-cache");
2065
- INTERCOM_LOG2 = path10.join(os5.homedir(), ".exe-os", "intercom.log");
2073
+ SPAWN_LOCK_DIR = path10.join(os6.homedir(), ".exe-os", "spawn-locks");
2074
+ SESSION_CACHE = path10.join(os6.homedir(), ".exe-os", "session-cache");
2075
+ INTERCOM_LOG2 = path10.join(os6.homedir(), ".exe-os", "intercom.log");
2066
2076
  DEBOUNCE_FILE = path10.join(SESSION_CACHE, "intercom-debounce.json");
2067
2077
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
2068
2078
  }
@@ -2105,9 +2115,9 @@ var init_memory = __esm({
2105
2115
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
2106
2116
  import { existsSync as existsSync9 } from "fs";
2107
2117
  import path11 from "path";
2108
- import os6 from "os";
2118
+ import os7 from "os";
2109
2119
  function getKeyDir() {
2110
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path11.join(os6.homedir(), ".exe-os");
2120
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path11.join(os7.homedir(), ".exe-os");
2111
2121
  }
2112
2122
  function getKeyPath() {
2113
2123
  return path11.join(getKeyDir(), "master.key");
@@ -2133,7 +2143,7 @@ async function getMasterKey() {
2133
2143
  const keyPath = getKeyPath();
2134
2144
  if (!existsSync9(keyPath)) {
2135
2145
  process.stderr.write(
2136
- `[keychain] Key not found at ${keyPath} (HOME=${os6.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2146
+ `[keychain] Key not found at ${keyPath} (HOME=${os7.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2137
2147
  `
2138
2148
  );
2139
2149
  return null;
@@ -659,6 +659,7 @@ var init_db_retry = __esm({
659
659
 
660
660
  // src/lib/exe-daemon-client.ts
661
661
  import net from "net";
662
+ import os5 from "os";
662
663
  import { spawn } from "child_process";
663
664
  import { randomUUID } from "crypto";
664
665
  import { existsSync as existsSync6, unlinkSync as unlinkSync3, readFileSync as readFileSync7, openSync, closeSync, statSync } from "fs";
@@ -722,6 +723,15 @@ function findPackageRoot() {
722
723
  return null;
723
724
  }
724
725
  function spawnDaemon() {
726
+ const freeGB = os5.freemem() / (1024 * 1024 * 1024);
727
+ const totalGB = os5.totalmem() / (1024 * 1024 * 1024);
728
+ if (freeGB < 1.5 && totalGB <= 8) {
729
+ process.stderr.write(
730
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
731
+ `
732
+ );
733
+ return;
734
+ }
725
735
  const pkgRoot = findPackageRoot();
726
736
  if (!pkgRoot) {
727
737
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -2211,7 +2221,7 @@ var init_plan_limits = __esm({
2211
2221
  // src/lib/notifications.ts
2212
2222
  import crypto from "crypto";
2213
2223
  import path10 from "path";
2214
- import os5 from "os";
2224
+ import os6 from "os";
2215
2225
  import {
2216
2226
  readFileSync as readFileSync10,
2217
2227
  readdirSync as readdirSync2,
@@ -2352,7 +2362,7 @@ var init_state_bus = __esm({
2352
2362
  // src/lib/tasks-crud.ts
2353
2363
  import crypto3 from "crypto";
2354
2364
  import path11 from "path";
2355
- import os6 from "os";
2365
+ import os7 from "os";
2356
2366
  import { execSync as execSync5 } from "child_process";
2357
2367
  import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
2358
2368
  import { existsSync as existsSync10, readFileSync as readFileSync11 } from "fs";
@@ -2567,7 +2577,7 @@ ${laneWarning}` : laneWarning;
2567
2577
  });
2568
2578
  if (input2.baseDir) {
2569
2579
  try {
2570
- const EXE_OS_DIR = path11.join(os6.homedir(), ".exe-os");
2580
+ const EXE_OS_DIR = path11.join(os7.homedir(), ".exe-os");
2571
2581
  const mdPath = path11.join(EXE_OS_DIR, taskFile);
2572
2582
  const mdDir = path11.dirname(mdPath);
2573
2583
  if (!existsSync10(mdDir)) await mkdir3(mdDir, { recursive: true });
@@ -4213,7 +4223,7 @@ __export(tmux_routing_exports, {
4213
4223
  import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
4214
4224
  import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, existsSync as existsSync12, appendFileSync } from "fs";
4215
4225
  import path16 from "path";
4216
- import os7 from "os";
4226
+ import os8 from "os";
4217
4227
  import { fileURLToPath as fileURLToPath2 } from "url";
4218
4228
  import { unlinkSync as unlinkSync7 } from "fs";
4219
4229
  function spawnLockPath(sessionName) {
@@ -4627,7 +4637,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4627
4637
  const transport = getTransport();
4628
4638
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
4629
4639
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
4630
- const logDir = path16.join(os7.homedir(), ".exe-os", "session-logs");
4640
+ const logDir = path16.join(os8.homedir(), ".exe-os", "session-logs");
4631
4641
  const logFile = path16.join(logDir, `${instanceLabel}-${Date.now()}.log`);
4632
4642
  if (!existsSync12(logDir)) {
4633
4643
  mkdirSync7(logDir, { recursive: true });
@@ -4643,7 +4653,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4643
4653
  } catch {
4644
4654
  }
4645
4655
  try {
4646
- const claudeJsonPath = path16.join(os7.homedir(), ".claude.json");
4656
+ const claudeJsonPath = path16.join(os8.homedir(), ".claude.json");
4647
4657
  let claudeJson = {};
4648
4658
  try {
4649
4659
  claudeJson = JSON.parse(readFileSync12(claudeJsonPath, "utf8"));
@@ -4658,7 +4668,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4658
4668
  } catch {
4659
4669
  }
4660
4670
  try {
4661
- const settingsDir = path16.join(os7.homedir(), ".claude", "projects");
4671
+ const settingsDir = path16.join(os8.homedir(), ".claude", "projects");
4662
4672
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
4663
4673
  const projSettingsDir = path16.join(settingsDir, normalizedKey);
4664
4674
  const settingsPath = path16.join(projSettingsDir, "settings.json");
@@ -4709,7 +4719,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4709
4719
  let legacyFallbackWarned = false;
4710
4720
  if (!useExeAgent && !useBinSymlink) {
4711
4721
  const identityPath = path16.join(
4712
- os7.homedir(),
4722
+ os8.homedir(),
4713
4723
  ".exe-os",
4714
4724
  "identity",
4715
4725
  `${employeeName}.md`
@@ -4739,7 +4749,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4739
4749
  }
4740
4750
  let sessionContextFlag = "";
4741
4751
  try {
4742
- const ctxDir = path16.join(os7.homedir(), ".exe-os", "session-cache");
4752
+ const ctxDir = path16.join(os8.homedir(), ".exe-os", "session-cache");
4743
4753
  mkdirSync7(ctxDir, { recursive: true });
4744
4754
  const ctxFile = path16.join(ctxDir, `session-context-${sessionName}.md`);
4745
4755
  const ctxContent = [
@@ -4900,13 +4910,13 @@ var init_tmux_routing = __esm({
4900
4910
  init_intercom_queue();
4901
4911
  init_plan_limits();
4902
4912
  init_employees();
4903
- SPAWN_LOCK_DIR = path16.join(os7.homedir(), ".exe-os", "spawn-locks");
4904
- SESSION_CACHE = path16.join(os7.homedir(), ".exe-os", "session-cache");
4913
+ SPAWN_LOCK_DIR = path16.join(os8.homedir(), ".exe-os", "spawn-locks");
4914
+ SESSION_CACHE = path16.join(os8.homedir(), ".exe-os", "session-cache");
4905
4915
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
4906
4916
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
4907
4917
  VERIFY_PANE_LINES = 200;
4908
4918
  INTERCOM_DEBOUNCE_MS = 3e4;
4909
- INTERCOM_LOG2 = path16.join(os7.homedir(), ".exe-os", "intercom.log");
4919
+ INTERCOM_LOG2 = path16.join(os8.homedir(), ".exe-os", "intercom.log");
4910
4920
  DEBOUNCE_FILE = path16.join(SESSION_CACHE, "intercom-debounce.json");
4911
4921
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
4912
4922
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
@@ -4950,9 +4960,9 @@ var init_memory = __esm({
4950
4960
  import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
4951
4961
  import { existsSync as existsSync13 } from "fs";
4952
4962
  import path17 from "path";
4953
- import os8 from "os";
4963
+ import os9 from "os";
4954
4964
  function getKeyDir() {
4955
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path17.join(os8.homedir(), ".exe-os");
4965
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path17.join(os9.homedir(), ".exe-os");
4956
4966
  }
4957
4967
  function getKeyPath() {
4958
4968
  return path17.join(getKeyDir(), "master.key");
@@ -4978,7 +4988,7 @@ async function getMasterKey() {
4978
4988
  const keyPath = getKeyPath();
4979
4989
  if (!existsSync13(keyPath)) {
4980
4990
  process.stderr.write(
4981
- `[keychain] Key not found at ${keyPath} (HOME=${os8.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
4991
+ `[keychain] Key not found at ${keyPath} (HOME=${os9.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
4982
4992
  `
4983
4993
  );
4984
4994
  return null;
@@ -698,6 +698,7 @@ var init_db_retry = __esm({
698
698
 
699
699
  // src/lib/exe-daemon-client.ts
700
700
  import net from "net";
701
+ import os5 from "os";
701
702
  import { spawn } from "child_process";
702
703
  import { randomUUID } from "crypto";
703
704
  import { existsSync as existsSync5, unlinkSync as unlinkSync3, readFileSync as readFileSync6, openSync, closeSync, statSync } from "fs";
@@ -761,6 +762,15 @@ function findPackageRoot() {
761
762
  return null;
762
763
  }
763
764
  function spawnDaemon() {
765
+ const freeGB = os5.freemem() / (1024 * 1024 * 1024);
766
+ const totalGB = os5.totalmem() / (1024 * 1024 * 1024);
767
+ if (freeGB < 1.5 && totalGB <= 8) {
768
+ process.stderr.write(
769
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
770
+ `
771
+ );
772
+ return;
773
+ }
764
774
  const pkgRoot = findPackageRoot();
765
775
  if (!pkgRoot) {
766
776
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
@@ -2180,7 +2190,7 @@ var init_plan_limits = __esm({
2180
2190
  // src/lib/tmux-routing.ts
2181
2191
  import { readFileSync as readFileSync9, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, existsSync as existsSync8, appendFileSync } from "fs";
2182
2192
  import path10 from "path";
2183
- import os5 from "os";
2193
+ import os6 from "os";
2184
2194
  import { fileURLToPath as fileURLToPath2 } from "url";
2185
2195
  function getMySession() {
2186
2196
  return getTransport().getMySession();
@@ -2227,9 +2237,9 @@ var init_tmux_routing = __esm({
2227
2237
  init_intercom_queue();
2228
2238
  init_plan_limits();
2229
2239
  init_employees();
2230
- SPAWN_LOCK_DIR = path10.join(os5.homedir(), ".exe-os", "spawn-locks");
2231
- SESSION_CACHE = path10.join(os5.homedir(), ".exe-os", "session-cache");
2232
- INTERCOM_LOG2 = path10.join(os5.homedir(), ".exe-os", "intercom.log");
2240
+ SPAWN_LOCK_DIR = path10.join(os6.homedir(), ".exe-os", "spawn-locks");
2241
+ SESSION_CACHE = path10.join(os6.homedir(), ".exe-os", "session-cache");
2242
+ INTERCOM_LOG2 = path10.join(os6.homedir(), ".exe-os", "intercom.log");
2233
2243
  DEBOUNCE_FILE = path10.join(SESSION_CACHE, "intercom-debounce.json");
2234
2244
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
2235
2245
  }
@@ -2272,7 +2282,7 @@ __export(cto_delegation_gate_exports, {
2272
2282
  hasValidScratchpadEscape: () => hasValidScratchpadEscape,
2273
2283
  scratchpadPath: () => scratchpadPath
2274
2284
  });
2275
- import os6 from "os";
2285
+ import os7 from "os";
2276
2286
  import path11 from "path";
2277
2287
  import { existsSync as existsSync9, readFileSync as readFileSync10, statSync as statSync2 } from "fs";
2278
2288
  function resolveGatedAgent() {
@@ -2345,7 +2355,7 @@ async function hasRecentEngineerDispatch(now = Date.now()) {
2345
2355
  return false;
2346
2356
  }
2347
2357
  }
2348
- function scratchpadPath(sessionId, homeDir = os6.homedir()) {
2358
+ function scratchpadPath(sessionId, homeDir = os7.homedir()) {
2349
2359
  return path11.join(
2350
2360
  homeDir,
2351
2361
  ".exe-os",
@@ -2353,7 +2363,7 @@ function scratchpadPath(sessionId, homeDir = os6.homedir()) {
2353
2363
  `cto-scratchpad-${sessionId}.txt`
2354
2364
  );
2355
2365
  }
2356
- function hasValidScratchpadEscape(sessionId, now = Date.now(), homeDir = os6.homedir()) {
2366
+ function hasValidScratchpadEscape(sessionId, now = Date.now(), homeDir = os7.homedir()) {
2357
2367
  const paths = [scratchpadPath(sessionId, homeDir)];
2358
2368
  for (const filePath of paths) {
2359
2369
  if (!existsSync9(filePath)) continue;
@@ -2453,9 +2463,9 @@ var init_memory = __esm({
2453
2463
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
2454
2464
  import { existsSync as existsSync10 } from "fs";
2455
2465
  import path12 from "path";
2456
- import os7 from "os";
2466
+ import os8 from "os";
2457
2467
  function getKeyDir() {
2458
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path12.join(os7.homedir(), ".exe-os");
2468
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path12.join(os8.homedir(), ".exe-os");
2459
2469
  }
2460
2470
  function getKeyPath() {
2461
2471
  return path12.join(getKeyDir(), "master.key");
@@ -2481,7 +2491,7 @@ async function getMasterKey() {
2481
2491
  const keyPath = getKeyPath();
2482
2492
  if (!existsSync10(keyPath)) {
2483
2493
  process.stderr.write(
2484
- `[keychain] Key not found at ${keyPath} (HOME=${os7.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2494
+ `[keychain] Key not found at ${keyPath} (HOME=${os8.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2485
2495
  `
2486
2496
  );
2487
2497
  return null;
@@ -1759,6 +1759,7 @@ ${p.content}`).join("\n\n");
1759
1759
 
1760
1760
  // src/lib/exe-daemon-client.ts
1761
1761
  import net from "net";
1762
+ import os4 from "os";
1762
1763
  import { spawn } from "child_process";
1763
1764
  import { randomUUID as randomUUID3 } from "crypto";
1764
1765
  import { existsSync as existsSync7, unlinkSync as unlinkSync2, readFileSync as readFileSync5, openSync, closeSync, statSync } from "fs";
@@ -1822,6 +1823,15 @@ function findPackageRoot() {
1822
1823
  return null;
1823
1824
  }
1824
1825
  function spawnDaemon() {
1826
+ const freeGB = os4.freemem() / (1024 * 1024 * 1024);
1827
+ const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
1828
+ if (freeGB < 1.5 && totalGB <= 8) {
1829
+ process.stderr.write(
1830
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
1831
+ `
1832
+ );
1833
+ return;
1834
+ }
1825
1835
  const pkgRoot = findPackageRoot();
1826
1836
  if (!pkgRoot) {
1827
1837
  process.stderr.write("[exed-client] WARN: cannot find package root\n");