@askexenow/exe-os 0.8.0
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/LICENSE +21 -0
- package/README.md +139 -0
- package/dist/bin/backfill-responses.js +1912 -0
- package/dist/bin/backfill-vectors.js +1642 -0
- package/dist/bin/cleanup-stale-review-tasks.js +1339 -0
- package/dist/bin/cli.js +18800 -0
- package/dist/bin/exe-agent.js +1858 -0
- package/dist/bin/exe-assign.js +1957 -0
- package/dist/bin/exe-boot.js +6460 -0
- package/dist/bin/exe-call.js +197 -0
- package/dist/bin/exe-cloud.js +850 -0
- package/dist/bin/exe-dispatch.js +1146 -0
- package/dist/bin/exe-doctor.js +1657 -0
- package/dist/bin/exe-export-behaviors.js +1494 -0
- package/dist/bin/exe-forget.js +1627 -0
- package/dist/bin/exe-gateway.js +7732 -0
- package/dist/bin/exe-healthcheck.js +207 -0
- package/dist/bin/exe-heartbeat.js +1647 -0
- package/dist/bin/exe-kill.js +1479 -0
- package/dist/bin/exe-launch-agent.js +1704 -0
- package/dist/bin/exe-link.js +192 -0
- package/dist/bin/exe-new-employee.js +852 -0
- package/dist/bin/exe-pending-messages.js +1446 -0
- package/dist/bin/exe-pending-notifications.js +1321 -0
- package/dist/bin/exe-pending-reviews.js +1468 -0
- package/dist/bin/exe-repo-drift.js +95 -0
- package/dist/bin/exe-review.js +1590 -0
- package/dist/bin/exe-search.js +2651 -0
- package/dist/bin/exe-session-cleanup.js +3173 -0
- package/dist/bin/exe-settings.js +354 -0
- package/dist/bin/exe-status.js +1532 -0
- package/dist/bin/exe-team.js +1324 -0
- package/dist/bin/git-sweep.js +2185 -0
- package/dist/bin/graph-backfill.js +1968 -0
- package/dist/bin/graph-export.js +1604 -0
- package/dist/bin/install.js +656 -0
- package/dist/bin/list-providers.js +140 -0
- package/dist/bin/scan-tasks.js +1820 -0
- package/dist/bin/setup.js +951 -0
- package/dist/bin/shard-migrate.js +1494 -0
- package/dist/bin/update.js +95 -0
- package/dist/bin/wiki-sync.js +1514 -0
- package/dist/gateway/index.js +8848 -0
- package/dist/hooks/bug-report-worker.js +2743 -0
- package/dist/hooks/commit-complete.js +2108 -0
- package/dist/hooks/error-recall.js +2861 -0
- package/dist/hooks/exe-heartbeat-hook.js +232 -0
- package/dist/hooks/ingest-worker.js +4793 -0
- package/dist/hooks/ingest.js +684 -0
- package/dist/hooks/instructions-loaded.js +1880 -0
- package/dist/hooks/notification.js +1726 -0
- package/dist/hooks/post-compact.js +1751 -0
- package/dist/hooks/pre-compact.js +1746 -0
- package/dist/hooks/pre-tool-use.js +2191 -0
- package/dist/hooks/prompt-ingest-worker.js +2126 -0
- package/dist/hooks/prompt-submit.js +4693 -0
- package/dist/hooks/response-ingest-worker.js +1936 -0
- package/dist/hooks/session-end.js +1752 -0
- package/dist/hooks/session-start.js +2795 -0
- package/dist/hooks/stop.js +1835 -0
- package/dist/hooks/subagent-stop.js +1726 -0
- package/dist/hooks/summary-worker.js +2661 -0
- package/dist/index.js +11834 -0
- package/dist/lib/cloud-sync.js +495 -0
- package/dist/lib/config.js +222 -0
- package/dist/lib/consolidation.js +476 -0
- package/dist/lib/crypto.js +51 -0
- package/dist/lib/database.js +730 -0
- package/dist/lib/device-registry.js +900 -0
- package/dist/lib/embedder.js +632 -0
- package/dist/lib/employee-templates.js +543 -0
- package/dist/lib/employees.js +177 -0
- package/dist/lib/error-detector.js +156 -0
- package/dist/lib/exe-daemon-client.js +451 -0
- package/dist/lib/exe-daemon.js +8285 -0
- package/dist/lib/file-grep.js +199 -0
- package/dist/lib/hybrid-search.js +1819 -0
- package/dist/lib/identity-templates.js +320 -0
- package/dist/lib/identity.js +223 -0
- package/dist/lib/keychain.js +145 -0
- package/dist/lib/license.js +377 -0
- package/dist/lib/messaging.js +1376 -0
- package/dist/lib/reminders.js +63 -0
- package/dist/lib/schedules.js +1396 -0
- package/dist/lib/session-registry.js +52 -0
- package/dist/lib/skill-learning.js +477 -0
- package/dist/lib/status-brief.js +235 -0
- package/dist/lib/store.js +1551 -0
- package/dist/lib/task-router.js +62 -0
- package/dist/lib/tasks.js +2456 -0
- package/dist/lib/tmux-routing.js +2836 -0
- package/dist/lib/tmux-status.js +261 -0
- package/dist/lib/tmux-transport.js +83 -0
- package/dist/lib/transport.js +128 -0
- package/dist/lib/ws-auth.js +19 -0
- package/dist/lib/ws-client.js +160 -0
- package/dist/mcp/server.js +10538 -0
- package/dist/mcp/tools/complete-reminder.js +67 -0
- package/dist/mcp/tools/create-reminder.js +52 -0
- package/dist/mcp/tools/create-task.js +1853 -0
- package/dist/mcp/tools/deactivate-behavior.js +263 -0
- package/dist/mcp/tools/list-reminders.js +62 -0
- package/dist/mcp/tools/list-tasks.js +463 -0
- package/dist/mcp/tools/send-message.js +1382 -0
- package/dist/mcp/tools/update-task.js +1692 -0
- package/dist/runtime/index.js +6809 -0
- package/dist/tui/App.js +17479 -0
- package/package.json +104 -0
- package/src/commands/exe/assign.md +17 -0
- package/src/commands/exe/build-adv.md +381 -0
- package/src/commands/exe/call.md +133 -0
- package/src/commands/exe/cloud.md +17 -0
- package/src/commands/exe/employee-heartbeat.md +44 -0
- package/src/commands/exe/forget.md +15 -0
- package/src/commands/exe/heartbeat.md +92 -0
- package/src/commands/exe/intercom.md +81 -0
- package/src/commands/exe/kill.md +34 -0
- package/src/commands/exe/launch.md +52 -0
- package/src/commands/exe/link.md +17 -0
- package/src/commands/exe/logs.md +22 -0
- package/src/commands/exe/new-employee.md +12 -0
- package/src/commands/exe/review.md +14 -0
- package/src/commands/exe/schedule.md +108 -0
- package/src/commands/exe/search.md +13 -0
- package/src/commands/exe/sessions.md +25 -0
- package/src/commands/exe/settings.md +13 -0
- package/src/commands/exe/setup.md +171 -0
- package/src/commands/exe/status.md +15 -0
- package/src/commands/exe/team.md +11 -0
- package/src/commands/exe/update.md +11 -0
- package/src/commands/exe.md +181 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Check task folder for open tasks and output directly if found
|
|
3
|
+
allowed-tools: Bash
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Employee Heartbeat — Task Check
|
|
7
|
+
|
|
8
|
+
This command is designed for `/loop`. It scans the employee's task folder and outputs task info directly when open tasks exist.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
# Detect agent from EXE_SESSION_NAME env var or tmux session name
|
|
12
|
+
SESSION_KEY="${EXE_SESSION_NAME:-$(tmux display-message -p '#{session_name}' 2>/dev/null)}"
|
|
13
|
+
if [ -n "$SESSION_KEY" ]; then
|
|
14
|
+
AGENT=$(echo "$SESSION_KEY" | sed -E 's/-exe[0-9]+$//; s/[0-9]+$//')
|
|
15
|
+
else
|
|
16
|
+
AGENT="UNKNOWN"
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
# Skip if no agent or exe/default
|
|
20
|
+
if [ "$AGENT" = "UNKNOWN" ] || [ "$AGENT" = "exe" ] || [ "$AGENT" = "default" ]; then
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Idle detection: stay silent if agent had activity within last 120 seconds
|
|
25
|
+
ACTIVITY_FILE="${HOME}/.exe-os/session-cache/last-activity-${SESSION_KEY}.json"
|
|
26
|
+
if [ -f "$ACTIVITY_FILE" ]; then
|
|
27
|
+
IDLE_CHECK=$(SESSION_KEY="$SESSION_KEY" node -e "
|
|
28
|
+
try {
|
|
29
|
+
const a = JSON.parse(require('fs').readFileSync(process.env.HOME+'/.exe-os/session-cache/last-activity-'+process.env.SESSION_KEY+'.json','utf8'));
|
|
30
|
+
const diff = Date.now() - a.timestamp;
|
|
31
|
+
console.log(diff < 120000 ? 'busy' : 'idle');
|
|
32
|
+
} catch { console.log('idle'); }
|
|
33
|
+
" 2>/dev/null)
|
|
34
|
+
if [ "$IDLE_CHECK" = "busy" ]; then
|
|
35
|
+
exit 0
|
|
36
|
+
fi
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# Use canonical scanner — single source of truth for task status detection
|
|
40
|
+
node "$(npm root -g)/exe-os/dist/bin/scan-tasks.js" "exe/$AGENT" --format=mandatory 2>/dev/null
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**If the script outputs task info:** read the task file and begin working immediately. Do not ask what to do.
|
|
44
|
+
**If the script outputs nothing:** no tasks — stay silent.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Delete memories by ID, agent, or search query
|
|
3
|
+
allowed-tools: Bash
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Delete memories from the local database. Requires confirmation before deletion.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
- `/exe-forget --id <memory-id>` — delete a single memory by ID
|
|
10
|
+
- `/exe-forget --agent <name>` — delete all memories for an employee
|
|
11
|
+
- `/exe-forget --query "<search>"` — delete memories matching a search query
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
node "$(npm root -g)/exe-os/dist/bin/exe-forget.js" "$ARGUMENTS"
|
|
15
|
+
```
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Proactive check — scan for notifications, stale tasks, and error spikes
|
|
3
|
+
allowed-tools: Bash, Read, Glob, recall_my_memory, ask_team_memory
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Heartbeat — Proactive Status Check
|
|
7
|
+
|
|
8
|
+
You are exe running a background heartbeat. Be SILENT unless something needs attention. Do NOT output anything if everything is fine.
|
|
9
|
+
|
|
10
|
+
## Check 1: Unread notifications
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
node -e "
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const dir = require('os').homedir() + '/.exe-os/notifications/';
|
|
16
|
+
try {
|
|
17
|
+
const files = fs.readdirSync(dir).filter(f => f.endsWith('.json'));
|
|
18
|
+
const unread = files.map(f => {
|
|
19
|
+
try { return JSON.parse(fs.readFileSync(dir + f, 'utf8')); } catch { return null; }
|
|
20
|
+
}).filter(n => n && !n.read);
|
|
21
|
+
if (unread.length > 0) {
|
|
22
|
+
console.log('UNREAD:' + JSON.stringify(unread));
|
|
23
|
+
// Mark as read so they don't repeat on next heartbeat
|
|
24
|
+
files.forEach(f => {
|
|
25
|
+
try {
|
|
26
|
+
const full = dir + f;
|
|
27
|
+
const n = JSON.parse(fs.readFileSync(full, 'utf8'));
|
|
28
|
+
if (!n.read) { n.read = true; fs.writeFileSync(full, JSON.stringify(n, null, 2)); }
|
|
29
|
+
} catch {}
|
|
30
|
+
});
|
|
31
|
+
} else {
|
|
32
|
+
console.log('HEARTBEAT_OK_NOTIFICATIONS');
|
|
33
|
+
}
|
|
34
|
+
} catch { console.log('HEARTBEAT_OK_NOTIFICATIONS'); }
|
|
35
|
+
"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Check 2: Stale tasks (open > 24h)
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
node -e "
|
|
42
|
+
const fs = require('fs');
|
|
43
|
+
const glob = require('path');
|
|
44
|
+
const home = require('os').homedir();
|
|
45
|
+
const dir = home + '/.exe-os/';
|
|
46
|
+
// Check task files across known project directories
|
|
47
|
+
try {
|
|
48
|
+
const { createClient } = require('@libsql/client');
|
|
49
|
+
const key = fs.readFileSync(dir + 'master.key', 'utf8').trim();
|
|
50
|
+
const client = createClient({ url: 'file:' + dir + 'memories.db', encryptionKey: key });
|
|
51
|
+
client.execute(\"SELECT id, title, assigned_to, project_name, created_at FROM tasks WHERE status = 'open'\").then(r => {
|
|
52
|
+
const now = Date.now();
|
|
53
|
+
const stale = r.rows.filter(row => (now - new Date(String(row.created_at)).getTime()) > 86400000);
|
|
54
|
+
if (stale.length > 0) {
|
|
55
|
+
console.log('STALE:' + JSON.stringify(stale.map(s => ({ title: s.title, assignee: s.assigned_to, project: s.project_name, age_hours: Math.round((now - new Date(String(s.created_at)).getTime()) / 3600000) }))));
|
|
56
|
+
} else {
|
|
57
|
+
console.log('HEARTBEAT_OK_TASKS');
|
|
58
|
+
}
|
|
59
|
+
}).catch(() => console.log('HEARTBEAT_OK_TASKS'));
|
|
60
|
+
} catch { console.log('HEARTBEAT_OK_TASKS'); }
|
|
61
|
+
"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Check 3: Recent error spikes
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
ls -t ~/.exe-os/notifications/*error_spike* 2>/dev/null | head -5 | while read f; do
|
|
68
|
+
age=$((( $(date +%s) - $(stat -f %m "$f") )))
|
|
69
|
+
if [ "$age" -lt 3600 ]; then
|
|
70
|
+
cat "$f"
|
|
71
|
+
fi
|
|
72
|
+
done || echo "HEARTBEAT_OK_ERRORS"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Evaluate results
|
|
76
|
+
|
|
77
|
+
After running all three checks:
|
|
78
|
+
|
|
79
|
+
- If ALL checks returned `HEARTBEAT_OK_*` — output NOTHING. Stay completely silent. The user doesn't need to know you checked.
|
|
80
|
+
- If ANY check found something, output a brief summary. Format:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
--- exe heartbeat ---
|
|
84
|
+
[what needs attention — keep it to 1-3 lines]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Examples:
|
|
88
|
+
- `yoshi completed 2 tasks in exe-os`
|
|
89
|
+
- `3 stale tasks: "fix auth" (yoshi, 36h), "brand update" (mari, 28h), "deploy fix" (yoshi, 25h)`
|
|
90
|
+
- `error spike: yoshi hit 18 errors in exe-create (45m ago)`
|
|
91
|
+
|
|
92
|
+
Do NOT explain what the heartbeat is. Do NOT say "everything is fine." If nothing needs attention, produce zero output.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Receive dispatched task via tmux send-keys and begin working
|
|
3
|
+
allowed-tools: Bash
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Intercom — Task Dispatch Receiver
|
|
7
|
+
|
|
8
|
+
Triggered by exe via `tmux send-keys -t {window} '/exe-intercom' Enter`. Scans the employee's task folder and starts working immediately if tasks exist.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
# Detect agent from EXE_SESSION_NAME env var or tmux session name
|
|
12
|
+
if [ -n "$EXE_SESSION_NAME" ]; then
|
|
13
|
+
AGENT=$(echo "$EXE_SESSION_NAME" | sed -E 's/-exe[0-9]+$//; s/[0-9]+$//')
|
|
14
|
+
elif [ -n "$TMUX" ]; then
|
|
15
|
+
AGENT=$(tmux display-message -p '#{session_name}' 2>/dev/null | sed -E 's/-exe[0-9]+$//; s/[0-9]+$//')
|
|
16
|
+
else
|
|
17
|
+
AGENT="UNKNOWN"
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
# Skip if no agent
|
|
21
|
+
if [ "$AGENT" = "UNKNOWN" ] || [ "$AGENT" = "default" ]; then
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# Exe gets review notifications instead of task dispatch
|
|
26
|
+
if [ "$AGENT" = "exe" ]; then
|
|
27
|
+
node "$(npm root -g)/exe-os/dist/bin/exe-pending-reviews.js" 2>/dev/null
|
|
28
|
+
# Exe also subscribes to notifications (subtasks_complete, task_complete, etc.)
|
|
29
|
+
# so parent-of-parent rollups surface live instead of only at boot.
|
|
30
|
+
node "$(npm root -g)/exe-os/dist/bin/exe-pending-notifications.js" "$AGENT" 2>/dev/null
|
|
31
|
+
exit 0
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
# Use canonical scanner — single source of truth for task status detection
|
|
35
|
+
node "$(npm root -g)/exe-os/dist/bin/scan-tasks.js" "exe/$AGENT" --format=mandatory 2>/dev/null
|
|
36
|
+
|
|
37
|
+
# Check for pending messages
|
|
38
|
+
node "$(npm root -g)/exe-os/dist/bin/exe-pending-messages.js" "$AGENT" 2>/dev/null
|
|
39
|
+
|
|
40
|
+
# Check for pending notifications (subtasks_complete, rollup signals, etc.)
|
|
41
|
+
# Employees acting as parent-of-parents (e.g. yoshi holding multiple parent
|
|
42
|
+
# tasks) need these too — not only exe. See the parent-cascade audit §6.
|
|
43
|
+
node "$(npm root -g)/exe-os/dist/bin/exe-pending-notifications.js" "$AGENT" 2>/dev/null
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### For exe (AGENT=exe)
|
|
47
|
+
**If output shows `[REVIEW NOTIFICATIONS]` and you are idle (no active conversation):** start reviewing immediately. Run `/exe-review`. Do not ask the founder for permission.
|
|
48
|
+
**If output shows `[REVIEW NOTIFICATIONS]` and the founder is mid-conversation:** note them briefly and continue. Review after the current topic concludes.
|
|
49
|
+
**If output is empty:** no pending reviews — stay silent.
|
|
50
|
+
|
|
51
|
+
### For employees (all other agents)
|
|
52
|
+
**If output starts with "MANDATORY:"** — you are idle. Read the task file and begin working immediately. Do not ask what to do.
|
|
53
|
+
**If output starts with "Continue working on:"** — you are already busy. Finish your current task first. Task chaining will pick up the next task automatically.
|
|
54
|
+
**If output is empty:** no tasks — stay silent.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Context-full intercom format
|
|
59
|
+
|
|
60
|
+
When an employee's context window fills, they send this intercom to exe before stopping:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
/exe-intercom context-full: <name> hit capacity. Checkpoint saved. Resume task <task-id>.
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**What exe does when it receives this:**
|
|
67
|
+
1. **Verify before killing.** Call `verifyPaneAtCapacity(sessionName)` from `src/lib/tmux-routing.ts`. It captures the last 200 lines of the employee's pane and runs the filtered capacity matcher.
|
|
68
|
+
- If `atCapacity: false`: the intercom is a false positive (pane echo, rendered skill doc, RESUME banner matching the intercom syntax). Do NOT kill. Send a nudge via `tmux send-keys`: `"False context-full detected (reason: <result.reason>). Continue working. If intentional, explain trigger."` Report to founder and stop.
|
|
69
|
+
- If `atCapacity: true`: proceed to step 2.
|
|
70
|
+
2. Kill the employee's session: `tmux kill-session -t <name>-<exe-session>`
|
|
71
|
+
3. Create a resume task via `create_task` (auto-dispatches a fresh session)
|
|
72
|
+
4. Report to founder
|
|
73
|
+
|
|
74
|
+
**What the employee does before sending this:**
|
|
75
|
+
1. `store_memory` with text starting `"CONTEXT CHECKPOINT [<task-id>]: ..."` — captures current state
|
|
76
|
+
2. Send the context-full intercom to exe
|
|
77
|
+
3. Stop — do not continue working
|
|
78
|
+
|
|
79
|
+
**What the resumed session does on boot:**
|
|
80
|
+
1. `recall_my_memory("CONTEXT CHECKPOINT [<task-id>]")` — retrieves exact state
|
|
81
|
+
2. Continues from where the previous session stopped
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Stop an employee's tmux session
|
|
3
|
+
allowed-tools: Bash
|
|
4
|
+
argument-hint: [employee-name]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Kill the tmux session for the named employee.
|
|
8
|
+
|
|
9
|
+
Delegates to `exe-kill` so the manual kill is recorded in `session_kills`
|
|
10
|
+
telemetry (SL-4 Phase 1) before tmux tears the session down. Falls back to
|
|
11
|
+
the raw tmux path when `exe-kill` is not on PATH (older installs).
|
|
12
|
+
|
|
13
|
+
Run:
|
|
14
|
+
```bash
|
|
15
|
+
NAME="$ARGUMENTS"
|
|
16
|
+
if command -v exe-kill >/dev/null 2>&1; then
|
|
17
|
+
exe-kill "${NAME}"
|
|
18
|
+
else
|
|
19
|
+
EXE_SESSION=$(tmux display-message -p '#{session_name}' 2>/dev/null)
|
|
20
|
+
TARGET="${NAME}-${EXE_SESSION}"
|
|
21
|
+
if tmux has-session -t "${TARGET}" 2>/dev/null; then
|
|
22
|
+
tmux kill-session -t "${TARGET}"
|
|
23
|
+
echo "Session '${TARGET}' killed."
|
|
24
|
+
elif tmux list-sessions -F '#{session_name}' 2>/dev/null | grep -q "^${NAME}-"; then
|
|
25
|
+
MATCH=$(tmux list-sessions -F '#{session_name}' 2>/dev/null | grep "^${NAME}-" | head -1)
|
|
26
|
+
tmux kill-session -t "${MATCH}"
|
|
27
|
+
echo "Session '${MATCH}' killed."
|
|
28
|
+
else
|
|
29
|
+
echo "No active session found for '${NAME}'."
|
|
30
|
+
fi
|
|
31
|
+
fi
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Report the result to the user.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Spawn employee sessions in tmux for parallel autonomous work
|
|
3
|
+
allowed-tools: Bash
|
|
4
|
+
argument-hint: [employee names...]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Launch one or more employees as detached tmux sessions. Each session uses `ensureEmployee()` — checks if alive first, spawns if not.
|
|
8
|
+
|
|
9
|
+
**Prerequisites:** Must be inside a tmux session. Claude Code CLI must be in PATH.
|
|
10
|
+
|
|
11
|
+
1. First, verify we're inside tmux:
|
|
12
|
+
```bash
|
|
13
|
+
# Robust tmux detection — handles su/sudo login shells (env vars stripped)
|
|
14
|
+
([ -n "$TMUX" ] || [ -n "$TMUX_PANE" ] || [[ "$TERM" == tmux* ]] || [[ "$TERM" == screen* ]] || tmux display-message -p '#{session_name}' >/dev/null 2>&1) && echo "TMUX_OK" || echo "TMUX_MISSING"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
If TMUX_MISSING, tell the user:
|
|
18
|
+
```
|
|
19
|
+
tmux is required. Start a tmux session first:
|
|
20
|
+
tmux new-session -s work
|
|
21
|
+
claude
|
|
22
|
+
/exe
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
2. Load the employee roster and validate all names from $ARGUMENTS:
|
|
26
|
+
```bash
|
|
27
|
+
cat ~/.exe-os/exe-employees.json 2>/dev/null || echo "NO_ROSTER"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
For each name in $ARGUMENTS, verify it exists in the roster. If any name is not found, report it and skip that name.
|
|
31
|
+
|
|
32
|
+
3. For each validated employee name, ensure they're running via `ensureEmployee()`:
|
|
33
|
+
```bash
|
|
34
|
+
NAME="<employee>"
|
|
35
|
+
EXE_SESSION=$(tmux display-message -p '#{session_name}' 2>/dev/null)
|
|
36
|
+
RESULT=$(node -e "const {ensureEmployee}=require('$(npm root -g)/exe-os/dist/lib/tmux-routing.js'); const r=ensureEmployee('${NAME}','${EXE_SESSION}','$(pwd)'); console.log(JSON.stringify(r));")
|
|
37
|
+
echo "${NAME}: ${RESULT}"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
4. After all sessions are spawned, show a summary:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
## Launched Sessions
|
|
44
|
+
|
|
45
|
+
| Employee | Session | Log |
|
|
46
|
+
|----------|---------|-----|
|
|
47
|
+
| bob | bob-exe1 | ~/.exe-os/session-logs/bob-1234567890.log |
|
|
48
|
+
| tom | tom-exe1 | ~/.exe-os/session-logs/tom-1234567890.log |
|
|
49
|
+
|
|
50
|
+
Use `/exe-sessions` to monitor, `/exe-logs <name>` to tail output, `/exe-kill <name>` to stop.
|
|
51
|
+
Switch sessions: Ctrl-b s (session picker)
|
|
52
|
+
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Link another device by exporting or importing your encryption key
|
|
3
|
+
allowed-tools: Bash
|
|
4
|
+
argument-hint: [export|import]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
**Deprecated:** Use `/exe-cloud` instead — it handles key import AND cloud sync in one step.
|
|
8
|
+
|
|
9
|
+
- `/exe-cloud` — full setup (key + cloud)
|
|
10
|
+
- `/exe-cloud sync` — export everything for a new device
|
|
11
|
+
- `/exe-cloud status` — check sync status
|
|
12
|
+
|
|
13
|
+
Legacy command still works:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
node "$(npm root -g)/exe-os/dist/bin/exe-link.js" $ARGUMENTS
|
|
17
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Tail recent output from an employee's session log
|
|
3
|
+
allowed-tools: Bash
|
|
4
|
+
argument-hint: [employee-name]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Show the last 50 lines from the most recent session log for the named employee.
|
|
8
|
+
|
|
9
|
+
Run:
|
|
10
|
+
```bash
|
|
11
|
+
NAME="$ARGUMENTS"
|
|
12
|
+
LOG=$(ls -t ~/.exe-os/session-logs/${NAME}-*.log 2>/dev/null | head -1)
|
|
13
|
+
if [ -n "$LOG" ]; then
|
|
14
|
+
echo "Log: $LOG"
|
|
15
|
+
echo "---"
|
|
16
|
+
tail -50 "$LOG"
|
|
17
|
+
else
|
|
18
|
+
echo "No session logs found for ${NAME}. Has the employee been launched with /exe-launch?"
|
|
19
|
+
fi
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Show the output to the user. If the log is empty or the employee hasn't been launched, say so.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Create a new employee with optional template (yoshi, mari, gen)
|
|
3
|
+
allowed-tools: Bash
|
|
4
|
+
argument-hint: <name> [--template <template>]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Create a new named employee for the exe-os system.
|
|
8
|
+
|
|
9
|
+
Run this command:
|
|
10
|
+
```bash
|
|
11
|
+
node "$(npm root -g)/exe-os/dist/bin/exe-new-employee.js" $ARGUMENTS
|
|
12
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Review a specialist's most recent session and verify completions
|
|
3
|
+
allowed-tools: Bash
|
|
4
|
+
argument-hint: <employee-name>
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
After a specialist session ends, run this to have exe review the session.
|
|
8
|
+
Exe will analyze the specialist's recent work, verify completions, and
|
|
9
|
+
update organizational memory with the outcomes.
|
|
10
|
+
|
|
11
|
+
Run this command:
|
|
12
|
+
```bash
|
|
13
|
+
node "$(npm root -g)/exe-os/dist/bin/exe-review.js" $ARGUMENTS
|
|
14
|
+
```
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Create, list, or delete scheduled recurring jobs
|
|
3
|
+
allowed-tools: Bash, Read, CronCreate, CronDelete
|
|
4
|
+
argument-hint: "<time> <description>" | list | delete <id>
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Manage time-based recurring jobs. Schedules persist in the DB and are re-registered on boot.
|
|
8
|
+
|
|
9
|
+
## Parse $ARGUMENTS
|
|
10
|
+
|
|
11
|
+
Determine the action:
|
|
12
|
+
|
|
13
|
+
- `list` → show all active schedules
|
|
14
|
+
- `delete <id>` → remove a schedule
|
|
15
|
+
- `run <id>` → execute a schedule's prompt immediately
|
|
16
|
+
- `"<time>" "<description>"` → create a new schedule
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Action: list
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
node -e "
|
|
24
|
+
const {initStore}=require(require('path').join(require('child_process').execSync('npm root -g',{encoding:'utf8'}).trim(),'exe-os/dist/lib/store.js'));
|
|
25
|
+
const {listSchedules}=require(require('path').join(require('child_process').execSync('npm root -g',{encoding:'utf8'}).trim(),'exe-os/dist/lib/schedules.js'));
|
|
26
|
+
(async()=>{
|
|
27
|
+
await initStore();
|
|
28
|
+
const schedules=await listSchedules();
|
|
29
|
+
if(schedules.length===0){console.log('No active schedules.');return;}
|
|
30
|
+
console.log('ID | Cron | Type | Description');
|
|
31
|
+
console.log('---------|------------------|---------|------------------');
|
|
32
|
+
for(const s of schedules){
|
|
33
|
+
console.log(s.id.padEnd(9)+'| '+s.cron.padEnd(17)+'| '+s.jobType.padEnd(8)+'| '+s.description);
|
|
34
|
+
}
|
|
35
|
+
})().catch(e=>console.error(e.message))
|
|
36
|
+
" 2>/dev/null
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Print the output as-is.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Action: delete <id>
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
ID="<extracted-id>"
|
|
47
|
+
node -e "
|
|
48
|
+
const {initStore}=require(require('path').join(require('child_process').execSync('npm root -g',{encoding:'utf8'}).trim(),'exe-os/dist/lib/store.js'));
|
|
49
|
+
const {deleteSchedule}=require(require('path').join(require('child_process').execSync('npm root -g',{encoding:'utf8'}).trim(),'exe-os/dist/lib/schedules.js'));
|
|
50
|
+
(async()=>{
|
|
51
|
+
await initStore();
|
|
52
|
+
const ok=await deleteSchedule('${ID}');
|
|
53
|
+
console.log(ok?'Schedule ${ID} deleted.':'Schedule ${ID} not found.');
|
|
54
|
+
})().catch(e=>console.error(e.message))
|
|
55
|
+
" 2>/dev/null
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Action: create
|
|
61
|
+
|
|
62
|
+
1. Parse the time expression from $ARGUMENTS. The first quoted string or recognizable time expression is the schedule, the rest is the description.
|
|
63
|
+
|
|
64
|
+
2. Convert to cron using the built-in parser:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
TIME_EXPR="<extracted-time>"
|
|
68
|
+
node -e "
|
|
69
|
+
const {parseHumanCron}=require(require('path').join(require('child_process').execSync('npm root -g',{encoding:'utf8'}).trim(),'exe-os/dist/lib/schedules.js'));
|
|
70
|
+
console.log(parseHumanCron('${TIME_EXPR}'))
|
|
71
|
+
" 2>/dev/null
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
3. Determine job type:
|
|
75
|
+
- If description mentions "test", "build", "deploy" → type: "work", assigned_to: "yoshi"
|
|
76
|
+
- If description mentions "report", "summary", "status" → type: "report"
|
|
77
|
+
- If description mentions "sync", "backfill", "clean" → type: "maintenance"
|
|
78
|
+
- Default: "report"
|
|
79
|
+
|
|
80
|
+
4. Ask the user: "Should this job survive session restarts? (Uses system crontab)"
|
|
81
|
+
- If yes: `use_crontab = true`
|
|
82
|
+
- If no: `use_crontab = false` (re-registered on boot via CronCreate)
|
|
83
|
+
|
|
84
|
+
5. Create the schedule:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
CRON="<cron-expression>"
|
|
88
|
+
DESC="<description>"
|
|
89
|
+
TYPE="<job-type>"
|
|
90
|
+
CRONTAB="<0-or-1>"
|
|
91
|
+
node -e "
|
|
92
|
+
const {initStore}=require(require('path').join(require('child_process').execSync('npm root -g',{encoding:'utf8'}).trim(),'exe-os/dist/lib/store.js'));
|
|
93
|
+
const {createSchedule}=require(require('path').join(require('child_process').execSync('npm root -g',{encoding:'utf8'}).trim(),'exe-os/dist/lib/schedules.js'));
|
|
94
|
+
(async()=>{
|
|
95
|
+
await initStore();
|
|
96
|
+
const s=await createSchedule({cron:'${CRON}',description:'${DESC}',jobType:'${TYPE}',useCrontab:${CRONTAB}===1});
|
|
97
|
+
console.log('Schedule created: '+s.id);
|
|
98
|
+
console.log('Cron: '+s.cron);
|
|
99
|
+
console.log('Type: '+s.jobType);
|
|
100
|
+
console.log('Crontab: '+(s.useCrontab?'yes (survives restarts)':'no (session-scoped, re-registered on boot)'));
|
|
101
|
+
})().catch(e=>console.error(e.message))
|
|
102
|
+
" 2>/dev/null
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
6. If not using crontab, register with CronCreate now:
|
|
106
|
+
- Use CronCreate with the cron expression and the description as the prompt
|
|
107
|
+
|
|
108
|
+
Report the result to the user.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Search your memories for relevant past work
|
|
3
|
+
allowed-tools: Bash
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Search your memories using keywords. Returns the most relevant past tool calls, errors, and outputs.
|
|
7
|
+
|
|
8
|
+
Usage: `/exe-search <query>`
|
|
9
|
+
|
|
10
|
+
Run this command with the user's query:
|
|
11
|
+
```bash
|
|
12
|
+
node "$(npm root -g)/exe-os/dist/bin/exe-search.js" "$ARGUMENTS"
|
|
13
|
+
```
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Show running employee tmux sessions
|
|
3
|
+
allowed-tools: Bash
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
List all active employee sessions.
|
|
7
|
+
|
|
8
|
+
Run:
|
|
9
|
+
```bash
|
|
10
|
+
tmux list-sessions -F '#{session_name} #{session_windows} #{?session_attached,(attached),}' 2>/dev/null || echo "NOT_IN_TMUX"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
If NOT_IN_TMUX, say: "Not in a tmux session. Use `tmux new-session -s work` to start one."
|
|
14
|
+
|
|
15
|
+
Format the output as a table. Employee sessions follow the naming convention `{name}-{exeSession}` (e.g., `yoshi-exe1`). Filter to only show sessions that match this pattern.
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
## Active Employee Sessions
|
|
19
|
+
|
|
20
|
+
| Session | Employee | Parent Exe | Status |
|
|
21
|
+
|---------|----------|------------|--------|
|
|
22
|
+
|
|
23
|
+
Use `/exe-launch <names>` to start, `/exe-logs <name>` to tail output, `/exe-kill <name>` to stop.
|
|
24
|
+
Switch sessions: Ctrl-b s (session picker)
|
|
25
|
+
```
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: settings
|
|
3
|
+
description: Configure exe-os memory system settings
|
|
4
|
+
allowed-tools: Bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Configure auto-ingestion, auto-retrieval, and search mode.
|
|
8
|
+
|
|
9
|
+
Run this command to open the settings menu:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
node "$(npm root -g)/exe-os/dist/bin/exe-settings.js"
|
|
13
|
+
```
|