soulhubcli 1.0.11 → 1.0.13

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.cjs +190 -115
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -13284,6 +13284,7 @@ var import_node_fs8 = __toESM(require("fs"), 1);
13284
13284
  var import_node_path11 = __toESM(require("path"), 1);
13285
13285
  var import_node_os2 = __toESM(require("os"), 1);
13286
13286
  var import_node_child_process = require("child_process");
13287
+ var import_node_readline = __toESM(require("readline"), 1);
13287
13288
 
13288
13289
  // node_modules/js-yaml/dist/js-yaml.mjs
13289
13290
  function isNothing(subject) {
@@ -19023,6 +19024,12 @@ function copyAgentFilesFromPackage(packageDir, targetDir) {
19023
19024
  import_node_fs8.default.copyFileSync(sourcePath, import_node_path11.default.join(targetDir, destName));
19024
19025
  }
19025
19026
  }
19027
+ const skillsSource = import_node_path11.default.join(packageDir, "skills");
19028
+ if (import_node_fs8.default.existsSync(skillsSource) && import_node_fs8.default.statSync(skillsSource).isDirectory()) {
19029
+ const skillsTarget = import_node_path11.default.join(targetDir, "skills");
19030
+ import_node_fs8.default.cpSync(skillsSource, skillsTarget, { recursive: true });
19031
+ logger.debug(`Skills directory copied`, { from: skillsSource, to: skillsTarget });
19032
+ }
19026
19033
  }
