create-yonderclaw 1.0.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.
Files changed (93) hide show
  1. package/LICENSE +44 -0
  2. package/README.md +288 -0
  3. package/bin/create-yonderclaw.mjs +43 -0
  4. package/docs/assets/favicon.png +0 -0
  5. package/docs/assets/metaclaw-banner.svg +86 -0
  6. package/docs/assets/qis-logo.png +0 -0
  7. package/docs/assets/yz-favicon.png +0 -0
  8. package/docs/assets/yz-logo.png +0 -0
  9. package/docs/index.html +1155 -0
  10. package/installer/assets/favicon.png +0 -0
  11. package/installer/auto-start.ts +330 -0
  12. package/installer/brand.ts +115 -0
  13. package/installer/core-scaffold.ts +448 -0
  14. package/installer/dashboard-generator.ts +657 -0
  15. package/installer/detect.ts +129 -0
  16. package/installer/index.ts +355 -0
  17. package/installer/module-loader.ts +412 -0
  18. package/installer/modules/boardroom/boardroom/client.ts.txt +201 -0
  19. package/installer/modules/boardroom/boardroom/db.ts.txt +322 -0
  20. package/installer/modules/boardroom/boardroom/meeting-agent.ts.txt +129 -0
  21. package/installer/modules/boardroom/boardroom/meeting-scheduler.ts.txt +194 -0
  22. package/installer/modules/boardroom/boardroom/server.ts.txt +473 -0
  23. package/installer/modules/boardroom/boardroom/start-boardroom.bat.txt +26 -0
  24. package/installer/modules/boardroom/boardroom/summons.ts.txt +76 -0
  25. package/installer/modules/boardroom/boardroom/turn-v2.ts.txt +172 -0
  26. package/installer/modules/boardroom/boardroom/turn.ts.txt +208 -0
  27. package/installer/modules/boardroom/boardroom/types.ts.txt +100 -0
  28. package/installer/modules/boardroom/metaclaw-module.json +35 -0
  29. package/installer/modules/boardroom/scripts/meeting-check.bat.txt +38 -0
  30. package/installer/modules/core/metaclaw-module.json +51 -0
  31. package/installer/modules/core/src/db.ts.txt +277 -0
  32. package/installer/modules/core/src/health-check.ts.txt +128 -0
  33. package/installer/modules/core/src/observability.ts.txt +20 -0
  34. package/installer/modules/core/src/safety.ts.txt +26 -0
  35. package/installer/modules/core/src/scan-capabilities.ts.txt +196 -0
  36. package/installer/modules/core/src/self-improve.ts.txt +48 -0
  37. package/installer/modules/core/src/self-update.ts.txt +345 -0
  38. package/installer/modules/core/src/sync-context.ts.txt +133 -0
  39. package/installer/modules/core/src/tasks.ts.txt +159 -0
  40. package/installer/modules/custom/metaclaw-module.json +15 -0
  41. package/installer/modules/custom/src/agent-custom.ts.txt +100 -0
  42. package/installer/modules/dashboard/metaclaw-module.json +23 -0
  43. package/installer/modules/dashboard/scripts/build-dashboard.cjs.txt +51 -0
  44. package/installer/modules/dashboard/src/update-dashboard.ts.txt +126 -0
  45. package/installer/modules/outreach/metaclaw-module.json +29 -0
  46. package/installer/modules/outreach/src/agent-outreach.ts.txt +193 -0
  47. package/installer/modules/outreach/src/inbox-agent.ts.txt +283 -0
  48. package/installer/modules/outreach/src/morning-report.ts.txt +124 -0
  49. package/installer/modules/research/metaclaw-module.json +15 -0
  50. package/installer/modules/research/src/agent-research.ts.txt +127 -0
  51. package/installer/modules/scheduler/metaclaw-module.json +27 -0
  52. package/installer/modules/scheduler/scripts/agent-cycle.bat.txt +85 -0
  53. package/installer/modules/scheduler/scripts/detect-session.bat.txt +41 -0
  54. package/installer/modules/scheduler/scripts/launch.bat.txt +120 -0
  55. package/installer/modules/scheduler/src/cron-manager.ts.txt +273 -0
  56. package/installer/modules/social/metaclaw-module.json +15 -0
  57. package/installer/modules/social/src/agent-social.ts.txt +110 -0
  58. package/installer/modules/support/metaclaw-module.json +15 -0
  59. package/installer/modules/support/src/agent-support.ts.txt +60 -0
  60. package/installer/modules/swarm/metaclaw-module.json +25 -0
  61. package/installer/modules/swarm/swarm/dht-client.ts.txt +376 -0
  62. package/installer/modules/swarm/swarm/relay-server.ts.txt +348 -0
  63. package/installer/modules/swarm/swarm/swarm-client.ts.txt +303 -0
  64. package/installer/modules/swarm/swarm/types.ts.txt +51 -0
  65. package/installer/modules/voice/metaclaw-module.json +16 -0
  66. package/installer/questionnaire.ts +277 -0
  67. package/installer/research.ts +258 -0
  68. package/installer/scaffold-from-config.ts +270 -0
  69. package/installer/task-generator.ts +324 -0
  70. package/installer/templates/agent-custom.ts.txt +100 -0
  71. package/installer/templates/agent-cycle.bat.txt +19 -0
  72. package/installer/templates/agent-outreach.ts.txt +193 -0
  73. package/installer/templates/agent-research.ts.txt +127 -0
  74. package/installer/templates/agent-social.ts.txt +110 -0
  75. package/installer/templates/agent-support.ts.txt +60 -0
  76. package/installer/templates/build-dashboard.cjs.txt +51 -0
  77. package/installer/templates/cron-manager.ts.txt +273 -0
  78. package/installer/templates/dashboard.html.txt +450 -0
  79. package/installer/templates/db.ts.txt +277 -0
  80. package/installer/templates/detect-session.bat.txt +41 -0
  81. package/installer/templates/health-check.ts.txt +128 -0
  82. package/installer/templates/inbox-agent.ts.txt +283 -0
  83. package/installer/templates/launch.bat.txt +120 -0
  84. package/installer/templates/morning-report.ts.txt +124 -0
  85. package/installer/templates/observability.ts.txt +20 -0
  86. package/installer/templates/safety.ts.txt +26 -0
  87. package/installer/templates/self-improve.ts.txt +48 -0
  88. package/installer/templates/self-update.ts.txt +345 -0
  89. package/installer/templates/state.json.txt +33 -0
  90. package/installer/templates/system-context.json.txt +33 -0
  91. package/installer/templates/update-dashboard.ts.txt +126 -0
  92. package/package.json +31 -0
  93. package/setup.bat +178 -0
