aihezu 1.5.1 → 1.6.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.
- package/README.md +33 -10
- package/bin/aihezu.js +9 -6
- package/bin/ccclear.js +2 -2
- package/bin/ccinstall.js +77 -10
- package/lib/cache.js +4 -4
- package/lib/hosts.js +24 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
# aihezu - Claude Code CLI
|
|
1
|
+
# aihezu - Claude Code CLI 工具集
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
快速配置或清理 Claude Code CLI,本地修改 hosts 并提供企业独立域名支持。
|
|
4
4
|
|
|
5
5
|
## 功能特性
|
|
6
6
|
|
|
7
|
+
- 🔑 一键配置 Claude Code API Key,默认使用 `cc.aihezu.dev`,支持企业独立域名(`--api` / `--api-url`)
|
|
7
8
|
- 🧹 一键清理 Claude Code CLI 的所有本地数据
|
|
8
9
|
- 🌐 自动修改 hosts 文件,将 Anthropic 域名指向本地
|
|
9
10
|
- 📦 自动备份配置文件和 hosts 文件(带时间戳)
|
|
@@ -11,6 +12,13 @@
|
|
|
11
12
|
- 🚀 支持 npx 直接运行,无需安装
|
|
12
13
|
- 🔄 自动刷新 DNS 缓存
|
|
13
14
|
|
|
15
|
+
## 命令列表
|
|
16
|
+
|
|
17
|
+
- `ccinstall` / `install`:配置 Claude Code API Key
|
|
18
|
+
- 默认 API 域名:`https://cc.aihezu.dev/api`
|
|
19
|
+
- 企业用户可通过 `--api` 或 `--api-url` 指定独立域名(如 `--api jfz.aihezu.dev`)
|
|
20
|
+
- `ccclear`:清理 Claude Code 缓存和配置
|
|
21
|
+
|
|
14
22
|
## 清理内容
|
|
15
23
|
|
|
16
24
|
该工具会执行以下操作:
|
|
@@ -30,27 +38,42 @@
|
|
|
30
38
|
|
|
31
39
|
⚠️ **重要提示**:由于需要修改系统 hosts 文件,必须使用管理员权限运行!
|
|
32
40
|
|
|
33
|
-
###
|
|
41
|
+
### 配置 Claude Code(ccinstall / install)
|
|
34
42
|
|
|
35
|
-
|
|
43
|
+
- 默认域名:
|
|
36
44
|
|
|
37
45
|
```bash
|
|
38
|
-
sudo npx aihezu
|
|
46
|
+
sudo npx aihezu install
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
- 企业独立域名(支持传入域名或完整 URL,自动补全为 `/api`):
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
sudo npx aihezu install --api https://jfz.aihezu.dev
|
|
53
|
+
# 或
|
|
54
|
+
sudo npx aihezu install --api jfz.aihezu.dev
|
|
39
55
|
```
|
|
40
56
|
|
|
41
|
-
|
|
57
|
+
也可以全局安装后运行:
|
|
42
58
|
|
|
43
59
|
```bash
|
|
44
60
|
npm install -g aihezu
|
|
45
|
-
sudo
|
|
61
|
+
sudo ccinstall --api your-company.aihezu.dev
|
|
46
62
|
```
|
|
47
63
|
|
|
48
|
-
###
|
|
64
|
+
### 清理 Claude Code(ccclear)
|
|
49
65
|
|
|
50
|
-
|
|
66
|
+
- 使用 npx(推荐):
|
|
51
67
|
|
|
52
68
|
```bash
|
|
53
|
-
npx aihezu ccclear
|
|
69
|
+
sudo npx aihezu ccclear
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- 全局安装后运行:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npm install -g aihezu
|
|
76
|
+
sudo ccclear
|
|
54
77
|
```
|
|
55
78
|
|
|
56
79
|
## 运行效果
|
package/bin/aihezu.js
CHANGED
|
@@ -5,6 +5,7 @@ const path = require('path');
|
|
|
5
5
|
|
|
6
6
|
const args = process.argv.slice(2);
|
|
7
7
|
const command = args[0];
|
|
8
|
+
const commandArgs = args.slice(1);
|
|
8
9
|
|
|
9
10
|
// 显示帮助信息
|
|
10
11
|
function showHelp() {
|
|
@@ -13,19 +14,20 @@ function showHelp() {
|
|
|
13
14
|
console.log('使用方法:');
|
|
14
15
|
console.log(' npx aihezu <command>\n');
|
|
15
16
|
console.log('可用命令:');
|
|
16
|
-
console.log(' ccinstall 配置 Claude Code API Key');
|
|
17
|
-
console.log(' ccclear
|
|
17
|
+
console.log(' ccinstall / install 配置 Claude Code API Key(企业可自定义域名)');
|
|
18
|
+
console.log(' ccclear 清理 Claude Code 缓存和配置');
|
|
18
19
|
console.log(' help 显示帮助信息\n');
|
|
19
20
|
console.log('示例:');
|
|
20
21
|
console.log(' npx aihezu ccinstall # 配置 API Key');
|
|
22
|
+
console.log(' npx aihezu install --api jfz.aihezu.dev # 企业用户自定义域名');
|
|
21
23
|
console.log(' npx aihezu ccclear # 清理缓存');
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
// 执行子命令
|
|
25
|
-
function runCommand(scriptName) {
|
|
27
|
+
function runCommand(scriptName, extraArgs = []) {
|
|
26
28
|
const scriptPath = path.join(__dirname, scriptName);
|
|
27
29
|
|
|
28
|
-
const child = spawn('node', [scriptPath], {
|
|
30
|
+
const child = spawn('node', [scriptPath, ...extraArgs], {
|
|
29
31
|
stdio: 'inherit',
|
|
30
32
|
env: process.env
|
|
31
33
|
});
|
|
@@ -43,11 +45,12 @@ function runCommand(scriptName) {
|
|
|
43
45
|
// 路由命令
|
|
44
46
|
switch (command) {
|
|
45
47
|
case 'ccinstall':
|
|
46
|
-
|
|
48
|
+
case 'install':
|
|
49
|
+
runCommand('ccinstall.js', commandArgs);
|
|
47
50
|
break;
|
|
48
51
|
|
|
49
52
|
case 'ccclear':
|
|
50
|
-
runCommand('ccclear.js');
|
|
53
|
+
runCommand('ccclear.js', commandArgs);
|
|
51
54
|
break;
|
|
52
55
|
|
|
53
56
|
case 'help':
|
package/bin/ccclear.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const { execSync } = require('child_process');
|
|
4
3
|
const path = require('path');
|
|
5
4
|
const os = require('os');
|
|
6
5
|
const fs = require('fs');
|
|
@@ -29,7 +28,8 @@ try {
|
|
|
29
28
|
const timestamp = getLocalTimestamp();
|
|
30
29
|
const backupJson = `${claudeJson}-backup-${timestamp}`;
|
|
31
30
|
console.log(`\n📦 备份 ~/.claude.json 到 ${path.basename(backupJson)}`);
|
|
32
|
-
|
|
31
|
+
// 使用 Node.js 原生 API,跨平台兼容
|
|
32
|
+
fs.renameSync(claudeJson, backupJson);
|
|
33
33
|
hasClaudeJson = true;
|
|
34
34
|
}
|
|
35
35
|
} catch (e) {
|
package/bin/ccinstall.js
CHANGED
|
@@ -10,9 +10,78 @@ const { cleanCache } = require('../lib/cache');
|
|
|
10
10
|
const homeDir = os.homedir();
|
|
11
11
|
const settingsPath = path.join(homeDir, '.claude', 'settings.json');
|
|
12
12
|
const claudeDir = path.join(homeDir, '.claude');
|
|
13
|
+
const DEFAULT_API_BASE = 'https://cc.aihezu.dev/api';
|
|
14
|
+
const cliArgs = process.argv.slice(2);
|
|
15
|
+
|
|
16
|
+
function parseApiBaseInput(argv) {
|
|
17
|
+
let apiBaseInput = '';
|
|
18
|
+
|
|
19
|
+
for (let i = 0; i < argv.length; i++) {
|
|
20
|
+
const arg = argv[i];
|
|
21
|
+
|
|
22
|
+
if (['--api', '--api-url', '--api-base', '--domain'].includes(arg)) {
|
|
23
|
+
apiBaseInput = argv[i + 1] || '';
|
|
24
|
+
i++;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!arg.startsWith('-') && !apiBaseInput) {
|
|
29
|
+
apiBaseInput = arg;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return apiBaseInput.trim();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function normalizeApiBaseUrl(input) {
|
|
37
|
+
if (!input) return DEFAULT_API_BASE;
|
|
38
|
+
|
|
39
|
+
let normalized = input;
|
|
40
|
+
|
|
41
|
+
if (!/^https?:\/\//i.test(normalized)) {
|
|
42
|
+
normalized = `https://${normalized}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let url;
|
|
46
|
+
try {
|
|
47
|
+
url = new URL(normalized);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
throw new Error('无效的域名或 URL,请输入类似 jfz.aihezu.dev 或 https://jfz.aihezu.dev');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let pathname = url.pathname.replace(/\/+$/, '');
|
|
53
|
+
if (!pathname || pathname === '/') {
|
|
54
|
+
pathname = '/api';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
url.pathname = pathname;
|
|
58
|
+
url.search = '';
|
|
59
|
+
url.hash = '';
|
|
60
|
+
|
|
61
|
+
return `${url.origin}${url.pathname}`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const apiBaseInput = parseApiBaseInput(cliArgs);
|
|
65
|
+
let apiBaseUrl;
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
apiBaseUrl = normalizeApiBaseUrl(apiBaseInput);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error(`❌ ${error.message}`);
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const usingCustomDomain = !!apiBaseInput;
|
|
13
75
|
|
|
14
76
|
console.log('🔧 Claude Code API 配置工具');
|
|
15
77
|
console.log('🌐 Powered by https://aihezu.dev\n');
|
|
78
|
+
if (usingCustomDomain) {
|
|
79
|
+
console.log(`🏢 已启用企业独立域名: ${apiBaseUrl}\n`);
|
|
80
|
+
} else {
|
|
81
|
+
console.log(`ℹ️ 未指定域名,将使用默认地址: ${DEFAULT_API_BASE}`);
|
|
82
|
+
console.log(' 企业用户可使用 --api 或 --api-url 指定独立域名,例如:');
|
|
83
|
+
console.log(' sudo npx aihezu install --api https://jfz.aihezu.dev\n');
|
|
84
|
+
}
|
|
16
85
|
|
|
17
86
|
// 创建 readline 接口
|
|
18
87
|
const rl = readline.createInterface({
|
|
@@ -71,14 +140,12 @@ rl.question('您是从其他服务切换过来的吗?(y/n,如果是首次使
|
|
|
71
140
|
}
|
|
72
141
|
}
|
|
73
142
|
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
settings.env.ANTHROPIC_AUTH_TOKEN = apiKey;
|
|
81
|
-
settings.env.ANTHROPIC_BASE_URL = 'https://cc.aihezu.dev/api';
|
|
143
|
+
// 完全替换 env 对象,清除所有旧的环境变量配置
|
|
144
|
+
// 这样可以避免旧配置(如 ANTHROPIC_MODEL 等)干扰新配置
|
|
145
|
+
settings.env = {
|
|
146
|
+
ANTHROPIC_AUTH_TOKEN: apiKey,
|
|
147
|
+
ANTHROPIC_BASE_URL: apiBaseUrl
|
|
148
|
+
};
|
|
82
149
|
|
|
83
150
|
// 写入配置文件
|
|
84
151
|
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8');
|
|
@@ -88,7 +155,7 @@ rl.question('您是从其他服务切换过来的吗?(y/n,如果是首次使
|
|
|
88
155
|
console.log('📝 已更新配置文件:', settingsPath);
|
|
89
156
|
console.log('\n配置内容:');
|
|
90
157
|
console.log(' ANTHROPIC_AUTH_TOKEN:', apiKey);
|
|
91
|
-
console.log(' ANTHROPIC_BASE_URL:',
|
|
158
|
+
console.log(' ANTHROPIC_BASE_URL:', apiBaseUrl);
|
|
92
159
|
|
|
93
160
|
// 修改 hosts 文件
|
|
94
161
|
console.log('\n=== 修改 hosts 文件 ===\n');
|
|
@@ -105,4 +172,4 @@ rl.question('您是从其他服务切换过来的吗?(y/n,如果是首次使
|
|
|
105
172
|
rl.close();
|
|
106
173
|
}
|
|
107
174
|
});
|
|
108
|
-
});
|
|
175
|
+
});
|
package/lib/cache.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const { execSync } = require('child_process');
|
|
2
1
|
const path = require('path');
|
|
3
2
|
const os = require('os');
|
|
4
3
|
const fs = require('fs');
|
|
@@ -61,12 +60,12 @@ function cleanCache(options = {}) {
|
|
|
61
60
|
|
|
62
61
|
if (stat.isDirectory()) {
|
|
63
62
|
console.log(`📦 备份并清理目录: ${item}/`);
|
|
64
|
-
execSync(`mv "${itemPath}" "${backupPath}"`);
|
|
65
63
|
} else {
|
|
66
64
|
console.log(`📦 备份并清理文件: ${item}`);
|
|
67
|
-
execSync(`mv "${itemPath}" "${backupPath}"`);
|
|
68
65
|
}
|
|
69
66
|
|
|
67
|
+
// 使用 Node.js 原生 API,跨平台兼容
|
|
68
|
+
fs.renameSync(itemPath, backupPath);
|
|
70
69
|
cleanedCount++;
|
|
71
70
|
}
|
|
72
71
|
} catch (e) {
|
|
@@ -84,7 +83,8 @@ function cleanCache(options = {}) {
|
|
|
84
83
|
|
|
85
84
|
if (stat.isDirectory()) {
|
|
86
85
|
console.log(`🗑️ 删除旧备份: ${item}/`);
|
|
87
|
-
|
|
86
|
+
// 使用 Node.js 原生 API,跨平台兼容
|
|
87
|
+
fs.rmSync(itemPath, { recursive: true, force: true });
|
|
88
88
|
cleanedCount++;
|
|
89
89
|
}
|
|
90
90
|
}
|
package/lib/hosts.js
CHANGED
|
@@ -86,18 +86,37 @@ function modifyHostsFile() {
|
|
|
86
86
|
console.log(' - api.anthropic.com -> 127.0.0.1');
|
|
87
87
|
|
|
88
88
|
// 刷新 DNS 缓存
|
|
89
|
+
console.log('🔄 刷新 DNS 缓存...');
|
|
89
90
|
try {
|
|
90
91
|
if (isWindows) {
|
|
91
|
-
|
|
92
|
+
// Windows: 需要管理员权限
|
|
93
|
+
execSync('ipconfig /flushdns', { stdio: 'pipe' });
|
|
94
|
+
console.log(' ✅ DNS 缓存已刷新');
|
|
92
95
|
} else if (os.platform() === 'darwin') {
|
|
93
|
-
|
|
96
|
+
// macOS: 如果已经是 root/sudo 运行,直接执行;否则会失败但不影响主要功能
|
|
97
|
+
try {
|
|
98
|
+
execSync('dscacheutil -flushcache; killall -HUP mDNSResponder', { stdio: 'pipe' });
|
|
99
|
+
console.log(' ✅ DNS 缓存已刷新');
|
|
100
|
+
} catch (e) {
|
|
101
|
+
console.log(' ⚠️ DNS 缓存刷新失败,请稍后手动执行:');
|
|
102
|
+
console.log(' sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder');
|
|
103
|
+
}
|
|
94
104
|
} else {
|
|
95
105
|
// Linux
|
|
96
|
-
|
|
106
|
+
try {
|
|
107
|
+
execSync('systemd-resolve --flush-caches 2>/dev/null || service nscd restart 2>/dev/null', { stdio: 'pipe' });
|
|
108
|
+
console.log(' ✅ DNS 缓存已刷新');
|
|
109
|
+
} catch (e) {
|
|
110
|
+
console.log(' ⚠️ DNS 缓存刷新失败,请稍后手动执行:');
|
|
111
|
+
console.log(' sudo systemd-resolve --flush-caches');
|
|
112
|
+
}
|
|
97
113
|
}
|
|
98
|
-
console.log('🔄 DNS 缓存已刷新');
|
|
99
114
|
} catch (e) {
|
|
100
|
-
|
|
115
|
+
if (isWindows) {
|
|
116
|
+
console.log(' ⚠️ DNS 缓存刷新失败,请以管理员身份运行命令提示符');
|
|
117
|
+
} else {
|
|
118
|
+
console.log(' ℹ️ DNS 缓存刷新失败(可能需要 root 权限)');
|
|
119
|
+
}
|
|
101
120
|
}
|
|
102
121
|
|
|
103
122
|
return true;
|