@askexenow/exe-os 0.9.98 → 0.9.100
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/bin/agentic-ontology-backfill.js +7 -0
- package/dist/bin/agentic-reflection-backfill.js +7 -0
- package/dist/bin/agentic-semantic-label.js +7 -0
- package/dist/bin/backfill-conversations.js +7 -0
- package/dist/bin/backfill-responses.js +7 -0
- package/dist/bin/backfill-vectors.js +7 -0
- package/dist/bin/bulk-sync-postgres.js +7 -0
- package/dist/bin/cleanup-stale-review-tasks.js +7 -0
- package/dist/bin/cli.js +36 -10
- package/dist/bin/exe-agent.js +7 -0
- package/dist/bin/exe-assign.js +7 -0
- package/dist/bin/exe-boot.js +36 -10
- package/dist/bin/exe-call.js +7 -0
- package/dist/bin/exe-cloud.js +36 -10
- package/dist/bin/exe-dispatch.js +7 -0
- package/dist/bin/exe-doctor.js +36 -10
- package/dist/bin/exe-export-behaviors.js +7 -0
- package/dist/bin/exe-forget.js +7 -0
- package/dist/bin/exe-gateway.js +7 -0
- package/dist/bin/exe-heartbeat.js +7 -0
- package/dist/bin/exe-kill.js +7 -0
- package/dist/bin/exe-launch-agent.js +7 -0
- package/dist/bin/exe-new-employee.js +7 -0
- package/dist/bin/exe-pending-messages.js +7 -0
- package/dist/bin/exe-pending-notifications.js +7 -0
- package/dist/bin/exe-pending-reviews.js +7 -0
- package/dist/bin/exe-rename.js +7 -0
- package/dist/bin/exe-review.js +7 -0
- package/dist/bin/exe-search.js +7 -0
- package/dist/bin/exe-session-cleanup.js +7 -0
- package/dist/bin/exe-start-codex.js +7 -0
- package/dist/bin/exe-start-opencode.js +7 -0
- package/dist/bin/exe-status.js +7 -0
- package/dist/bin/exe-team.js +7 -0
- package/dist/bin/git-sweep.js +7 -0
- package/dist/bin/graph-backfill.js +7 -0
- package/dist/bin/graph-export.js +7 -0
- package/dist/bin/intercom-check.js +7 -0
- package/dist/bin/scan-tasks.js +7 -0
- package/dist/bin/setup.js +36 -10
- package/dist/bin/shard-migrate.js +7 -0
- package/dist/gateway/index.js +7 -0
- package/dist/hooks/bug-report-worker.js +7 -0
- package/dist/hooks/codex-stop-task-finalizer.js +7 -0
- package/dist/hooks/commit-complete.js +7 -0
- package/dist/hooks/error-recall.js +7 -0
- package/dist/hooks/ingest.js +7 -0
- package/dist/hooks/instructions-loaded.js +7 -0
- package/dist/hooks/notification.js +7 -0
- package/dist/hooks/post-compact.js +7 -0
- package/dist/hooks/post-tool-combined.js +7 -0
- package/dist/hooks/pre-compact.js +7 -0
- package/dist/hooks/pre-tool-use.js +7 -0
- package/dist/hooks/prompt-submit.js +7 -0
- package/dist/hooks/session-end.js +7 -0
- package/dist/hooks/session-start.js +7 -0
- package/dist/hooks/stop.js +7 -0
- package/dist/hooks/subagent-stop.js +7 -0
- package/dist/hooks/summary-worker.js +36 -10
- package/dist/index.js +7 -0
- package/dist/lib/cloud-sync.js +29 -10
- package/dist/lib/employee-templates.js +7 -0
- package/dist/lib/exe-daemon.js +36 -10
- package/dist/lib/hybrid-search.js +7 -0
- package/dist/lib/keychain.js +29 -10
- package/dist/lib/schedules.js +7 -0
- package/dist/lib/store.js +7 -0
- package/dist/mcp/server.js +36 -10
- package/dist/runtime/index.js +7 -0
- package/dist/tui/App.js +36 -10
- package/package.json +1 -1
- package/src/commands/exe/setup.md +1 -1
|
@@ -3587,20 +3587,39 @@ async function getKeyStorageInfo() {
|
|
|
3587
3587
|
}
|
|
3588
3588
|
async function setMasterKey(key) {
|
|
3589
3589
|
const b64 = key.toString("base64");
|
|
3590
|
-
|
|
3591
|
-
|
|
3590
|
+
let keychainOk = false;
|
|
3591
|
+
if (macKeychainSet(b64)) {
|
|
3592
|
+
const readBack = macKeychainGet();
|
|
3593
|
+
if (readBack === b64) {
|
|
3594
|
+
keychainOk = true;
|
|
3595
|
+
} else {
|
|
3596
|
+
process.stderr.write(
|
|
3597
|
+
"[keychain] macOS Keychain write appeared to succeed but read-back failed.\n This can happen on macOS Tahoe with new permission patterns.\n"
|
|
3598
|
+
);
|
|
3599
|
+
}
|
|
3600
|
+
} else if (linuxSecretSet(b64)) {
|
|
3601
|
+
const readBack = linuxSecretGet();
|
|
3602
|
+
if (readBack === b64) {
|
|
3603
|
+
keychainOk = true;
|
|
3604
|
+
} else {
|
|
3605
|
+
process.stderr.write("[keychain] Linux secret-tool write appeared to succeed but read-back failed.\n");
|
|
3606
|
+
}
|
|
3592
3607
|
}
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3608
|
+
if (!keychainOk) {
|
|
3609
|
+
const keytar = await tryKeytar();
|
|
3610
|
+
if (keytar) {
|
|
3611
|
+
try {
|
|
3612
|
+
await keytar.setPassword(SERVICE, ACCOUNT, b64);
|
|
3613
|
+
keychainOk = true;
|
|
3614
|
+
} catch {
|
|
3615
|
+
}
|
|
3599
3616
|
}
|
|
3600
3617
|
}
|
|
3601
3618
|
const fallback = await writeMachineBoundFileFallback(b64);
|
|
3602
|
-
if (
|
|
3603
|
-
process.stderr.write("[keychain] Key stored
|
|
3619
|
+
if (keychainOk) {
|
|
3620
|
+
process.stderr.write("[keychain] Key stored in OS keychain (file backup also written).\n");
|
|
3621
|
+
} else if (fallback === "encrypted") {
|
|
3622
|
+
process.stderr.write("[keychain] Key stored encrypted (machine-bound file fallback).\n");
|
|
3604
3623
|
} else {
|
|
3605
3624
|
process.stderr.write(
|
|
3606
3625
|
"[keychain] WARNING: Key stored in plaintext file \u2014 no OS keychain available.\n"
|
|
@@ -4334,6 +4353,13 @@ var init_platform_procedures = __esm({
|
|
|
4334
4353
|
priority: "p0",
|
|
4335
4354
|
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."
|
|
4336
4355
|
},
|
|
4356
|
+
// --- Encryption key + cloud sync ---
|
|
4357
|
+
{
|
|
4358
|
+
title: "Encryption key lives in Keychain, not on disk \u2014 never expose the recovery phrase",
|
|
4359
|
+
domain: "security",
|
|
4360
|
+
priority: "p0",
|
|
4361
|
+
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."
|
|
4362
|
+
},
|
|
4337
4363
|
// --- MCP is the ONLY data interface ---
|
|
4338
4364
|
{
|
|
4339
4365
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
package/dist/index.js
CHANGED
|
@@ -8403,6 +8403,13 @@ var init_platform_procedures = __esm({
|
|
|
8403
8403
|
priority: "p0",
|
|
8404
8404
|
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."
|
|
8405
8405
|
},
|
|
8406
|
+
// --- Encryption key + cloud sync ---
|
|
8407
|
+
{
|
|
8408
|
+
title: "Encryption key lives in Keychain, not on disk \u2014 never expose the recovery phrase",
|
|
8409
|
+
domain: "security",
|
|
8410
|
+
priority: "p0",
|
|
8411
|
+
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."
|
|
8412
|
+
},
|
|
8406
8413
|
// --- MCP is the ONLY data interface ---
|
|
8407
8414
|
{
|
|
8408
8415
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
package/dist/lib/cloud-sync.js
CHANGED
|
@@ -3480,20 +3480,39 @@ async function getKeyStorageInfo() {
|
|
|
3480
3480
|
}
|
|
3481
3481
|
async function setMasterKey(key) {
|
|
3482
3482
|
const b64 = key.toString("base64");
|
|
3483
|
-
|
|
3484
|
-
|
|
3483
|
+
let keychainOk = false;
|
|
3484
|
+
if (macKeychainSet(b64)) {
|
|
3485
|
+
const readBack = macKeychainGet();
|
|
3486
|
+
if (readBack === b64) {
|
|
3487
|
+
keychainOk = true;
|
|
3488
|
+
} else {
|
|
3489
|
+
process.stderr.write(
|
|
3490
|
+
"[keychain] macOS Keychain write appeared to succeed but read-back failed.\n This can happen on macOS Tahoe with new permission patterns.\n"
|
|
3491
|
+
);
|
|
3492
|
+
}
|
|
3493
|
+
} else if (linuxSecretSet(b64)) {
|
|
3494
|
+
const readBack = linuxSecretGet();
|
|
3495
|
+
if (readBack === b64) {
|
|
3496
|
+
keychainOk = true;
|
|
3497
|
+
} else {
|
|
3498
|
+
process.stderr.write("[keychain] Linux secret-tool write appeared to succeed but read-back failed.\n");
|
|
3499
|
+
}
|
|
3485
3500
|
}
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3501
|
+
if (!keychainOk) {
|
|
3502
|
+
const keytar = await tryKeytar();
|
|
3503
|
+
if (keytar) {
|
|
3504
|
+
try {
|
|
3505
|
+
await keytar.setPassword(SERVICE, ACCOUNT, b64);
|
|
3506
|
+
keychainOk = true;
|
|
3507
|
+
} catch {
|
|
3508
|
+
}
|
|
3492
3509
|
}
|
|
3493
3510
|
}
|
|
3494
3511
|
const fallback = await writeMachineBoundFileFallback(b64);
|
|
3495
|
-
if (
|
|
3496
|
-
process.stderr.write("[keychain] Key stored
|
|
3512
|
+
if (keychainOk) {
|
|
3513
|
+
process.stderr.write("[keychain] Key stored in OS keychain (file backup also written).\n");
|
|
3514
|
+
} else if (fallback === "encrypted") {
|
|
3515
|
+
process.stderr.write("[keychain] Key stored encrypted (machine-bound file fallback).\n");
|
|
3497
3516
|
} else {
|
|
3498
3517
|
process.stderr.write(
|
|
3499
3518
|
"[keychain] WARNING: Key stored in plaintext file \u2014 no OS keychain available.\n"
|
|
@@ -337,6 +337,13 @@ var PLATFORM_PROCEDURES = [
|
|
|
337
337
|
priority: "p0",
|
|
338
338
|
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."
|
|
339
339
|
},
|
|
340
|
+
// --- Encryption key + cloud sync ---
|
|
341
|
+
{
|
|
342
|
+
title: "Encryption key lives in Keychain, not on disk \u2014 never expose the recovery phrase",
|
|
343
|
+
domain: "security",
|
|
344
|
+
priority: "p0",
|
|
345
|
+
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."
|
|
346
|
+
},
|
|
340
347
|
// --- MCP is the ONLY data interface ---
|
|
341
348
|
{
|
|
342
349
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
package/dist/lib/exe-daemon.js
CHANGED
|
@@ -5637,20 +5637,39 @@ async function getKeyStorageInfo() {
|
|
|
5637
5637
|
}
|
|
5638
5638
|
async function setMasterKey(key) {
|
|
5639
5639
|
const b64 = key.toString("base64");
|
|
5640
|
-
|
|
5641
|
-
|
|
5640
|
+
let keychainOk = false;
|
|
5641
|
+
if (macKeychainSet(b64)) {
|
|
5642
|
+
const readBack = macKeychainGet();
|
|
5643
|
+
if (readBack === b64) {
|
|
5644
|
+
keychainOk = true;
|
|
5645
|
+
} else {
|
|
5646
|
+
process.stderr.write(
|
|
5647
|
+
"[keychain] macOS Keychain write appeared to succeed but read-back failed.\n This can happen on macOS Tahoe with new permission patterns.\n"
|
|
5648
|
+
);
|
|
5649
|
+
}
|
|
5650
|
+
} else if (linuxSecretSet(b64)) {
|
|
5651
|
+
const readBack = linuxSecretGet();
|
|
5652
|
+
if (readBack === b64) {
|
|
5653
|
+
keychainOk = true;
|
|
5654
|
+
} else {
|
|
5655
|
+
process.stderr.write("[keychain] Linux secret-tool write appeared to succeed but read-back failed.\n");
|
|
5656
|
+
}
|
|
5642
5657
|
}
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5658
|
+
if (!keychainOk) {
|
|
5659
|
+
const keytar = await tryKeytar();
|
|
5660
|
+
if (keytar) {
|
|
5661
|
+
try {
|
|
5662
|
+
await keytar.setPassword(SERVICE, ACCOUNT, b64);
|
|
5663
|
+
keychainOk = true;
|
|
5664
|
+
} catch {
|
|
5665
|
+
}
|
|
5649
5666
|
}
|
|
5650
5667
|
}
|
|
5651
5668
|
const fallback = await writeMachineBoundFileFallback(b64);
|
|
5652
|
-
if (
|
|
5653
|
-
process.stderr.write("[keychain] Key stored
|
|
5669
|
+
if (keychainOk) {
|
|
5670
|
+
process.stderr.write("[keychain] Key stored in OS keychain (file backup also written).\n");
|
|
5671
|
+
} else if (fallback === "encrypted") {
|
|
5672
|
+
process.stderr.write("[keychain] Key stored encrypted (machine-bound file fallback).\n");
|
|
5654
5673
|
} else {
|
|
5655
5674
|
process.stderr.write(
|
|
5656
5675
|
"[keychain] WARNING: Key stored in plaintext file \u2014 no OS keychain available.\n"
|
|
@@ -5969,6 +5988,13 @@ var init_platform_procedures = __esm({
|
|
|
5969
5988
|
priority: "p0",
|
|
5970
5989
|
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."
|
|
5971
5990
|
},
|
|
5991
|
+
// --- Encryption key + cloud sync ---
|
|
5992
|
+
{
|
|
5993
|
+
title: "Encryption key lives in Keychain, not on disk \u2014 never expose the recovery phrase",
|
|
5994
|
+
domain: "security",
|
|
5995
|
+
priority: "p0",
|
|
5996
|
+
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."
|
|
5997
|
+
},
|
|
5972
5998
|
// --- MCP is the ONLY data interface ---
|
|
5973
5999
|
{
|
|
5974
6000
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
|
@@ -4286,6 +4286,13 @@ var init_platform_procedures = __esm({
|
|
|
4286
4286
|
priority: "p0",
|
|
4287
4287
|
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."
|
|
4288
4288
|
},
|
|
4289
|
+
// --- Encryption key + cloud sync ---
|
|
4290
|
+
{
|
|
4291
|
+
title: "Encryption key lives in Keychain, not on disk \u2014 never expose the recovery phrase",
|
|
4292
|
+
domain: "security",
|
|
4293
|
+
priority: "p0",
|
|
4294
|
+
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."
|
|
4295
|
+
},
|
|
4289
4296
|
// --- MCP is the ONLY data interface ---
|
|
4290
4297
|
{
|
|
4291
4298
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
package/dist/lib/keychain.js
CHANGED
|
@@ -399,20 +399,39 @@ async function getKeyStorageInfo() {
|
|
|
399
399
|
}
|
|
400
400
|
async function setMasterKey(key) {
|
|
401
401
|
const b64 = key.toString("base64");
|
|
402
|
-
|
|
403
|
-
|
|
402
|
+
let keychainOk = false;
|
|
403
|
+
if (macKeychainSet(b64)) {
|
|
404
|
+
const readBack = macKeychainGet();
|
|
405
|
+
if (readBack === b64) {
|
|
406
|
+
keychainOk = true;
|
|
407
|
+
} else {
|
|
408
|
+
process.stderr.write(
|
|
409
|
+
"[keychain] macOS Keychain write appeared to succeed but read-back failed.\n This can happen on macOS Tahoe with new permission patterns.\n"
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
} else if (linuxSecretSet(b64)) {
|
|
413
|
+
const readBack = linuxSecretGet();
|
|
414
|
+
if (readBack === b64) {
|
|
415
|
+
keychainOk = true;
|
|
416
|
+
} else {
|
|
417
|
+
process.stderr.write("[keychain] Linux secret-tool write appeared to succeed but read-back failed.\n");
|
|
418
|
+
}
|
|
404
419
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
420
|
+
if (!keychainOk) {
|
|
421
|
+
const keytar = await tryKeytar();
|
|
422
|
+
if (keytar) {
|
|
423
|
+
try {
|
|
424
|
+
await keytar.setPassword(SERVICE, ACCOUNT, b64);
|
|
425
|
+
keychainOk = true;
|
|
426
|
+
} catch {
|
|
427
|
+
}
|
|
411
428
|
}
|
|
412
429
|
}
|
|
413
430
|
const fallback = await writeMachineBoundFileFallback(b64);
|
|
414
|
-
if (
|
|
415
|
-
process.stderr.write("[keychain] Key stored
|
|
431
|
+
if (keychainOk) {
|
|
432
|
+
process.stderr.write("[keychain] Key stored in OS keychain (file backup also written).\n");
|
|
433
|
+
} else if (fallback === "encrypted") {
|
|
434
|
+
process.stderr.write("[keychain] Key stored encrypted (machine-bound file fallback).\n");
|
|
416
435
|
} else {
|
|
417
436
|
process.stderr.write(
|
|
418
437
|
"[keychain] WARNING: Key stored in plaintext file \u2014 no OS keychain available.\n"
|
package/dist/lib/schedules.js
CHANGED
|
@@ -3515,6 +3515,13 @@ var init_platform_procedures = __esm({
|
|
|
3515
3515
|
priority: "p0",
|
|
3516
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."
|
|
3517
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
|
+
},
|
|
3518
3525
|
// --- MCP is the ONLY data interface ---
|
|
3519
3526
|
{
|
|
3520
3527
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
package/dist/lib/store.js
CHANGED
|
@@ -3515,6 +3515,13 @@ var init_platform_procedures = __esm({
|
|
|
3515
3515
|
priority: "p0",
|
|
3516
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."
|
|
3517
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
|
+
},
|
|
3518
3525
|
// --- MCP is the ONLY data interface ---
|
|
3519
3526
|
{
|
|
3520
3527
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
package/dist/mcp/server.js
CHANGED
|
@@ -3994,20 +3994,39 @@ async function getKeyStorageInfo() {
|
|
|
3994
3994
|
}
|
|
3995
3995
|
async function setMasterKey(key) {
|
|
3996
3996
|
const b64 = key.toString("base64");
|
|
3997
|
-
|
|
3998
|
-
|
|
3997
|
+
let keychainOk = false;
|
|
3998
|
+
if (macKeychainSet(b64)) {
|
|
3999
|
+
const readBack = macKeychainGet();
|
|
4000
|
+
if (readBack === b64) {
|
|
4001
|
+
keychainOk = true;
|
|
4002
|
+
} else {
|
|
4003
|
+
process.stderr.write(
|
|
4004
|
+
"[keychain] macOS Keychain write appeared to succeed but read-back failed.\n This can happen on macOS Tahoe with new permission patterns.\n"
|
|
4005
|
+
);
|
|
4006
|
+
}
|
|
4007
|
+
} else if (linuxSecretSet(b64)) {
|
|
4008
|
+
const readBack = linuxSecretGet();
|
|
4009
|
+
if (readBack === b64) {
|
|
4010
|
+
keychainOk = true;
|
|
4011
|
+
} else {
|
|
4012
|
+
process.stderr.write("[keychain] Linux secret-tool write appeared to succeed but read-back failed.\n");
|
|
4013
|
+
}
|
|
3999
4014
|
}
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4015
|
+
if (!keychainOk) {
|
|
4016
|
+
const keytar = await tryKeytar();
|
|
4017
|
+
if (keytar) {
|
|
4018
|
+
try {
|
|
4019
|
+
await keytar.setPassword(SERVICE, ACCOUNT, b64);
|
|
4020
|
+
keychainOk = true;
|
|
4021
|
+
} catch {
|
|
4022
|
+
}
|
|
4006
4023
|
}
|
|
4007
4024
|
}
|
|
4008
4025
|
const fallback = await writeMachineBoundFileFallback(b64);
|
|
4009
|
-
if (
|
|
4010
|
-
process.stderr.write("[keychain] Key stored
|
|
4026
|
+
if (keychainOk) {
|
|
4027
|
+
process.stderr.write("[keychain] Key stored in OS keychain (file backup also written).\n");
|
|
4028
|
+
} else if (fallback === "encrypted") {
|
|
4029
|
+
process.stderr.write("[keychain] Key stored encrypted (machine-bound file fallback).\n");
|
|
4011
4030
|
} else {
|
|
4012
4031
|
process.stderr.write(
|
|
4013
4032
|
"[keychain] WARNING: Key stored in plaintext file \u2014 no OS keychain available.\n"
|
|
@@ -4935,6 +4954,13 @@ var init_platform_procedures = __esm({
|
|
|
4935
4954
|
priority: "p0",
|
|
4936
4955
|
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."
|
|
4937
4956
|
},
|
|
4957
|
+
// --- Encryption key + cloud sync ---
|
|
4958
|
+
{
|
|
4959
|
+
title: "Encryption key lives in Keychain, not on disk \u2014 never expose the recovery phrase",
|
|
4960
|
+
domain: "security",
|
|
4961
|
+
priority: "p0",
|
|
4962
|
+
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."
|
|
4963
|
+
},
|
|
4938
4964
|
// --- MCP is the ONLY data interface ---
|
|
4939
4965
|
{
|
|
4940
4966
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
package/dist/runtime/index.js
CHANGED
|
@@ -8163,6 +8163,13 @@ var init_platform_procedures = __esm({
|
|
|
8163
8163
|
priority: "p0",
|
|
8164
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."
|
|
8165
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
|
+
},
|
|
8166
8173
|
// --- MCP is the ONLY data interface ---
|
|
8167
8174
|
{
|
|
8168
8175
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
package/dist/tui/App.js
CHANGED
|
@@ -9134,6 +9134,13 @@ var init_platform_procedures = __esm({
|
|
|
9134
9134
|
priority: "p0",
|
|
9135
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."
|
|
9136
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
|
+
},
|
|
9137
9144
|
// --- MCP is the ONLY data interface ---
|
|
9138
9145
|
{
|
|
9139
9146
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
|
@@ -11326,20 +11333,39 @@ async function getKeyStorageInfo() {
|
|
|
11326
11333
|
}
|
|
11327
11334
|
async function setMasterKey(key) {
|
|
11328
11335
|
const b64 = key.toString("base64");
|
|
11329
|
-
|
|
11330
|
-
|
|
11336
|
+
let keychainOk = false;
|
|
11337
|
+
if (macKeychainSet(b64)) {
|
|
11338
|
+
const readBack = macKeychainGet();
|
|
11339
|
+
if (readBack === b64) {
|
|
11340
|
+
keychainOk = true;
|
|
11341
|
+
} else {
|
|
11342
|
+
process.stderr.write(
|
|
11343
|
+
"[keychain] macOS Keychain write appeared to succeed but read-back failed.\n This can happen on macOS Tahoe with new permission patterns.\n"
|
|
11344
|
+
);
|
|
11345
|
+
}
|
|
11346
|
+
} else if (linuxSecretSet(b64)) {
|
|
11347
|
+
const readBack = linuxSecretGet();
|
|
11348
|
+
if (readBack === b64) {
|
|
11349
|
+
keychainOk = true;
|
|
11350
|
+
} else {
|
|
11351
|
+
process.stderr.write("[keychain] Linux secret-tool write appeared to succeed but read-back failed.\n");
|
|
11352
|
+
}
|
|
11331
11353
|
}
|
|
11332
|
-
|
|
11333
|
-
|
|
11334
|
-
|
|
11335
|
-
|
|
11336
|
-
|
|
11337
|
-
|
|
11354
|
+
if (!keychainOk) {
|
|
11355
|
+
const keytar = await tryKeytar();
|
|
11356
|
+
if (keytar) {
|
|
11357
|
+
try {
|
|
11358
|
+
await keytar.setPassword(SERVICE, ACCOUNT, b64);
|
|
11359
|
+
keychainOk = true;
|
|
11360
|
+
} catch {
|
|
11361
|
+
}
|
|
11338
11362
|
}
|
|
11339
11363
|
}
|
|
11340
11364
|
const fallback = await writeMachineBoundFileFallback(b64);
|
|
11341
|
-
if (
|
|
11342
|
-
process.stderr.write("[keychain] Key stored
|
|
11365
|
+
if (keychainOk) {
|
|
11366
|
+
process.stderr.write("[keychain] Key stored in OS keychain (file backup also written).\n");
|
|
11367
|
+
} else if (fallback === "encrypted") {
|
|
11368
|
+
process.stderr.write("[keychain] Key stored encrypted (machine-bound file fallback).\n");
|
|
11343
11369
|
} else {
|
|
11344
11370
|
process.stderr.write(
|
|
11345
11371
|
"[keychain] WARNING: Key stored in plaintext file \u2014 no OS keychain available.\n"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askexenow/exe-os",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.100",
|
|
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",
|
|
@@ -68,7 +68,7 @@ Use AskUserQuestion to ask for their Exe Cloud API key (exe_sk_...).
|
|
|
68
68
|
|
|
69
69
|
Validate the key:
|
|
70
70
|
```bash
|
|
71
|
-
curl -s "https://askexe.com/
|
|
71
|
+
curl -s "https://cloud.askexe.com/auth/verify" \
|
|
72
72
|
-H "Authorization: Bearer USER_API_KEY" | cat
|
|
73
73
|
```
|
|
74
74
|
|