@askexenow/exe-os 0.9.97 → 0.9.99

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 (81) hide show
  1. package/dist/bin/agentic-ontology-backfill.js +7 -29
  2. package/dist/bin/agentic-reflection-backfill.js +7 -29
  3. package/dist/bin/agentic-semantic-label.js +7 -29
  4. package/dist/bin/backfill-conversations.js +7 -29
  5. package/dist/bin/backfill-responses.js +7 -29
  6. package/dist/bin/backfill-vectors.js +7 -29
  7. package/dist/bin/bulk-sync-postgres.js +7 -29
  8. package/dist/bin/cleanup-stale-review-tasks.js +7 -29
  9. package/dist/bin/cli.js +11 -33
  10. package/dist/bin/exe-agent.js +7 -0
  11. package/dist/bin/exe-assign.js +7 -29
  12. package/dist/bin/exe-boot.js +7 -29
  13. package/dist/bin/exe-call.js +7 -0
  14. package/dist/bin/exe-cloud.js +7 -29
  15. package/dist/bin/exe-dispatch.js +7 -29
  16. package/dist/bin/exe-doctor.js +7 -29
  17. package/dist/bin/exe-export-behaviors.js +7 -29
  18. package/dist/bin/exe-forget.js +7 -29
  19. package/dist/bin/exe-gateway.js +7 -29
  20. package/dist/bin/exe-heartbeat.js +7 -29
  21. package/dist/bin/exe-kill.js +7 -29
  22. package/dist/bin/exe-launch-agent.js +7 -29
  23. package/dist/bin/exe-new-employee.js +7 -0
  24. package/dist/bin/exe-pending-messages.js +7 -29
  25. package/dist/bin/exe-pending-notifications.js +7 -29
  26. package/dist/bin/exe-pending-reviews.js +7 -29
  27. package/dist/bin/exe-rename.js +7 -29
  28. package/dist/bin/exe-review.js +7 -29
  29. package/dist/bin/exe-search.js +7 -29
  30. package/dist/bin/exe-session-cleanup.js +7 -29
  31. package/dist/bin/exe-start-codex.js +7 -29
  32. package/dist/bin/exe-start-opencode.js +7 -29
  33. package/dist/bin/exe-status.js +7 -29
  34. package/dist/bin/exe-team.js +7 -29
  35. package/dist/bin/git-sweep.js +7 -29
  36. package/dist/bin/graph-backfill.js +7 -29
  37. package/dist/bin/graph-export.js +7 -29
  38. package/dist/bin/intercom-check.js +7 -29
  39. package/dist/bin/scan-tasks.js +7 -29
  40. package/dist/bin/setup.js +11 -33
  41. package/dist/bin/shard-migrate.js +7 -29
  42. package/dist/gateway/index.js +7 -29
  43. package/dist/hooks/bug-report-worker.js +7 -29
  44. package/dist/hooks/codex-stop-task-finalizer.js +7 -29
  45. package/dist/hooks/commit-complete.js +7 -29
  46. package/dist/hooks/error-recall.js +7 -29
  47. package/dist/hooks/ingest.js +7 -29
  48. package/dist/hooks/instructions-loaded.js +7 -29
  49. package/dist/hooks/notification.js +7 -29
  50. package/dist/hooks/post-compact.js +7 -29
  51. package/dist/hooks/post-tool-combined.js +7 -29
  52. package/dist/hooks/pre-compact.js +7 -29
  53. package/dist/hooks/pre-tool-use.js +7 -29
  54. package/dist/hooks/prompt-submit.js +7 -29
  55. package/dist/hooks/session-end.js +7 -29
  56. package/dist/hooks/session-start.js +7 -29
  57. package/dist/hooks/stop.js +7 -29
  58. package/dist/hooks/subagent-stop.js +7 -29
  59. package/dist/hooks/summary-worker.js +7 -29
  60. package/dist/index.js +7 -29
  61. package/dist/lib/cloud-sync.js +0 -29
  62. package/dist/lib/database.js +0 -35
  63. package/dist/lib/db-daemon-client.js +0 -36
  64. package/dist/lib/db.js +0 -35
  65. package/dist/lib/device-registry.js +0 -35
  66. package/dist/lib/embedder.js +0 -35
  67. package/dist/lib/employee-templates.js +7 -0
  68. package/dist/lib/exe-daemon-client.js +0 -36
  69. package/dist/lib/exe-daemon.js +7 -29
  70. package/dist/lib/hybrid-search.js +7 -29
  71. package/dist/lib/schedules.js +7 -29
  72. package/dist/lib/skill-learning.js +0 -35
  73. package/dist/lib/store.js +7 -29
  74. package/dist/lib/tasks.js +0 -29
  75. package/dist/lib/tmux-routing.js +0 -29
  76. package/dist/mcp/server.js +7 -29
  77. package/dist/mcp/tools/create-task.js +0 -29
  78. package/dist/mcp/tools/update-task.js +0 -29
  79. package/dist/runtime/index.js +7 -29
  80. package/dist/tui/App.js +7 -29
  81. package/package.json +1 -1
