create-metaclaw 3.3.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 (92) hide show
  1. package/LICENSE +44 -0
  2. package/README.md +282 -0
  3. package/docs/assets/favicon.png +0 -0
  4. package/docs/assets/metaclaw-banner.svg +86 -0
  5. package/docs/assets/qis-logo.png +0 -0
  6. package/docs/assets/yz-favicon.png +0 -0
  7. package/docs/assets/yz-logo.png +0 -0
  8. package/docs/index.html +895 -0
  9. package/installer/assets/favicon.png +0 -0
  10. package/installer/auto-start.ts +330 -0
  11. package/installer/brand.ts +115 -0
  12. package/installer/core-scaffold.ts +448 -0
  13. package/installer/dashboard-generator.ts +657 -0
  14. package/installer/detect.ts +129 -0
  15. package/installer/index.ts +355 -0
  16. package/installer/module-loader.ts +412 -0
  17. package/installer/modules/boardroom/boardroom/client.ts.txt +201 -0
  18. package/installer/modules/boardroom/boardroom/db.ts.txt +322 -0
  19. package/installer/modules/boardroom/boardroom/meeting-agent.ts.txt +129 -0
  20. package/installer/modules/boardroom/boardroom/meeting-scheduler.ts.txt +194 -0
  21. package/installer/modules/boardroom/boardroom/server.ts.txt +473 -0
  22. package/installer/modules/boardroom/boardroom/start-boardroom.bat.txt +26 -0
  23. package/installer/modules/boardroom/boardroom/summons.ts.txt +76 -0
  24. package/installer/modules/boardroom/boardroom/turn-v2.ts.txt +172 -0
  25. package/installer/modules/boardroom/boardroom/turn.ts.txt +208 -0
  26. package/installer/modules/boardroom/boardroom/types.ts.txt +100 -0
  27. package/installer/modules/boardroom/metaclaw-module.json +35 -0
  28. package/installer/modules/boardroom/scripts/meeting-check.bat.txt +38 -0
  29. package/installer/modules/core/metaclaw-module.json +51 -0
  30. package/installer/modules/core/src/db.ts.txt +277 -0
  31. package/installer/modules/core/src/health-check.ts.txt +128 -0
  32. package/installer/modules/core/src/observability.ts.txt +20 -0
  33. package/installer/modules/core/src/safety.ts.txt +26 -0
  34. package/installer/modules/core/src/scan-capabilities.ts.txt +196 -0
  35. package/installer/modules/core/src/self-improve.ts.txt +48 -0
  36. package/installer/modules/core/src/self-update.ts.txt +345 -0
  37. package/installer/modules/core/src/sync-context.ts.txt +133 -0
  38. package/installer/modules/core/src/tasks.ts.txt +159 -0
  39. package/installer/modules/custom/metaclaw-module.json +15 -0
  40. package/installer/modules/custom/src/agent-custom.ts.txt +100 -0
  41. package/installer/modules/dashboard/metaclaw-module.json +23 -0
  42. package/installer/modules/dashboard/scripts/build-dashboard.cjs.txt +51 -0
  43. package/installer/modules/dashboard/src/update-dashboard.ts.txt +126 -0
  44. package/installer/modules/outreach/metaclaw-module.json +29 -0
  45. package/installer/modules/outreach/src/agent-outreach.ts.txt +193 -0
  46. package/installer/modules/outreach/src/inbox-agent.ts.txt +283 -0
  47. package/installer/modules/outreach/src/morning-report.ts.txt +124 -0
  48. package/installer/modules/research/metaclaw-module.json +15 -0
  49. package/installer/modules/research/src/agent-research.ts.txt +127 -0
  50. package/installer/modules/scheduler/metaclaw-module.json +27 -0
  51. package/installer/modules/scheduler/scripts/agent-cycle.bat.txt +85 -0
  52. package/installer/modules/scheduler/scripts/detect-session.bat.txt +41 -0
  53. package/installer/modules/scheduler/scripts/launch.bat.txt +120 -0
  54. package/installer/modules/scheduler/src/cron-manager.ts.txt +273 -0
  55. package/installer/modules/social/metaclaw-module.json +15 -0
  56. package/installer/modules/social/src/agent-social.ts.txt +110 -0
  57. package/installer/modules/support/metaclaw-module.json +15 -0
  58. package/installer/modules/support/src/agent-support.ts.txt +60 -0
  59. package/installer/modules/swarm/metaclaw-module.json +25 -0
  60. package/installer/modules/swarm/swarm/dht-client.ts.txt +376 -0
  61. package/installer/modules/swarm/swarm/relay-server.ts.txt +348 -0
  62. package/installer/modules/swarm/swarm/swarm-client.ts.txt +303 -0
  63. package/installer/modules/swarm/swarm/types.ts.txt +51 -0
  64. package/installer/modules/voice/metaclaw-module.json +16 -0
  65. package/installer/questionnaire.ts +277 -0
  66. package/installer/research.ts +258 -0
  67. package/installer/scaffold-from-config.ts +270 -0
  68. package/installer/task-generator.ts +324 -0
  69. package/installer/templates/agent-custom.ts.txt +100 -0
  70. package/installer/templates/agent-cycle.bat.txt +19 -0
  71. package/installer/templates/agent-outreach.ts.txt +193 -0
  72. package/installer/templates/agent-research.ts.txt +127 -0
  73. package/installer/templates/agent-social.ts.txt +110 -0
  74. package/installer/templates/agent-support.ts.txt +60 -0
  75. package/installer/templates/build-dashboard.cjs.txt +51 -0
  76. package/installer/templates/cron-manager.ts.txt +273 -0
  77. package/installer/templates/dashboard.html.txt +450 -0
  78. package/installer/templates/db.ts.txt +277 -0
  79. package/installer/templates/detect-session.bat.txt +41 -0
  80. package/installer/templates/health-check.ts.txt +128 -0
  81. package/installer/templates/inbox-agent.ts.txt +283 -0
  82. package/installer/templates/launch.bat.txt +120 -0
  83. package/installer/templates/morning-report.ts.txt +124 -0
  84. package/installer/templates/observability.ts.txt +20 -0
  85. package/installer/templates/safety.ts.txt +26 -0
  86. package/installer/templates/self-improve.ts.txt +48 -0
  87. package/installer/templates/self-update.ts.txt +345 -0
  88. package/installer/templates/state.json.txt +33 -0
  89. package/installer/templates/system-context.json.txt +33 -0
  90. package/installer/templates/update-dashboard.ts.txt +126 -0
  91. package/package.json +31 -0
  92. package/setup.bat +178 -0