19027
19034
  function findOpenClawDir(customDir) {
19028
19035
  if (customDir) {
@@ -19032,7 +19039,7 @@ function findOpenClawDir(customDir) {
19032
19039
  }
19033
19040
  return resolved;
19034
19041
  }
19035
- const envHome = process.env.OPENCLAW_HOME;
19042
+ const envHome = process.env.OPENCLAW_HOME || process.env.LIGHTCLAW_HOME;
19036
19043
  if (envHome) {
19037
19044
  const resolved = import_node_path11.default.resolve(envHome);
19038
19045
  if (import_node_fs8.default.existsSync(resolved)) {
@@ -19040,9 +19047,12 @@ function findOpenClawDir(customDir) {
19040
19047
  }
19041
19048
  return resolved;
19042
19049
  }
19050
+ const home = process.env.HOME || "~";
19043
19051
  const candidates = [
19044
- import_node_path11.default.join(process.env.HOME || "~", ".openclaw"),
19045
- import_node_path11.default.join(process.cwd(), ".openclaw")
19052
+ import_node_path11.default.join(home, ".openclaw"),
19053
+ import_node_path11.default.join(home, ".lightclaw"),
19054
+ import_node_path11.default.join(process.cwd(), ".openclaw"),
19055
+ import_node_path11.default.join(process.cwd(), ".lightclaw")
19046
19056
  ];
19047
19057
  for (const candidate of candidates) {
19048
19058
  if (import_node_fs8.default.existsSync(candidate)) {
@@ -19051,6 +19061,58 @@ function findOpenClawDir(customDir) {
19051
19061
  }
19052
19062
  return null;
19053
19063
  }
19064
+ function findAllClawDirs(customDir) {
19065
+ if (customDir) {
19066
+ const resolved = import_node_path11.default.resolve(customDir);
19067
+ return import_node_fs8.default.existsSync(resolved) ? [resolved] : [resolved];
19068
+ }
19069
+ const envHome = process.env.OPENCLAW_HOME || process.env.LIGHTCLAW_HOME;
19070
+ if (envHome) {
19071
+ const resolved = import_node_path11.default.resolve(envHome);
19072
+ return [resolved];
19073
+ }
19074
+ const home = process.env.HOME || "~";
19075
+ const candidates = [
19076
+ import_node_path11.default.join(home, ".openclaw"),
19077
+ import_node_path11.default.join(home, ".lightclaw"),
19078
+ import_node_path11.default.join(process.cwd(), ".openclaw"),
19079
+ import_node_path11.default.join(process.cwd(), ".lightclaw")
19080
+ ];
19081
+ return candidates.filter((c) => import_node_fs8.default.existsSync(c));
19082
+ }
19083
+ async function promptSelectClawDir(customDir) {
19084
+ const dirs = findAllClawDirs(customDir);
19085
+ if (dirs.length === 0) {
19086
+ return null;
19087
+ }
19088
+ if (dirs.length === 1) {
19089
+ return dirs[0];
19090
+ }
19091
+ console.log();
19092
+ console.log(" Detected multiple Claw installations:");
19093
+ console.log();
19094
+ dirs.forEach((dir, index) => {
19095
+ const brand = detectClawBrand(dir);
19096
+ console.log(` ${index + 1}) ${brand} ${dir}`);
19097
+ });
19098
+ console.log();
19099
+ const rl = import_node_readline.default.createInterface({
19100
+ input: process.stdin,
19101
+ output: process.stdout
19102
+ });
19103
+ return new Promise((resolve) => {
19104
+ rl.question(` Please select target (1-${dirs.length}): `, (answer) => {
19105
+ rl.close();
19106
+ const idx = parseInt(answer.trim(), 10);
19107
+ if (idx >= 1 && idx <= dirs.length) {
19108
+ resolve(dirs[idx - 1]);
19109
+ } else {
19110
+ console.log(" Invalid selection, operation cancelled.");
19111
+ resolve(null);
19112
+ }
19113
+ });
19114
+ });
19115
+ }
19054
19116
  function getConfigPath() {
19055
19117
  const home = process.env.HOME || "~";
19056
19118
  return import_node_path11.default.join(home, ".soulhub", "config.json");
@@ -19105,8 +19167,22 @@ function checkMainAgentExists(clawDir) {
19105
19167
  workspaceDir
19106
19168
  };
19107
19169
  }
19170
+ function detectClawBrand(clawDir) {
19171
+ const dirName = import_node_path11.default.basename(clawDir).toLowerCase();
19172
+ if (dirName.includes("lightclaw")) {
19173
+ return "LightClaw";
19174
+ }
19175
+ if (import_node_fs8.default.existsSync(import_node_path11.default.join(clawDir, "lightclaw.json"))) {
19176
+ return "LightClaw";
19177
+ }
19178
+ return "OpenClaw";
19179
+ }
19180
+ function getClawConfigFileName(clawDir) {
19181
+ const brand = detectClawBrand(clawDir);
19182
+ return brand === "LightClaw" ? "lightclaw.json" : "openclaw.json";
19183
+ }
19108
19184
  function getOpenClawConfigPath(clawDir) {
19109
- return import_node_path11.default.join(clawDir, "openclaw.json");
19185
+ return import_node_path11.default.join(clawDir, getClawConfigFileName(clawDir));
19110
19186
  }
19111
19187
  function readOpenClawConfig(clawDir) {
19112
19188
  const configPath = getOpenClawConfigPath(clawDir);
@@ -19202,32 +19278,6 @@ function detectPackageKind(dir) {
19202
19278
  }
19203
19279
  return "unknown";
19204
19280
  }
19205
- function checkOpenClawInstalled(customDir) {
19206
- const clawDir = findOpenClawDir(customDir);
19207
- if (clawDir) {
19208
- return {
19209
- installed: true,
19210
- clawDir,
19211
- message: `OpenClaw detected at: ${clawDir}`
19212
- };
19213
- }
19214
- try {
19215
- (0, import_node_child_process.execSync)("which openclaw 2>/dev/null || where openclaw 2>nul", {
19216
- stdio: "pipe"
19217
- });
19218
- return {
19219
- installed: true,
19220
- clawDir: null,
19221
- message: "OpenClaw command found in PATH, but workspace directory not detected."
19222
- };
19223
- } catch {
19224
- }
19225
- return {
19226
- installed: false,
19227
- clawDir: null,
19228
- message: "OpenClaw is not installed. Please install OpenClaw first, use --claw-dir to specify OpenClaw directory, or set OPENCLAW_HOME environment variable."
19229
- };
19230
- }
19231
19281
  function backupAgentWorkspace(workspaceDir) {
19232
19282
  if (!import_node_fs8.default.existsSync(workspaceDir)) {
19233
19283
  return null;
@@ -19327,7 +19377,7 @@ function generateBackupId() {
19327
19377
  }
19328
19378
  function createBackupRecord(installType, packageName, clawDir) {
19329
19379
  let openclawJsonSnapshot = null;
19330
- const configPath = import_node_path11.default.join(clawDir, "openclaw.json");
19380
+ const configPath = getOpenClawConfigPath(clawDir);
19331
19381
  if (import_node_fs8.default.existsSync(configPath)) {
19332
19382
  try {
19333
19383
  openclawJsonSnapshot = import_node_fs8.default.readFileSync(configPath, "utf-8");
@@ -19369,30 +19419,31 @@ var CATEGORY_LABELS = {
19369
19419
  };
19370
19420
  function registerAgentToOpenClaw(agentName, workspaceDir, _clawDir) {
19371
19421
  const agentId = agentName.toLowerCase().replace(/[\s_]+/g, "-");
19372
- logger.debug(`Registering agent to OpenClaw`, { agentId, workspaceDir });
19422
+ logger.debug(`Registering agent to OpenClaw/LightClaw`, { agentId, workspaceDir });
19373
19423
  try {
19424
+ const clawCmd = detectClawCommand();
19374
19425
  (0, import_node_child_process.execSync)(
19375
- `openclaw agents add "${agentId}" --workspace "${workspaceDir}" --non-interactive --json`,
19426
+ `${clawCmd} agents add "${agentId}" --workspace "${workspaceDir}" --non-interactive --json`,
19376
19427
  { stdio: "pipe", timeout: 15e3 }
19377
19428
  );
19378
19429
  return {
19379
19430
  success: true,
19380
- message: `Agent "${agentId}" registered via OpenClaw CLI.`
19431
+ message: `Agent "${agentId}" registered via CLI.`
19381
19432
  };
19382
19433
  } catch (cliError) {
19383
19434
  const stderr = cliError && typeof cliError === "object" && "stderr" in cliError ? String(cliError.stderr) : "";
19384
19435
  if (stderr.includes("already exists")) {
19385
19436
  return {
19386
19437
  success: true,
19387
- message: `Agent "${agentId}" already registered in OpenClaw.`
19438
+ message: `Agent "${agentId}" already registered.`
19388
19439
  };
19389
19440
  }
19390
19441
  const isCommandNotFound = cliError && typeof cliError === "object" && "code" in cliError && cliError.code === "ENOENT" || stderr.includes("not found") || stderr.includes("not recognized");
19391
19442
  if (isCommandNotFound) {
19392
- logger.error(`OpenClaw CLI not found`);
19443
+ logger.error(`OpenClaw/LightClaw CLI not found`);
19393
19444
  return {
19394
19445
  success: false,
19395
- message: "OpenClaw CLI not found. Please install OpenClaw first: https://github.com/anthropics/openclaw"
19446
+ message: "OpenClaw/LightClaw CLI not found. Please install first."
19396
19447
  };
19397
19448
  }
19398
19449
  const errMsg = cliError instanceof Error ? cliError.message : String(cliError);
@@ -19403,17 +19454,31 @@ function registerAgentToOpenClaw(agentName, workspaceDir, _clawDir) {
19403
19454
  };
19404
19455
  }
19405
19456
  }
19457
+ function detectClawCommand() {
19458
+ try {
19459
+ (0, import_node_child_process.execSync)("which lightclaw 2>/dev/null || where lightclaw 2>nul", { stdio: "pipe" });
19460
+ return "lightclaw";
19461
+ } catch {
19462
+ }
19463
+ try {
19464
+ (0, import_node_child_process.execSync)("which openclaw 2>/dev/null || where openclaw 2>nul", { stdio: "pipe" });
19465
+ return "openclaw";
19466
+ } catch {
19467
+ }
19468
+ return "openclaw";
19469
+ }
19406
19470
  function restartOpenClawGateway() {
19407
- logger.debug(`Restarting OpenClaw Gateway`);
19471
+ const clawCmd = detectClawCommand();
19472
+ logger.debug(`Restarting ${clawCmd} Gateway`);
19408
19473
  try {
19409
- (0, import_node_child_process.execSync)("openclaw gateway restart", {
19474
+ (0, import_node_child_process.execSync)(`${clawCmd} gateway restart`, {
19410
19475
  stdio: "pipe",
19411
19476
  timeout: 3e4
19412
19477
  // 30 秒超时
19413
19478
  });
19414
19479
  return {
19415
19480
  success: true,
19416
- message: "OpenClaw Gateway restarted successfully."
19481
+ message: `${clawCmd} Gateway restarted successfully.`
19417
19482
  };
19418
19483
  } catch (error) {
19419
19484
  const stderr = error && typeof error === "object" && "stderr" in error ? String(error.stderr).trim() : "";
@@ -19653,12 +19718,18 @@ function createSpinner(initialText = "") {
19653
19718
  // src/commands/install.ts
19654
19719
  var import_node_fs9 = __toESM(require("fs"), 1);
19655
19720
  var import_node_path12 = __toESM(require("path"), 1);
19721
+ async function resolveClawDir(clawDir) {
19722
+ if (clawDir) {
19723
+ return findOpenClawDir(clawDir);
19724
+ }
19725
+ return promptSelectClawDir();
19726
+ }
19656
19727
  var installCommand = new Command("install").description("Install an agent or team from the SoulHub registry").argument("[name]", "Agent or team name to install").option("--from <source>", "Install from a local directory, ZIP file, or URL").option(
19657
19728
  "--dir <path>",
19658
- "Target directory (defaults to OpenClaw workspace)"
19729
+ "Target directory (defaults to OpenClaw/LightClaw workspace)"
19659
19730
  ).option(
19660
19731
  "--claw-dir <path>",
19661
- "OpenClaw installation directory (overrides OPENCLAW_HOME env var, defaults to ~/.openclaw)"
19732
+ "OpenClaw/LightClaw installation directory (overrides OPENCLAW_HOME/LIGHTCLAW_HOME env var, defaults to ~/.openclaw or ~/.lightclaw)"
19662
19733
  ).action(async (name, options) => {
19663
19734
  try {
19664
19735
  if (options.from) {
@@ -19703,14 +19774,18 @@ async function installFromRegistry(name, targetDir, clawDir) {
19703
19774
  }
19704
19775
  async function installSingleAgent(name, targetDir, clawDir) {
19705
19776
  const spinner = createSpinner(`Checking environment...`).start();
19777
+ let selectedClawDir = null;
19706
19778
  if (!targetDir) {
19707
- const clawCheck = checkOpenClawInstalled(clawDir);
19708
- if (!clawCheck.installed) {
19709
- spinner.fail("OpenClaw is not installed.");
19779
+ spinner.stop();
19780
+ selectedClawDir = await resolveClawDir(clawDir);
19781
+ if (!selectedClawDir) {
19782
+ console.log(source_default.red("OpenClaw/LightClaw workspace directory not found."));
19710
19783
  printOpenClawInstallHelp();
19711
19784
  return;
19712
19785
  }
19713
- spinner.text = source_default.dim(`OpenClaw detected: ${clawCheck.clawDir || "via PATH"}`);
19786
+ spinner.start();
19787
+ const brand = detectClawBrand(selectedClawDir);
19788
+ spinner.text = source_default.dim(`${brand} detected: ${selectedClawDir}`);
19714
19789
  }
19715
19790
  spinner.text = `Fetching agent ${source_default.cyan(name)}...`;
19716
19791
  const index = await fetchIndex();
@@ -19724,18 +19799,11 @@ async function installSingleAgent(name, targetDir, clawDir) {
19724
19799
  if (targetDir) {
19725
19800
  workspaceDir = import_node_path12.default.resolve(targetDir);
19726
19801
  } else {
19727
- const resolvedClawDir = findOpenClawDir(clawDir);
19728
- if (!resolvedClawDir) {
19729
- spinner.fail("OpenClaw workspace directory not found.");
19730
- printOpenClawInstallHelp();
19731
- return;
19732
- }
19733
- workspaceDir = getMainWorkspaceDir(resolvedClawDir);
19802
+ workspaceDir = getMainWorkspaceDir(selectedClawDir);
19734
19803
  }
19735
- const resolvedClawDirForBackup = findOpenClawDir(clawDir);
19736
- const backupRecord = !targetDir ? createBackupRecord("single-agent", name, resolvedClawDirForBackup) : null;
19804
+ const backupRecord = !targetDir ? createBackupRecord("single-agent", name, selectedClawDir) : null;
19737
19805
  if (!targetDir) {
19738
- const mainCheck = checkMainAgentExists(resolvedClawDirForBackup);
19806
+ const mainCheck = checkMainAgentExists(selectedClawDir);
19739
19807
  if (mainCheck.hasContent) {
19740
19808
  spinner.warn(
19741
19809
  `Existing main agent detected. Backing up workspace...`
@@ -19763,9 +19831,8 @@ async function installSingleAgent(name, targetDir, clawDir) {
19763
19831
  }
19764
19832
  if (!targetDir) {
19765
19833
  spinner.text = `Registering ${source_default.cyan(agent.displayName)} as main agent...`;
19766
- const resolvedClawDir = findOpenClawDir(clawDir);
19767
- addAgentToOpenClawConfig(resolvedClawDir, "main", name, true);
19768
- spinner.text = source_default.dim(`Main agent registered in openclaw.json`);
19834
+ addAgentToOpenClawConfig(selectedClawDir, "main", name, true);
19835
+ spinner.text = source_default.dim(`Main agent registered in config`);
19769
19836
  }
19770
19837
  spinner.text = `Downloading ${source_default.cyan(agent.displayName)} package...`;
19771
19838
  const pkgDir = await downloadAgentPackage(name, agent.version);
@@ -19791,19 +19858,19 @@ async function installSingleAgent(name, targetDir, clawDir) {
19791
19858
  }
19792
19859
  async function installRecipeFromRegistry(name, recipe, targetDir, clawDir) {
19793
19860
  const spinner = createSpinner(`Installing team ${source_default.cyan(recipe.displayName)}...`).start();
19794
- if (!targetDir) {
19795
- const clawCheck = checkOpenClawInstalled(clawDir);
19796
- if (!clawCheck.installed) {
19797
- spinner.fail("OpenClaw is not installed.");
19861
+ let resolvedClawDir;
19862
+ if (targetDir) {
19863
+ resolvedClawDir = import_node_path12.default.resolve(targetDir);
19864
+ } else {
19865
+ spinner.stop();
19866
+ const selected = await resolveClawDir(clawDir);
19867
+ if (!selected) {
19868
+ console.log(source_default.red("OpenClaw/LightClaw workspace directory not found."));
19798
19869
  printOpenClawInstallHelp();
19799
19870
  return;
19800
19871
  }
19801
- }
19802
- const resolvedClawDir = targetDir ? import_node_path12.default.resolve(targetDir) : findOpenClawDir(clawDir);
19803
- if (!resolvedClawDir) {
19804
- spinner.fail("OpenClaw workspace directory not found.");
19805
- printOpenClawInstallHelp();
19806
- return;
19872
+ resolvedClawDir = selected;
19873
+ spinner.start();
19807
19874
  }
19808
19875
  spinner.text = `Fetching team configuration...`;
19809
19876
  let pkg;
@@ -19951,29 +20018,26 @@ async function installSingleAgentFromDir(packageDir, targetDir, clawDir) {
19951
20018
  const spinner = createSpinner("Installing single agent...").start();
19952
20019
  const pkg = readSoulHubPackage(packageDir);
19953
20020
  const agentName = pkg?.name || import_node_path12.default.basename(packageDir);
20021
+ let selectedClawDir = null;
19954
20022
  if (!targetDir) {
19955
- const clawCheck = checkOpenClawInstalled(clawDir);
19956
- if (!clawCheck.installed) {
19957
- spinner.fail("OpenClaw is not installed.");
20023
+ spinner.stop();
20024
+ selectedClawDir = await resolveClawDir(clawDir);
20025
+ if (!selectedClawDir) {
20026
+ console.log(source_default.red("OpenClaw/LightClaw workspace directory not found."));
19958
20027
  printOpenClawInstallHelp();
19959
20028
  return;
19960
20029
  }
20030
+ spinner.start();
19961
20031
  }
19962
20032
  let workspaceDir;
19963
20033
  if (targetDir) {
19964
20034
  workspaceDir = import_node_path12.default.resolve(targetDir);
19965
20035
  } else {
19966
- const resolvedClawDir = findOpenClawDir(clawDir);
19967
- if (!resolvedClawDir) {
19968
- spinner.fail("OpenClaw workspace directory not found.");
19969
- return;
19970
- }
19971
- workspaceDir = getMainWorkspaceDir(resolvedClawDir);
20036
+ workspaceDir = getMainWorkspaceDir(selectedClawDir);
19972
20037
  }
19973
- const localBackupRecord = !targetDir ? createBackupRecord("single-agent-local", agentName, findOpenClawDir(clawDir)) : null;
20038
+ const localBackupRecord = !targetDir ? createBackupRecord("single-agent-local", agentName, selectedClawDir) : null;
19974
20039
  if (!targetDir) {
19975
- const resolvedClawDir = findOpenClawDir(clawDir);
19976
- const mainCheck = checkMainAgentExists(resolvedClawDir);
20040
+ const mainCheck = checkMainAgentExists(selectedClawDir);
19977
20041
  if (mainCheck.hasContent) {
19978
20042
  spinner.warn("Existing main agent detected. Backing up...");
19979
20043
  const backupDir = backupAgentWorkspace(workspaceDir);
@@ -19994,8 +20058,7 @@ async function installSingleAgentFromDir(packageDir, targetDir, clawDir) {
19994
20058
  }
19995
20059
  if (!targetDir) {
19996
20060
  spinner.text = `Registering ${source_default.cyan(agentName)} as main agent...`;
19997
- const resolvedClawDir = findOpenClawDir(clawDir);
19998
- addAgentToOpenClawConfig(resolvedClawDir, "main", agentName, true);
20061
+ addAgentToOpenClawConfig(selectedClawDir, "main", agentName, true);
19999
20062
  }
20000
20063
  spinner.text = `Copying soul files...`;
20001
20064
  copyAgentFilesFromDir(packageDir, workspaceDir);
@@ -20022,18 +20085,19 @@ async function installTeamFromDir(packageDir, targetDir, clawDir) {
20022
20085
  spinner.fail("Invalid team package. Missing soulhub.yaml.");
20023
20086
  return;
20024
20087
  }
20025
- if (!targetDir) {
20026
- const clawCheck = checkOpenClawInstalled(clawDir);
20027
- if (!clawCheck.installed) {
20028
- spinner.fail("OpenClaw is not installed.");
20088
+ let resolvedClawDir;
20089
+ if (targetDir) {
20090
+ resolvedClawDir = import_node_path12.default.resolve(targetDir);
20091
+ } else {
20092
+ spinner.stop();
20093
+ const selected = await resolveClawDir(clawDir);
20094
+ if (!selected) {
20095
+ console.log(source_default.red("OpenClaw/LightClaw workspace directory not found."));
20029
20096
  printOpenClawInstallHelp();
20030
20097
  return;
20031
20098
  }
20032
- }
20033
- const resolvedClawDir = targetDir ? import_node_path12.default.resolve(targetDir) : findOpenClawDir(clawDir);
20034
- if (!resolvedClawDir) {
20035
- spinner.fail("OpenClaw workspace directory not found.");
20036
- return;
20099
+ resolvedClawDir = selected;
20100
+ spinner.start();
20037
20101
  }
20038
20102
  const teamBackupRecord = !targetDir ? createBackupRecord("team-local", pkg.name, resolvedClawDir) : null;
20039
20103
  if (!targetDir) {
@@ -20131,13 +20195,19 @@ async function installTeamFromDir(packageDir, targetDir, clawDir) {
20131
20195
  }
20132
20196
  function copyAgentFilesFromDir(sourceDir, targetDir) {
20133
20197
  const filesToCopy = ["IDENTITY.md", "SOUL.md", "USER.md", "TOOLS.md", "AGENTS.md", "HEARTBEAT.md"];
20198
+ import_node_fs9.default.mkdirSync(targetDir, { recursive: true });
20134
20199
  for (const fileName of filesToCopy) {
20135
20200
  const sourcePath = import_node_path12.default.join(sourceDir, fileName);
20136
20201
  if (import_node_fs9.default.existsSync(sourcePath)) {
20137
- import_node_fs9.default.mkdirSync(targetDir, { recursive: true });
20138
20202
  import_node_fs9.default.copyFileSync(sourcePath, import_node_path12.default.join(targetDir, fileName));
20139
20203
  }
20140
20204
  }
20205
+ const skillsSource = import_node_path12.default.join(sourceDir, "skills");
20206
+ if (import_node_fs9.default.existsSync(skillsSource) && import_node_fs9.default.statSync(skillsSource).isDirectory()) {
20207
+ const skillsTarget = import_node_path12.default.join(targetDir, "skills");
20208
+ import_node_fs9.default.cpSync(skillsSource, skillsTarget, { recursive: true });
20209
+ logger.debug(`Skills directory copied`, { from: skillsSource, to: skillsTarget });
20210
+ }
20141
20211
  }
20142
20212
  async function installDispatcher(dispatcher, resolvedClawDir, clawDir, targetDir, spinner, backupRecord) {
20143
20213
  const mainWorkspace = targetDir ? import_node_path12.default.join(resolvedClawDir, "workspace") : getMainWorkspaceDir(resolvedClawDir);
@@ -20187,11 +20257,11 @@ async function extractZipToDir(zip, targetDir) {
20187
20257
  }
20188
20258
  }
20189
20259
  function printOpenClawInstallHelp() {
20190
- console.log(source_default.dim(" Please install OpenClaw first, or use one of the following options:"));
20191
- console.log(source_default.dim(" --claw-dir <path> Specify OpenClaw installation directory"));
20192
- console.log(source_default.dim(" --dir <path> Specify agent target directory directly"));
20193
- console.log(source_default.dim(" OPENCLAW_HOME=<path> Set environment variable"));
20194
- console.log(source_default.dim(" Visit: https://github.com/anthropics/openclaw for installation instructions."));
20260
+ console.log(source_default.dim(" Please install OpenClaw or LightClaw first, or use one of the following options:"));
20261
+ console.log(source_default.dim(" --claw-dir <path> Specify OpenClaw/LightClaw installation directory"));
20262
+ console.log(source_default.dim(" --dir <path> Specify agent target directory directly"));
20263
+ console.log(source_default.dim(" OPENCLAW_HOME=<path> Set environment variable (for OpenClaw)"));
20264
+ console.log(source_default.dim(" LIGHTCLAW_HOME=<path> Set environment variable (for LightClaw)"));
20195
20265
  }
20196
20266
  function printTeamSummary(pkg, workerIds) {
20197
20267
  console.log();
@@ -20209,15 +20279,17 @@ function printTeamSummary(pkg, workerIds) {
20209
20279
  console.log();
20210
20280
  }
20211
20281
  async function tryRestartGateway() {
20212
- const restartSpinner = createSpinner("Restarting OpenClaw Gateway...").start();
20282
+ const clawCmd = detectClawCommand();
20283
+ const brandName = clawCmd === "lightclaw" ? "LightClaw" : "OpenClaw";
20284
+ const restartSpinner = createSpinner(`Restarting ${brandName} Gateway...`).start();
20213
20285
  const result = restartOpenClawGateway();
20214
20286
  if (result.success) {
20215
- restartSpinner.succeed("OpenClaw Gateway restarted successfully.");
20287
+ restartSpinner.succeed(`${brandName} Gateway restarted successfully.`);
20216
20288
  } else {
20217
- restartSpinner.warn("Failed to restart OpenClaw Gateway.");
20289
+ restartSpinner.warn(`Failed to restart ${brandName} Gateway.`);
20218
20290
  console.log(source_default.yellow(` Reason: ${result.message}`));
20219
20291
  console.log(source_default.dim(" Please restart manually:"));
20220
- console.log(source_default.dim(" openclaw gateway restart"));
20292
+ console.log(source_default.dim(` ${clawCmd} gateway restart`));
20221
20293
  }
20222
20294
  }
20223
20295
 
@@ -20323,7 +20395,7 @@ var import_node_fs11 = __toESM(require("fs"), 1);
20323
20395
  var import_node_path13 = __toESM(require("path"), 1);
20324
20396
  var rollbackCommand = new Command("rollback").description("Rollback to a previous agent installation state").option("--list", "List available rollback records").option("--id <id>", "Rollback to a specific backup record by ID").option(
20325
20397
  "--claw-dir <path>",
20326
- "OpenClaw installation directory (overrides OPENCLAW_HOME env var)"
20398
+ "OpenClaw/LightClaw installation directory (overrides OPENCLAW_HOME/LIGHTCLAW_HOME env var)"
20327
20399
  ).action(async (options) => {
20328
20400
  try {
20329
20401
  if (options.list) {
@@ -20395,20 +20467,21 @@ async function performRollback(recordId, clawDir) {
20395
20467
  const spinner = createSpinner(
20396
20468
  `Rolling back ${source_default.cyan(record.packageName)}...`
20397
20469
  ).start();
20398
- const resolvedClawDir = findOpenClawDir(clawDir) || record.clawDir;
20470
+ const resolvedClawDir = clawDir ? findOpenClawDir(clawDir) || record.clawDir : await promptSelectClawDir() || record.clawDir;
20399
20471
  if (!resolvedClawDir || !import_node_fs11.default.existsSync(resolvedClawDir)) {
20400
- spinner.fail(`OpenClaw directory not found: ${record.clawDir}`);
20472
+ spinner.fail(`OpenClaw/LightClaw directory not found: ${record.clawDir}`);
20401
20473
  return;
20402
20474
  }
20475
+ const brand = detectClawBrand(resolvedClawDir);
20403
20476
  if (record.openclawJsonSnapshot) {
20404
- spinner.text = "Restoring openclaw.json...";
20477
+ spinner.text = `Restoring ${brand.toLowerCase()}.json...`;
20405
20478
  try {
20406
20479
  const configObj = JSON.parse(record.openclawJsonSnapshot);
20407
20480
  writeOpenClawConfig(resolvedClawDir, configObj);
20408
- logger.info("openclaw.json restored from snapshot", { recordId: record.id });
20481
+ logger.info(`${brand.toLowerCase()}.json restored from snapshot`, { recordId: record.id });
20409
20482
  } catch (err) {
20410
- logger.error("Failed to restore openclaw.json", { error: err });
20411
- console.log(source_default.yellow(" \u26A0 Failed to restore openclaw.json, skipping..."));
20483
+ logger.error(`Failed to restore ${brand.toLowerCase()}.json`, { error: err });
20484
+ console.log(source_default.yellow(` \u26A0 Failed to restore ${brand.toLowerCase()}.json, skipping...`));
20412
20485
  }
20413
20486
  }
20414
20487
  if (record.installedWorkerIds.length > 0) {
@@ -20471,15 +20544,17 @@ async function performRollback(recordId, clawDir) {
20471
20544
  spinner.succeed(
20472
20545
  `Rolled back ${source_default.cyan.bold(record.packageName)} successfully! (${restoredCount} item(s) restored)`
20473
20546
  );
20474
- const restartSpinner = createSpinner("Restarting OpenClaw Gateway...").start();
20547
+ const clawCmd = detectClawCommand();
20548
+ const brandName = clawCmd === "lightclaw" ? "LightClaw" : "OpenClaw";
20549
+ const restartSpinner = createSpinner(`Restarting ${brandName} Gateway...`).start();
20475
20550
  const result = restartOpenClawGateway();
20476
20551
  if (result.success) {
20477
- restartSpinner.succeed("OpenClaw Gateway restarted successfully.");
20552
+ restartSpinner.succeed(`${brandName} Gateway restarted successfully.`);
20478
20553
  } else {
20479
- restartSpinner.warn("Failed to restart OpenClaw Gateway.");
20554
+ restartSpinner.warn(`Failed to restart ${brandName} Gateway.`);
20480
20555
  console.log(source_default.yellow(` Reason: ${result.message}`));
20481
20556
  console.log(source_default.dim(" Please restart manually:"));
20482
- console.log(source_default.dim(" openclaw gateway restart"));
20557
+ console.log(source_default.dim(` ${clawCmd} gateway restart`));
20483
20558
  }
20484
20559
  console.log();
20485
20560
  }
@@ -20500,13 +20575,13 @@ function formatInstallType(type2) {
20500
20575
 
20501
20576
  // src/index.ts
20502
20577
  var program2 = new Command();
20503
- program2.name("soulhub").description("SoulHub CLI - Install and manage AI agent persona templates").version("1.0.11").option("--verbose", "Enable verbose debug logging").hook("preAction", () => {
20578
+ program2.name("soulhub").description("SoulHub CLI - Install and manage AI agent persona templates").version("1.0.13").option("--verbose", "Enable verbose debug logging").hook("preAction", () => {
20504
20579
  const opts = program2.opts();
20505
20580
  const verbose = opts.verbose || process.env.SOULHUB_DEBUG === "1";
20506
20581
  logger.init(verbose);
20507
20582
  logger.info("CLI started", {
20508
20583
  args: process.argv.slice(2),
20509
- version: "1.0.11",
20584
+ version: "1.0.13",
20510
20585
  node: process.version
20511
20586
  });
20512
20587
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "soulhubcli",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "SoulHub CLI - Install and manage AI agent persona templates for OpenClaw",
5
5
  "type": "module",
6
6
  "bin": {