@@ -1054,40 +1054,11 @@ function findPackageRoot() {
1054
1054
  }
1055
1055
  return null;
1056
1056
  }
1057
- function getAvailableMemoryGB() {
1058
- if (process.platform === "darwin") {
1059
- try {
1060
- const { execSync: execSync5 } = __require("child_process");
1061
- const vmstat = execSync5("vm_stat", { encoding: "utf8" });
1062
- const pageSize = 16384;
1063
- const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1064
- const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
1065
- const free = vmstat.match(/Pages free:\s+(\d+)/);
1066
- const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
1067
- const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
1068
- const freePages = free ? parseInt(free[1], 10) : 0;
1069
- const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
1070
- const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
1071
- return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
1072
- } catch {
1073
- return os4.freemem() / (1024 * 1024 * 1024);
1074
- }
1075
- }
1076
- return os4.freemem() / (1024 * 1024 * 1024);
1077
- }
1078
1057
  function spawnDaemon() {
1079
- const freeGB = getAvailableMemoryGB();
1080
1058
  const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
1081
1059
  if (totalGB <= 8) {
1082
1060
  process.stderr.write(
1083
1061
  `[exed-client] SKIP: ${totalGB.toFixed(0)}GB system \u2014 embedding daemon disabled. Using keyword search only. Minimum 16GB recommended for vector search.
1084
- `
1085
- );
1086
- return;
1087
- }
1088
- if (totalGB <= 16 && freeGB < 2) {
1089
- process.stderr.write(
1090
- `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
1091
1062
  `
1092
1063
  );
1093
1064
  return;
@@ -3544,6 +3515,13 @@ var init_platform_procedures = __esm({
3544
3515
  priority: "p0",
3545
3516
  content: "Tasks live in the DB. Intercom (tmux send-keys) is fire-and-forget \u2014 it may fail, get garbled, or arrive mid-work. Never rely on intercom for task delivery. The UserPromptSubmit hook checks the DB for new tasks on every prompt. Your operating procedures step 7 says check for next work. The daemon nudges idle agents as a speedup. If you have no tasks, you found them all."
3546
3517
  },
3518
+ // --- Encryption key + cloud sync ---
3519
+ {
3520
+ title: "Encryption key lives in Keychain, not on disk \u2014 never expose the recovery phrase",
3521
+ domain: "security",
3522
+ priority: "p0",
3523
+ content: "The master encryption key is stored in macOS Keychain (Secure Enclave) or Linux secret-tool \u2014 NOT as a file. There is no ~/.exe-os/master.key on modern installs. If an older install had one, it was auto-migrated to Keychain and the file deleted. Device linking uses a 24-word BIP39 recovery phrase: Device 1 runs `exe-os cloud link --show-full` in their local Terminal to reveal it, Device 2 runs `exe-os cloud` and pastes the phrase to import the key into its own Keychain, then cloud sync pulls encrypted memories. NEVER display, log, or return the recovery phrase in agent output. MCP tools are hardened \u2014 they cannot reveal it. If the user needs the phrase, tell them: 'Run exe-os cloud link --show-full in your Terminal.' If searching for master.key returns nothing, that is CORRECT \u2014 the key is in Keychain."
3524
+ },
3547
3525
  // --- MCP is the ONLY data interface ---
3548
3526
  {
3549
3527
  title: "MCP disconnect \u2014 ask the user, never work around it",
@@ -1,11 +1,5 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
3
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
4
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
5
- }) : x)(function(x) {
6
- if (typeof require !== "undefined") return require.apply(this, arguments);
7
- throw Error('Dynamic require of "' + x + '" is not supported');
8
- });
9
3
  var __esm = (fn, res) => function __init() {
10
4
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
5
  };
@@ -442,40 +436,11 @@ function findPackageRoot() {
442
436
  }
443
437
  return null;
444
438
  }
