yingclaw 2.5.0 → 2.5.1
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/bin/cli.js +28 -4
- package/lib/install.js +86 -1
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -21,7 +21,7 @@ const {
|
|
|
21
21
|
const { execSync, spawn, spawnSync } = require('child_process');
|
|
22
22
|
const pkg = require('../package.json');
|
|
23
23
|
const { buildMenuStatusLines, buildStatusView } = require('../lib/panel');
|
|
24
|
-
const { buildClaudeInstallCommand } = require('../lib/install');
|
|
24
|
+
const { buildClaudeInstallCommand, checkNodeEnv, getNodeInstallGuide, getInstallFailureHints } = require('../lib/install');
|
|
25
25
|
const { clearClaudeDesktopConfig, isDesktopConfigured, openClaudeDesktop, writeClaudeDesktopConfig } = require('../lib/desktop');
|
|
26
26
|
const { runDoctorChecks, summarize, STATUS_OK, STATUS_FAIL, STATUS_WARN, STATUS_INFO } = require('../lib/doctor');
|
|
27
27
|
|
|
@@ -402,6 +402,31 @@ program
|
|
|
402
402
|
if (!yes) return;
|
|
403
403
|
} catch {}
|
|
404
404
|
|
|
405
|
+
// 检查 npm / Node.js 环境
|
|
406
|
+
const nodeEnv = checkNodeEnv();
|
|
407
|
+
if (!nodeEnv.npmOk) {
|
|
408
|
+
console.log(boxen(
|
|
409
|
+
chalk.bold.red('未检测到 npm,无法安装 Claude Code\n\n') +
|
|
410
|
+
chalk.dim('Claude Code 通过 npm 安装,需要先安装 Node.js(含 npm)。\n\n') +
|
|
411
|
+
chalk.bold('安装方式:\n') +
|
|
412
|
+
getNodeInstallGuide().map(l => chalk.cyan(' ' + l)).join('\n') +
|
|
413
|
+
'\n\n' + chalk.dim('安装完成后重新运行 claw install-claude'),
|
|
414
|
+
{ padding: { top: 0, bottom: 0, left: 2, right: 2 }, borderStyle: 'round', borderColor: 'red', margin: { top: 1, bottom: 1 } }
|
|
415
|
+
));
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
if (!nodeEnv.nodeOk) {
|
|
419
|
+
console.log(boxen(
|
|
420
|
+
chalk.bold.yellow(`Node.js 版本过低(当前 v${nodeEnv.nodeVersion},需要 ≥18)\n\n`) +
|
|
421
|
+
chalk.dim('Claude Code 要求 Node.js ≥18,当前版本可能导致安装或运行失败。\n\n') +
|
|
422
|
+
chalk.bold('升级方式:\n') +
|
|
423
|
+
getNodeInstallGuide().map(l => chalk.cyan(' ' + l)).join('\n'),
|
|
424
|
+
{ padding: { top: 0, bottom: 0, left: 2, right: 2 }, borderStyle: 'round', borderColor: 'yellow', margin: { top: 1, bottom: 1 } }
|
|
425
|
+
));
|
|
426
|
+
const proceed = await confirm({ message: '仍然尝试安装?', default: false });
|
|
427
|
+
if (!proceed) return;
|
|
428
|
+
}
|
|
429
|
+
|
|
405
430
|
const network = await select({ loop: false,
|
|
406
431
|
message: chalk.cyan('你的网络环境'),
|
|
407
432
|
choices: [
|
|
@@ -423,10 +448,9 @@ program
|
|
|
423
448
|
console.log(chalk.green('\n✔ Claude Code 安装成功!'));
|
|
424
449
|
} else {
|
|
425
450
|
console.log(chalk.red('\n✘ 安装失败'));
|
|
451
|
+
const hints = getInstallFailureHints(result, chalk);
|
|
426
452
|
console.log(boxen(
|
|
427
|
-
|
|
428
|
-
chalk.cyan('npm config set registry https://registry.npmmirror.com\n') +
|
|
429
|
-
chalk.cyan('npm install -g @anthropic-ai/claude-code'),
|
|
453
|
+
hints.join(''),
|
|
430
454
|
{ padding: { top: 0, bottom: 0, left: 2, right: 2 }, borderStyle: 'round', borderColor: 'yellow', margin: { top: 1, bottom: 1 } }
|
|
431
455
|
));
|
|
432
456
|
return;
|
package/lib/install.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const { execSync } = require('child_process');
|
|
2
|
+
|
|
1
3
|
function buildClaudeInstallCommand(network) {
|
|
2
4
|
const args = ['install', '-g', '@anthropic-ai/claude-code'];
|
|
3
5
|
if (network === 'cn') {
|
|
@@ -6,4 +8,87 @@ function buildClaudeInstallCommand(network) {
|
|
|
6
8
|
return { command: 'npm', args };
|
|
7
9
|
}
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
function checkNodeEnv() {
|
|
12
|
+
const nodeVersion = process.versions.node;
|
|
13
|
+
const nodeMajor = parseInt(nodeVersion.split('.')[0], 10);
|
|
14
|
+
|
|
15
|
+
let npmVersion = null;
|
|
16
|
+
try {
|
|
17
|
+
// Windows 上 npm 是 .cmd 文件,必须加 shell: true 才能找到
|
|
18
|
+
npmVersion = execSync('npm --version', {
|
|
19
|
+
encoding: 'utf8',
|
|
20
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
21
|
+
shell: process.platform === 'win32',
|
|
22
|
+
}).trim();
|
|
23
|
+
} catch {}
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
nodeVersion,
|
|
27
|
+
nodeMajor,
|
|
28
|
+
nodeOk: nodeMajor >= 18,
|
|
29
|
+
npmVersion,
|
|
30
|
+
npmOk: !!npmVersion,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function getNodeInstallGuide() {
|
|
35
|
+
const platform = process.platform;
|
|
36
|
+
if (platform === 'darwin') {
|
|
37
|
+
return [
|
|
38
|
+
'Homebrew: brew install node',
|
|
39
|
+
'官方安装包: https://nodejs.org (选 LTS 版本)',
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
if (platform === 'win32') {
|
|
43
|
+
return [
|
|
44
|
+
'官方安装包: https://nodejs.org (选 LTS 版本)',
|
|
45
|
+
'winget: winget install OpenJS.NodeJS.LTS',
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
return [
|
|
49
|
+
'Ubuntu/Debian: sudo apt install nodejs npm',
|
|
50
|
+
'CentOS/RHEL: sudo yum install nodejs npm',
|
|
51
|
+
'nvm(推荐): https://github.com/nvm-sh/nvm',
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 根据 spawnSync 结果判断失败原因,返回对应的提示内容(chalk 字符串数组)。
|
|
57
|
+
* @param {object} result spawnSync 返回值
|
|
58
|
+
* @param {Function} chalk chalk 实例
|
|
59
|
+
* @returns {string[]}
|
|
60
|
+
*/
|
|
61
|
+
function getInstallFailureHints(result, chalk) {
|
|
62
|
+
// spawnSync 找不到命令(npm 在执行时消失或环境问题)
|
|
63
|
+
if (result.status === null && result.error?.code === 'ENOENT') {
|
|
64
|
+
return [
|
|
65
|
+
chalk.bold.red('npm 命令未找到\n\n'),
|
|
66
|
+
chalk.dim('安装 Node.js 后重试:\n'),
|
|
67
|
+
...getNodeInstallGuide().map(l => chalk.cyan(' ' + l)),
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 尝试从 stderr 判断权限错误(stdio inherit 时 stderr 为 null,兜底靠文字提示)
|
|
72
|
+
const stderr = result.stderr ? result.stderr.toString() : '';
|
|
73
|
+
if (stderr.includes('EACCES') || stderr.includes('permission denied') || stderr.includes('Access is denied')) {
|
|
74
|
+
const fixes = process.platform === 'win32'
|
|
75
|
+
? ['以管理员身份运行 PowerShell / CMD,然后重试']
|
|
76
|
+
: [
|
|
77
|
+
'sudo npm install -g @anthropic-ai/claude-code',
|
|
78
|
+
'或修复 npm 全局目录权限:https://docs.npmjs.com/resolving-eacces-permissions-errors',
|
|
79
|
+
];
|
|
80
|
+
return [
|
|
81
|
+
chalk.bold.red('权限不足(EACCES)\n\n'),
|
|
82
|
+
...fixes.map(l => chalk.cyan(' ' + l)),
|
|
83
|
+
];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 通用失败:显示手动安装命令
|
|
87
|
+
return [
|
|
88
|
+
chalk.bold('手动安装:\n\n'),
|
|
89
|
+
chalk.cyan('npm config set registry https://registry.npmmirror.com\n'),
|
|
90
|
+
chalk.cyan('npm install -g @anthropic-ai/claude-code'),
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = { buildClaudeInstallCommand, checkNodeEnv, getNodeInstallGuide, getInstallFailureHints };
|