@clawtrail/init 1.3.1 → 1.4.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 (2) hide show
  1. package/dist/index.js +100 -31
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -200,37 +200,94 @@ async function configureOpenClaw(apiKey, staging) {
200
200
  await fs.writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
201
201
  console.log(chalk.green(` Configured ClawTrail in ${chalk.cyan("~/.openclaw/openclaw.json")}`));
202
202
  }
203
- async function copyToOpenClawSkills(targetDir, staging) {
204
- const workspaceDir = path.join(os.homedir(), ".openclaw", "workspace");
205
- const skillFolder = staging ? "clawtrail-staging" : "clawtrail";
206
- const skillsDir = path.join(workspaceDir, "skills", skillFolder);
207
- await ensureDirectory(workspaceDir);
208
- await ensureDirectory(skillsDir);
209
- const copies = [
210
- { file: "HEARTBEAT.md", dest: path.join(workspaceDir, "HEARTBEAT.md") },
211
- { file: "SKILL.md", dest: path.join(skillsDir, "SKILL.md") }
203
+ async function findOpenClawSkillsDir() {
204
+ const candidates = [
205
+ // npm global (Linux default)
206
+ "/usr/lib/node_modules/openclaw/skills",
207
+ // npm global (macOS/nvm)
208
+ path.join(os.homedir(), ".nvm/versions/node", "**", "lib/node_modules/openclaw/skills"),
209
+ // npm global (macOS Homebrew)
210
+ "/usr/local/lib/node_modules/openclaw/skills",
211
+ // npm global (prefix-based)
212
+ "/usr/local/share/npm/lib/node_modules/openclaw/skills"
212
213
  ];
213
- let copied = 0;
214
- for (const { file, dest } of copies) {
215
- const src = path.join(targetDir, file);
214
+ try {
215
+ const { execSync } = await import("child_process");
216
+ const globalRoot = execSync("npm root -g", { timeout: 5e3 }).toString().trim();
217
+ const npmGlobalPath = path.join(globalRoot, "openclaw", "skills");
216
218
  try {
217
- await fs.copyFile(src, dest);
218
- copied++;
219
+ await fs.access(npmGlobalPath);
220
+ return npmGlobalPath;
219
221
  } catch {
220
222
  }
223
+ } catch {
224
+ }
225
+ for (const candidate of candidates) {
226
+ if (candidate.includes("**")) continue;
227
+ try {
228
+ await fs.access(candidate);
229
+ return candidate;
230
+ } catch {
231
+ }
232
+ }
233
+ return null;
234
+ }
235
+ async function copyToOpenClawSkills(targetDir, staging) {
236
+ const skillFolder = staging ? "clawtrail-staging" : "clawtrail";
237
+ const openclawSkillsDir = await findOpenClawSkillsDir();
238
+ if (openclawSkillsDir) {
239
+ const destDir = path.join(openclawSkillsDir, skillFolder);
240
+ await ensureDirectory(destDir);
241
+ const copies = [
242
+ { file: "SKILL.md", dest: path.join(destDir, "SKILL.md") },
243
+ { file: "HEARTBEAT.md", dest: path.join(destDir, "HEARTBEAT.md") }
244
+ ];
245
+ let copied = 0;
246
+ for (const { file, dest } of copies) {
247
+ const src = path.join(targetDir, file);
248
+ try {
249
+ await fs.copyFile(src, dest);
250
+ copied++;
251
+ } catch {
252
+ }
253
+ }
254
+ const prettyPath = openclawSkillsDir.replace(os.homedir(), "~");
255
+ console.log(
256
+ chalk.green(` Installed ${copied} file${copied !== 1 ? "s" : ""} to OpenClaw skills`)
257
+ );
258
+ console.log(chalk.gray(` ${chalk.cyan(`${prettyPath}/${skillFolder}/SKILL.md`)}`));
259
+ console.log(chalk.gray(` ${chalk.cyan(`${prettyPath}/${skillFolder}/HEARTBEAT.md`)}`));
260
+ } else {
261
+ const workspaceDir = path.join(os.homedir(), ".openclaw", "workspace");
262
+ const skillsDir = path.join(workspaceDir, "skills", skillFolder);
263
+ await ensureDirectory(workspaceDir);
264
+ await ensureDirectory(skillsDir);
265
+ const copies = [
266
+ { file: "SKILL.md", dest: path.join(skillsDir, "SKILL.md") },
267
+ { file: "HEARTBEAT.md", dest: path.join(skillsDir, "HEARTBEAT.md") }
268
+ ];
269
+ let copied = 0;
270
+ for (const { file, dest } of copies) {
271
+ const src = path.join(targetDir, file);
272
+ try {
273
+ await fs.copyFile(src, dest);
274
+ copied++;
275
+ } catch {
276
+ }
277
+ }
278
+ console.log(
279
+ chalk.yellow(` Could not find OpenClaw global install \u2014 placed files in workspace fallback`)
280
+ );
281
+ console.log(chalk.gray(` ${chalk.cyan(`~/.openclaw/workspace/skills/${skillFolder}/`)}`));
282
+ console.log(chalk.gray(` You may need to manually copy SKILL.md to your OpenClaw skills directory.`));
221
283
  }
222
- console.log(
223
- chalk.green(` Copied ${copied} file${copied !== 1 ? "s" : ""} to OpenClaw workspace`)
224
- );
225
- console.log(chalk.gray(` HEARTBEAT.md -> ${chalk.cyan("~/.openclaw/workspace/HEARTBEAT.md")}`));
226
- console.log(chalk.gray(` Skills -> ${chalk.cyan(`~/.openclaw/workspace/skills/${skillFolder}/`)}`));
227
284
  }
228
285
  async function main() {
229
286
  console.log(
230
287
  chalk.cyan.bold("\n ClawTrail Agent Skill Installer\n")
231
288
  );
232
289
  const program = new Command();
233
- program.name("clawtrail-init").description("Initialize ClawTrail skill files for AI agents").version("1.3.1").option("-d, --dir <path>", "Target directory", "./clawtrail-skills").option("-s, --staging", "Use staging environment", false).option("--no-register", "Skip agent registration").option("--no-interactive", "Skip interactive prompts").action(async (options) => {
290
+ program.name("clawtrail-init").description("Initialize ClawTrail skill files for AI agents").version("1.4.0").option("-d, --dir <path>", "Target directory", "./clawtrail-skills").option("-s, --staging", "Use staging environment", false).option("--no-register", "Skip agent registration").option("--no-interactive", "Skip interactive prompts").action(async (options) => {
234
291
  const targetDir = path.resolve(process.cwd(), options.dir);
235
292
  const staging = options.staging;
236
293
  await downloadSkillFiles(targetDir, staging);
@@ -265,15 +322,30 @@ async function main() {
265
322
  }
266
323
  if (options.register && options.interactive) {
267
324
  console.log(chalk.cyan("\n Agent Registration (Optional)\n"));
268
- const { shouldRegister } = await inquirer.prompt([
325
+ const { registrationChoice } = await inquirer.prompt([
269
326
  {
270
- type: "confirm",
271
- name: "shouldRegister",
272
- message: "Would you like to register an agent now?",
273
- default: false
327
+ type: "list",
328
+ name: "registrationChoice",
329
+ message: "How would you like to register your agent?",
330
+ choices: [
331
+ { name: "Let my bot register itself (recommended for OpenClaw)", value: "bot" },
332
+ { name: "Enter agent info manually now", value: "manual" },
333
+ { name: "Skip registration", value: "skip" }
334
+ ],
335
+ default: hasOpenClaw ? "bot" : "manual"
274
336
  }
275
337
  ]);
276
- if (shouldRegister) {
338
+ if (registrationChoice === "bot") {
339
+ console.log(chalk.green("\n Got it! Your bot will register itself.\n"));
340
+ console.log(chalk.gray(" Your bot can register using the SKILL.md instructions."));
341
+ console.log(chalk.gray(" It will call POST /api/agents/register with its own info."));
342
+ if (hasOpenClaw) {
343
+ console.log(chalk.gray(" The ClawTrail skill file has been placed in your OpenClaw workspace."));
344
+ console.log(chalk.gray(" Just start your bot \u2014 it will read the skill and register automatically.\n"));
345
+ } else {
346
+ console.log(chalk.gray(" Point your agent at the SKILL.md file to get started.\n"));
347
+ }
348
+ } else if (registrationChoice === "manual") {
277
349
  const answers = await inquirer.prompt([
278
350
  {
279
351
  type: "input",
@@ -312,7 +384,7 @@ async function main() {
312
384
  { name: "A2A Agent", value: "a2a-agent" },
313
385
  { name: "ERC-8004 Agent", value: "erc8004" }
314
386
  ],
315
- default: "openclaw"
387
+ default: hasOpenClaw ? "openclaw" : "custom"
316
388
  },
317
389
  {
318
390
  type: "input",
@@ -411,10 +483,7 @@ async function main() {
411
483
  chalk.white("5. ") + chalk.gray("(OpenClaw) Plugin config at ") + chalk.cyan("~/.openclaw/openclaw.json")
412
484
  );
413
485
  console.log(
414
- chalk.white("6. ") + chalk.gray("(OpenClaw) HEARTBEAT.md at ") + chalk.cyan("~/.openclaw/workspace/HEARTBEAT.md")
415
- );
416
- console.log(
417
- chalk.white("7. ") + chalk.gray("(OpenClaw) Skill files at ") + chalk.cyan("~/.openclaw/workspace/skills/clawtrail/")
486
+ chalk.white("6. ") + chalk.gray("(OpenClaw) Skill installed to OpenClaw skills directory")
418
487
  );
419
488
  }
420
489
  const env = staging ? "staging" : "production";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawtrail/init",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "description": "CLI installer for ClawTrail AI agent skill files",
5
5
  "main": "dist/index.js",
6
6
  "bin": {