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.
- package/LICENSE +44 -0
- package/README.md +288 -0
- package/bin/create-yonderclaw.mjs +43 -0
- package/docs/assets/favicon.png +0 -0
- package/docs/assets/metaclaw-banner.svg +86 -0
- package/docs/assets/qis-logo.png +0 -0
- package/docs/assets/yz-favicon.png +0 -0
- package/docs/assets/yz-logo.png +0 -0
- package/docs/index.html +1155 -0
- package/installer/assets/favicon.png +0 -0
- package/installer/auto-start.ts +330 -0
- package/installer/brand.ts +115 -0
- package/installer/core-scaffold.ts +448 -0
- package/installer/dashboard-generator.ts +657 -0
- package/installer/detect.ts +129 -0
- package/installer/index.ts +355 -0
- package/installer/module-loader.ts +412 -0
- package/installer/modules/boardroom/boardroom/client.ts.txt +201 -0
- package/installer/modules/boardroom/boardroom/db.ts.txt +322 -0
- package/installer/modules/boardroom/boardroom/meeting-agent.ts.txt +129 -0
- package/installer/modules/boardroom/boardroom/meeting-scheduler.ts.txt +194 -0
- package/installer/modules/boardroom/boardroom/server.ts.txt +473 -0
- package/installer/modules/boardroom/boardroom/start-boardroom.bat.txt +26 -0
- package/installer/modules/boardroom/boardroom/summons.ts.txt +76 -0
- package/installer/modules/boardroom/boardroom/turn-v2.ts.txt +172 -0
- package/installer/modules/boardroom/boardroom/turn.ts.txt +208 -0
- package/installer/modules/boardroom/boardroom/types.ts.txt +100 -0
- package/installer/modules/boardroom/metaclaw-module.json +35 -0
- package/installer/modules/boardroom/scripts/meeting-check.bat.txt +38 -0
- package/installer/modules/core/metaclaw-module.json +51 -0
- package/installer/modules/core/src/db.ts.txt +277 -0
- package/installer/modules/core/src/health-check.ts.txt +128 -0
- package/installer/modules/core/src/observability.ts.txt +20 -0
- package/installer/modules/core/src/safety.ts.txt +26 -0
- package/installer/modules/core/src/scan-capabilities.ts.txt +196 -0
- package/installer/modules/core/src/self-improve.ts.txt +48 -0
- package/installer/modules/core/src/self-update.ts.txt +345 -0
- package/installer/modules/core/src/sync-context.ts.txt +133 -0
- package/installer/modules/core/src/tasks.ts.txt +159 -0
- package/installer/modules/custom/metaclaw-module.json +15 -0
- package/installer/modules/custom/src/agent-custom.ts.txt +100 -0
- package/installer/modules/dashboard/metaclaw-module.json +23 -0
- package/installer/modules/dashboard/scripts/build-dashboard.cjs.txt +51 -0
- package/installer/modules/dashboard/src/update-dashboard.ts.txt +126 -0
- package/installer/modules/outreach/metaclaw-module.json +29 -0
- package/installer/modules/outreach/src/agent-outreach.ts.txt +193 -0
- package/installer/modules/outreach/src/inbox-agent.ts.txt +283 -0
- package/installer/modules/outreach/src/morning-report.ts.txt +124 -0
- package/installer/modules/research/metaclaw-module.json +15 -0
- package/installer/modules/research/src/agent-research.ts.txt +127 -0
- package/installer/modules/scheduler/metaclaw-module.json +27 -0
- package/installer/modules/scheduler/scripts/agent-cycle.bat.txt +85 -0
- package/installer/modules/scheduler/scripts/detect-session.bat.txt +41 -0
- package/installer/modules/scheduler/scripts/launch.bat.txt +120 -0
- package/installer/modules/scheduler/src/cron-manager.ts.txt +273 -0
- package/installer/modules/social/metaclaw-module.json +15 -0
- package/installer/modules/social/src/agent-social.ts.txt +110 -0
- package/installer/modules/support/metaclaw-module.json +15 -0
- package/installer/modules/support/src/agent-support.ts.txt +60 -0
- package/installer/modules/swarm/metaclaw-module.json +25 -0
- package/installer/modules/swarm/swarm/dht-client.ts.txt +376 -0
- package/installer/modules/swarm/swarm/relay-server.ts.txt +348 -0
- package/installer/modules/swarm/swarm/swarm-client.ts.txt +303 -0
- package/installer/modules/swarm/swarm/types.ts.txt +51 -0
- package/installer/modules/voice/metaclaw-module.json +16 -0
- package/installer/questionnaire.ts +277 -0
- package/installer/research.ts +258 -0
- package/installer/scaffold-from-config.ts +270 -0
- package/installer/task-generator.ts +324 -0
- package/installer/templates/agent-custom.ts.txt +100 -0
- package/installer/templates/agent-cycle.bat.txt +19 -0
- package/installer/templates/agent-outreach.ts.txt +193 -0
- package/installer/templates/agent-research.ts.txt +127 -0
- package/installer/templates/agent-social.ts.txt +110 -0
- package/installer/templates/agent-support.ts.txt +60 -0
- package/installer/templates/build-dashboard.cjs.txt +51 -0
- package/installer/templates/cron-manager.ts.txt +273 -0
- package/installer/templates/dashboard.html.txt +450 -0
- package/installer/templates/db.ts.txt +277 -0
- package/installer/templates/detect-session.bat.txt +41 -0
- package/installer/templates/health-check.ts.txt +128 -0
- package/installer/templates/inbox-agent.ts.txt +283 -0
- package/installer/templates/launch.bat.txt +120 -0
- package/installer/templates/morning-report.ts.txt +124 -0
- package/installer/templates/observability.ts.txt +20 -0
- package/installer/templates/safety.ts.txt +26 -0
- package/installer/templates/self-improve.ts.txt +48 -0
- package/installer/templates/self-update.ts.txt +345 -0
- package/installer/templates/state.json.txt +33 -0
- package/installer/templates/system-context.json.txt +33 -0
- package/installer/templates/update-dashboard.ts.txt +126 -0
- package/package.json +31 -0
- package/setup.bat +178 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MetaClaw System Detection — auto-detect everything about the environment
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { execSync } from "child_process";
|
|
6
|
+
import os from "os";
|
|
7
|
+
import fs from "fs";
|
|
8
|
+
import path from "path";
|
|
9
|
+
import { status, muted } from "./brand.js";
|
|
10
|
+
|
|
11
|
+
export type SystemInfo = {
|
|
12
|
+
os: { platform: string; release: string; arch: string; hostname: string };
|
|
13
|
+
user: { username: string; homedir: string; desktop: string };
|
|
14
|
+
node: { installed: boolean; version: string };
|
|
15
|
+
git: { installed: boolean; version: string };
|
|
16
|
+
claude: { installed: boolean; version: string; authenticated: boolean };
|
|
17
|
+
docker: { installed: boolean; version: string };
|
|
18
|
+
python: { installed: boolean; version: string };
|
|
19
|
+
hardware: { cpus: number; ram: string; gpu: string };
|
|
20
|
+
paths: {
|
|
21
|
+
workspace: string;
|
|
22
|
+
claudeDir: string;
|
|
23
|
+
projectMemory: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
function tryExec(cmd: string): string {
|
|
28
|
+
try {
|
|
29
|
+
return execSync(cmd, { encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
30
|
+
} catch {
|
|
31
|
+
return "";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getGpuInfo(): string {
|
|
36
|
+
const platform = os.platform();
|
|
37
|
+
if (platform === "win32") {
|
|
38
|
+
const result = tryExec('wmic path win32_VideoController get name /format:list');
|
|
39
|
+
const match = result.match(/Name=(.+)/);
|
|
40
|
+
return match ? match[1].trim() : "Not detected";
|
|
41
|
+
}
|
|
42
|
+
if (platform === "linux") {
|
|
43
|
+
return tryExec("lspci | grep -i vga | head -1 | cut -d: -f3") || "Not detected";
|
|
44
|
+
}
|
|
45
|
+
if (platform === "darwin") {
|
|
46
|
+
return tryExec("system_profiler SPDisplaysDataType | grep 'Chipset Model' | head -1 | cut -d: -f2") || "Not detected";
|
|
47
|
+
}
|
|
48
|
+
return "Not detected";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Detect everything about the current system.
|
|
53
|
+
*/
|
|
54
|
+
export function detectSystem(): SystemInfo {
|
|
55
|
+
const platform = os.platform();
|
|
56
|
+
const username = os.userInfo().username;
|
|
57
|
+
const homedir = os.homedir();
|
|
58
|
+
const desktop = path.join(homedir, "Desktop");
|
|
59
|
+
|
|
60
|
+
// Encode workspace path for Claude project memory
|
|
61
|
+
const workspacePath = path.join(desktop, "claude-workspace");
|
|
62
|
+
const encodedPath = workspacePath.replace(/[:/\\]/g, "-").replace(/^-/, "");
|
|
63
|
+
|
|
64
|
+
const nodeVersion = tryExec("node --version");
|
|
65
|
+
const gitVersion = tryExec("git --version").replace("git version ", "");
|
|
66
|
+
const claudeVersion = tryExec("claude --version") || tryExec(`"${homedir}\\.local\\bin\\claude.exe" --version`);
|
|
67
|
+
const dockerVersion = tryExec("docker --version").replace("Docker version ", "").split(",")[0];
|
|
68
|
+
const pythonVersion = tryExec("python --version").replace("Python ", "") || tryExec("python3 --version").replace("Python ", "");
|
|
69
|
+
|
|
70
|
+
const ramGB = (os.totalmem() / 1024 / 1024 / 1024).toFixed(1);
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
os: {
|
|
74
|
+
platform: platform === "win32" ? "Windows" : platform === "darwin" ? "macOS" : "Linux",
|
|
75
|
+
release: os.release(),
|
|
76
|
+
arch: os.arch(),
|
|
77
|
+
hostname: os.hostname(),
|
|
78
|
+
},
|
|
79
|
+
user: {
|
|
80
|
+
username,
|
|
81
|
+
homedir,
|
|
82
|
+
desktop,
|
|
83
|
+
},
|
|
84
|
+
node: { installed: !!nodeVersion, version: nodeVersion || "Not installed" },
|
|
85
|
+
git: { installed: !!gitVersion, version: gitVersion || "Not installed" },
|
|
86
|
+
claude: {
|
|
87
|
+
installed: !!claudeVersion,
|
|
88
|
+
version: claudeVersion || "Not installed",
|
|
89
|
+
authenticated: fs.existsSync(path.join(homedir, ".claude", ".credentials.json")),
|
|
90
|
+
},
|
|
91
|
+
docker: { installed: !!dockerVersion, version: dockerVersion || "Not installed" },
|
|
92
|
+
python: { installed: !!pythonVersion, version: pythonVersion || "Not installed" },
|
|
93
|
+
hardware: {
|
|
94
|
+
cpus: os.cpus().length,
|
|
95
|
+
ram: `${ramGB} GB`,
|
|
96
|
+
gpu: getGpuInfo(),
|
|
97
|
+
},
|
|
98
|
+
paths: {
|
|
99
|
+
workspace: workspacePath,
|
|
100
|
+
claudeDir: path.join(homedir, ".claude"),
|
|
101
|
+
projectMemory: path.join(homedir, ".claude", "projects", encodedPath),
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Display system detection results.
|
|
108
|
+
*/
|
|
109
|
+
export function displayDetection(info: SystemInfo): void {
|
|
110
|
+
// OS
|
|
111
|
+
console.log(status.info(`${info.os.platform} ${info.os.release} (${info.os.arch})`));
|
|
112
|
+
console.log(status.info(`User: ${info.user.username} @ ${info.os.hostname}`));
|
|
113
|
+
console.log(status.info(`${info.hardware.cpus} CPUs, ${info.hardware.ram} RAM`));
|
|
114
|
+
if (info.hardware.gpu !== "Not detected") {
|
|
115
|
+
console.log(status.ok(`GPU: ${info.hardware.gpu}`));
|
|
116
|
+
} else {
|
|
117
|
+
console.log(status.warn("GPU: Not detected (will use cloud inference)"));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
console.log("");
|
|
121
|
+
|
|
122
|
+
// Required tools only — no Docker/Python clutter
|
|
123
|
+
console.log(info.node.installed ? status.ok(`Node.js ${info.node.version}`) : status.fail("Node.js — not installed"));
|
|
124
|
+
console.log(info.git.installed ? status.ok(`Git ${info.git.version}`) : status.warn("Git — not installed"));
|
|
125
|
+
console.log(info.claude.installed ? status.ok(`Claude Code ${info.claude.version}`) : status.fail("Claude Code — not installed"));
|
|
126
|
+
if (info.claude.installed) {
|
|
127
|
+
console.log(info.claude.authenticated ? status.ok("Claude — authenticated") : status.warn("Claude — not authenticated"));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MetaClaw Installer v3.3.0
|
|
4
|
+
* by Christopher Trevethan / Yonder Zenith LLC
|
|
5
|
+
*
|
|
6
|
+
* Fully automated: Detect → Configure → Research → Deploy → Launch
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as clack from "@clack/prompts";
|
|
10
|
+
import chalk from "chalk";
|
|
11
|
+
import ora from "ora";
|
|
12
|
+
import { Listr } from "listr2";
|
|
13
|
+
import {
|
|
14
|
+
welcomeScreen, completionScreen, sectionHeader, status,
|
|
15
|
+
brand, muted, success, purple, accent, gold,
|
|
16
|
+
box, brandGradient, successGradient, goldGradient, cyanGradient,
|
|
17
|
+
} from "./brand.js";
|
|
18
|
+
import { detectSystem, displayDetection } from "./detect.js";
|
|
19
|
+
import type { SystemInfo } from "./detect.js";
|
|
20
|
+
import { runQuestionnaire } from "./questionnaire.js";
|
|
21
|
+
import type { QuestionnaireResult } from "./questionnaire.js";
|
|
22
|
+
import { runResearch } from "./research.js";
|
|
23
|
+
import type { ClawConfig } from "./research.js";
|
|
24
|
+
import { scaffoldProject } from "./core-scaffold.js";
|
|
25
|
+
import fs from "fs";
|
|
26
|
+
import path from "path";
|
|
27
|
+
import { execSync, spawn } from "child_process";
|
|
28
|
+
|
|
29
|
+
function sleep(ms: number): Promise<void> {
|
|
30
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function findClaudePath(systemInfo: SystemInfo): string {
|
|
34
|
+
const candidates = [
|
|
35
|
+
path.join(systemInfo.user.homedir, ".local", "bin", "claude.exe"),
|
|
36
|
+
path.join(systemInfo.user.homedir, ".local", "bin", "claude"),
|
|
37
|
+
];
|
|
38
|
+
for (const p of candidates) {
|
|
39
|
+
if (fs.existsSync(p)) return p;
|
|
40
|
+
}
|
|
41
|
+
return "claude";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// ═══════════════════════════════════════════════
|
|
45
|
+
// MAIN
|
|
46
|
+
// ═══════════════════════════════════════════════
|
|
47
|
+
|
|
48
|
+
async function main() {
|
|
49
|
+
// Phase 1: Welcome (with pause so they can see the branding)
|
|
50
|
+
console.clear();
|
|
51
|
+
console.log(welcomeScreen());
|
|
52
|
+
await sleep(2500);
|
|
53
|
+
|
|
54
|
+
// Phase 2: System Detection
|
|
55
|
+
console.log(sectionHeader("System Detection"));
|
|
56
|
+
console.log("");
|
|
57
|
+
const spinner = ora({ text: "Scanning system...", color: "magenta", spinner: "dots12" }).start();
|
|
58
|
+
const systemInfo = detectSystem();
|
|
59
|
+
spinner.stop();
|
|
60
|
+
displayDetection(systemInfo);
|
|
61
|
+
console.log("");
|
|
62
|
+
|
|
63
|
+
if (!systemInfo.node.installed) {
|
|
64
|
+
console.log(accent(" Node.js is required. Install from https://nodejs.org"));
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Phase 2.5: Claude Authentication (MANDATORY)
|
|
69
|
+
const claudePath = findClaudePath(systemInfo);
|
|
70
|
+
|
|
71
|
+
if (!systemInfo.claude.installed) {
|
|
72
|
+
console.log(sectionHeader("Installing Claude Code"));
|
|
73
|
+
console.log("");
|
|
74
|
+
try {
|
|
75
|
+
execSync('powershell -Command "irm https://claude.ai/install.ps1 | iex"', { stdio: "inherit", timeout: 120000 });
|
|
76
|
+
} catch {
|
|
77
|
+
console.log(accent(" Install Claude Code manually: https://claude.ai/download"));
|
|
78
|
+
console.log(accent(" Then run setup.bat again."));
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
const recheck = detectSystem();
|
|
82
|
+
if (!recheck.claude.installed) {
|
|
83
|
+
console.log(accent(" Close this window, open a NEW terminal, run setup.bat again."));
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
systemInfo.claude = recheck.claude;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!systemInfo.claude.authenticated) {
|
|
90
|
+
console.log(sectionHeader("Claude Authentication Required"));
|
|
91
|
+
console.log("");
|
|
92
|
+
console.log(brand(" MetaClaw requires Claude to power your agent."));
|
|
93
|
+
console.log(muted(" You need a Claude Pro or Max subscription."));
|
|
94
|
+
console.log(muted(" A browser window will open — log in with your Claude account."));
|
|
95
|
+
console.log("");
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
execSync(`"${claudePath}" auth login`, { stdio: "inherit", timeout: 300000 });
|
|
99
|
+
} catch {
|
|
100
|
+
try {
|
|
101
|
+
execSync(`"${path.join(systemInfo.user.homedir, ".local", "bin", "claude.exe")}" auth login`, { stdio: "inherit", timeout: 300000 });
|
|
102
|
+
} catch {
|
|
103
|
+
console.log(accent(" Run manually: claude auth login"));
|
|
104
|
+
console.log(accent(" Then run setup.bat again."));
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const recheck = detectSystem();
|
|
110
|
+
if (!recheck.claude.authenticated) {
|
|
111
|
+
console.log(accent(" Authentication failed. Run: claude auth login"));
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
systemInfo.claude = recheck.claude;
|
|
115
|
+
console.log(status.ok("Claude authenticated!"));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log(status.ok("Claude ready"));
|
|
119
|
+
console.log("");
|
|
120
|
+
|
|
121
|
+
// Phase 3: Questionnaire
|
|
122
|
+
const result = await runQuestionnaire(systemInfo);
|
|
123
|
+
if (!result) { console.log(muted("\n Cancelled.\n")); process.exit(0); }
|
|
124
|
+
|
|
125
|
+
// Phase 3.5: Name the agent
|
|
126
|
+
console.log(sectionHeader("Agent Identity"));
|
|
127
|
+
const agentName = await clack.text({
|
|
128
|
+
message: "Name your agent",
|
|
129
|
+
placeholder: "Atlas",
|
|
130
|
+
defaultValue: "Atlas",
|
|
131
|
+
});
|
|
132
|
+
if (clack.isCancel(agentName)) process.exit(0);
|
|
133
|
+
|
|
134
|
+
const wantAutoStart = await clack.confirm({
|
|
135
|
+
message: "Start this agent automatically when your PC boots?",
|
|
136
|
+
initialValue: true,
|
|
137
|
+
});
|
|
138
|
+
if (clack.isCancel(wantAutoStart)) process.exit(0);
|
|
139
|
+
|
|
140
|
+
// Phase 4: AI Research
|
|
141
|
+
console.log("");
|
|
142
|
+
let clawConfig: ClawConfig | null = null;
|
|
143
|
+
console.log(status.route("Assembling the MetaClaw board for your " + result.template.name + "..."));
|
|
144
|
+
console.log("");
|
|
145
|
+
try {
|
|
146
|
+
clawConfig = await runResearch(result, systemInfo);
|
|
147
|
+
} catch {
|
|
148
|
+
console.log(status.warn("Board session had an issue — using battle-tested defaults."));
|
|
149
|
+
}
|
|
150
|
+
if (!clawConfig) {
|
|
151
|
+
console.log(status.info("Deploying with optimized defaults. The agent will self-improve from here."));
|
|
152
|
+
}
|
|
153
|
+
console.log("");
|
|
154
|
+
|
|
155
|
+
// Phase 5: Install & Configure
|
|
156
|
+
const projectDir = path.join(systemInfo.user.desktop, result.projectName);
|
|
157
|
+
|
|
158
|
+
const finalConfig: ClawConfig = clawConfig || {
|
|
159
|
+
name: agentName as string,
|
|
160
|
+
template: result.template.id,
|
|
161
|
+
systemPrompt: `You are ${agentName}, a ${result.template.name}. ${result.template.description}`,
|
|
162
|
+
tools: result.template.requiredTools,
|
|
163
|
+
safety: { maxActionsPerDay: 50, maxActionsPerHour: 10 },
|
|
164
|
+
schedule: { cron: "*/30 * * * *", description: "every 30 minutes" },
|
|
165
|
+
selfImprovement: { enabled: true, reflectionFrequency: "daily", metricsToTrack: ["success_rate"] },
|
|
166
|
+
rawResearch: "",
|
|
167
|
+
};
|
|
168
|
+
finalConfig.name = agentName as string;
|
|
169
|
+
(finalConfig as any).selfUpdateIntervalHours = parseInt(result.answers.selfUpdateIntervalHours as string) || 6;
|
|
170
|
+
(finalConfig as any).answers = result.answers;
|
|
171
|
+
|
|
172
|
+
console.log(sectionHeader(`Deploying ${result.template.icon} ${agentName}`));
|
|
173
|
+
console.log("");
|
|
174
|
+
|
|
175
|
+
const tasks = new Listr(
|
|
176
|
+
[
|
|
177
|
+
{
|
|
178
|
+
title: "Scaffolding project (all files + launch scripts + dashboard)",
|
|
179
|
+
task: async (ctx, task) => {
|
|
180
|
+
// THIS is the ONLY place files are created — core-scaffold handles EVERYTHING
|
|
181
|
+
// including launch.bat, open-dashboard.bat, Agents folder launcher
|
|
182
|
+
scaffoldProject(projectDir, finalConfig, systemInfo);
|
|
183
|
+
task.output = "20+ files generated";
|
|
184
|
+
},
|
|
185
|
+
options: { bottomBar: 1 },
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
title: "Installing dependencies",
|
|
189
|
+
task: async (ctx, task) => {
|
|
190
|
+
task.output = "Running npm install...";
|
|
191
|
+
try {
|
|
192
|
+
execSync("npm install", { cwd: projectDir, stdio: "pipe", timeout: 180000 });
|
|
193
|
+
task.output = "Dependencies installed";
|
|
194
|
+
} catch { task.output = "npm install had issues — may need manual retry"; }
|
|
195
|
+
},
|
|
196
|
+
options: { bottomBar: 1 },
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
title: "Initializing database",
|
|
200
|
+
task: async (ctx, task) => {
|
|
201
|
+
try {
|
|
202
|
+
execSync("npx tsx src/init-config.ts", { cwd: projectDir, stdio: "pipe", timeout: 15000 });
|
|
203
|
+
execSync("npx tsx src/init-prompts.ts", { cwd: projectDir, stdio: "pipe", timeout: 15000 });
|
|
204
|
+
task.output = "Database seeded";
|
|
205
|
+
} catch { task.output = "Init will run on first start"; }
|
|
206
|
+
},
|
|
207
|
+
options: { bottomBar: 1 },
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
title: "Generating dashboard data",
|
|
211
|
+
task: async (ctx, task) => {
|
|
212
|
+
try {
|
|
213
|
+
execSync("npx tsx src/update-dashboard.ts", { cwd: projectDir, stdio: "pipe", timeout: 15000 });
|
|
214
|
+
task.output = "Dashboard ready";
|
|
215
|
+
} catch { task.output = "Dashboard generates on first run"; }
|
|
216
|
+
},
|
|
217
|
+
options: { bottomBar: 1 },
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
title: "Setting up scheduled tasks",
|
|
221
|
+
task: async (ctx, task) => {
|
|
222
|
+
try {
|
|
223
|
+
execSync("npx tsx src/cron-manager.ts setup", { cwd: projectDir, encoding: "utf-8", stdio: "pipe", timeout: 15000 });
|
|
224
|
+
task.output = "Crons configured";
|
|
225
|
+
} catch { task.output = "Crons set up on first start"; }
|
|
226
|
+
},
|
|
227
|
+
options: { bottomBar: 1 },
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
title: "Running health check",
|
|
231
|
+
task: async (ctx, task) => {
|
|
232
|
+
try {
|
|
233
|
+
const output = execSync("npx tsx src/health-check.ts", { cwd: projectDir, encoding: "utf-8", stdio: "pipe", timeout: 15000 });
|
|
234
|
+
task.output = output.trim().split("\n")[0] || "All systems nominal";
|
|
235
|
+
} catch { task.output = "Health check runs on first start"; }
|
|
236
|
+
},
|
|
237
|
+
options: { bottomBar: 1 },
|
|
238
|
+
},
|
|
239
|
+
],
|
|
240
|
+
{ rendererOptions: { showTimer: true, collapseSubtasks: false } }
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
await tasks.run();
|
|
244
|
+
|
|
245
|
+
// Phase 5.5: Auto-start (Startup folder — no admin needed)
|
|
246
|
+
if (wantAutoStart) {
|
|
247
|
+
console.log(sectionHeader("Auto-Start Configuration"));
|
|
248
|
+
const sessionName = (agentName as string).toLowerCase().replace(/[^a-z0-9]/g, "-");
|
|
249
|
+
try {
|
|
250
|
+
const startupDir = path.join(systemInfo.user.homedir, "AppData", "Roaming", "Microsoft", "Windows", "Start Menu", "Programs", "Startup");
|
|
251
|
+
if (fs.existsSync(startupDir)) {
|
|
252
|
+
const launcherPath = path.join(projectDir, "scripts", "launch.bat");
|
|
253
|
+
fs.writeFileSync(
|
|
254
|
+
path.join(startupDir, `MetaClaw-${sessionName}.bat`),
|
|
255
|
+
`@echo off\r\nstart "" "${launcherPath}"\r\n`
|
|
256
|
+
);
|
|
257
|
+
console.log(status.ok("Auto-start on login: added to Startup folder"));
|
|
258
|
+
}
|
|
259
|
+
} catch {
|
|
260
|
+
console.log(status.warn("Add scripts\\launch.bat to Startup folder manually"));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Phase 5.7: Shortcuts
|
|
265
|
+
const launcherContent = `@echo off\r\nstart "" cmd /k "cd /d ""${projectDir}"" && scripts\\launch.bat"\r\n`;
|
|
266
|
+
|
|
267
|
+
// Always create Agents folder launcher
|
|
268
|
+
try {
|
|
269
|
+
const agentsDir = path.join(systemInfo.user.desktop, "Agents");
|
|
270
|
+
fs.mkdirSync(agentsDir, { recursive: true });
|
|
271
|
+
fs.writeFileSync(path.join(agentsDir, `Launch ${agentName}.bat`), launcherContent);
|
|
272
|
+
console.log(status.ok(`Launcher: Desktop/Agents/Launch ${agentName}.bat`));
|
|
273
|
+
} catch {
|
|
274
|
+
console.log(status.warn("Could not create Agents folder launcher"));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Desktop shortcut if requested
|
|
278
|
+
if (result.answers.addDesktopShortcut) {
|
|
279
|
+
try {
|
|
280
|
+
fs.writeFileSync(
|
|
281
|
+
path.join(systemInfo.user.desktop, `${agentName}.bat`),
|
|
282
|
+
launcherContent
|
|
283
|
+
);
|
|
284
|
+
console.log(status.ok(`Desktop shortcut: ${agentName}.bat`));
|
|
285
|
+
} catch {
|
|
286
|
+
console.log(status.warn("Could not create Desktop shortcut"));
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Phase 6: Completion
|
|
291
|
+
console.log(completionScreen(agentName as string, projectDir, result.template.icon + " " + result.template.name));
|
|
292
|
+
|
|
293
|
+
// Phase 7: Launch dashboard + Claude
|
|
294
|
+
const shouldLaunch = await clack.confirm({
|
|
295
|
+
message: `Launch ${agentName} now?`,
|
|
296
|
+
initialValue: true,
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
if (!clack.isCancel(shouldLaunch) && shouldLaunch) {
|
|
300
|
+
console.log(sectionHeader("Launching " + agentName));
|
|
301
|
+
console.log("");
|
|
302
|
+
|
|
303
|
+
// Open dashboard in app mode
|
|
304
|
+
console.log(status.route("Opening Command Center..."));
|
|
305
|
+
try {
|
|
306
|
+
const dashPath = path.join(projectDir, "dashboard.html").replace(/\\/g, "/");
|
|
307
|
+
const edgePaths = [
|
|
308
|
+
"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",
|
|
309
|
+
"C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe",
|
|
310
|
+
];
|
|
311
|
+
let dashLaunched = false;
|
|
312
|
+
for (const ep of edgePaths) {
|
|
313
|
+
if (fs.existsSync(ep)) {
|
|
314
|
+
spawn(ep, [`--app=file:///${dashPath}`, "--window-size=1400,900"], { detached: true, stdio: "ignore" }).unref();
|
|
315
|
+
dashLaunched = true;
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (!dashLaunched) execSync(`start "" "${path.join(projectDir, "dashboard.html")}"`, { stdio: "ignore", shell: true });
|
|
320
|
+
console.log(status.ok("Command Center opened"));
|
|
321
|
+
} catch {
|
|
322
|
+
console.log(status.warn("Open dashboard manually: " + path.join(projectDir, "dashboard.html")));
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Launch Claude via launch.bat in its own window
|
|
326
|
+
console.log(status.route("Launching Claude Code..."));
|
|
327
|
+
try {
|
|
328
|
+
const launcherPath = path.join(projectDir, "scripts", "launch.bat");
|
|
329
|
+
execSync(`start "" "${launcherPath}"`, { stdio: "ignore", shell: true });
|
|
330
|
+
console.log(status.ok(agentName + " is launching in a new window"));
|
|
331
|
+
} catch {
|
|
332
|
+
console.log(status.warn("Double-click: " + path.join(projectDir, "scripts", "launch.bat")));
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
console.log("");
|
|
336
|
+
console.log(status.info("Files created:"));
|
|
337
|
+
console.log(muted(` Launch: scripts\\launch.bat`));
|
|
338
|
+
console.log(muted(` Dashboard: scripts\\open-dashboard.bat`));
|
|
339
|
+
console.log(muted(` Agents: Desktop\\Agents\\Launch ${agentName}.bat`));
|
|
340
|
+
} else {
|
|
341
|
+
console.log("");
|
|
342
|
+
console.log(muted(" To launch later:"));
|
|
343
|
+
console.log(brand(` Double-click: Desktop\\Agents\\Launch ${agentName}.bat`));
|
|
344
|
+
console.log("");
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
console.log("");
|
|
348
|
+
console.log(goldGradient(" Your agent is ready. Go build something amazing."));
|
|
349
|
+
console.log("");
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
main().catch((err) => {
|
|
353
|
+
console.error(accent(`\n Error: ${err.message}\n`));
|
|
354
|
+
process.exit(1);
|
|
355
|
+
});
|