create-openclaw-bot 5.0.5 → 5.0.6

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/cli.js CHANGED
@@ -50,14 +50,95 @@ function isPm2Installed() {
50
50
  }
51
51
  }
52
52
 
53
+ function getUserNpmPrefixInfo() {
54
+ if (process.platform === 'win32') {
55
+ return null;
56
+ }
57
+
58
+ const prefixDir = path.join(os.homedir(), '.local');
59
+ return {
60
+ prefixDir,
61
+ binDir: path.join(prefixDir, 'bin')
62
+ };
63
+ }
64
+
65
+ function ensureBinDirOnPath(binDir) {
66
+ const delimiter = path.delimiter;
67
+ const pathParts = String(process.env.PATH || '').split(delimiter).filter(Boolean);
68
+ if (!pathParts.includes(binDir)) {
69
+ process.env.PATH = [binDir, ...pathParts].join(delimiter);
70
+ }
71
+ }
72
+
73
+ function appendLineIfMissing(filePath, line) {
74
+ let content = '';
75
+ if (fs.existsSync(filePath)) {
76
+ content = fs.readFileSync(filePath, 'utf8');
77
+ }
78
+
79
+ if (!content.includes(line)) {
80
+ const prefix = content && !content.endsWith('\n') ? '\n' : '';
81
+ fs.appendFileSync(filePath, `${prefix}${line}\n`);
82
+ }
83
+ }
84
+
85
+ function ensureUserWritableGlobalNpm({ isVi, osChoice }) {
86
+ if (process.platform === 'win32') {
87
+ return true;
88
+ }
89
+
90
+ const npmInfo = getUserNpmPrefixInfo();
91
+ if (!npmInfo) {
92
+ return true;
93
+ }
94
+
95
+ try {
96
+ fs.ensureDirSync(npmInfo.binDir);
97
+ process.env.npm_config_prefix = npmInfo.prefixDir;
98
+ ensureBinDirOnPath(npmInfo.binDir);
99
+
100
+ execSync(`npm config set prefix "${npmInfo.prefixDir.replace(/"/g, '\\"')}"`, {
101
+ stdio: 'ignore',
102
+ shell: true,
103
+ env: process.env
104
+ });
105
+
106
+ appendLineIfMissing(path.join(os.homedir(), '.profile'), 'export PATH="$HOME/.local/bin:$PATH"');
107
+ appendLineIfMissing(
108
+ path.join(os.homedir(), osChoice === 'macos' ? '.zshrc' : '.bashrc'),
109
+ 'export PATH="$HOME/.local/bin:$PATH"'
110
+ );
111
+ return true;
112
+ } catch {
113
+ console.log(chalk.yellow(isVi
114
+ ? '⚠️ Không thể cấu hình npm global prefix trong ~/.local. Tiếp tục thử cài đặt trực tiếp.'
115
+ : '⚠️ Could not configure npm global prefix in ~/.local. Falling back to direct install.'));
116
+ return false;
117
+ }
118
+ }
119
+
120
+ const userNpmInfo = getUserNpmPrefixInfo();
121
+ if (userNpmInfo) {
122
+ ensureBinDirOnPath(userNpmInfo.binDir);
123
+ }
124
+
53
125
  function installGlobalPackage(pkg, { isVi, osChoice, displayName }) {
54
- const installCommands = osChoice === 'windows'
55
- ? [`npm install -g ${pkg}`]
56
- : [`npm install -g ${pkg}`, `sudo npm install -g ${pkg}`];
126
+ const installCommands = [];
127
+
128
+ if (osChoice === 'windows') {
129
+ installCommands.push(`npm install -g ${pkg}`);
130
+ } else {
131
+ ensureUserWritableGlobalNpm({ isVi, osChoice });
132
+ installCommands.push(`npm install -g ${pkg}`);
133
+ const npmInfo = getUserNpmPrefixInfo();
134
+ if (npmInfo) {
135
+ installCommands.push(`npm install -g --prefix "${npmInfo.prefixDir.replace(/"/g, '\\"')}" ${pkg}`);
136
+ }
137
+ }
57
138
 
58
139
  for (const cmd of installCommands) {
59
140
  try {
60
- execSync(cmd, { stdio: 'inherit', shell: true });
141
+ execSync(cmd, { stdio: 'inherit', shell: true, env: process.env });
61
142
  return true;
62
143
  } catch {
63
144
  // try next candidate
@@ -65,8 +146,8 @@ function installGlobalPackage(pkg, { isVi, osChoice, displayName }) {
65
146
  }
66
147
 
67
148
  console.log(chalk.yellow(isVi
68
- ? `⚠️ Không thể tự cài ${displayName}. Chạy thủ công: ${osChoice === 'windows' ? `npm install -g ${pkg}` : `sudo npm install -g ${pkg}`}`
69
- : `⚠️ Could not auto-install ${displayName}. Run manually: ${osChoice === 'windows' ? `npm install -g ${pkg}` : `sudo npm install -g ${pkg}`}`));
149
+ ? `⚠️ Không thể tự cài ${displayName}. Chạy thủ công: ${osChoice === 'windows' ? `npm install -g ${pkg}` : `npm config set prefix ~/.local && npm install -g ${pkg}`}`
150
+ : `⚠️ Could not auto-install ${displayName}. Run manually: ${osChoice === 'windows' ? `npm install -g ${pkg}` : `npm config set prefix ~/.local && npm install -g ${pkg}`}`));
70
151
  return false;
71
152
  }