@@ -0,0 +1,100 @@
1
+ /**
2
+ * __AGENT_NAME__ — Custom Claw
3
+ * Generated by MetaClaw Installer v3.3.0
4
+ *
5
+ * This is a blank-slate agent configured by Claude's research phase.
6
+ * The system prompt below was AI-generated based on your requirements.
7
+ */
8
+
9
+ import { query } from "@anthropic-ai/claude-agent-sdk";
10
+ import type { SDKResultMessage, SDKResultSuccess, SDKAssistantMessage, Options } from "@anthropic-ai/claude-agent-sdk";
11
+ import { getDb, recordAction, getTodayMetrics, getCircuitBreaker, getConfig } from "./db.js";
12
+ import { checkCanAct } from "./safety.js";
13
+ import { log } from "./observability.js";
14
+ import { recordOutcome, getCurrentPrompt } from "./self-improve.js";
15
+ import { runSelfUpdate } from "./self-update.js";
16
+
17
+ const DRY_RUN = process.argv.includes("--dry-run");
18
+ const STATUS = process.argv.includes("--status");
19
+
20
+ if (STATUS) {
21
+ getDb();
22
+ const metrics = getTodayMetrics();
23
+ const breaker = getCircuitBreaker("main");
24
+ console.log("__AGENT_NAME__ Status");
25
+ console.log("=".repeat(40));
26
+ console.log("Circuit breaker:", breaker?.state?.toUpperCase() || "CLOSED");
27
+ if (metrics) {
28
+ console.log("Today:", metrics.actions_taken, "actions, $" + (metrics.total_cost_usd || 0).toFixed(4));
29
+ } else {
30
+ console.log("No activity today.");
31
+ }
32
+ process.exit(0);
33
+ }
34
+
35
+ const DEFAULT_SYSTEM_PROMPT = `__SYSTEM_PROMPT__`;
36
+
37
+ async function main() {
38
+ getDb();
39
+ // NOTE: self-update runs AFTER task, NOT before (AXIOM Bug #1)
40
+
41
+ const task = process.argv.slice(2).filter(a => !a.startsWith("--")).join(" ");
42
+
43
+ if (!task && !DRY_RUN) {
44
+ console.log("__AGENT_NAME__ — Custom Claw");
45
+ console.log("");
46
+ console.log("Usage:");
47
+ console.log(' npm start -- "your task or instruction"');
48
+ console.log(' npm run dry-run -- "task"');
49
+ console.log(" npm run status");
50
+ process.exit(0);
51
+ }
52
+
53
+ const safety = checkCanAct();
54
+ if (!safety.allowed) {
55
+ console.log("BLOCKED: " + safety.reason);
56
+ process.exit(0);
57
+ }
58
+
59
+ const systemPrompt = getCurrentPrompt("custom") || DEFAULT_SYSTEM_PROMPT;
60
+
61
+ console.log("__AGENT_NAME__" + (DRY_RUN ? " (DRY RUN)" : ""));
62
+ log("info", "agent.start", { task, dryRun: DRY_RUN });
63
+
64
+ try {
65
+ const stream = query({
66
+ prompt: task || "Run your default task as described in your system prompt.",
67
+ options: {
68
+ systemPrompt,
69
+ allowedTools: ["WebSearch", "WebFetch", "Read", "Write", "Bash", "Glob", "Grep"],
70
+ maxTurns: 30,
71
+ model: "claude-sonnet-4-6",
72
+ },
73
+ });
74
+
75
+ for await (const message of stream) {
76
+ if (message.type === "assistant") {
77
+ const msg = message as any;
78
+ if (msg.message?.content) {
79
+ for (const block of msg.message.content) {
80
+ if (block.type === "text") console.log(block.text);
81
+ }
82
+ }
83
+ }
84
+ if (message.type === "result" && (message as any).subtype === "success") {
85
+ const s = message as SDKResultSuccess;
86
+ console.log("\nDone ($" + s.total_cost_usd.toFixed(4) + ")");
87
+ recordAction("custom_task", task || "default", "success", undefined, s.total_cost_usd);
88
+ recordOutcome("custom", 8);
89
+ }
90
+ }
91
+ } catch (err: unknown) {
92
+ const msg = err instanceof Error ? err.message : String(err);
93
+ log("error", "agent.error", { error: msg });
94
+ recordAction("custom_task", task || "default", "error", msg);
95
+ }
96
+ }
97
+
98
+ // Self-update AFTER task (never before)
99
+ try { await runSelfUpdate(); } catch { /* non-critical */ }
100
+ main();
@@ -0,0 +1,19 @@
1
+ @echo off
2
+ setlocal
3
+ title __AGENT_NAME__ — Autonomous Cycle
4
+ set PATH=C:\Program Files\nodejs;%USERPROFILE%\AppData\Roaming\npm;%USERPROFILE%\.local\bin;%PATH%
5
+ cd /d "__PROJECT_DIR__"
6
+
7
+ echo [%date% %time%] __AGENT_NAME__ cycle starting... >> data\logs\scheduler.log
8
+
9
+ REM Run the main agent with SPECIFIC instructions (not generic "do your job")
10
+ REM The cron agent (Sonnet, 30 turns, no context) needs EXPLICIT steps
11
+ call npm start -- "AUTONOMOUS CYCLE. Do these steps in order: 1. Use Read tool to read __PROJECT_DIR__\data\state.json — get next_priority_action and current metrics. 2. Use Read tool to read __PROJECT_DIR__\data\system-context.json — get whatWorks, whatDoesntWork, coreRules. 3. Execute the next_priority_action. Produce at least 1 tangible output. 4. Update state.json with what you accomplished and set a new next_priority_action. 5. Append a log entry to data\logs\cycle.log with timestamp and what you did."
12
+
13
+ echo [%date% %time%] __AGENT_NAME__ cycle completed. >> data\logs\scheduler.log
14
+
15
+ REM Rebuild dashboard with fresh data (AFTER agent, not inside)
16
+ call npx tsx src/update-dashboard.ts 2>nul
17
+ node scripts\build-dashboard.cjs 2>nul
18
+
19
+ exit /b 0
@@ -0,0 +1,193 @@
1
+ /**
2
+ * __AGENT_NAME__ — Outreach Claw
3
+ * Generated by MetaClaw Installer v3.3.0
4
+ *
5
+ * Full pipeline: research → safety → draft → AI detection → send → follow-up → inbox → auto-reply
6
+ */
7
+
8
+ import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
9
+ import type { SDKResultMessage, SDKResultSuccess, SDKAssistantMessage, Options } from "@anthropic-ai/claude-agent-sdk";
10
+ import { z } from "zod/v4";
11
+ import { getDb, recordAction, getTodayMetrics, getCircuitBreaker, isSuppressed, getConfig, setConfig } from "./db.js";
12
+ import { checkCanAct, SAFETY_CONFIG } from "./safety.js";
13
+ import { log } from "./observability.js";
14
+ import { recordOutcome, shouldOptimize, getCurrentPrompt, savePromptVersion } from "./self-improve.js";
15
+ import { runSelfUpdate } from "./self-update.js";
16
+
17
+ const DRY_RUN = process.argv.includes("--dry-run");
18
+ const STATUS = process.argv.includes("--status");
19
+
20
+ // --- Status Mode ---
21
+ if (STATUS) {
22
+ getDb();
23
+ const metrics = getTodayMetrics();
24
+ const breaker = getCircuitBreaker("main");
25
+ console.log("__AGENT_NAME__ Status");
26
+ console.log("=".repeat(40));
27
+ console.log("Circuit breaker:", breaker?.state?.toUpperCase() || "CLOSED");
28
+ if (metrics) {
29
+ console.log("Today:", metrics.actions_taken, "actions,", metrics.actions_succeeded, "succeeded");
30
+ console.log("Cost: $" + (metrics.total_cost_usd || 0).toFixed(4));
31
+ } else {
32
+ console.log("No activity today.");
33
+ }
34
+ // Check self-update schedule
35
+ const lastUpdate = getConfig("last_self_update");
36
+ console.log("Last self-update:", lastUpdate || "never");
37
+ process.exit(0);
38
+ }
39
+
40
+ // --- Custom MCP Tools ---
41
+
42
+ const safetyCheckTool = tool(
43
+ "check_recipient",
44
+ "Check if safe to send to this email. Checks suppression, dedup, rate limits, circuit breaker.",
45
+ { email: z.string().describe("Recipient email address") },
46
+ async (args) => {
47
+ const check = checkCanAct(args.email);
48
+ if (!check.allowed) return { content: [{ type: "text" as const, text: "BLOCKED: " + check.reason }] };
49
+ return { content: [{ type: "text" as const, text: "OK: Safe to send to " + args.email }] };
50
+ }
51
+ );
52
+
53
+ const saveDraftTool = tool(
54
+ "save_draft",
55
+ "Save a drafted outreach email. Records to database. Always call check_recipient FIRST.",
56
+ {
57
+ to: z.string().describe("Recipient email address"),
58
+ subject: z.string().describe("Email subject — casual, lowercase, under 50 chars"),
59
+ body: z.string().describe("Email body — under 80 words, single CTA, casual"),
60
+ prospect: z.string().describe("Prospect name"),
61
+ company: z.string().describe("Company"),
62
+ researchNotes: z.string().describe("Research findings used to personalize"),
63
+ },
64
+ async (args) => {
65
+ const check = checkCanAct(args.to);
66
+ if (!check.allowed) return { content: [{ type: "text" as const, text: "BLOCKED: " + check.reason }] };
67
+
68
+ // Record the draft
69
+ recordAction("draft", args.to, "success", JSON.stringify({ subject: args.subject, body: args.body, prospect: args.prospect, company: args.company }));
70
+
71
+ console.log("\n" + "=".repeat(50));
72
+ console.log("DRAFT");
73
+ console.log("To: " + args.to);
74
+ console.log("Subject: " + args.subject);
75
+ console.log("-".repeat(50));
76
+ console.log(args.body);
77
+ console.log("=".repeat(50));
78
+
79
+ if (DRY_RUN) {
80
+ return { content: [{ type: "text" as const, text: "Draft saved. DRY RUN — not sending." }] };
81
+ }
82
+
83
+ // TODO: Wire in mailer.ts for actual sending
84
+ // For now, record as drafted
85
+ return { content: [{ type: "text" as const, text: "Draft saved. Configure SMTP in npm run setup to enable sending." }] };
86
+ }
87
+ );
88
+
89
+ const customTools = createSdkMcpServer({
90
+ name: "__SESSION_NAME__",
91
+ version: "1.0.0",
92
+ tools: [safetyCheckTool, saveDraftTool],
93
+ });
94
+
95
+ // --- System Prompt ---
96
+ const DEFAULT_SYSTEM_PROMPT = `__SYSTEM_PROMPT__`;
97
+
98
+ // --- Main ---
99
+ async function main() {
100
+ getDb();
101
+ // NOTE: self-update runs AFTER task, NOT before (AXIOM Bug #1 — blocks real work)
102
+
103
+ const args = process.argv.slice(2).filter(a => !a.startsWith("--"));
104
+ const prospect = args[0] || "";
105
+ const company = args[1] || "";
106
+
107
+ if (!prospect && !DRY_RUN) {
108
+ console.log("__AGENT_NAME__ — Outreach Claw");
109
+ console.log("");
110
+ console.log("Usage:");
111
+ console.log(' npm start -- "Prospect Name" "Company"');
112
+ console.log(' npm run dry-run -- "Prospect Name" "Company"');
113
+ console.log(" npm run status");
114
+ process.exit(0);
115
+ }
116
+
117
+ const safety = checkCanAct();
118
+ if (!safety.allowed) {
119
+ console.log("BLOCKED: " + safety.reason);
120
+ process.exit(0);
121
+ }
122
+
123
+ // Use self-improved prompt if available, otherwise default
124
+ const systemPrompt = getCurrentPrompt("outreach") || DEFAULT_SYSTEM_PROMPT;
125
+
126
+ const userPrompt = prospect
127
+ ? "Research " + prospect + " at " + company + " and draft a personalized outreach email. Start with check_recipient."
128
+ : "Pick a sample prospect and draft a demo outreach email. Use check_recipient and save_draft.";
129
+
130
+ console.log("__AGENT_NAME__" + (DRY_RUN ? " (DRY RUN)" : ""));
131
+ console.log("Prospect: " + (prospect || "(demo mode)"));
132
+ log("info", "agent.start", { prospect, company, dryRun: DRY_RUN });
133
+
134
+ const options: Options = {
135
+ systemPrompt,
136
+ allowedTools: [
137
+ "WebSearch", "WebFetch",
138
+ "mcp____SESSION_NAME____check_recipient",
139
+ "mcp____SESSION_NAME____save_draft",
140
+ ],
141
+ mcpServers: { "__SESSION_NAME__": customTools },
142
+ maxTurns: 20,
143
+ model: "claude-sonnet-4-6",
144
+ };
145
+
146
+ try {
147
+ const stream = query({ prompt: userPrompt, options });
148
+ let resultText = "";
149
+
150
+ for await (const message of stream) {
151
+ if (message.type === "assistant") {
152
+ const msg = message as SDKAssistantMessage;
153
+ if (msg.message?.content) {
154
+ for (const block of msg.message.content) {
155
+ if (block.type === "text" && "text" in block) {
156
+ const text = (block as any).text;
157
+ console.log(text);
158
+ resultText += text;
159
+ }
160
+ }
161
+ }
162
+ }
163
+ if (message.type === "result") {
164
+ const result = message as SDKResultMessage;
165
+ if (result.subtype === "success") {
166
+ const s = result as SDKResultSuccess;
167
+ console.log("\nDone ($" + s.total_cost_usd.toFixed(4) + ")");
168
+ recordAction("outreach_cycle", prospect || "demo", "success", undefined, s.total_cost_usd, (s.usage?.input_tokens || 0) + (s.usage?.output_tokens || 0));
169
+
170
+ // Self-improvement: score this run
171
+ // Simple heuristic: if draft was created, score 8. If blocked, score 3.
172
+ const score = resultText.includes("Draft") ? 8 : resultText.includes("BLOCKED") ? 3 : 6;
173
+ recordOutcome("outreach", score);
174
+
175
+ if (shouldOptimize("outreach")) {
176
+ log("info", "self_improve.trigger", { reason: "30 runs completed" });
177
+ // TODO: Run curator to optimize prompt
178
+ }
179
+ }
180
+ }
181
+ }
182
+ } catch (err: unknown) {
183
+ const msg = err instanceof Error ? err.message : String(err);
184
+ log("error", "agent.error", { error: msg });
185
+ console.error("Error: " + msg);
186
+ recordAction("outreach_cycle", prospect || "demo", "error", msg);
187
+ }
188
+
189
+ // Self-update runs AFTER task — never before (prevents housekeeping-only sessions)
190
+ try { await runSelfUpdate(); } catch { /* non-critical */ }
191
+ }
192
+
193
+ main();
@@ -0,0 +1,127 @@
1
+ /**
2
+ * __AGENT_NAME__ — Research Claw
3
+ * Generated by MetaClaw Installer v3.3.0
4
+ *
5
+ * Pipeline: query → web research → synthesize → report → self-improve
6
+ */
7
+
8
+ import { query } from "@anthropic-ai/claude-agent-sdk";
9
+ import type { SDKResultMessage, SDKResultSuccess, SDKAssistantMessage, Options } 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, shouldOptimize, getCurrentPrompt } from "./self-improve.js";
17
+ import { runSelfUpdate } from "./self-update.js";
18
+
19
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
20
+ const DRY_RUN = process.argv.includes("--dry-run");
21
+ const STATUS = process.argv.includes("--status");
22
+
23
+ if (STATUS) {
24
+ getDb();
25
+ const metrics = getTodayMetrics();
26
+ const breaker = getCircuitBreaker("main");
27
+ console.log("__AGENT_NAME__ Status");
28
+ console.log("=".repeat(40));
29
+ console.log("Circuit breaker:", breaker?.state?.toUpperCase() || "CLOSED");
30
+ if (metrics) {
31
+ console.log("Today:", metrics.actions_taken, "research tasks,", "$" + (metrics.total_cost_usd || 0).toFixed(4));
32
+ } else {
33
+ console.log("No activity today.");
34
+ }
35
+ const lastUpdate = getConfig("last_self_update");
36
+ console.log("Last self-update:", lastUpdate || "never");
37
+ process.exit(0);
38
+ }
39
+
40
+ const DEFAULT_SYSTEM_PROMPT = `__SYSTEM_PROMPT__`;
41
+
42
+ async function main() {
43
+ getDb();
44
+ // NOTE: self-update runs AFTER task, NOT before (AXIOM Bug #1)
45
+
46
+ const topic = process.argv.slice(2).filter(a => !a.startsWith("--")).join(" ");
47
+
48
+ if (!topic) {
49
+ console.log("__AGENT_NAME__ — Research Claw");
50
+ console.log("");
51
+ console.log("Usage:");
52
+ console.log(' npm start -- "research topic or question"');
53
+ console.log(' npm run dry-run -- "topic"');
54
+ console.log(" npm run status");
55
+ process.exit(0);
56
+ }
57
+
58
+ const safety = checkCanAct();
59
+ if (!safety.allowed) {
60
+ console.log("BLOCKED: " + safety.reason);
61
+ process.exit(0);
62
+ }
63
+
64
+ const systemPrompt = getCurrentPrompt("research") || DEFAULT_SYSTEM_PROMPT;
65
+
66
+ console.log("__AGENT_NAME__" + (DRY_RUN ? " (DRY RUN)" : ""));
67
+ console.log("Topic: " + topic);
68
+ log("info", "agent.start", { topic, dryRun: DRY_RUN });
69
+
70
+ const options: Options = {
71
+ systemPrompt,
72
+ allowedTools: ["WebSearch", "WebFetch", "Read", "Write"],
73
+ maxTurns: 30,
74
+ model: "claude-sonnet-4-6",
75
+ };
76
+
77
+ const reportPath = path.join(__dirname, "..", "data", "reports", topic.replace(/[^a-z0-9]/gi, "-").slice(0, 50) + ".md");
78
+ fs.mkdirSync(path.dirname(reportPath), { recursive: true });
79
+
80
+ try {
81
+ let fullResponse = "";
82
+ const stream = query({
83
+ prompt: "Research this topic thoroughly using web search. Produce a comprehensive markdown report with sources. Topic: " + topic,
84
+ options,
85
+ });
86
+
87
+ for await (const message of stream) {
88
+ if (message.type === "assistant") {
89
+ const msg = message as SDKAssistantMessage;
90
+ if (msg.message?.content) {
91
+ for (const block of msg.message.content) {
92
+ if (block.type === "text" && "text" in block) {
93
+ const text = (block as any).text;
94
+ process.stdout.write(text);
95
+ fullResponse += text;
96
+ }
97
+ }
98
+ }
99
+ }
100
+ if (message.type === "result") {
101
+ const result = message as SDKResultMessage;
102
+ if (result.subtype === "success") {
103
+ const s = result as SDKResultSuccess;
104
+ console.log("\n\nDone ($" + s.total_cost_usd.toFixed(4) + ")");
105
+ recordAction("research", topic, "success", undefined, s.total_cost_usd);
106
+
107
+ // Save report
108
+ if (!DRY_RUN && fullResponse.trim()) {
109
+ fs.writeFileSync(reportPath, fullResponse);
110
+ console.log("Report saved: " + reportPath);
111
+ }
112
+
113
+ recordOutcome("research", 8);
114
+ }
115
+ }
116
+ }
117
+ } catch (err: unknown) {
118
+ const msg = err instanceof Error ? err.message : String(err);
119
+ log("error", "agent.error", { error: msg });
120
+ console.error("Error: " + msg);
121
+ recordAction("research", topic, "error", msg);
122
+ }
123
+ }
124
+
125
+ // Self-update AFTER task (never before)
126
+ try { await runSelfUpdate(); } catch { /* non-critical */ }
127
+ main();
@@ -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,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,51 @@
1
+ /**
2
+ * Dashboard Builder — bakes data inline for file:// compatibility
3
+ * Auto-generated by MetaClaw Installer
4
+ *
5
+ * Pattern from AXIOM: HTML has <script type="application/json"> placeholders.
6
+ * This script reads JSON files and injects them inline.
7
+ * Dashboard JS uses tryInline() || fetch() — works both offline and served.
8
+ *
9
+ * Run: node scripts/build-dashboard.cjs
10
+ * Also called by cron after each agent cycle.
11
+ */
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+
16
+ const PROJECT = __dirname.replace(/[\\/]scripts$/, '');
17
+ const DASH_PATH = path.join(PROJECT, 'dashboard.html');
18
+ const DATA_DIR = path.join(PROJECT, 'data');
19
+
20
+ function readJSON(filePath) {
21
+ try { return fs.readFileSync(filePath, 'utf-8').trim(); }
22
+ catch { return 'null'; }
23
+ }
24
+
25
+ // Data sources to bake into the dashboard
26
+ const replacements = {
27
+ 'inline-dashboard': readJSON(path.join(DATA_DIR, 'dashboard.json')),
28
+ 'inline-state': readJSON(path.join(DATA_DIR, 'state.json')),
29
+ 'inline-context': readJSON(path.join(DATA_DIR, 'system-context.json')),
30
+ };
31
+
32
+ if (!fs.existsSync(DASH_PATH)) {
33
+ console.log('dashboard.html not found at ' + DASH_PATH);
34
+ process.exit(0);
35
+ }
36
+
37
+ let html = fs.readFileSync(DASH_PATH, 'utf-8');
38
+ let replaced = 0;
39
+
40
+ for (const [id, json] of Object.entries(replacements)) {
41
+ const regex = new RegExp(
42
+ '(<script id="' + id + '" type="application/json">)[\\s\\S]*?(</script>)'
43
+ );
44
+ if (regex.test(html)) {
45
+ html = html.replace(regex, '$1' + json + '$2');
46
+ replaced++;
47
+ }
48
+ }
49
+
50
+ fs.writeFileSync(DASH_PATH, html, 'utf-8');
51
+ console.log('Dashboard rebuilt — ' + replaced + ' data source(s) baked inline.');