445
- function getAvailableMemoryGB() {
446
- if (process.platform === "darwin") {
447
- try {
448
- const { execSync: execSync3 } = __require("child_process");
449
- const vmstat = execSync3("vm_stat", { encoding: "utf8" });
450
- const pageSize = 16384;
451
- const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
452
- const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
453
- const free = vmstat.match(/Pages free:\s+(\d+)/);
454
- const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
455
- const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
456
- const freePages = free ? parseInt(free[1], 10) : 0;
457
- const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
458
- const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
459
- return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
460
- } catch {
461
- return os4.freemem() / (1024 * 1024 * 1024);
462
- }
463
- }
464
- return os4.freemem() / (1024 * 1024 * 1024);
465
- }
466
439
  function spawnDaemon() {
467
- const freeGB = getAvailableMemoryGB();
468
440
  const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
469
441
  if (totalGB <= 8) {
470
442
  process.stderr.write(
471
443
  `[exed-client] SKIP: ${totalGB.toFixed(0)}GB system \u2014 embedding daemon disabled. Using keyword search only. Minimum 16GB recommended for vector search.
472
- `
473
- );
474
- return;
475
- }
476
- if (totalGB <= 16 && freeGB < 2) {
477
- process.stderr.write(
478
- `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
479
444
  `
480
445
  );
481
446
  return;
package/dist/lib/store.js CHANGED
@@ -1054,40 +1054,11 @@ function findPackageRoot() {
1054
1054
  }
1055
1055
  return null;
1056
1056
  }
1057
- function getAvailableMemoryGB() {
1058
- if (process.platform === "darwin") {
1059
- try {
1060
- const { execSync: execSync4 } = __require("child_process");
1061
- const vmstat = execSync4("vm_stat", { encoding: "utf8" });
1062
- const pageSize = 16384;
1063
- const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1064
- const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
1065
- const free = vmstat.match(/Pages free:\s+(\d+)/);
1066
- const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
1067
- const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
1068
- const freePages = free ? parseInt(free[1], 10) : 0;
1069
- const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
1070
- const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
1071
- return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
1072
- } catch {
1073
- return os4.freemem() / (1024 * 1024 * 1024);
1074
- }
1075
- }
1076
- return os4.freemem() / (1024 * 1024 * 1024);
1077
- }
1078
1057
  function spawnDaemon() {
1079
- const freeGB = getAvailableMemoryGB();
1080
1058
  const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
1081
1059
  if (totalGB <= 8) {
1082
1060
  process.stderr.write(
1083
1061
  `[exed-client] SKIP: ${totalGB.toFixed(0)}GB system \u2014 embedding daemon disabled. Using keyword search only. Minimum 16GB recommended for vector search.
1084
- `
1085
- );
1086
- return;
1087
- }
1088
- if (totalGB <= 16 && freeGB < 2) {
1089
- process.stderr.write(
1090
- `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
1091
1062
  `
1092
1063
  );
1093
1064
  return;
@@ -3544,6 +3515,13 @@ var init_platform_procedures = __esm({
3544
3515
  priority: "p0",
3545
3516
  content: "Tasks live in the DB. Intercom (tmux send-keys) is fire-and-forget \u2014 it may fail, get garbled, or arrive mid-work. Never rely on intercom for task delivery. The UserPromptSubmit hook checks the DB for new tasks on every prompt. Your operating procedures step 7 says check for next work. The daemon nudges idle agents as a speedup. If you have no tasks, you found them all."
3546
3517
  },
3518
+ // --- Encryption key + cloud sync ---
3519
+ {
3520
+ title: "Encryption key lives in Keychain, not on disk \u2014 never expose the recovery phrase",
3521
+ domain: "security",
3522
+ priority: "p0",
3523
+ content: "The master encryption key is stored in macOS Keychain (Secure Enclave) or Linux secret-tool \u2014 NOT as a file. There is no ~/.exe-os/master.key on modern installs. If an older install had one, it was auto-migrated to Keychain and the file deleted. Device linking uses a 24-word BIP39 recovery phrase: Device 1 runs `exe-os cloud link --show-full` in their local Terminal to reveal it, Device 2 runs `exe-os cloud` and pastes the phrase to import the key into its own Keychain, then cloud sync pulls encrypted memories. NEVER display, log, or return the recovery phrase in agent output. MCP tools are hardened \u2014 they cannot reveal it. If the user needs the phrase, tell them: 'Run exe-os cloud link --show-full in your Terminal.' If searching for master.key returns nothing, that is CORRECT \u2014 the key is in Keychain."
3524
+ },
3547
3525
  // --- MCP is the ONLY data interface ---
3548
3526
  {
3549
3527
  title: "MCP disconnect \u2014 ask the user, never work around it",
package/dist/lib/tasks.js CHANGED
@@ -3761,40 +3761,11 @@ function findPackageRoot() {
3761
3761
  }
3762
3762
  return null;
3763
3763
  }
3764
- function getAvailableMemoryGB() {
3765
- if (process.platform === "darwin") {
3766
- try {
3767
- const { execSync: execSync8 } = __require("child_process");
3768
- const vmstat = execSync8("vm_stat", { encoding: "utf8" });
3769
- const pageSize = 16384;
3770
- const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
3771
- const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
3772
- const free = vmstat.match(/Pages free:\s+(\d+)/);
3773
- const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
3774
- const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
3775
- const freePages = free ? parseInt(free[1], 10) : 0;
3776
- const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
3777
- const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
3778
- return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
3779
- } catch {
3780
- return os11.freemem() / (1024 * 1024 * 1024);
3781
- }
3782
- }
3783
- return os11.freemem() / (1024 * 1024 * 1024);
3784
- }
3785
3764
  function spawnDaemon() {
3786
- const freeGB = getAvailableMemoryGB();
3787
3765
  const totalGB = os11.totalmem() / (1024 * 1024 * 1024);
3788
3766
  if (totalGB <= 8) {
3789
3767
  process.stderr.write(
3790
3768
  `[exed-client] SKIP: ${totalGB.toFixed(0)}GB system \u2014 embedding daemon disabled. Using keyword search only. Minimum 16GB recommended for vector search.
3791
- `
3792
- );
3793
- return;
3794
- }
3795
- if (totalGB <= 16 && freeGB < 2) {
3796
- process.stderr.write(
3797
- `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
3798
3769
  `
3799
3770
  );
3800
3771
  return;
@@ -2611,40 +2611,11 @@ function findPackageRoot() {
2611
2611
  }
2612
2612
  return null;
2613
2613
  }
2614
- function getAvailableMemoryGB() {
2615
- if (process.platform === "darwin") {
2616
- try {
2617
- const { execSync: execSync8 } = __require("child_process");
2618
- const vmstat = execSync8("vm_stat", { encoding: "utf8" });
2619
- const pageSize = 16384;
2620
- const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
2621
- const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
2622
- const free = vmstat.match(/Pages free:\s+(\d+)/);
2623
- const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
2624
- const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
2625
- const freePages = free ? parseInt(free[1], 10) : 0;
2626
- const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
2627
- const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
2628
- return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
2629
- } catch {
2630
- return os10.freemem() / (1024 * 1024 * 1024);
2631
- }
2632
- }
2633
- return os10.freemem() / (1024 * 1024 * 1024);
2634
- }
2635
2614
  function spawnDaemon() {
2636
- const freeGB = getAvailableMemoryGB();
2637
2615
  const totalGB = os10.totalmem() / (1024 * 1024 * 1024);
2638
2616
  if (totalGB <= 8) {
2639
2617
  process.stderr.write(
2640
2618
  `[exed-client] SKIP: ${totalGB.toFixed(0)}GB system \u2014 embedding daemon disabled. Using keyword search only. Minimum 16GB recommended for vector search.
2641
- `
2642
- );
2643
- return;
2644
- }
2645
- if (totalGB <= 16 && freeGB < 2) {
2646
- process.stderr.write(
2647
- `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
2648
2619
  `
2649
2620
  );
2650
2621
  return;
@@ -464,40 +464,11 @@ function findPackageRoot() {
464
464
  }
465
465
  return null;
466
466
  }
467
- function getAvailableMemoryGB() {
468
- if (process.platform === "darwin") {
469
- try {
470
- const { execSync: execSync16 } = __require("child_process");
471
- const vmstat = execSync16("vm_stat", { encoding: "utf8" });
472
- const pageSize = 16384;
473
- const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
474
- const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
475
- const free = vmstat.match(/Pages free:\s+(\d+)/);
476
- const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
477
- const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
478
- const freePages = free ? parseInt(free[1], 10) : 0;
479
- const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
480
- const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
481
- return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
482
- } catch {
483
- return os2.freemem() / (1024 * 1024 * 1024);
484
- }
485
- }
486
- return os2.freemem() / (1024 * 1024 * 1024);
487
- }
488
467
  function spawnDaemon() {
489
- const freeGB = getAvailableMemoryGB();
490
468
  const totalGB = os2.totalmem() / (1024 * 1024 * 1024);
491
469
  if (totalGB <= 8) {
492
470
  process.stderr.write(
493
471
  `[exed-client] SKIP: ${totalGB.toFixed(0)}GB system \u2014 embedding daemon disabled. Using keyword search only. Minimum 16GB recommended for vector search.
494
- `
495
- );
496
- return;
497
- }
498
- if (totalGB <= 16 && freeGB < 2) {
499
- process.stderr.write(
500
- `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
501
472
  `
502
473
  );
503
474
  return;
@@ -4964,6 +4935,13 @@ var init_platform_procedures = __esm({
4964
4935
  priority: "p0",
4965
4936
  content: "Tasks live in the DB. Intercom (tmux send-keys) is fire-and-forget \u2014 it may fail, get garbled, or arrive mid-work. Never rely on intercom for task delivery. The UserPromptSubmit hook checks the DB for new tasks on every prompt. Your operating procedures step 7 says check for next work. The daemon nudges idle agents as a speedup. If you have no tasks, you found them all."
4966
4937
  },
4938
+ // --- Encryption key + cloud sync ---
4939
+ {
4940
+ title: "Encryption key lives in Keychain, not on disk \u2014 never expose the recovery phrase",
4941
+ domain: "security",
4942
+ priority: "p0",
4943
+ content: "The master encryption key is stored in macOS Keychain (Secure Enclave) or Linux secret-tool \u2014 NOT as a file. There is no ~/.exe-os/master.key on modern installs. If an older install had one, it was auto-migrated to Keychain and the file deleted. Device linking uses a 24-word BIP39 recovery phrase: Device 1 runs `exe-os cloud link --show-full` in their local Terminal to reveal it, Device 2 runs `exe-os cloud` and pastes the phrase to import the key into its own Keychain, then cloud sync pulls encrypted memories. NEVER display, log, or return the recovery phrase in agent output. MCP tools are hardened \u2014 they cannot reveal it. If the user needs the phrase, tell them: 'Run exe-os cloud link --show-full in your Terminal.' If searching for master.key returns nothing, that is CORRECT \u2014 the key is in Keychain."
4944
+ },
4967
4945
  // --- MCP is the ONLY data interface ---
4968
4946
  {
4969
4947
  title: "MCP disconnect \u2014 ask the user, never work around it",
@@ -4001,40 +4001,11 @@ function findPackageRoot() {
4001
4001
  }
4002
4002
  return null;
4003
4003
  }
4004
- function getAvailableMemoryGB() {
4005
- if (process.platform === "darwin") {
4006
- try {
4007
- const { execSync: execSync9 } = __require("child_process");
4008
- const vmstat = execSync9("vm_stat", { encoding: "utf8" });
4009
- const pageSize = 16384;
4010
- const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
4011
- const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
4012
- const free = vmstat.match(/Pages free:\s+(\d+)/);
4013
- const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
4014
- const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
4015
- const freePages = free ? parseInt(free[1], 10) : 0;
4016
- const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
4017
- const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
4018
- return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
4019
- } catch {
4020
- return os11.freemem() / (1024 * 1024 * 1024);
4021
- }
4022
- }
4023
- return os11.freemem() / (1024 * 1024 * 1024);
4024
- }
4025
4004
  function spawnDaemon() {
4026
- const freeGB = getAvailableMemoryGB();
4027
4005
  const totalGB = os11.totalmem() / (1024 * 1024 * 1024);
4028
4006
  if (totalGB <= 8) {
4029
4007
  process.stderr.write(
4030
4008
  `[exed-client] SKIP: ${totalGB.toFixed(0)}GB system \u2014 embedding daemon disabled. Using keyword search only. Minimum 16GB recommended for vector search.
4031
- `
4032
- );
4033
- return;
4034
- }
4035
- if (totalGB <= 16 && freeGB < 2) {
4036
- process.stderr.write(
4037
- `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
4038
4009
  `
4039
4010
  );
4040
4011
  return;
@@ -3764,40 +3764,11 @@ function findPackageRoot() {
3764
3764
  }
3765
3765
  return null;
3766
3766
  }
3767
- function getAvailableMemoryGB() {
3768
- if (process.platform === "darwin") {
3769
- try {
3770
- const { execSync: execSync9 } = __require("child_process");
3771
- const vmstat = execSync9("vm_stat", { encoding: "utf8" });
3772
- const pageSize = 16384;
3773
- const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
3774
- const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
3775
- const free = vmstat.match(/Pages free:\s+(\d+)/);
3776
- const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
3777
- const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
3778
- const freePages = free ? parseInt(free[1], 10) : 0;
3779
- const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
3780
- const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
3781
- return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
3782
- } catch {
3783
- return os11.freemem() / (1024 * 1024 * 1024);
3784
- }
3785
- }
3786
- return os11.freemem() / (1024 * 1024 * 1024);
3787
- }
3788
3767
  function spawnDaemon() {
3789
- const freeGB = getAvailableMemoryGB();
3790
3768
  const totalGB = os11.totalmem() / (1024 * 1024 * 1024);
3791
3769
  if (totalGB <= 8) {
3792
3770
  process.stderr.write(
3793
3771
  `[exed-client] SKIP: ${totalGB.toFixed(0)}GB system \u2014 embedding daemon disabled. Using keyword search only. Minimum 16GB recommended for vector search.
3794
- `
3795
- );
3796
- return;
3797
- }
3798
- if (totalGB <= 16 && freeGB < 2) {
3799
- process.stderr.write(
3800
- `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
3801
3772
  `
3802
3773
  );
3803
3774
  return;
@@ -1690,40 +1690,11 @@ function findPackageRoot() {
1690
1690
  }
1691
1691
  return null;
1692
1692
  }
1693
- function getAvailableMemoryGB() {
1694
- if (process.platform === "darwin") {
1695
- try {
1696
- const { execSync: execSync10 } = __require("child_process");
1697
- const vmstat = execSync10("vm_stat", { encoding: "utf8" });
1698
- const pageSize = 16384;
1699
- const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1700
- const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
1701
- const free = vmstat.match(/Pages free:\s+(\d+)/);
1702
- const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
1703
- const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
1704
- const freePages = free ? parseInt(free[1], 10) : 0;
1705
- const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
1706
- const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
1707
- return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
1708
- } catch {
1709
- return os7.freemem() / (1024 * 1024 * 1024);
1710
- }
1711
- }
1712
- return os7.freemem() / (1024 * 1024 * 1024);
1713
- }
1714
1693
  function spawnDaemon() {
1715
- const freeGB = getAvailableMemoryGB();
1716
1694
  const totalGB = os7.totalmem() / (1024 * 1024 * 1024);
1717
1695
  if (totalGB <= 8) {
1718
1696
  process.stderr.write(
1719
1697
  `[exed-client] SKIP: ${totalGB.toFixed(0)}GB system \u2014 embedding daemon disabled. Using keyword search only. Minimum 16GB recommended for vector search.
1720
- `
1721
- );
1722
- return;
1723
- }
1724
- if (totalGB <= 16 && freeGB < 2) {
1725
- process.stderr.write(
1726
- `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
1727
1698
  `
1728
1699
  );
1729
1700
  return;
@@ -8192,6 +8163,13 @@ var init_platform_procedures = __esm({
8192
8163
  priority: "p0",
8193
8164
  content: "Tasks live in the DB. Intercom (tmux send-keys) is fire-and-forget \u2014 it may fail, get garbled, or arrive mid-work. Never rely on intercom for task delivery. The UserPromptSubmit hook checks the DB for new tasks on every prompt. Your operating procedures step 7 says check for next work. The daemon nudges idle agents as a speedup. If you have no tasks, you found them all."
8194
8165
  },
8166
+ // --- Encryption key + cloud sync ---
8167
+ {
8168
+ title: "Encryption key lives in Keychain, not on disk \u2014 never expose the recovery phrase",
8169
+ domain: "security",
8170
+ priority: "p0",
8171
+ content: "The master encryption key is stored in macOS Keychain (Secure Enclave) or Linux secret-tool \u2014 NOT as a file. There is no ~/.exe-os/master.key on modern installs. If an older install had one, it was auto-migrated to Keychain and the file deleted. Device linking uses a 24-word BIP39 recovery phrase: Device 1 runs `exe-os cloud link --show-full` in their local Terminal to reveal it, Device 2 runs `exe-os cloud` and pastes the phrase to import the key into its own Keychain, then cloud sync pulls encrypted memories. NEVER display, log, or return the recovery phrase in agent output. MCP tools are hardened \u2014 they cannot reveal it. If the user needs the phrase, tell them: 'Run exe-os cloud link --show-full in your Terminal.' If searching for master.key returns nothing, that is CORRECT \u2014 the key is in Keychain."
8172
+ },
8195
8173
  // --- MCP is the ONLY data interface ---
8196
8174
  {
8197
8175
  title: "MCP disconnect \u2014 ask the user, never work around it",
package/dist/tui/App.js CHANGED
@@ -1942,40 +1942,11 @@ function findPackageRoot() {
1942
1942
  }
1943
1943
  return null;
1944
1944
  }
1945
- function getAvailableMemoryGB() {
1946
- if (process.platform === "darwin") {
1947
- try {
1948
- const { execSync: execSync12 } = __require("child_process");
1949
- const vmstat = execSync12("vm_stat", { encoding: "utf8" });
1950
- const pageSize = 16384;
1951
- const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1952
- const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
1953
- const free = vmstat.match(/Pages free:\s+(\d+)/);
1954
- const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
1955
- const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
1956
- const freePages = free ? parseInt(free[1], 10) : 0;
1957
- const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
1958
- const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
1959
- return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
1960
- } catch {
1961
- return os6.freemem() / (1024 * 1024 * 1024);
1962
- }
1963
- }
1964
- return os6.freemem() / (1024 * 1024 * 1024);
1965
- }
1966
1945
  function spawnDaemon() {
1967
- const freeGB = getAvailableMemoryGB();
1968
1946
  const totalGB = os6.totalmem() / (1024 * 1024 * 1024);
1969
1947
  if (totalGB <= 8) {
1970
1948
  process.stderr.write(
1971
1949
  `[exed-client] SKIP: ${totalGB.toFixed(0)}GB system \u2014 embedding daemon disabled. Using keyword search only. Minimum 16GB recommended for vector search.
1972
- `
1973
- );
1974
- return;
1975
- }
1976
- if (totalGB <= 16 && freeGB < 2) {
1977
- process.stderr.write(
1978
- `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
1979
1950
  `
1980
1951
  );
1981
1952
  return;
@@ -9163,6 +9134,13 @@ var init_platform_procedures = __esm({
9163
9134
  priority: "p0",
9164
9135
  content: "Tasks live in the DB. Intercom (tmux send-keys) is fire-and-forget \u2014 it may fail, get garbled, or arrive mid-work. Never rely on intercom for task delivery. The UserPromptSubmit hook checks the DB for new tasks on every prompt. Your operating procedures step 7 says check for next work. The daemon nudges idle agents as a speedup. If you have no tasks, you found them all."
9165
9136
  },
9137
+ // --- Encryption key + cloud sync ---
9138
+ {
9139
+ title: "Encryption key lives in Keychain, not on disk \u2014 never expose the recovery phrase",
9140
+ domain: "security",
9141
+ priority: "p0",
9142
+ content: "The master encryption key is stored in macOS Keychain (Secure Enclave) or Linux secret-tool \u2014 NOT as a file. There is no ~/.exe-os/master.key on modern installs. If an older install had one, it was auto-migrated to Keychain and the file deleted. Device linking uses a 24-word BIP39 recovery phrase: Device 1 runs `exe-os cloud link --show-full` in their local Terminal to reveal it, Device 2 runs `exe-os cloud` and pastes the phrase to import the key into its own Keychain, then cloud sync pulls encrypted memories. NEVER display, log, or return the recovery phrase in agent output. MCP tools are hardened \u2014 they cannot reveal it. If the user needs the phrase, tell them: 'Run exe-os cloud link --show-full in your Terminal.' If searching for master.key returns nothing, that is CORRECT \u2014 the key is in Keychain."
9143
+ },
9166
9144
  // --- MCP is the ONLY data interface ---
9167
9145
  {
9168
9146
  title: "MCP disconnect \u2014 ask the user, never work around it",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askexenow/exe-os",
3
- "version": "0.9.97",
3
+ "version": "0.9.99",
4
4
  "description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",