72
153
 
@@ -1712,7 +1793,7 @@ fi
1712
1793
  : `Could not auto-sync config. Run manually:\n cp -rn ${localClawDir}/. ${globalClawDir}/`}`));
1713
1794
  }
1714
1795
 
1715
- console.log(chalk.cyan(`\n👉 ${isVi ? 'Đã tạo xong file cấu hình native.' : 'Native config files are ready.'}`));
1796
+ console.log(chalk.cyan(`\n👉 ${isVi ? 'Đã tạo xong file cấu hình Docker.' : 'Docker config files are ready.'}`));
1716
1797
  console.log(chalk.gray(isVi
1717
1798
  ? ` Cấu trúc config: ${isMultiBot && channelKey === 'telegram' ? '.openclaw/ dùng chung + agents/workspace-*' : (isMultiBot ? 'bot1/, bot2/, ...' : '.openclaw/')}`
1718
1799
  : ` Config layout: ${isMultiBot && channelKey === 'telegram' ? 'shared .openclaw/ with agents/workspace-*' : (isMultiBot ? 'bot1/, bot2/, ...' : '.openclaw/')}`));
@@ -1736,7 +1817,7 @@ fi
1736
1817
  console.log(chalk.cyan(isVi
1737
1818
  ? '\n📦 Dang cai openclaw binary (npm install -g openclaw)...'
1738
1819
  : '\n📦 Installing openclaw binary (npm install -g openclaw)...'));
1739
- if (!installGlobalPackage('openclaw', { isVi, osChoice, displayName: 'openclaw' })) {
1820
+ if (!installGlobalPackage('openclaw@latest', { isVi, osChoice, displayName: 'openclaw' })) {
1740
1821
  process.exit(1);
1741
1822
  }
1742
1823
  console.log(chalk.green(isVi ? '✅ openclaw da cai xong!' : '✅ openclaw installed!'));
@@ -1751,7 +1832,7 @@ fi
1751
1832
  if (osChoice === 'vps') {
1752
1833
  if (!isPm2Installed()) {
1753
1834
  console.log(chalk.cyan(isVi ? '\n📦 Dang cai PM2...' : '\n📦 Installing PM2...'));
1754
- if (!installGlobalPackage('pm2', { isVi, osChoice, displayName: 'PM2' })) {
1835
+ if (!installGlobalPackage('pm2@latest', { isVi, osChoice, displayName: 'PM2' })) {
1755
1836
  process.exit(1);
1756
1837
  }
1757
1838
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-openclaw-bot",
3
- "version": "5.0.5",
3
+ "version": "5.0.6",
4
4
  "description": "Interactive CLI installer for OpenClaw Bot",
5
5
  "main": "cli.js",
6
6
  "bin": {
package/setup.js CHANGED
@@ -3452,12 +3452,17 @@ ${selectedSkillNames.length ? selectedSkillNames.join('\n') : '- _(No skills ins
3452
3452
  } else if (state.nativeOs === 'linux') {
3453
3453
  const isDocker = state.deployMode === 'docker';
3454
3454
  scriptName = isDocker ? 'setup-openclaw-docker-macos.sh' : 'setup-openclaw-macos.sh';
3455
- const sh = [
3456
- '#!/usr/bin/env bash', 'set -e',
3457
- `echo "=== OpenClaw Setup — macOS${isDocker ? ' Docker' : ' Native'} ==="`,
3458
- 'command -v node > /dev/null 2>&1 || { echo "ERROR: Node.js chua cai! https://nodejs.org"; exit 1; }',
3459
- 'npm install -g openclaw@latest',
3460
- ];
3455
+ const sh = [
3456
+ '#!/usr/bin/env bash', 'set -e',
3457
+ `echo "=== OpenClaw Setup — macOS${isDocker ? ' Docker' : ' Native'} ==="`,
3458
+ 'command -v node > /dev/null 2>&1 || { echo "ERROR: Node.js chua cai! https://nodejs.org"; exit 1; }',
3459
+ 'mkdir -p "$HOME/.local/bin"',
3460
+ 'npm config set prefix "$HOME/.local"',
3461
+ 'export PATH="$HOME/.local/bin:$PATH"',
3462
+ 'grep -Fqx \'export PATH="$HOME/.local/bin:$PATH"\' "$HOME/.zshrc" 2>/dev/null || echo \'export PATH="$HOME/.local/bin:$PATH"\' >> "$HOME/.zshrc"',
3463
+ 'grep -Fqx \'export PATH="$HOME/.local/bin:$PATH"\' "$HOME/.profile" 2>/dev/null || echo \'export PATH="$HOME/.local/bin:$PATH"\' >> "$HOME/.profile"',
3464
+ 'npm install -g openclaw@latest',
3465
+ ];
3461
3466
  providerLines(sh, 'sh');
3462
3467
  if (pluginCmd) sh.push(pluginCmd);
3463
3468
 
@@ -3474,16 +3479,21 @@ ${selectedSkillNames.length ? selectedSkillNames.join('\n') : '- _(No skills ins
3474
3479
  // ─── VPS/Ubuntu PM2 .SH ──────────────────────────────────────────────────
3475
3480
  } else if (state.nativeOs === 'vps') {
3476
3481
  scriptName = 'setup-openclaw-vps.sh';
3477
- const vps = [
3478
- '#!/usr/bin/env bash', 'set -e',
3479
- `echo "=== OpenClaw Setup — Ubuntu/VPS${isMultiBot ? ` Multi-Bot (${state.botCount} bots)` : ''} ==="`,
3480
- '# Auto-install Node.js 20 LTS if missing',
3481
- 'if ! command -v node > /dev/null 2>&1; then',
3482
- ' curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -',
3483
- ' sudo apt-get install -y nodejs',
3484
- 'fi',
3485
- 'npm install -g openclaw@latest pm2',
3486
- ];
3482
+ const vps = [
3483
+ '#!/usr/bin/env bash', 'set -e',
3484
+ `echo "=== OpenClaw Setup — Ubuntu/VPS${isMultiBot ? ` Multi-Bot (${state.botCount} bots)` : ''} ==="`,
3485
+ '# Auto-install Node.js 20 LTS if missing',
3486
+ 'if ! command -v node > /dev/null 2>&1; then',
3487
+ ' curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -',
3488
+ ' sudo apt-get install -y nodejs',
3489
+ 'fi',
3490
+ 'mkdir -p "$HOME/.local/bin"',
3491
+ 'npm config set prefix "$HOME/.local"',
3492
+ 'export PATH="$HOME/.local/bin:$PATH"',
3493
+ 'grep -Fqx \'export PATH="$HOME/.local/bin:$PATH"\' "$HOME/.bashrc" 2>/dev/null || echo \'export PATH="$HOME/.local/bin:$PATH"\' >> "$HOME/.bashrc"',
3494
+ 'grep -Fqx \'export PATH="$HOME/.local/bin:$PATH"\' "$HOME/.profile" 2>/dev/null || echo \'export PATH="$HOME/.local/bin:$PATH"\' >> "$HOME/.profile"',
3495
+ 'npm install -g openclaw@latest pm2@latest',
3496
+ ];
3487
3497
  providerLines(vps, 'sh');
3488
3498
  if (pluginCmd) vps.push(pluginCmd);
3489
3499
 
@@ -3509,15 +3519,20 @@ ${selectedSkillNames.length ? selectedSkillNames.join('\n') : '- _(No skills ins
3509
3519
  // ─── Linux Desktop .SH ───────────────────────────────────────────────────
3510
3520
  } else if (state.nativeOs === 'linux-desktop') {
3511
3521
  scriptName = 'setup-openclaw-linux.sh';
3512
- const lnx = [
3513
- '#!/usr/bin/env bash', 'set -e',
3514
- `echo "=== OpenClaw Setup — Linux Desktop${isMultiBot ? ' Multi-Bot' : ''} ==="`,
3515
- 'if ! command -v node > /dev/null 2>&1; then',
3516
- ' curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -',
3517
- ' sudo apt-get install -y nodejs',
3518
- 'fi',
3519
- 'npm install -g openclaw@latest',
3520
- ];
3522
+ const lnx = [
3523
+ '#!/usr/bin/env bash', 'set -e',
3524
+ `echo "=== OpenClaw Setup — Linux Desktop${isMultiBot ? ' Multi-Bot' : ''} ==="`,
3525
+ 'if ! command -v node > /dev/null 2>&1; then',
3526
+ ' curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -',
3527
+ ' sudo apt-get install -y nodejs',
3528
+ 'fi',
3529
+ 'mkdir -p "$HOME/.local/bin"',
3530
+ 'npm config set prefix "$HOME/.local"',
3531
+ 'export PATH="$HOME/.local/bin:$PATH"',
3532
+ 'grep -Fqx \'export PATH="$HOME/.local/bin:$PATH"\' "$HOME/.bashrc" 2>/dev/null || echo \'export PATH="$HOME/.local/bin:$PATH"\' >> "$HOME/.bashrc"',
3533
+ 'grep -Fqx \'export PATH="$HOME/.local/bin:$PATH"\' "$HOME/.profile" 2>/dev/null || echo \'export PATH="$HOME/.local/bin:$PATH"\' >> "$HOME/.profile"',
3534
+ 'npm install -g openclaw@latest',
3535
+ ];
3521
3536
  providerLines(lnx, 'sh');
3522
3537
  if (pluginCmd) lnx.push(pluginCmd);
3523
3538
 
@@ -40,16 +40,22 @@ checks.push(() => expectMatch(
40
40
 
41
41
  checks.push(() => expectMatch(
42
42
  cli,
43
- /if \(!isOpenClawInstalled\(\)\) \{[\s\S]*installGlobalPackage\('openclaw', \{ isVi, osChoice, displayName: 'openclaw' \}\)/,
43
+ /if \(!isOpenClawInstalled\(\)\) \{[\s\S]*installGlobalPackage\('openclaw@latest', \{ isVi, osChoice, displayName: 'openclaw' \}\)/,
44
44
  'Native branch must auto-install openclaw'
45
45
  ));
46
46
 
47
47
  checks.push(() => expectMatch(
48
48
  cli,
49
- /if \(osChoice === 'vps'\) \{[\s\S]*installGlobalPackage\('pm2', \{ isVi, osChoice, displayName: 'PM2' \}\)/,
49
+ /if \(osChoice === 'vps'\) \{[\s\S]*installGlobalPackage\('pm2@latest', \{ isVi, osChoice, displayName: 'PM2' \}\)/,
50
50
  'VPS native branch must auto-install PM2'
51
51
  ));
52
52
 
53
+ checks.push(() => expectMatch(
54
+ cli,
55
+ /function ensureUserWritableGlobalNpm\(\{ isVi, osChoice \}\) \{[\s\S]*process\.env\.npm_config_prefix = npmInfo\.prefixDir[\s\S]*npm config set prefix "\$\{npmInfo\.prefixDir\.replace/s,
56
+ 'Native CLI must configure a user-writable npm global prefix for non-Windows installs'
57
+ ));
58
+
53
59
  checks.push(() => expectMatch(
54
60
  cli,
55
61
  /execSync\('pm2 start ecosystem\.config\.js && pm2 save'/,
@@ -107,13 +113,13 @@ checks.push(() => expectMatch(
107
113
 
108
114
  checks.push(() => expectMatch(
109
115
  setup,
110
- /else if \(state\.nativeOs === 'linux'\) \{[\s\S]*scriptName = isDocker \? 'setup-openclaw-docker-macos\.sh' : 'setup-openclaw-macos\.sh';[\s\S]*npm install -g openclaw@latest[\s\S]*openclaw gateway run/s,
116
+ /else if \(state\.nativeOs === 'linux'\) \{[\s\S]*scriptName = isDocker \? 'setup-openclaw-docker-macos\.sh' : 'setup-openclaw-macos\.sh';[\s\S]*npm config set prefix "\$HOME\/\.local"[\s\S]*npm install -g openclaw@latest[\s\S]*openclaw gateway run/s,
111
117
  'macOS script generation must use the correct file name and start command'
112
118
  ));
113
119
 
114
120
  checks.push(() => expectMatch(
115
121
  setup,
116
- /else if \(state\.nativeOs === 'vps'\) \{[\s\S]*scriptName = 'setup-openclaw-vps\.sh';[\s\S]*npm install -g openclaw@latest pm2[\s\S]*pm2 save && pm2 startup/s,
122
+ /else if \(state\.nativeOs === 'vps'\) \{[\s\S]*scriptName = 'setup-openclaw-vps\.sh';[\s\S]*npm config set prefix "\$HOME\/\.local"[\s\S]*npm install -g openclaw@latest pm2@latest[\s\S]*pm2 save && pm2 startup/s,
117
123
  'VPS native script generation must install openclaw+pm2 and persist PM2 startup'
118
124
  ));
119
125
 
@@ -131,7 +137,7 @@ checks.push(() => expectMatch(
131
137
 
132
138
  checks.push(() => expectMatch(
133
139
  setup,
134
- /else if \(state\.nativeOs === 'linux-desktop'\) \{[\s\S]*scriptName = 'setup-openclaw-linux\.sh';[\s\S]*npm install -g openclaw@latest[\s\S]*openclaw gateway run/s,
140
+ /else if \(state\.nativeOs === 'linux-desktop'\) \{[\s\S]*scriptName = 'setup-openclaw-linux\.sh';[\s\S]*npm config set prefix "\$HOME\/\.local"[\s\S]*npm install -g openclaw@latest[\s\S]*openclaw gateway run/s,
135
141
  'Linux Desktop native script generation must install openclaw and run the gateway'
136
142
  ));
137
143