@@ -0,0 +1,41 @@
1
+ @echo off
2
+ setlocal enabledelayedexpansion
3
+ REM Detect the Claude Code session ID for this agent's project directory
4
+ REM Writes session ID to data\session-id.txt for reliable --resume launches
5
+
6
+ set "PROJECT_DIR=__PROJECT_DIR__"
7
+ set "SESSION_FILE=%PROJECT_DIR%\data\session-id.txt"
8
+
9
+ REM Encode the project path the way Claude does (replace \ and : with -)
10
+ set "ENCODED=%PROJECT_DIR:\=-%"
11
+ set "ENCODED=!ENCODED::=-!"
12
+ set "ENCODED=!ENCODED:~1!"
13
+
14
+ set "SESSION_DIR=%USERPROFILE%\.claude\projects\!ENCODED!"
15
+
16
+ REM Check if session directory exists
17
+ if not exist "!SESSION_DIR!" (
18
+ echo No Claude session found for this project yet.
19
+ echo Run Claude Code in this directory first, then run this script.
20
+ exit /b 1
21
+ )
22
+
23
+ REM Find the most recent .jsonl file (that's the session)
24
+ set "LATEST_SESSION="
25
+ set "LATEST_TIME=0"
26
+ for %%F in ("!SESSION_DIR!\*.jsonl") do (
27
+ set "FNAME=%%~nF"
28
+ set "LATEST_SESSION=!FNAME!"
29
+ )
30
+
31
+ if "!LATEST_SESSION!"=="" (
32
+ echo No session files found.
33
+ exit /b 1
34
+ )
35
+
36
+ REM Write session ID to file
37
+ echo !LATEST_SESSION!> "!SESSION_FILE!"
38
+ echo Session ID detected: !LATEST_SESSION!
39
+ echo Saved to: !SESSION_FILE!
40
+ echo.
41
+ echo Future launches will use: claude --resume !LATEST_SESSION!
@@ -0,0 +1,120 @@
1
+ @echo off
2
+ setlocal enabledelayedexpansion
3
+ title MetaClaw: __AGENT_NAME__
4
+
5
+ REM Ensure PATH includes Node.js and Claude
6
+ set PATH=C:\Program Files\nodejs;%USERPROFILE%\AppData\Roaming\npm;%USERPROFILE%\.local\bin;%PATH%
7
+
8
+ echo.
9
+ echo ==========================================
10
+ echo MetaClaw: __AGENT_NAME__
11
+ echo ==========================================
12
+ echo.
13
+
14
+ REM Set working directory
15
+ cd /d "__PROJECT_DIR__"
16
+
17
+ REM Find Claude executable (check npm install first, then .local)
18
+ set "CLAUDE_CMD="
19
+ if exist "%USERPROFILE%\AppData\Roaming\npm\claude.cmd" (
20
+ set "CLAUDE_CMD=%USERPROFILE%\AppData\Roaming\npm\claude.cmd"
21
+ ) else if exist "%USERPROFILE%\.local\bin\claude.exe" (
22
+ set "CLAUDE_CMD=%USERPROFILE%\.local\bin\claude.exe"
23
+ ) else (
24
+ where claude >nul 2>&1
25
+ if !ERRORLEVEL! equ 0 set "CLAUDE_CMD=claude"
26
+ )
27
+
28
+ if "!CLAUDE_CMD!"=="" (
29
+ echo [ERROR] Claude Code not found.
30
+ echo Install: https://claude.ai/download
31
+ pause
32
+ exit /b 1
33
+ )
34
+
35
+ REM Ensure authenticated
36
+ if not exist "%USERPROFILE%\.claude\.credentials.json" (
37
+ echo [!] Claude not logged in...
38
+ "!CLAUDE_CMD!" auth login
39
+ if not exist "%USERPROFILE%\.claude\.credentials.json" (
40
+ echo [ERROR] Authentication failed.
41
+ pause
42
+ exit /b 1
43
+ )
44
+ )
45
+
46
+ echo Directory: %CD%
47
+ echo.
48
+
49
+ REM === SESSION ID DETECTION ===
50
+ REM Check if we have a saved session ID (most reliable)
51
+ set "SESSION_ID="
52
+ if exist "data\session-id.txt" (
53
+ set /p SESSION_ID=<"data\session-id.txt"
54
+ REM Trim whitespace
55
+ for /f "tokens=* delims= " %%a in ("!SESSION_ID!") do set "SESSION_ID=%%a"
56
+ )
57
+
58
+ if not "!SESSION_ID!"=="" (
59
+ echo Resuming __AGENT_NAME__ (session: !SESSION_ID:~0,8!...)
60
+ echo.
61
+ "!CLAUDE_CMD!" --resume !SESSION_ID!
62
+ goto :post_session
63
+ )
64
+
65
+ REM No saved session — check if one exists in the project folder
66
+ set "ENCODED_PATH=__ENCODED_PATH__"
67
+ set "SESSION_DIR=%USERPROFILE%\.claude\projects\!ENCODED_PATH!"
68
+ set "FOUND_SESSION="
69
+
70
+ if exist "!SESSION_DIR!" (
71
+ for %%F in ("!SESSION_DIR!\*.jsonl") do (
72
+ set "FOUND_SESSION=%%~nF"
73
+ )
74
+ )
75
+
76
+ if not "!FOUND_SESSION!"=="" (
77
+ REM Save it for future launches
78
+ echo !FOUND_SESSION!> "data\session-id.txt"
79
+ echo Resuming __AGENT_NAME__ (detected session: !FOUND_SESSION:~0,8!...)
80
+ echo.
81
+ "!CLAUDE_CMD!" --resume !FOUND_SESSION!
82
+ goto :post_session
83
+ )
84
+
85
+ REM No session at all — first launch
86
+ echo First launch - initializing __AGENT_NAME__...
87
+ echo Claude will read CLAUDE.md and SOUL.md for context.
88
+ echo.
89
+ "!CLAUDE_CMD!" --name "__AGENT_NAME__"
90
+
91
+ REM After first launch, detect and save the session ID
92
+ if exist "!SESSION_DIR!" (
93
+ for %%F in ("!SESSION_DIR!\*.jsonl") do (
94
+ set "FOUND_SESSION=%%~nF"
95
+ )
96
+ if not "!FOUND_SESSION!"=="" (
97
+ echo !FOUND_SESSION!> "data\session-id.txt"
98
+ echo Session ID saved: !FOUND_SESSION:~0,8!...
99
+ )
100
+ )
101
+
102
+ :post_session
103
+ echo.
104
+ echo __AGENT_NAME__ session ended.
105
+ echo Press any key to relaunch (Ctrl+C to quit)...
106
+ pause >nul
107
+
108
+ REM Re-read session ID (may have been updated)
109
+ if exist "data\session-id.txt" (
110
+ set /p SESSION_ID=<"data\session-id.txt"
111
+ for /f "tokens=* delims= " %%a in ("!SESSION_ID!") do set "SESSION_ID=%%a"
112
+ )
113
+
114
+ if not "!SESSION_ID!"=="" (
115
+ echo Resuming __AGENT_NAME__...
116
+ "!CLAUDE_CMD!" --resume !SESSION_ID!
117
+ ) else (
118
+ "!CLAUDE_CMD!" --continue
119
+ )
120
+ goto :post_session
@@ -0,0 +1,273 @@
1
+ /**
2
+ * MetaClaw Cron Manager — manages scheduled tasks
3
+ * Auto-generated by MetaClaw Installer
4
+ *
5
+ * Handles:
6
+ * - Setting up initial crons (self-update, dashboard refresh, health check)
7
+ * - Listing active crons
8
+ * - Rescheduling crons
9
+ * - Removing crons
10
+ * - Health monitoring of cron execution
11
+ *
12
+ * Uses Windows Task Scheduler (schtasks) with proper error handling.
13
+ * All tasks use .bat wrappers for PATH reliability.
14
+ */
15
+
16
+ import { execSync } from "child_process";
17
+ import fs from "fs";
18
+ import path from "path";
19
+ import { fileURLToPath } from "url";
20
+ import { getDb, getConfig, setConfig } from "./db.js";
21
+ import { log } from "./observability.js";
22
+
23
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
24
+ const PROJECT_DIR = path.join(__dirname, "..");
25
+ const SCRIPTS_DIR = path.join(PROJECT_DIR, "scripts");
26
+ const AGENT_NAME = "__AGENT_NAME__";
27
+ const SESSION_NAME = "__SESSION_NAME__";
28
+
29
+ // Task prefix for all MetaClaw tasks
30
+ const TASK_PREFIX = `MetaClaw-${SESSION_NAME}`;
31
+
32
+ export type CronTask = {
33
+ name: string;
34
+ script: string;
35
+ intervalMinutes: number;
36
+ description: string;
37
+ businessHoursOnly: boolean;
38
+ };
39
+
40
+ // Default cron tasks every agent gets
41
+ export const DEFAULT_CRONS: CronTask[] = [
42
+ {
43
+ name: "SelfUpdate",
44
+ script: "src/self-update.ts",
45
+ intervalMinutes: __SELF_UPDATE_INTERVAL__,
46
+ description: "Self-improvement cycle (dashboard, prompts, logs, metrics)",
47
+ businessHoursOnly: false,
48
+ },
49
+ {
50
+ name: "DashboardRefresh",
51
+ script: "src/update-dashboard.ts",
52
+ intervalMinutes: 5,
53
+ description: "Refresh dashboard data",
54
+ businessHoursOnly: false,
55
+ },
56
+ {
57
+ name: "HealthCheck",
58
+ script: "src/health-check.ts",
59
+ intervalMinutes: 60,
60
+ description: "System health check (circuit breakers, disk, errors)",
61
+ businessHoursOnly: false,
62
+ },
63
+ ];
64
+
65
+ /**
66
+ * Create a .bat wrapper for a task (needed for schtasks PATH reliability).
67
+ */
68
+ function createBatWrapper(task: CronTask): string {
69
+ const batPath = path.join(SCRIPTS_DIR, `${task.name.toLowerCase()}.bat`);
70
+ const logPath = path.join(PROJECT_DIR, "data", "logs", `${task.name.toLowerCase()}.log`);
71
+
72
+ // Critical: Task Scheduler runs with minimal PATH — must set explicitly
73
+ const content = [
74
+ "@echo off",
75
+ `setlocal`,
76
+ `set PATH=C:\\Program Files\\nodejs;%USERPROFILE%\\AppData\\Roaming\\npm;%USERPROFILE%\\.local\\bin;%PATH%`,
77
+ `cd /d "${PROJECT_DIR}"`,
78
+ `echo [%DATE% %TIME%] Running ${task.name} >> "${logPath}"`,
79
+ `call npx tsx ${task.script} >> "${logPath}" 2>&1`,
80
+ `echo [%DATE% %TIME%] ${task.name} complete (exit: %ERRORLEVEL%) >> "${logPath}"`,
81
+ ].join("\r\n");
82
+
83
+ fs.mkdirSync(SCRIPTS_DIR, { recursive: true });
84
+ fs.writeFileSync(batPath, content);
85
+ return batPath;
86
+ }
87
+
88
+ /**
89
+ * Register a task with Windows Task Scheduler.
90
+ * Falls back gracefully if admin not available.
91
+ */
92
+ function registerTask(task: CronTask): { success: boolean; method: string; error?: string } {
93
+ const batPath = createBatWrapper(task);
94
+ const taskName = `${TASK_PREFIX}-${task.name}`;
95
+
96
+ // Build schtasks command
97
+ let schedArgs: string;
98
+ if (task.businessHoursOnly) {
99
+ schedArgs = `/sc MINUTE /mo ${task.intervalMinutes} /st 08:00 /et 18:00`;
100
+ } else {
101
+ schedArgs = `/sc MINUTE /mo ${task.intervalMinutes}`;
102
+ }
103
+
104
+ // Try Task Scheduler first
105
+ try {
106
+ execSync(
107
+ `schtasks /create /tn "${taskName}" /tr "\\"${batPath}\\"" ${schedArgs} /ru "%USERNAME%" /f`,
108
+ { stdio: "pipe", timeout: 10000 }
109
+ );
110
+ log("info", "cron.registered", { task: taskName, method: "schtasks", interval: task.intervalMinutes });
111
+ return { success: true, method: "schtasks" };
112
+ } catch {
113
+ // Task Scheduler failed (likely needs admin)
114
+ }
115
+
116
+ // Fallback: save to config for self-update to handle
117
+ try {
118
+ const cronConfig = JSON.parse(getConfig("cron_tasks") || "[]");
119
+ cronConfig.push({
120
+ name: task.name,
121
+ script: task.script,
122
+ intervalMinutes: task.intervalMinutes,
123
+ lastRun: null,
124
+ });
125
+ setConfig("cron_tasks", JSON.stringify(cronConfig));
126
+ log("info", "cron.registered", { task: task.name, method: "config_fallback", interval: task.intervalMinutes });
127
+ return { success: true, method: "config_fallback" };
128
+ } catch (err) {
129
+ const msg = err instanceof Error ? err.message : String(err);
130
+ return { success: false, method: "failed", error: msg };
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Set up all default cron tasks.
136
+ */
137
+ export function setupDefaultCrons(): { registered: number; failed: number; method: string } {
138
+ let registered = 0;
139
+ let failed = 0;
140
+ let method = "";
141
+
142
+ for (const task of DEFAULT_CRONS) {
143
+ const result = registerTask(task);
144
+ if (result.success) {
145
+ registered++;
146
+ method = result.method;
147
+ } else {
148
+ failed++;
149
+ }
150
+ }
151
+
152
+ setConfig("crons_initialized", "true");
153
+ setConfig("crons_method", method);
154
+ return { registered, failed, method };
155
+ }
156
+
157
+ /**
158
+ * List all MetaClaw scheduled tasks.
159
+ */
160
+ export function listCrons(): Array<{ name: string; status: string; nextRun: string }> {
161
+ const tasks: Array<{ name: string; status: string; nextRun: string }> = [];
162
+
163
+ try {
164
+ const output = execSync(
165
+ `schtasks /query /fo CSV /nh 2>nul | findstr "${TASK_PREFIX}"`,
166
+ { encoding: "utf-8", timeout: 5000 }
167
+ );
168
+ const lines = output.trim().split("\n").filter(Boolean);
169
+ for (const line of lines) {
170
+ const parts = line.split('","').map(s => s.replace(/"/g, ""));
171
+ if (parts.length >= 3) {
172
+ tasks.push({ name: parts[0], nextRun: parts[1], status: parts[2] });
173
+ }
174
+ }
175
+ } catch {
176
+ // No tasks found or schtasks not available
177
+ }
178
+
179
+ // Also check config fallback
180
+ try {
181
+ const cronConfig = JSON.parse(getConfig("cron_tasks") || "[]");
182
+ for (const c of cronConfig) {
183
+ if (!tasks.some(t => t.name.includes(c.name))) {
184
+ tasks.push({
185
+ name: `${TASK_PREFIX}-${c.name} (managed by self-update)`,
186
+ nextRun: c.lastRun ? `Last: ${c.lastRun}` : "Pending",
187
+ status: "Active (config)",
188
+ });
189
+ }
190
+ }
191
+ } catch {}
192
+
193
+ return tasks;
194
+ }
195
+
196
+ /**
197
+ * Remove a MetaClaw scheduled task.
198
+ */
199
+ export function removeCron(taskName: string): boolean {
200
+ const fullName = taskName.startsWith(TASK_PREFIX) ? taskName : `${TASK_PREFIX}-${taskName}`;
201
+ try {
202
+ execSync(`schtasks /delete /tn "${fullName}" /f`, { stdio: "pipe", timeout: 5000 });
203
+ log("info", "cron.removed", { task: fullName });
204
+ return true;
205
+ } catch {
206
+ // Try removing from config
207
+ try {
208
+ const cronConfig = JSON.parse(getConfig("cron_tasks") || "[]");
209
+ const filtered = cronConfig.filter((c: any) => !fullName.includes(c.name));
210
+ setConfig("cron_tasks", JSON.stringify(filtered));
211
+ return true;
212
+ } catch {
213
+ return false;
214
+ }
215
+ }
216
+ }
217
+
218
+ /**
219
+ * Run any config-based crons that are due (called by self-update).
220
+ */
221
+ export function runDueCrons(): number {
222
+ let ran = 0;
223
+ try {
224
+ const cronConfig = JSON.parse(getConfig("cron_tasks") || "[]");
225
+ const now = Date.now();
226
+
227
+ for (const c of cronConfig) {
228
+ const lastRun = c.lastRun ? new Date(c.lastRun).getTime() : 0;
229
+ const intervalMs = c.intervalMinutes * 60 * 1000;
230
+
231
+ if (now - lastRun >= intervalMs) {
232
+ try {
233
+ execSync(`npx tsx ${c.script}`, { cwd: PROJECT_DIR, stdio: "pipe", timeout: 60000 });
234
+ c.lastRun = new Date().toISOString();
235
+ ran++;
236
+ } catch (err) {
237
+ log("error", "cron.run_failed", { task: c.name, error: String(err) });
238
+ }
239
+ }
240
+ }
241
+
242
+ setConfig("cron_tasks", JSON.stringify(cronConfig));
243
+ } catch {}
244
+ return ran;
245
+ }
246
+
247
+ // --- CLI ---
248
+ if (process.argv[1]?.includes("cron-manager")) {
249
+ getDb();
250
+ const cmd = process.argv[2];
251
+
252
+ if (cmd === "setup") {
253
+ console.log("Setting up default cron tasks...\n");
254
+ const result = setupDefaultCrons();
255
+ console.log(`Registered: ${result.registered}, Failed: ${result.failed}`);
256
+ console.log(`Method: ${result.method}`);
257
+ } else if (cmd === "list") {
258
+ const tasks = listCrons();
259
+ console.log("Active cron tasks:\n");
260
+ for (const t of tasks) {
261
+ console.log(` ${t.name}`);
262
+ console.log(` Next: ${t.nextRun} | Status: ${t.status}`);
263
+ }
264
+ if (tasks.length === 0) console.log(" No tasks found. Run: npm run crons setup");
265
+ } else if (cmd === "remove" && process.argv[3]) {
266
+ removeCron(process.argv[3]) ? console.log("Removed.") : console.log("Not found.");
267
+ } else {
268
+ console.log("Cron Manager — MetaClaw");
269
+ console.log(" npm run crons setup — set up default crons");
270
+ console.log(" npm run crons list — list active crons");
271
+ console.log(" npm run crons remove <name> — remove a cron");
272
+ }
273
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "social",
3
+ "displayName": "Social Media Agent",
4
+ "version": "1.0.0",
5
+ "description": "Content creation, scheduling, engagement tracking, multi-platform posting",
6
+ "category": "agent-type",
7
+ "engines": { "metaclaw": ">=3.3.0" },
8
+ "requires": { "modules": ["core", "scheduler"] },
9
+ "contributes": {
10
+ "src": { "agent-social.ts.txt": "src/agent.ts" },
11
+ "npmScripts": { "start": "tsx src/agent.ts", "dry-run": "tsx src/agent.ts --dry-run" },
12
+ "claudeMd": ["social-commands"]
13
+ },
14
+ "placeholders": ["__AGENT_NAME__", "__SESSION_NAME__", "__SYSTEM_PROMPT__"]
15
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * __AGENT_NAME__ — Social Claw
3
+ * Generated by MetaClaw Installer v3.3.0
4
+ *
5
+ * Pipeline: research trends → generate content → schedule posts → monitor engagement
6
+ */
7
+
8
+ import { query } from "@anthropic-ai/claude-agent-sdk";
9
+ import type { SDKResultMessage, SDKResultSuccess, SDKAssistantMessage } from "@anthropic-ai/claude-agent-sdk";
10
+ import fs from "fs";
11
+ import path from "path";
12
+ import { fileURLToPath } from "url";
13
+ import { getDb, recordAction, getTodayMetrics, getCircuitBreaker, getConfig } from "./db.js";
14
+ import { checkCanAct } from "./safety.js";
15
+ import { log } from "./observability.js";
16
+ import { recordOutcome, getCurrentPrompt } from "./self-improve.js";
17
+ import { runSelfUpdate } from "./self-update.js";
18
+
19
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
20
+ const STATUS = process.argv.includes("--status");
21
+ const DRY_RUN = process.argv.includes("--dry-run");
22
+
23
+ if (STATUS) {
24
+ getDb();
25
+ const metrics = getTodayMetrics();
26
+ console.log("__AGENT_NAME__ Status");
27
+ console.log("=".repeat(40));
28
+ if (metrics) {
29
+ console.log("Today:", metrics.actions_taken, "posts created");
30
+ console.log("Cost: $" + (metrics.total_cost_usd || 0).toFixed(4));
31
+ } else {
32
+ console.log("No activity today.");
33
+ }
34
+ process.exit(0);
35
+ }
36
+
37
+ const DEFAULT_SYSTEM_PROMPT = `__SYSTEM_PROMPT__`;
38
+
39
+ async function main() {
40
+ getDb();
41
+ // NOTE: self-update runs AFTER task, NOT before (AXIOM Bug #1)
42
+
43
+ const topic = process.argv.slice(2).filter(a => !a.startsWith("--")).join(" ");
44
+
45
+ const safety = checkCanAct();
46
+ if (!safety.allowed) {
47
+ console.log("BLOCKED: " + safety.reason);
48
+ process.exit(0);
49
+ }
50
+
51
+ const systemPrompt = getCurrentPrompt("social") || DEFAULT_SYSTEM_PROMPT;
52
+
53
+ console.log("__AGENT_NAME__" + (DRY_RUN ? " (DRY RUN)" : ""));
54
+ log("info", "agent.start", { topic, dryRun: DRY_RUN });
55
+
56
+ // Generate content
57
+ const contentDir = path.join(__dirname, "..", "data", "content");
58
+ fs.mkdirSync(contentDir, { recursive: true });
59
+
60
+ try {
61
+ const stream = query({
62
+ prompt: topic
63
+ ? "Create a social media post about: " + topic + ". Research current trends first."
64
+ : "Research trending topics in our domain and create 3 social media posts. Include hooks, hashtags, and optimal posting times.",
65
+ options: {
66
+ systemPrompt,
67
+ allowedTools: ["WebSearch", "WebFetch"],
68
+ maxTurns: 15,
69
+ model: "claude-sonnet-4-6",
70
+ },
71
+ });
72
+
73
+ let content = "";
74
+ for await (const message of stream) {
75
+ if (message.type === "assistant") {
76
+ const msg = message as any;
77
+ if (msg.message?.content) {
78
+ for (const block of msg.message.content) {
79
+ if (block.type === "text") {
80
+ const text = block.text;
81
+ console.log(text);
82
+ content += text;
83
+ }
84
+ }
85
+ }
86
+ }
87
+ if (message.type === "result" && (message as any).subtype === "success") {
88
+ const s = message as SDKResultSuccess;
89
+ console.log("\nDone ($" + s.total_cost_usd.toFixed(4) + ")");
90
+ recordAction("content_creation", topic || "auto", "success", undefined, s.total_cost_usd);
91
+
92
+ if (!DRY_RUN && content.trim()) {
93
+ const filename = new Date().toISOString().slice(0, 10) + "-posts.md";
94
+ fs.writeFileSync(path.join(contentDir, filename), content);
95
+ console.log("Content saved: data/content/" + filename);
96
+ }
97
+
98
+ recordOutcome("social", 8);
99
+ }
100
+ }
101
+ } catch (err: unknown) {
102
+ const msg = err instanceof Error ? err.message : String(err);
103
+ log("error", "agent.error", { error: msg });
104
+ recordAction("content_creation", topic || "auto", "error", msg);
105
+ }
106
+ }
107
+
108
+ // Self-update AFTER task (never before)
109
+ try { await runSelfUpdate(); } catch { /* non-critical */ }
110
+ main();
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "support",
3
+ "displayName": "Support Agent",
4
+ "version": "1.0.0",
5
+ "description": "Inbox monitoring, ticket triage, auto-resolution, escalation",
6
+ "category": "agent-type",
7
+ "engines": { "metaclaw": ">=3.3.0" },
8
+ "requires": { "modules": ["core", "scheduler"] },
9
+ "contributes": {
10
+ "src": { "agent-support.ts.txt": "src/agent.ts" },
11
+ "npmScripts": { "start": "tsx src/agent.ts", "dry-run": "tsx src/agent.ts --dry-run" },
12
+ "claudeMd": ["support-commands"]
13
+ },
14
+ "placeholders": ["__AGENT_NAME__", "__SESSION_NAME__", "__SYSTEM_PROMPT__"]
15
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * __AGENT_NAME__ — Support Claw
3
+ * Generated by MetaClaw Installer v3.3.0
4
+ *
5
+ * Pipeline: monitor inbox → classify tickets → auto-respond or escalate → track
6
+ */
7
+
8
+ import { query } from "@anthropic-ai/claude-agent-sdk";
9
+ import type { SDKResultMessage, SDKResultSuccess, SDKAssistantMessage } from "@anthropic-ai/claude-agent-sdk";
10
+ import { getDb, recordAction, getTodayMetrics, getCircuitBreaker, getConfig } from "./db.js";
11
+ import { checkCanAct } from "./safety.js";
12
+ import { log } from "./observability.js";
13
+ import { recordOutcome, getCurrentPrompt } from "./self-improve.js";
14
+ import { runSelfUpdate } from "./self-update.js";
15
+
16
+ const STATUS = process.argv.includes("--status");
17
+
18
+ if (STATUS) {
19
+ getDb();
20
+ const metrics = getTodayMetrics();
21
+ const breaker = getCircuitBreaker("main");
22
+ console.log("__AGENT_NAME__ Status");
23
+ console.log("=".repeat(40));
24
+ console.log("Circuit breaker:", breaker?.state?.toUpperCase() || "CLOSED");
25
+ if (metrics) {
26
+ console.log("Today:", metrics.actions_taken, "tickets processed");
27
+ console.log("Cost: $" + (metrics.total_cost_usd || 0).toFixed(4));
28
+ } else {
29
+ console.log("No activity today.");
30
+ }
31
+ process.exit(0);
32
+ }
33
+
34
+ const DEFAULT_SYSTEM_PROMPT = `__SYSTEM_PROMPT__`;
35
+
36
+ async function main() {
37
+ getDb();
38
+ // NOTE: self-update runs AFTER task, NOT before (AXIOM Bug #1)
39
+
40
+ const safety = checkCanAct();
41
+ if (!safety.allowed) {
42
+ console.log("BLOCKED: " + safety.reason);
43
+ process.exit(0);
44
+ }
45
+
46
+ console.log("__AGENT_NAME__ — Support Claw");
47
+ console.log("Checking for incoming support requests...");
48
+ log("info", "agent.start", {});
49
+
50
+ // TODO: Wire in IMAP inbox monitoring for support email
51
+ // Classify incoming emails into: billing, technical, feature_request, bug, other
52
+ // Auto-respond to common questions using knowledge base
53
+ // Escalate complex issues to escalation email
54
+
55
+ console.log("Support agent ready. Configure IMAP in npm run setup to monitor inbox.");
56
+ }
57
+
58
+ // Self-update AFTER task (never before)
59
+ try { await runSelfUpdate(); } catch { /* non-critical */ }
60
+ main();
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "swarm",
3
+ "displayName": "QIS Intelligence Network",
4
+ "version": "1.0.0",
5
+ "description": "Shared intelligence buckets — local personal swarm + global MetaClaw network. The QIS proof of concept.",
6
+ "category": "intelligence",
7
+ "alwaysInstall": true,
8
+ "engines": { "metaclaw": ">=3.3.0" },
9
+ "requires": { "modules": ["core"] },
10
+ "contributes": {
11
+ "swarm": {
12
+ "types.ts.txt": "swarm/types.ts",
13
+ "swarm-client.ts.txt": "swarm/swarm-client.ts",
14
+ "relay-server.ts.txt": "swarm/relay-server.ts",
15
+ "dht-client.ts.txt": "swarm/dht-client.ts"
16
+ },
17
+ "npmScripts": {
18
+ "swarm-relay": "tsx swarm/relay-server.ts",
19
+ "swarm-stats": "tsx swarm/relay-server.ts --port 7891"
20
+ },
21
+ "claudeMd": ["swarm"],
22
+ "directories": ["swarm"]
23
+ },
24
+ "placeholders": ["__AGENT_NAME__", "__ENABLE_LOCAL__", "__ENABLE_GLOBAL__", "__RELAY_URL__"]
25
+ }