@clawtrail/init 2.2.0 → 2.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 (2) hide show
  1. package/dist/index.js +108 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -254,12 +254,114 @@ async function restartGateway(oldVersion, newVersion) {
254
254
  return false;
255
255
  }
256
256
  }
257
+ async function handleUninstall(staging) {
258
+ console.log(chalk.yellow.bold("\n Uninstalling ClawTrail...\n"));
259
+ const openclawDir = path.join(os.homedir(), ".openclaw");
260
+ const skillFolder = staging ? "clawtrail-staging" : "clawtrail";
261
+ const removed = [];
262
+ const spinner1 = ora("Removing skill files...").start();
263
+ const filesToRemove = [
264
+ path.join(openclawDir, "workspace", "HEARTBEAT.md"),
265
+ path.join(openclawDir, "skills", skillFolder, "SKILL.md")
266
+ ];
267
+ for (const filePath of filesToRemove) {
268
+ try {
269
+ await fs.unlink(filePath);
270
+ removed.push(filePath.replace(os.homedir(), "~"));
271
+ } catch {
272
+ }
273
+ }
274
+ try {
275
+ await fs.rmdir(path.join(openclawDir, "skills", skillFolder));
276
+ } catch {
277
+ }
278
+ if (removed.length > 0) {
279
+ spinner1.succeed(chalk.green(`Removed ${removed.length} skill files`));
280
+ } else {
281
+ spinner1.info(chalk.gray("No skill files found to remove"));
282
+ }
283
+ const spinner2 = ora("Cleaning OpenClaw config...").start();
284
+ const configPath = path.join(openclawDir, "openclaw.json");
285
+ let configCleaned = false;
286
+ try {
287
+ const raw = await fs.readFile(configPath, "utf-8");
288
+ const config = JSON5.parse(raw);
289
+ if (config.agents?.defaults?.heartbeat) {
290
+ delete config.agents.defaults.heartbeat;
291
+ if (Object.keys(config.agents.defaults).length === 0) delete config.agents.defaults;
292
+ if (Object.keys(config.agents).length === 0) delete config.agents;
293
+ }
294
+ if (config.skills?.entries?.clawtrail) {
295
+ delete config.skills.entries.clawtrail;
296
+ if (Object.keys(config.skills.entries).length === 0) delete config.skills.entries;
297
+ if (Object.keys(config.skills).length === 0) delete config.skills;
298
+ }
299
+ if (config.skills?.entries?.["clawtrail-staging"]) {
300
+ delete config.skills.entries["clawtrail-staging"];
301
+ if (Object.keys(config.skills.entries).length === 0) delete config.skills.entries;
302
+ if (Object.keys(config.skills).length === 0) delete config.skills;
303
+ }
304
+ await fs.writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
305
+ configCleaned = true;
306
+ spinner2.succeed(chalk.green("Removed ClawTrail config from openclaw.json"));
307
+ } catch {
308
+ spinner2.info(chalk.gray("No openclaw.json found or nothing to clean"));
309
+ }
310
+ let gatewayRestarted = false;
311
+ if (isGatewayRunning()) {
312
+ const cleared = await clearOpenClawSessions();
313
+ const spinner3 = ora("Restarting gateway...").start();
314
+ try {
315
+ try {
316
+ execSync("pkill -f openclaw-gateway", { stdio: "pipe" });
317
+ } catch {
318
+ }
319
+ await new Promise((r) => setTimeout(r, 2e3));
320
+ try {
321
+ const logPath = path.join(os.homedir(), "openclaw-gateway.log");
322
+ execSync(`nohup openclaw-gateway > ${logPath} 2>&1 &`, {
323
+ stdio: "pipe",
324
+ shell: "/bin/bash"
325
+ });
326
+ } catch {
327
+ }
328
+ await new Promise((r) => setTimeout(r, 4e3));
329
+ gatewayRestarted = isGatewayRunning();
330
+ if (gatewayRestarted) {
331
+ spinner3.succeed(
332
+ chalk.green(`Gateway restarted \u2014 ${cleared} cached sessions cleared`)
333
+ );
334
+ } else {
335
+ spinner3.warn(chalk.yellow("Gateway killed but may not have restarted"));
336
+ }
337
+ } catch (err) {
338
+ const message = err instanceof Error ? err.message : String(err);
339
+ spinner3.fail(chalk.red(`Gateway restart failed: ${message}`));
340
+ }
341
+ }
342
+ console.log(chalk.yellow.bold("\n \u2500\u2500\u2500 Uninstall Summary \u2500\u2500\u2500\n"));
343
+ if (removed.length > 0) {
344
+ for (const f of removed) {
345
+ console.log(chalk.white(" Removed: ") + chalk.red(f));
346
+ }
347
+ }
348
+ if (configCleaned) {
349
+ console.log(chalk.white(" Config: ") + chalk.green("cleaned ~/.openclaw/openclaw.json"));
350
+ }
351
+ if (gatewayRestarted) {
352
+ console.log(chalk.white(" Gateway: ") + chalk.green("restarted (ClawTrail skill removed)"));
353
+ }
354
+ console.log(chalk.yellow("\n ClawTrail has been uninstalled.\n"));
355
+ console.log(
356
+ chalk.gray(" To reinstall: ") + chalk.cyan("npx @clawtrail/init@latest\n")
357
+ );
358
+ }
257
359
  async function main() {
258
360
  console.log(chalk.cyan.bold("\n ClawTrail Agent Installer\n"));
259
361
  const program = new Command();
260
362
  program.name("clawtrail-init").description(
261
363
  "Install ClawTrail skill files, configure heartbeat, and optionally register an agent"
262
- ).version("2.2.0").option(
364
+ ).version("2.3.0").option(
263
365
  "-d, --dir <path>",
264
366
  "Download directory for skill files",
265
367
  "./clawtrail-skills"
@@ -276,7 +378,11 @@ async function main() {
276
378
  ).option(
277
379
  "--api-key <key>",
278
380
  "Existing API key (skip registration, just configure)"
279
- ).option("--no-restart", "Skip gateway restart after updating files").action(async (options) => {
381
+ ).option("--no-restart", "Skip gateway restart after updating files").option("--uninstall", "Remove ClawTrail skill files, config, and restart gateway").action(async (options) => {
382
+ if (options.uninstall) {
383
+ await handleUninstall(options.staging);
384
+ return;
385
+ }
280
386
  const staging = options.staging;
281
387
  const env = staging ? "staging" : "production";
282
388
  const hasOpenClaw = await detectOpenClaw();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawtrail/init",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "description": "CLI installer for ClawTrail AI agent skill files",
5
5
  "main": "dist/index.js",
6
6
  "bin": {