@askexenow/exe-os 0.8.88 → 0.8.90
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.
- package/dist/assets/ghostty.conf +83 -0
- package/dist/bin/cli.js +78 -0
- package/dist/bin/exe-new-employee.js +43 -0
- package/dist/bin/install.js +43 -0
- package/dist/bin/setup.js +35 -0
- package/package.json +3 -3
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Exe OS — Ghostty defaults
|
|
2
|
+
# Optimized for tmux + Claude Code agent workflows
|
|
3
|
+
|
|
4
|
+
font-size = 11
|
|
5
|
+
|
|
6
|
+
# ─── Theme: warm light background ───────────────────────────
|
|
7
|
+
background = #fff8f0
|
|
8
|
+
foreground = #000000
|
|
9
|
+
cursor-color = #000000
|
|
10
|
+
selection-background = #b4d5fe
|
|
11
|
+
|
|
12
|
+
# ANSI palette (0-15)
|
|
13
|
+
palette = 0=#000000
|
|
14
|
+
palette = 1=#c91b00
|
|
15
|
+
palette = 2=#00c200
|
|
16
|
+
palette = 3=#c7c400
|
|
17
|
+
palette = 4=#0225c7
|
|
18
|
+
palette = 5=#c930c7
|
|
19
|
+
palette = 6=#00c5c7
|
|
20
|
+
palette = 7=#c7c7c7
|
|
21
|
+
palette = 8=#686868
|
|
22
|
+
palette = 9=#ff6e67
|
|
23
|
+
palette = 10=#5ffa68
|
|
24
|
+
palette = 11=#e5daab
|
|
25
|
+
palette = 12=#6871ff
|
|
26
|
+
palette = 13=#ff77ff
|
|
27
|
+
palette = 14=#60fdff
|
|
28
|
+
palette = 15=#ffffff
|
|
29
|
+
|
|
30
|
+
# ─── Ghostty → tmux keybindings ─────────────────────────────
|
|
31
|
+
# Forward Cmd+key combos to tmux as prefix sequences.
|
|
32
|
+
# Tmux prefix is Ctrl+B (\x02).
|
|
33
|
+
|
|
34
|
+
# Splits (native Ghostty splits)
|
|
35
|
+
keybind = super+d=new_split:right
|
|
36
|
+
keybind = super+shift+d=new_split:down
|
|
37
|
+
|
|
38
|
+
# Close pane/tab
|
|
39
|
+
keybind = super+w=close_surface
|
|
40
|
+
|
|
41
|
+
# New tab
|
|
42
|
+
keybind = super+t=text:\x02t
|
|
43
|
+
|
|
44
|
+
# Tab navigation: Cmd+Shift+[ / ]
|
|
45
|
+
keybind = super+shift+[=text:\x02[
|
|
46
|
+
keybind = super+shift+]=text:\x02]
|
|
47
|
+
|
|
48
|
+
# Go to tab by number: Cmd+1..9
|
|
49
|
+
keybind = super+1=text:\x021
|
|
50
|
+
keybind = super+digit_1=text:\x021
|
|
51
|
+
keybind = super+2=text:\x022
|
|
52
|
+
keybind = super+digit_2=text:\x022
|
|
53
|
+
keybind = super+3=text:\x023
|
|
54
|
+
keybind = super+digit_3=text:\x023
|
|
55
|
+
keybind = super+4=text:\x024
|
|
56
|
+
keybind = super+digit_4=text:\x024
|
|
57
|
+
keybind = super+5=text:\x025
|
|
58
|
+
keybind = super+digit_5=text:\x025
|
|
59
|
+
keybind = super+6=text:\x026
|
|
60
|
+
keybind = super+digit_6=text:\x026
|
|
61
|
+
keybind = super+7=text:\x027
|
|
62
|
+
keybind = super+digit_7=text:\x027
|
|
63
|
+
keybind = super+8=text:\x028
|
|
64
|
+
keybind = super+digit_8=text:\x028
|
|
65
|
+
keybind = super+9=text:\x029
|
|
66
|
+
|
|
67
|
+
# Zoom pane (fullscreen): Cmd+Shift+Enter
|
|
68
|
+
keybind = super+shift+enter=text:\x02z
|
|
69
|
+
|
|
70
|
+
# Clear screen: Cmd+K
|
|
71
|
+
keybind = super+k=text:\x02k
|
|
72
|
+
|
|
73
|
+
# Search: Cmd+F
|
|
74
|
+
keybind = super+f=text:\x02f
|
|
75
|
+
|
|
76
|
+
# Resize splits: Cmd+Ctrl+Arrow
|
|
77
|
+
keybind = super+ctrl+arrow_up=text:\x02\x1b[A
|
|
78
|
+
keybind = super+ctrl+arrow_down=text:\x02\x1b[B
|
|
79
|
+
keybind = super+ctrl+arrow_right=text:\x02\x1b[C
|
|
80
|
+
keybind = super+ctrl+arrow_left=text:\x02\x1b[D
|
|
81
|
+
|
|
82
|
+
# Equalize splits: Cmd+Ctrl+=
|
|
83
|
+
keybind = super+ctrl+=text:\x02=
|
package/dist/bin/cli.js
CHANGED
|
@@ -572,6 +572,7 @@ __export(installer_exports, {
|
|
|
572
572
|
registerMcpServer: () => registerMcpServer,
|
|
573
573
|
resolvePackageRoot: () => resolvePackageRoot,
|
|
574
574
|
runInstaller: () => runInstaller,
|
|
575
|
+
setupGhostty: () => setupGhostty,
|
|
575
576
|
setupTmux: () => setupTmux
|
|
576
577
|
});
|
|
577
578
|
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, readdir } from "fs/promises";
|
|
@@ -1085,6 +1086,48 @@ ${sourceLine}
|
|
|
1085
1086
|
}
|
|
1086
1087
|
process.stderr.write("exe-os: tmux config installed\n");
|
|
1087
1088
|
}
|
|
1089
|
+
function setupGhostty(home) {
|
|
1090
|
+
const homeDir = home ?? os4.homedir();
|
|
1091
|
+
const xdgConfig = path4.join(homeDir, ".config", "ghostty");
|
|
1092
|
+
const macConfig = path4.join(homeDir, "Library", "Application Support", "com.mitchellh.ghostty");
|
|
1093
|
+
const ghosttyInstalled = existsSync4(xdgConfig) || existsSync4(macConfig) || (() => {
|
|
1094
|
+
try {
|
|
1095
|
+
execSync2("which ghostty 2>/dev/null");
|
|
1096
|
+
return true;
|
|
1097
|
+
} catch {
|
|
1098
|
+
return false;
|
|
1099
|
+
}
|
|
1100
|
+
})();
|
|
1101
|
+
if (!ghosttyInstalled) {
|
|
1102
|
+
return;
|
|
1103
|
+
}
|
|
1104
|
+
const pkgRoot = resolvePackageRoot();
|
|
1105
|
+
const assetPath = path4.join(pkgRoot, "dist", "assets", "ghostty.conf");
|
|
1106
|
+
if (!existsSync4(assetPath)) {
|
|
1107
|
+
process.stderr.write("exe-os: ghostty.conf asset not found \u2014 skipping Ghostty setup\n");
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1110
|
+
const configDir = xdgConfig;
|
|
1111
|
+
const configPath = path4.join(configDir, "config");
|
|
1112
|
+
const backupPath = path4.join(configDir, "config.backup");
|
|
1113
|
+
mkdirSync2(configDir, { recursive: true });
|
|
1114
|
+
if (existsSync4(configPath)) {
|
|
1115
|
+
const existing = readFileSync3(configPath, "utf8");
|
|
1116
|
+
if (existing.includes("Exe OS")) {
|
|
1117
|
+
copyFileSync(assetPath, configPath);
|
|
1118
|
+
} else {
|
|
1119
|
+
if (!existsSync4(backupPath)) {
|
|
1120
|
+
copyFileSync(configPath, backupPath);
|
|
1121
|
+
process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
|
|
1122
|
+
`);
|
|
1123
|
+
}
|
|
1124
|
+
copyFileSync(assetPath, configPath);
|
|
1125
|
+
}
|
|
1126
|
+
} else {
|
|
1127
|
+
copyFileSync(assetPath, configPath);
|
|
1128
|
+
}
|
|
1129
|
+
process.stderr.write("exe-os: Ghostty config installed\n");
|
|
1130
|
+
}
|
|
1088
1131
|
function summarizeSymlinkResults(results) {
|
|
1089
1132
|
if (results.length === 0) return "no employees in roster";
|
|
1090
1133
|
const created = results.filter((r) => r.action === "created").length;
|
|
@@ -12320,7 +12363,33 @@ function ask2(rl, prompt) {
|
|
|
12320
12363
|
doAsk();
|
|
12321
12364
|
});
|
|
12322
12365
|
}
|
|
12366
|
+
function getAvailableMemoryGB() {
|
|
12367
|
+
return os11.freemem() / (1024 * 1024 * 1024);
|
|
12368
|
+
}
|
|
12369
|
+
function getTotalMemoryGB() {
|
|
12370
|
+
return os11.totalmem() / (1024 * 1024 * 1024);
|
|
12371
|
+
}
|
|
12372
|
+
function isLowMemory() {
|
|
12373
|
+
return getAvailableMemoryGB() < 2;
|
|
12374
|
+
}
|
|
12323
12375
|
async function validateModel(log) {
|
|
12376
|
+
const totalGB = getTotalMemoryGB();
|
|
12377
|
+
const freeGB = getAvailableMemoryGB();
|
|
12378
|
+
if (totalGB <= 8 || isLowMemory()) {
|
|
12379
|
+
log(`System memory: ${totalGB.toFixed(0)}GB total, ${freeGB.toFixed(1)}GB free`);
|
|
12380
|
+
log("Skipping in-memory model validation (low memory \u2014 will validate on first use).");
|
|
12381
|
+
const modelPath = path28.join(MODELS_DIR, LOCAL_FILENAME);
|
|
12382
|
+
if (existsSync23(modelPath)) {
|
|
12383
|
+
const { statSync: statSync2 } = await import("fs");
|
|
12384
|
+
const size = statSync2(modelPath).size;
|
|
12385
|
+
if (size > 300 * 1e6) {
|
|
12386
|
+
log(`Model file verified (${(size / 1e6).toFixed(0)} MB).`);
|
|
12387
|
+
return;
|
|
12388
|
+
}
|
|
12389
|
+
throw new Error(`Model file too small (${(size / 1e6).toFixed(0)} MB) \u2014 may be corrupted. Delete and re-run setup.`);
|
|
12390
|
+
}
|
|
12391
|
+
throw new Error("Model file not found after download.");
|
|
12392
|
+
}
|
|
12324
12393
|
log("Validating model...");
|
|
12325
12394
|
const { embedDirect: embedDirect2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
|
|
12326
12395
|
const result = await embedDirect2("test embedding");
|
|
@@ -12512,6 +12581,15 @@ async function runSetupWizard(opts = {}) {
|
|
|
12512
12581
|
log("");
|
|
12513
12582
|
if (!state.completedSteps.includes(3)) {
|
|
12514
12583
|
if (!skipModel) {
|
|
12584
|
+
const freeGB = getAvailableMemoryGB();
|
|
12585
|
+
const totalGB = getTotalMemoryGB();
|
|
12586
|
+
if (freeGB < 2) {
|
|
12587
|
+
log(`\u26A0 Low memory detected: ${freeGB.toFixed(1)}GB free of ${totalGB.toFixed(0)}GB total`);
|
|
12588
|
+
log(" Close other applications (browser, Slack, etc.) before continuing.");
|
|
12589
|
+
log(" The embedding model needs ~500MB to download and load.");
|
|
12590
|
+
log("");
|
|
12591
|
+
await ask2(rl, "Press Enter when ready, or Ctrl+C to abort and free memory first: ");
|
|
12592
|
+
}
|
|
12515
12593
|
log("Note: jina-embeddings-v5-text-small is licensed CC-BY-NC-4.0 (non-commercial)");
|
|
12516
12594
|
log("");
|
|
12517
12595
|
await downloadModel({
|
|
@@ -994,6 +994,7 @@ __export(installer_exports, {
|
|
|
994
994
|
registerMcpServer: () => registerMcpServer,
|
|
995
995
|
resolvePackageRoot: () => resolvePackageRoot,
|
|
996
996
|
runInstaller: () => runInstaller,
|
|
997
|
+
setupGhostty: () => setupGhostty,
|
|
997
998
|
setupTmux: () => setupTmux
|
|
998
999
|
});
|
|
999
1000
|
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, readdir } from "fs/promises";
|
|
@@ -1507,6 +1508,48 @@ ${sourceLine}
|
|
|
1507
1508
|
}
|
|
1508
1509
|
process.stderr.write("exe-os: tmux config installed\n");
|
|
1509
1510
|
}
|
|
1511
|
+
function setupGhostty(home) {
|
|
1512
|
+
const homeDir = home ?? os4.homedir();
|
|
1513
|
+
const xdgConfig = path8.join(homeDir, ".config", "ghostty");
|
|
1514
|
+
const macConfig = path8.join(homeDir, "Library", "Application Support", "com.mitchellh.ghostty");
|
|
1515
|
+
const ghosttyInstalled = existsSync8(xdgConfig) || existsSync8(macConfig) || (() => {
|
|
1516
|
+
try {
|
|
1517
|
+
execSync2("which ghostty 2>/dev/null");
|
|
1518
|
+
return true;
|
|
1519
|
+
} catch {
|
|
1520
|
+
return false;
|
|
1521
|
+
}
|
|
1522
|
+
})();
|
|
1523
|
+
if (!ghosttyInstalled) {
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1526
|
+
const pkgRoot = resolvePackageRoot();
|
|
1527
|
+
const assetPath = path8.join(pkgRoot, "dist", "assets", "ghostty.conf");
|
|
1528
|
+
if (!existsSync8(assetPath)) {
|
|
1529
|
+
process.stderr.write("exe-os: ghostty.conf asset not found \u2014 skipping Ghostty setup\n");
|
|
1530
|
+
return;
|
|
1531
|
+
}
|
|
1532
|
+
const configDir = xdgConfig;
|
|
1533
|
+
const configPath = path8.join(configDir, "config");
|
|
1534
|
+
const backupPath = path8.join(configDir, "config.backup");
|
|
1535
|
+
mkdirSync5(configDir, { recursive: true });
|
|
1536
|
+
if (existsSync8(configPath)) {
|
|
1537
|
+
const existing = readFileSync7(configPath, "utf8");
|
|
1538
|
+
if (existing.includes("Exe OS")) {
|
|
1539
|
+
copyFileSync(assetPath, configPath);
|
|
1540
|
+
} else {
|
|
1541
|
+
if (!existsSync8(backupPath)) {
|
|
1542
|
+
copyFileSync(configPath, backupPath);
|
|
1543
|
+
process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
|
|
1544
|
+
`);
|
|
1545
|
+
}
|
|
1546
|
+
copyFileSync(assetPath, configPath);
|
|
1547
|
+
}
|
|
1548
|
+
} else {
|
|
1549
|
+
copyFileSync(assetPath, configPath);
|
|
1550
|
+
}
|
|
1551
|
+
process.stderr.write("exe-os: Ghostty config installed\n");
|
|
1552
|
+
}
|
|
1510
1553
|
function summarizeSymlinkResults(results) {
|
|
1511
1554
|
if (results.length === 0) return "no employees in roster";
|
|
1512
1555
|
const created = results.filter((r) => r.action === "created").length;
|
package/dist/bin/install.js
CHANGED
|
@@ -914,6 +914,48 @@ ${sourceLine}
|
|
|
914
914
|
}
|
|
915
915
|
process.stderr.write("exe-os: tmux config installed\n");
|
|
916
916
|
}
|
|
917
|
+
function setupGhostty(home) {
|
|
918
|
+
const homeDir = home ?? os4.homedir();
|
|
919
|
+
const xdgConfig = path4.join(homeDir, ".config", "ghostty");
|
|
920
|
+
const macConfig = path4.join(homeDir, "Library", "Application Support", "com.mitchellh.ghostty");
|
|
921
|
+
const ghosttyInstalled = existsSync4(xdgConfig) || existsSync4(macConfig) || (() => {
|
|
922
|
+
try {
|
|
923
|
+
execSync2("which ghostty 2>/dev/null");
|
|
924
|
+
return true;
|
|
925
|
+
} catch {
|
|
926
|
+
return false;
|
|
927
|
+
}
|
|
928
|
+
})();
|
|
929
|
+
if (!ghosttyInstalled) {
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
932
|
+
const pkgRoot = resolvePackageRoot();
|
|
933
|
+
const assetPath = path4.join(pkgRoot, "dist", "assets", "ghostty.conf");
|
|
934
|
+
if (!existsSync4(assetPath)) {
|
|
935
|
+
process.stderr.write("exe-os: ghostty.conf asset not found \u2014 skipping Ghostty setup\n");
|
|
936
|
+
return;
|
|
937
|
+
}
|
|
938
|
+
const configDir = xdgConfig;
|
|
939
|
+
const configPath = path4.join(configDir, "config");
|
|
940
|
+
const backupPath = path4.join(configDir, "config.backup");
|
|
941
|
+
mkdirSync2(configDir, { recursive: true });
|
|
942
|
+
if (existsSync4(configPath)) {
|
|
943
|
+
const existing = readFileSync3(configPath, "utf8");
|
|
944
|
+
if (existing.includes("Exe OS")) {
|
|
945
|
+
copyFileSync(assetPath, configPath);
|
|
946
|
+
} else {
|
|
947
|
+
if (!existsSync4(backupPath)) {
|
|
948
|
+
copyFileSync(configPath, backupPath);
|
|
949
|
+
process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
|
|
950
|
+
`);
|
|
951
|
+
}
|
|
952
|
+
copyFileSync(assetPath, configPath);
|
|
953
|
+
}
|
|
954
|
+
} else {
|
|
955
|
+
copyFileSync(assetPath, configPath);
|
|
956
|
+
}
|
|
957
|
+
process.stderr.write("exe-os: Ghostty config installed\n");
|
|
958
|
+
}
|
|
917
959
|
function summarizeSymlinkResults(results) {
|
|
918
960
|
if (results.length === 0) return "no employees in roster";
|
|
919
961
|
const created = results.filter((r) => r.action === "created").length;
|
|
@@ -1183,6 +1225,7 @@ if (args.includes("--commands-only")) {
|
|
|
1183
1225
|
try {
|
|
1184
1226
|
await runInstaller();
|
|
1185
1227
|
setupTmux();
|
|
1228
|
+
setupGhostty();
|
|
1186
1229
|
try {
|
|
1187
1230
|
const { normalizeRosterCase: normalizeRosterCase2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
1188
1231
|
const changed = await normalizeRosterCase2();
|
package/dist/bin/setup.js
CHANGED
|
@@ -5753,7 +5753,33 @@ function ask(rl, prompt) {
|
|
|
5753
5753
|
doAsk();
|
|
5754
5754
|
});
|
|
5755
5755
|
}
|
|
5756
|
+
function getAvailableMemoryGB() {
|
|
5757
|
+
return os4.freemem() / (1024 * 1024 * 1024);
|
|
5758
|
+
}
|
|
5759
|
+
function getTotalMemoryGB() {
|
|
5760
|
+
return os4.totalmem() / (1024 * 1024 * 1024);
|
|
5761
|
+
}
|
|
5762
|
+
function isLowMemory() {
|
|
5763
|
+
return getAvailableMemoryGB() < 2;
|
|
5764
|
+
}
|
|
5756
5765
|
async function validateModel(log) {
|
|
5766
|
+
const totalGB = getTotalMemoryGB();
|
|
5767
|
+
const freeGB = getAvailableMemoryGB();
|
|
5768
|
+
if (totalGB <= 8 || isLowMemory()) {
|
|
5769
|
+
log(`System memory: ${totalGB.toFixed(0)}GB total, ${freeGB.toFixed(1)}GB free`);
|
|
5770
|
+
log("Skipping in-memory model validation (low memory \u2014 will validate on first use).");
|
|
5771
|
+
const modelPath = path11.join(MODELS_DIR, LOCAL_FILENAME);
|
|
5772
|
+
if (existsSync11(modelPath)) {
|
|
5773
|
+
const { statSync: statSync2 } = await import("fs");
|
|
5774
|
+
const size = statSync2(modelPath).size;
|
|
5775
|
+
if (size > 300 * 1e6) {
|
|
5776
|
+
log(`Model file verified (${(size / 1e6).toFixed(0)} MB).`);
|
|
5777
|
+
return;
|
|
5778
|
+
}
|
|
5779
|
+
throw new Error(`Model file too small (${(size / 1e6).toFixed(0)} MB) \u2014 may be corrupted. Delete and re-run setup.`);
|
|
5780
|
+
}
|
|
5781
|
+
throw new Error("Model file not found after download.");
|
|
5782
|
+
}
|
|
5757
5783
|
log("Validating model...");
|
|
5758
5784
|
const { embedDirect: embedDirect2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
|
|
5759
5785
|
const result = await embedDirect2("test embedding");
|
|
@@ -5945,6 +5971,15 @@ async function runSetupWizard(opts = {}) {
|
|
|
5945
5971
|
log("");
|
|
5946
5972
|
if (!state.completedSteps.includes(3)) {
|
|
5947
5973
|
if (!skipModel2) {
|
|
5974
|
+
const freeGB = getAvailableMemoryGB();
|
|
5975
|
+
const totalGB = getTotalMemoryGB();
|
|
5976
|
+
if (freeGB < 2) {
|
|
5977
|
+
log(`\u26A0 Low memory detected: ${freeGB.toFixed(1)}GB free of ${totalGB.toFixed(0)}GB total`);
|
|
5978
|
+
log(" Close other applications (browser, Slack, etc.) before continuing.");
|
|
5979
|
+
log(" The embedding model needs ~500MB to download and load.");
|
|
5980
|
+
log("");
|
|
5981
|
+
await ask(rl, "Press Enter when ready, or Ctrl+C to abort and free memory first: ");
|
|
5982
|
+
}
|
|
5948
5983
|
log("Note: jina-embeddings-v5-text-small is licensed CC-BY-NC-4.0 (non-commercial)");
|
|
5949
5984
|
log("");
|
|
5950
5985
|
await downloadModel({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askexenow/exe-os",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.90",
|
|
4
4
|
"description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
|
|
5
5
|
"license": "CC-BY-NC-4.0",
|
|
6
6
|
"type": "module",
|
|
@@ -61,8 +61,8 @@
|
|
|
61
61
|
"test": "vitest run",
|
|
62
62
|
"test:watch": "vitest",
|
|
63
63
|
"typecheck": "tsc --noEmit",
|
|
64
|
-
"build": "tsup && mkdir -p dist/assets && cp src/assets/tmux.conf dist/assets/ && cp src/bin/exe-start.sh dist/bin/exe-start.sh",
|
|
65
|
-
"deploy": "node dist/bin/pre-build-guard.js 2>/dev/null; tsup && mkdir -p dist/assets && cp src/assets/tmux.conf dist/assets/ && cp src/bin/exe-start.sh dist/bin/exe-start.sh && npm install -g . && node dist/bin/install.js --global && echo '[exe-os] Deploy complete. MCP servers will auto-reconnect on next tool call.'",
|
|
64
|
+
"build": "tsup && mkdir -p dist/assets && cp src/assets/tmux.conf dist/assets/ && cp src/assets/ghostty.conf dist/assets/ && cp src/bin/exe-start.sh dist/bin/exe-start.sh",
|
|
65
|
+
"deploy": "node dist/bin/pre-build-guard.js 2>/dev/null; tsup && mkdir -p dist/assets && cp src/assets/tmux.conf dist/assets/ && cp src/assets/ghostty.conf dist/assets/ && cp src/bin/exe-start.sh dist/bin/exe-start.sh && npm install -g . && node dist/bin/install.js --global && echo '[exe-os] Deploy complete. MCP servers will auto-reconnect on next tool call.'",
|
|
66
66
|
"postinstall": "node dist/bin/install.js --global 2>/dev/null || true",
|
|
67
67
|
"prepublishOnly": "npm run typecheck && npm run build && node dist/bin/customer-readiness.js",
|
|
68
68
|
"test:publish": "npx vitest run --maxWorkers=4 --exclude 'tests/tui/**' --exclude 'tests/lib/tmux-routing.test.ts' --exclude 'tests/lib/intercom-routing.test.ts' --exclude 'tests/gateway/**' --exclude 'tests/installer/setup-wizard.test.ts' --exclude 'tests/mcp/ingest-document.test.ts' --exclude 'tests/lib/hybrid-search.test.ts' --exclude 'tests/lib/worker-gate.test.ts'",
|