ccbot-cli 1.0.0 → 1.2.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/dist/index.js +279 -395
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,52 +1,59 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
#!/usr/bin/env node
|
|
3
|
+
|
|
4
|
+
// src/index.ts
|
|
5
|
+
import { createRequire } from "module";
|
|
2
6
|
|
|
3
7
|
// src/utils/logger.ts
|
|
4
8
|
import pc from "picocolors";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
function step(n, total, title) {
|
|
10
|
+
console.log(pc.cyan(`
|
|
11
|
+
[${n}/${total}] `) + pc.bold(title));
|
|
12
|
+
}
|
|
13
|
+
function hint(msg) {
|
|
14
|
+
console.log(pc.dim(` ${msg}`));
|
|
15
|
+
}
|
|
16
|
+
function ok(msg) {
|
|
17
|
+
console.log(pc.green(" \u2713 ") + msg);
|
|
18
|
+
}
|
|
19
|
+
function fail(msg) {
|
|
20
|
+
console.log(pc.red(" \u2717 ") + msg);
|
|
21
|
+
}
|
|
22
|
+
function warn(msg) {
|
|
23
|
+
console.log(pc.yellow(" \u26A0 ") + msg);
|
|
24
|
+
}
|
|
25
|
+
function info(msg) {
|
|
26
|
+
console.log(pc.cyan(" \u2139 ") + msg);
|
|
27
|
+
}
|
|
28
|
+
function banner(version2) {
|
|
14
29
|
console.log();
|
|
15
|
-
console.log(pc.cyan(" \
|
|
16
|
-
console.log(pc.cyan(" \u2502 \u2502"));
|
|
17
|
-
console.log(pc.cyan(" \u2502") + " \u{1F916} ccbot - Claude Code \u73AF\u5883\u914D\u7F6E " + pc.cyan("\u2502"));
|
|
18
|
-
console.log(pc.cyan(" \u2502") + pc.dim(` \u4E00\u952E\u914D\u7F6E\u5DE5\u5177 v${version}`) + " " + pc.cyan("\u2502"));
|
|
19
|
-
console.log(pc.cyan(" \u2502 \u2502"));
|
|
20
|
-
console.log(pc.cyan(" \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F"));
|
|
30
|
+
console.log(pc.cyan(" \u{1F916} ccbot") + pc.dim(` v${version2}`) + pc.cyan(" \u2014 Claude Code \u73AF\u5883\u4E00\u952E\u914D\u7F6E"));
|
|
21
31
|
console.log();
|
|
22
32
|
}
|
|
23
|
-
function
|
|
33
|
+
function done(items) {
|
|
34
|
+
const okCount = items.filter((i) => i.ok).length;
|
|
35
|
+
const failCount = items.filter((i) => !i.ok).length;
|
|
24
36
|
console.log();
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
37
|
+
if (failCount === 0) {
|
|
38
|
+
console.log(pc.green(pc.bold(" \u2713 \u5168\u90E8\u5B8C\u6210!")));
|
|
39
|
+
} else {
|
|
40
|
+
console.log(pc.yellow(` \u26A0 \u5B8C\u6210 ${okCount} \u9879, ${failCount} \u9879\u9700\u6CE8\u610F`));
|
|
41
|
+
}
|
|
28
42
|
console.log();
|
|
29
43
|
for (const item of items) {
|
|
30
|
-
if (item.ok)
|
|
31
|
-
|
|
32
|
-
} else {
|
|
33
|
-
log.error(item.label);
|
|
34
|
-
}
|
|
44
|
+
if (item.ok) ok(item.label);
|
|
45
|
+
else fail(item.label);
|
|
35
46
|
}
|
|
36
47
|
console.log();
|
|
37
|
-
log.
|
|
38
|
-
log.dim("1.
|
|
39
|
-
log.dim("2. \u7F16\u8F91 CLAUDE.md \u81EA\u5B9A\u4E49\
|
|
48
|
+
console.log(pc.dim(" \u4E0B\u4E00\u6B65:"));
|
|
49
|
+
console.log(pc.dim(" 1. ") + pc.green("claude") + pc.dim(" \u542F\u52A8 Claude Code"));
|
|
50
|
+
console.log(pc.dim(" 2. \u7F16\u8F91 ") + pc.green("CLAUDE.md") + pc.dim(" \u81EA\u5B9A\u4E49\u6307\u4EE4"));
|
|
40
51
|
console.log();
|
|
41
52
|
}
|
|
42
53
|
|
|
43
54
|
// src/cli.ts
|
|
44
|
-
import
|
|
45
|
-
import
|
|
46
|
-
|
|
47
|
-
// src/steps/detect.ts
|
|
48
|
-
import * as p from "@clack/prompts";
|
|
49
|
-
import pc2 from "picocolors";
|
|
55
|
+
import { confirm as confirm2 } from "@inquirer/prompts";
|
|
56
|
+
import pc3 from "picocolors";
|
|
50
57
|
|
|
51
58
|
// src/utils/exec.ts
|
|
52
59
|
import { execa } from "execa";
|
|
@@ -79,7 +86,6 @@ var SENSITIVE_PATTERNS = [
|
|
|
79
86
|
/^ANTHROPIC_API_KEY$/i,
|
|
80
87
|
/^CLAUDE_API_KEY$/i,
|
|
81
88
|
/^OPENAI_API_KEY$/i,
|
|
82
|
-
/^OPENAI_ORG_ID$/i,
|
|
83
89
|
/^GOOGLE_API_KEY$/i,
|
|
84
90
|
/^AZURE_OPENAI_API_KEY$/i,
|
|
85
91
|
/^HUGGINGFACE_TOKEN$/i,
|
|
@@ -92,148 +98,97 @@ var SENSITIVE_PATTERNS = [
|
|
|
92
98
|
/_TOKEN$/i,
|
|
93
99
|
/_API_KEY$/i
|
|
94
100
|
];
|
|
95
|
-
function
|
|
96
|
-
|
|
97
|
-
return val.slice(0, 4) + "..." + val.slice(-4);
|
|
98
|
-
}
|
|
99
|
-
function scanSensitiveEnvVars() {
|
|
100
|
-
const found = [];
|
|
101
|
-
for (const [key, value] of Object.entries(process.env)) {
|
|
102
|
-
if (!value) continue;
|
|
103
|
-
for (const pattern of SENSITIVE_PATTERNS) {
|
|
104
|
-
if (pattern.test(key)) {
|
|
105
|
-
found.push({ key, value });
|
|
106
|
-
break;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return found;
|
|
111
|
-
}
|
|
112
|
-
async function detect() {
|
|
113
|
-
const s = p.spinner();
|
|
114
|
-
s.start("\u6B63\u5728\u68C0\u6D4B\u73AF\u5883...");
|
|
101
|
+
async function detect(total) {
|
|
102
|
+
step(1, total, "\u73AF\u5883\u68C0\u6D4B");
|
|
115
103
|
const nodeVersion = process.version;
|
|
116
104
|
const npmResult = await run("npm", ["--version"]);
|
|
117
105
|
const npmVersion = npmResult.stdout.trim();
|
|
118
|
-
const osMap = {
|
|
119
|
-
win32: "Windows",
|
|
120
|
-
darwin: "macOS",
|
|
121
|
-
linux: "Linux"
|
|
122
|
-
};
|
|
106
|
+
const osMap = { win32: "Windows", darwin: "macOS", linux: "Linux" };
|
|
123
107
|
const os = osMap[process.platform] ?? process.platform;
|
|
124
108
|
const claudeInstalled = await commandExists("claude");
|
|
125
109
|
let claudeVersion = null;
|
|
126
110
|
if (claudeInstalled) {
|
|
127
|
-
const
|
|
128
|
-
claudeVersion =
|
|
111
|
+
const r = await run("claude", ["--version"]);
|
|
112
|
+
claudeVersion = r.stdout.trim();
|
|
129
113
|
}
|
|
130
|
-
const sensitiveEnvVars =
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
p.log.success(`Claude Code CLI ${claudeVersion}`);
|
|
137
|
-
} else {
|
|
138
|
-
p.log.warning("Claude Code CLI \u672A\u5B89\u88C5");
|
|
114
|
+
const sensitiveEnvVars = [];
|
|
115
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
116
|
+
if (!value) continue;
|
|
117
|
+
if (SENSITIVE_PATTERNS.some((p) => p.test(key))) {
|
|
118
|
+
sensitiveEnvVars.push({ key, value });
|
|
119
|
+
}
|
|
139
120
|
}
|
|
121
|
+
ok(`Node ${nodeVersion} \xB7 npm v${npmVersion} \xB7 ${os}`);
|
|
122
|
+
if (claudeInstalled) ok(`Claude CLI ${claudeVersion}`);
|
|
123
|
+
else warn("Claude CLI \u672A\u5B89\u88C5");
|
|
140
124
|
if (sensitiveEnvVars.length > 0) {
|
|
141
|
-
|
|
142
|
-
for (const { key, value } of sensitiveEnvVars) {
|
|
143
|
-
console.log(pc2.yellow(` ${key}=${maskValue(value)}`));
|
|
144
|
-
}
|
|
125
|
+
warn(`\u53D1\u73B0 ${sensitiveEnvVars.length} \u4E2A\u654F\u611F\u73AF\u5883\u53D8\u91CF`);
|
|
145
126
|
}
|
|
146
|
-
return {
|
|
147
|
-
nodeVersion,
|
|
148
|
-
npmVersion,
|
|
149
|
-
os,
|
|
150
|
-
platform: process.platform,
|
|
151
|
-
claudeInstalled,
|
|
152
|
-
claudeVersion,
|
|
153
|
-
sensitiveEnvVars
|
|
154
|
-
};
|
|
127
|
+
return { nodeVersion, npmVersion, os, platform: process.platform, claudeInstalled, claudeVersion, sensitiveEnvVars };
|
|
155
128
|
}
|
|
156
129
|
|
|
157
130
|
// src/steps/select.ts
|
|
158
|
-
import
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
console.log(pc3.dim(" \u2191/\u2193 \u4E0A\u4E0B\u79FB\u52A8\u5149\u6807"));
|
|
164
|
-
console.log(pc3.dim(" \u7A7A\u683C \u9009\u4E2D/\u53D6\u6D88\u9009\u4E2D\u5F53\u524D\u9879"));
|
|
165
|
-
console.log(pc3.dim(" a \u5168\u9009/\u5168\u4E0D\u9009"));
|
|
166
|
-
console.log(pc3.dim(" \u56DE\u8F66 \u786E\u8BA4\u9009\u62E9"));
|
|
167
|
-
console.log();
|
|
168
|
-
}
|
|
169
|
-
async function selectComponents(env) {
|
|
170
|
-
const options = [
|
|
131
|
+
import { checkbox } from "@inquirer/prompts";
|
|
132
|
+
async function selectComponents(env, total) {
|
|
133
|
+
step(2, total, "\u9009\u62E9\u7EC4\u4EF6");
|
|
134
|
+
hint("\u7A7A\u683C=\u5207\u6362 a=\u5168\u9009 \u56DE\u8F66=\u786E\u8BA4");
|
|
135
|
+
const choices = [
|
|
171
136
|
{
|
|
172
137
|
value: "installCli",
|
|
173
|
-
|
|
174
|
-
|
|
138
|
+
name: `Claude Code CLI ${env.claudeInstalled ? "(\u5DF2\u5B89\u88C5, \u8DF3\u8FC7)" : "(\u672A\u5B89\u88C5)"}`,
|
|
139
|
+
checked: true
|
|
175
140
|
},
|
|
176
|
-
{ value: "scaffold",
|
|
177
|
-
{ value: "installMcp",
|
|
178
|
-
{ value: "installSkills",
|
|
141
|
+
{ value: "scaffold", name: "\u9879\u76EE\u914D\u7F6E\u6587\u4EF6 (CLAUDE.md + .claude/)", checked: true },
|
|
142
|
+
{ value: "installMcp", name: "MCP Servers (AI\u5DE5\u5177\u670D\u52A1)", checked: true },
|
|
143
|
+
{ value: "installSkills", name: "Skills / Plugins (\u5DE5\u4F5C\u6D41\u589E\u5F3A)", checked: true }
|
|
179
144
|
];
|
|
180
145
|
if (env.sensitiveEnvVars.length > 0) {
|
|
181
|
-
|
|
146
|
+
choices.push({
|
|
182
147
|
value: "cleanEnv",
|
|
183
|
-
|
|
184
|
-
|
|
148
|
+
name: `\u73AF\u5883\u53D8\u91CF\u6E05\u7406 (${env.sensitiveEnvVars.length} \u4E2A\u654F\u611F\u53D8\u91CF)`,
|
|
149
|
+
checked: true
|
|
185
150
|
});
|
|
186
151
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
options,
|
|
191
|
-
initialValues: options.map((o) => o.value),
|
|
152
|
+
const selected = await checkbox({
|
|
153
|
+
message: "\u5B89\u88C5\u7EC4\u4EF6",
|
|
154
|
+
choices,
|
|
192
155
|
required: true
|
|
193
156
|
});
|
|
194
|
-
if (p2.isCancel(selected)) {
|
|
195
|
-
p2.cancel("\u5DF2\u53D6\u6D88");
|
|
196
|
-
process.exit(0);
|
|
197
|
-
}
|
|
198
|
-
const values = selected;
|
|
199
157
|
return {
|
|
200
|
-
installCli:
|
|
201
|
-
scaffold:
|
|
202
|
-
installMcp:
|
|
203
|
-
installSkills:
|
|
204
|
-
cleanEnv:
|
|
158
|
+
installCli: selected.includes("installCli"),
|
|
159
|
+
scaffold: selected.includes("scaffold"),
|
|
160
|
+
installMcp: selected.includes("installMcp"),
|
|
161
|
+
installSkills: selected.includes("installSkills"),
|
|
162
|
+
cleanEnv: selected.includes("cleanEnv")
|
|
205
163
|
};
|
|
206
164
|
}
|
|
207
165
|
|
|
208
166
|
// src/steps/install-cli.ts
|
|
209
|
-
import * as p3 from "@clack/prompts";
|
|
210
167
|
async function installCli(alreadyInstalled) {
|
|
211
168
|
if (alreadyInstalled) {
|
|
212
|
-
|
|
169
|
+
info("Claude CLI \u5DF2\u5B89\u88C5, \u8DF3\u8FC7");
|
|
213
170
|
return { success: true, version: null, skipped: true };
|
|
214
171
|
}
|
|
215
|
-
|
|
216
|
-
s.start("\u6B63\u5728\u5B89\u88C5 Claude Code CLI...");
|
|
172
|
+
info("\u6B63\u5728\u5B89\u88C5 Claude Code CLI...");
|
|
217
173
|
const result = await npmInstallGlobal("@anthropic-ai/claude-code");
|
|
218
174
|
if (result.exitCode !== 0) {
|
|
219
|
-
|
|
220
|
-
|
|
175
|
+
fail("Claude CLI \u5B89\u88C5\u5931\u8D25");
|
|
176
|
+
warn("\u624B\u52A8: npm install -g @anthropic-ai/claude-code");
|
|
221
177
|
return { success: false, version: null, skipped: false };
|
|
222
178
|
}
|
|
223
179
|
const exists = await commandExists("claude");
|
|
224
180
|
if (!exists) {
|
|
225
|
-
|
|
226
|
-
p3.log.warning("\u5B89\u88C5\u5B8C\u6210\u4F46 claude \u547D\u4EE4\u4E0D\u53EF\u7528\uFF0C\u53EF\u80FD\u9700\u8981\u91CD\u542F\u7EC8\u7AEF");
|
|
181
|
+
warn("\u5B89\u88C5\u5B8C\u6210\u4F46 claude \u547D\u4EE4\u4E0D\u53EF\u7528, \u53EF\u80FD\u9700\u91CD\u542F\u7EC8\u7AEF");
|
|
227
182
|
return { success: false, version: null, skipped: false };
|
|
228
183
|
}
|
|
229
|
-
const
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
return { success: true, version, skipped: false };
|
|
184
|
+
const v = await run("claude", ["--version"]);
|
|
185
|
+
const version2 = v.stdout.trim();
|
|
186
|
+
ok(`Claude CLI ${version2}`);
|
|
187
|
+
return { success: true, version: version2, skipped: false };
|
|
233
188
|
}
|
|
234
189
|
|
|
235
190
|
// src/steps/scaffold.ts
|
|
236
|
-
import
|
|
191
|
+
import { select } from "@inquirer/prompts";
|
|
237
192
|
import { join as join2 } from "path";
|
|
238
193
|
|
|
239
194
|
// src/utils/fs.ts
|
|
@@ -281,79 +236,98 @@ function deepMerge(target, source) {
|
|
|
281
236
|
}
|
|
282
237
|
|
|
283
238
|
// src/steps/scaffold.ts
|
|
284
|
-
var
|
|
239
|
+
var TEMPLATES = {
|
|
240
|
+
minimal: `# Project Instructions
|
|
285
241
|
|
|
286
|
-
|
|
242
|
+
- Follow existing code style
|
|
243
|
+
- Read before write
|
|
244
|
+
- Keep changes minimal
|
|
245
|
+
`,
|
|
246
|
+
standard: `# Project Instructions
|
|
287
247
|
|
|
288
|
-
##
|
|
248
|
+
## Overview
|
|
249
|
+
<!-- Project purpose and tech stack -->
|
|
289
250
|
|
|
290
|
-
|
|
251
|
+
## Coding Standards
|
|
252
|
+
- Follow existing patterns
|
|
253
|
+
- Read context before modifying
|
|
254
|
+
- Keep changes focused
|
|
291
255
|
|
|
292
|
-
##
|
|
256
|
+
## Key Files
|
|
257
|
+
<!-- Important file paths -->
|
|
293
258
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
259
|
+
## Notes
|
|
260
|
+
<!-- Special considerations -->
|
|
261
|
+
`,
|
|
262
|
+
detailed: `# Project Instructions
|
|
297
263
|
|
|
298
|
-
##
|
|
264
|
+
## Overview
|
|
265
|
+
<!-- Project purpose, goals, tech stack -->
|
|
299
266
|
|
|
300
|
-
|
|
267
|
+
## Architecture
|
|
268
|
+
<!-- High-level design decisions -->
|
|
301
269
|
|
|
302
|
-
##
|
|
270
|
+
## Coding Standards
|
|
271
|
+
- Follow existing patterns
|
|
272
|
+
- Read context before modifying
|
|
273
|
+
- Write clear commit messages
|
|
274
|
+
- Add comments for complex logic
|
|
303
275
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
},
|
|
317
|
-
mcpServers: {}
|
|
276
|
+
## Key Files
|
|
277
|
+
<!-- Important paths and purposes -->
|
|
278
|
+
|
|
279
|
+
## Dependencies
|
|
280
|
+
<!-- Key deps and roles -->
|
|
281
|
+
|
|
282
|
+
## Testing
|
|
283
|
+
<!-- How to run tests -->
|
|
284
|
+
|
|
285
|
+
## Notes
|
|
286
|
+
<!-- Gotchas and context -->
|
|
287
|
+
`
|
|
318
288
|
};
|
|
319
|
-
var
|
|
320
|
-
node_modules/
|
|
289
|
+
var CLAUDEIGNORE = `node_modules/
|
|
321
290
|
dist/
|
|
291
|
+
build/
|
|
322
292
|
.env
|
|
323
293
|
.env.*
|
|
324
294
|
*.log
|
|
325
295
|
.DS_Store
|
|
326
296
|
coverage/
|
|
297
|
+
.git/
|
|
327
298
|
`;
|
|
328
|
-
async function
|
|
329
|
-
|
|
330
|
-
|
|
299
|
+
async function scaffoldConfig(total) {
|
|
300
|
+
step(3, total, "CLAUDE.md \u6A21\u677F");
|
|
301
|
+
const style = await select({
|
|
302
|
+
message: "\u9009\u62E9\u6A21\u677F\u98CE\u683C",
|
|
303
|
+
choices: [
|
|
304
|
+
{ value: "minimal", name: "\u6781\u7B80 \u2014 \u51E0\u884C\u6838\u5FC3\u89C4\u5219" },
|
|
305
|
+
{ value: "standard", name: "\u6807\u51C6 \u2014 \u5E38\u7528\u5206\u533A (\u63A8\u8350)" },
|
|
306
|
+
{ value: "detailed", name: "\u8BE6\u7EC6 \u2014 \u542B\u67B6\u6784/\u6D4B\u8BD5/\u4F9D\u8D56" }
|
|
307
|
+
],
|
|
308
|
+
default: "standard"
|
|
309
|
+
});
|
|
310
|
+
return { style };
|
|
311
|
+
}
|
|
312
|
+
async function scaffold(targetDir, opts) {
|
|
331
313
|
const files = [];
|
|
332
|
-
const
|
|
333
|
-
const r1 = writeFileSafe(claudeMdPath, CLAUDE_MD_TEMPLATE);
|
|
314
|
+
const r1 = writeFileSafe(join2(targetDir, "CLAUDE.md"), TEMPLATES[opts.style]);
|
|
334
315
|
files.push({ path: "CLAUDE.md", written: r1.written });
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
const
|
|
338
|
-
const r2 = writeFileSafe(settingsPath, JSON.stringify(SETTINGS_TEMPLATE, null, 2) + "\n");
|
|
316
|
+
ensureDir(join2(targetDir, ".claude"));
|
|
317
|
+
const settings = { permissions: { allow: ["Read", "Glob", "Grep", "WebFetch", "WebSearch"], deny: [] }, mcpServers: {} };
|
|
318
|
+
const r2 = writeFileSafe(join2(targetDir, ".claude", "settings.json"), JSON.stringify(settings, null, 2) + "\n");
|
|
339
319
|
files.push({ path: ".claude/settings.json", written: r2.written });
|
|
340
|
-
const
|
|
341
|
-
const r3 = writeFileSafe(ignorePath, CLAUDEIGNORE_TEMPLATE);
|
|
320
|
+
const r3 = writeFileSafe(join2(targetDir, ".claudeignore"), CLAUDEIGNORE);
|
|
342
321
|
files.push({ path: ".claudeignore", written: r3.written });
|
|
343
|
-
s.stop("\u914D\u7F6E\u6587\u4EF6\u751F\u6210\u5B8C\u6210");
|
|
344
322
|
for (const f of files) {
|
|
345
|
-
if (f.written)
|
|
346
|
-
|
|
347
|
-
} else {
|
|
348
|
-
p4.log.info(`${f.path} \u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7`);
|
|
349
|
-
}
|
|
323
|
+
if (f.written) ok(f.path);
|
|
324
|
+
else info(`${f.path} (\u5DF2\u5B58\u5728, \u8DF3\u8FC7)`);
|
|
350
325
|
}
|
|
351
326
|
return { files };
|
|
352
327
|
}
|
|
353
328
|
|
|
354
329
|
// src/steps/install-mcp.ts
|
|
355
|
-
import
|
|
356
|
-
import pc4 from "picocolors";
|
|
330
|
+
import { checkbox as checkbox2, confirm, input } from "@inquirer/prompts";
|
|
357
331
|
import { join as join3 } from "path";
|
|
358
332
|
import { homedir } from "os";
|
|
359
333
|
|
|
@@ -418,99 +392,73 @@ var MCP_SERVERS = [
|
|
|
418
392
|
];
|
|
419
393
|
|
|
420
394
|
// src/steps/install-mcp.ts
|
|
421
|
-
async function selectMcpServers() {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
console.log(pc4.dim(" \u56DE\u8F66 \u786E\u8BA4\u9009\u62E9"));
|
|
428
|
-
console.log();
|
|
429
|
-
const selected = await p5.multiselect({
|
|
430
|
-
message: "\u9009\u62E9\u8981\u5B89\u88C5\u7684 MCP Servers (\u7A7A\u683C\u5207\u6362, \u56DE\u8F66\u786E\u8BA4)",
|
|
431
|
-
options: MCP_SERVERS.map((s) => ({
|
|
395
|
+
async function selectMcpServers(total) {
|
|
396
|
+
step(4, total, "MCP Servers");
|
|
397
|
+
hint("\u7A7A\u683C=\u5207\u6362 a=\u5168\u9009 \u56DE\u8F66=\u786E\u8BA4");
|
|
398
|
+
const selected = await checkbox2({
|
|
399
|
+
message: "\u9009\u62E9 MCP Servers",
|
|
400
|
+
choices: MCP_SERVERS.map((s) => ({
|
|
432
401
|
value: s.name,
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
}))
|
|
436
|
-
initialValues: MCP_SERVERS.map((s) => s.name),
|
|
437
|
-
required: false
|
|
402
|
+
name: `${s.name} \u2014 ${s.description}`,
|
|
403
|
+
checked: true
|
|
404
|
+
}))
|
|
438
405
|
});
|
|
439
|
-
|
|
440
|
-
|
|
406
|
+
const servers = MCP_SERVERS.filter((s) => selected.includes(s.name));
|
|
407
|
+
const addCustom = await confirm({ message: "\u6DFB\u52A0\u81EA\u5B9A\u4E49 MCP (npm\u5305)?", default: false });
|
|
408
|
+
if (addCustom) {
|
|
409
|
+
const raw = await input({
|
|
410
|
+
message: "npm \u5305\u540D (\u9017\u53F7\u5206\u9694)"
|
|
411
|
+
});
|
|
412
|
+
if (raw.trim()) {
|
|
413
|
+
for (const pkg of raw.split(",").map((s) => s.trim()).filter(Boolean)) {
|
|
414
|
+
const name = pkg.split("/").pop()?.replace(/^mcp-/, "") ?? pkg;
|
|
415
|
+
servers.push({ name, package: pkg, description: `\u81EA\u5B9A\u4E49: ${pkg}`, scope: "user", command: "npx", args: ["-y", pkg] });
|
|
416
|
+
}
|
|
417
|
+
}
|
|
441
418
|
}
|
|
442
|
-
|
|
443
|
-
return MCP_SERVERS.filter((s) => names.includes(s.name));
|
|
419
|
+
return servers;
|
|
444
420
|
}
|
|
445
421
|
async function installMcp(servers) {
|
|
446
|
-
if (servers.length === 0) {
|
|
447
|
-
return { installed: [], failed: [] };
|
|
448
|
-
}
|
|
449
|
-
const s = p5.spinner();
|
|
450
|
-
s.start("\u6B63\u5728\u914D\u7F6E MCP Servers...");
|
|
422
|
+
if (servers.length === 0) return { installed: [], failed: [] };
|
|
451
423
|
const installed = [];
|
|
452
424
|
const failed = [];
|
|
453
|
-
const userServers = servers.filter((
|
|
454
|
-
const projectServers = servers.filter((
|
|
425
|
+
const userServers = servers.filter((s) => s.scope === "user");
|
|
426
|
+
const projectServers = servers.filter((s) => s.scope === "project");
|
|
455
427
|
if (userServers.length > 0) {
|
|
456
|
-
const
|
|
457
|
-
ensureDir(
|
|
458
|
-
const
|
|
459
|
-
const
|
|
460
|
-
|
|
461
|
-
mcpConfig[sv.name] = {
|
|
462
|
-
command: sv.command,
|
|
463
|
-
args: sv.args,
|
|
464
|
-
...sv.env ? { env: sv.env } : {}
|
|
465
|
-
};
|
|
428
|
+
const dir = join3(homedir(), ".claude");
|
|
429
|
+
ensureDir(dir);
|
|
430
|
+
const cfg = {};
|
|
431
|
+
for (const s of userServers) {
|
|
432
|
+
cfg[s.name] = { command: s.command, args: s.args, ...s.env ? { env: s.env } : {} };
|
|
466
433
|
}
|
|
467
434
|
try {
|
|
468
|
-
mergeJsonFile(
|
|
469
|
-
|
|
470
|
-
installed.push(sv.name);
|
|
471
|
-
}
|
|
435
|
+
mergeJsonFile(join3(dir, "settings.json"), { mcpServers: cfg });
|
|
436
|
+
userServers.forEach((s) => installed.push(s.name));
|
|
472
437
|
} catch {
|
|
473
|
-
|
|
474
|
-
failed.push(sv.name);
|
|
475
|
-
}
|
|
438
|
+
userServers.forEach((s) => failed.push(s.name));
|
|
476
439
|
}
|
|
477
440
|
}
|
|
478
441
|
if (projectServers.length > 0) {
|
|
479
|
-
const
|
|
480
|
-
ensureDir(
|
|
481
|
-
const
|
|
482
|
-
const
|
|
483
|
-
|
|
484
|
-
mcpConfig[sv.name] = {
|
|
485
|
-
command: sv.command,
|
|
486
|
-
args: sv.args,
|
|
487
|
-
...sv.env ? { env: sv.env } : {}
|
|
488
|
-
};
|
|
442
|
+
const dir = join3(process.cwd(), ".claude");
|
|
443
|
+
ensureDir(dir);
|
|
444
|
+
const cfg = {};
|
|
445
|
+
for (const s of projectServers) {
|
|
446
|
+
cfg[s.name] = { command: s.command, args: s.args, ...s.env ? { env: s.env } : {} };
|
|
489
447
|
}
|
|
490
448
|
try {
|
|
491
|
-
mergeJsonFile(
|
|
492
|
-
|
|
493
|
-
installed.push(sv.name);
|
|
494
|
-
}
|
|
449
|
+
mergeJsonFile(join3(dir, "settings.json"), { mcpServers: cfg });
|
|
450
|
+
projectServers.forEach((s) => installed.push(s.name));
|
|
495
451
|
} catch {
|
|
496
|
-
|
|
497
|
-
failed.push(sv.name);
|
|
498
|
-
}
|
|
452
|
+
projectServers.forEach((s) => failed.push(s.name));
|
|
499
453
|
}
|
|
500
454
|
}
|
|
501
|
-
|
|
502
|
-
for (const
|
|
503
|
-
p5.log.success(`${name} MCP \u5DF2\u914D\u7F6E`);
|
|
504
|
-
}
|
|
505
|
-
for (const name of failed) {
|
|
506
|
-
p5.log.error(`${name} MCP \u914D\u7F6E\u5931\u8D25`);
|
|
507
|
-
}
|
|
455
|
+
for (const n of installed) ok(`${n} MCP`);
|
|
456
|
+
for (const n of failed) fail(`${n} MCP`);
|
|
508
457
|
return { installed, failed };
|
|
509
458
|
}
|
|
510
459
|
|
|
511
460
|
// src/steps/install-skills.ts
|
|
512
|
-
import
|
|
513
|
-
import pc5 from "picocolors";
|
|
461
|
+
import { checkbox as checkbox3 } from "@inquirer/prompts";
|
|
514
462
|
|
|
515
463
|
// src/registry/skills.ts
|
|
516
464
|
var SKILLS = [
|
|
@@ -535,213 +483,149 @@ var SKILLS = [
|
|
|
535
483
|
];
|
|
536
484
|
|
|
537
485
|
// src/steps/install-skills.ts
|
|
538
|
-
async function selectSkills() {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
console.log(pc5.dim(" \u56DE\u8F66 \u786E\u8BA4\u9009\u62E9"));
|
|
545
|
-
console.log();
|
|
546
|
-
const selected = await p6.multiselect({
|
|
547
|
-
message: "\u9009\u62E9\u8981\u5B89\u88C5\u7684 Skills / Plugins (\u7A7A\u683C\u5207\u6362, \u56DE\u8F66\u786E\u8BA4)",
|
|
548
|
-
options: SKILLS.map((s) => ({
|
|
486
|
+
async function selectSkills(total) {
|
|
487
|
+
step(5, total, "Skills / Plugins");
|
|
488
|
+
hint("\u7A7A\u683C=\u5207\u6362 a=\u5168\u9009 \u56DE\u8F66=\u786E\u8BA4");
|
|
489
|
+
const selected = await checkbox3({
|
|
490
|
+
message: "\u9009\u62E9 Skills",
|
|
491
|
+
choices: SKILLS.map((s) => ({
|
|
549
492
|
value: s.name,
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
}))
|
|
553
|
-
initialValues: SKILLS.map((s) => s.name),
|
|
554
|
-
required: false
|
|
493
|
+
name: `${s.name} \u2014 ${s.description}`,
|
|
494
|
+
checked: true
|
|
495
|
+
}))
|
|
555
496
|
});
|
|
556
|
-
|
|
557
|
-
return [];
|
|
558
|
-
}
|
|
559
|
-
const names = selected;
|
|
560
|
-
return SKILLS.filter((s) => names.includes(s.name));
|
|
497
|
+
return SKILLS.filter((s) => selected.includes(s.name));
|
|
561
498
|
}
|
|
562
499
|
async function installSkills(skills) {
|
|
563
|
-
if (skills.length === 0) {
|
|
564
|
-
return { installed: [], failed: [] };
|
|
565
|
-
}
|
|
566
|
-
const s = p6.spinner();
|
|
500
|
+
if (skills.length === 0) return { installed: [], failed: [] };
|
|
567
501
|
const installed = [];
|
|
568
502
|
const failed = [];
|
|
569
503
|
for (const skill of skills) {
|
|
570
|
-
s.start(`\u6B63\u5728\u5B89\u88C5 ${skill.name}...`);
|
|
571
504
|
const [cmd, ...args] = skill.installCmd;
|
|
572
505
|
const result = await run(cmd, args);
|
|
573
506
|
if (result.exitCode === 0) {
|
|
574
507
|
installed.push(skill.name);
|
|
575
|
-
|
|
508
|
+
ok(skill.name);
|
|
576
509
|
} else {
|
|
577
510
|
failed.push(skill.name);
|
|
578
|
-
|
|
579
|
-
|
|
511
|
+
fail(skill.name);
|
|
512
|
+
warn(` \u624B\u52A8: ${skill.installCmd.join(" ")}`);
|
|
580
513
|
}
|
|
581
514
|
}
|
|
582
515
|
return { installed, failed };
|
|
583
516
|
}
|
|
584
517
|
|
|
585
518
|
// src/steps/clean-env.ts
|
|
586
|
-
import
|
|
587
|
-
import
|
|
588
|
-
|
|
589
|
-
if (
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
const selected = await p7.multiselect({
|
|
600
|
-
message: "\u9009\u62E9\u8981\u79FB\u9664\u7684\u654F\u611F\u73AF\u5883\u53D8\u91CF (\u7A7A\u683C\u5207\u6362, \u56DE\u8F66\u786E\u8BA4)",
|
|
601
|
-
options: sensitiveVars.map((v) => ({
|
|
519
|
+
import { checkbox as checkbox4 } from "@inquirer/prompts";
|
|
520
|
+
import pc2 from "picocolors";
|
|
521
|
+
function mask(val) {
|
|
522
|
+
if (val.length <= 8) return "****";
|
|
523
|
+
return val.slice(0, 4) + "..." + val.slice(-4);
|
|
524
|
+
}
|
|
525
|
+
async function cleanEnv(vars, total) {
|
|
526
|
+
if (vars.length === 0) return { removed: [], skipped: [] };
|
|
527
|
+
step(6, total, "\u73AF\u5883\u53D8\u91CF\u6E05\u7406");
|
|
528
|
+
hint("\u7A7A\u683C=\u5207\u6362 \u56DE\u8F66=\u786E\u8BA4 (\u4E0D\u9009\u5219\u5168\u90E8\u4FDD\u7559)");
|
|
529
|
+
const selected = await checkbox4({
|
|
530
|
+
message: "\u9009\u62E9\u8981\u79FB\u9664\u7684\u53D8\u91CF",
|
|
531
|
+
choices: vars.map((v) => ({
|
|
602
532
|
value: v.key,
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
}))
|
|
606
|
-
initialValues: [],
|
|
607
|
-
required: false
|
|
533
|
+
name: `${v.key} = ${pc2.dim(mask(v.value))}`,
|
|
534
|
+
checked: false
|
|
535
|
+
}))
|
|
608
536
|
});
|
|
609
|
-
if (
|
|
610
|
-
return { removed: [], skipped: sensitiveVars.map((v) => v.key) };
|
|
611
|
-
}
|
|
612
|
-
const toRemove = selected;
|
|
537
|
+
if (selected.length === 0) return { removed: [], skipped: vars.map((v) => v.key) };
|
|
613
538
|
const removed = [];
|
|
614
539
|
const skipped = [];
|
|
615
|
-
const
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
540
|
+
for (const key of selected) {
|
|
541
|
+
if (process.platform === "win32") {
|
|
542
|
+
const r = await run("powershell", ["-Command", `[Environment]::SetEnvironmentVariable('${key}', $null, 'User')`]);
|
|
543
|
+
if (r.exitCode === 0) {
|
|
544
|
+
removed.push(key);
|
|
545
|
+
ok(`${key} \u5DF2\u79FB\u9664`);
|
|
546
|
+
} else {
|
|
547
|
+
skipped.push(key);
|
|
548
|
+
warn(`${key} \u79FB\u9664\u5931\u8D25`);
|
|
549
|
+
}
|
|
621
550
|
} else {
|
|
551
|
+
delete process.env[key];
|
|
622
552
|
skipped.push(key);
|
|
623
|
-
|
|
624
|
-
}
|
|
625
|
-
s.stop("\u73AF\u5883\u53D8\u91CF\u6E05\u7406\u5B8C\u6210");
|
|
626
|
-
for (const key of removed) {
|
|
627
|
-
p7.log.success(`${key} \u5DF2\u79FB\u9664`);
|
|
628
|
-
}
|
|
629
|
-
for (const key of skipped) {
|
|
630
|
-
p7.log.warning(`${key} \u79FB\u9664\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u5904\u7406`);
|
|
631
|
-
}
|
|
632
|
-
if (skipped.length > 0 && process.platform !== "win32") {
|
|
633
|
-
p7.log.info("\u624B\u52A8\u79FB\u9664\u65B9\u6CD5:");
|
|
634
|
-
for (const key of skipped) {
|
|
635
|
-
console.log(pc6.dim(` \u4ECE ~/.bashrc \u6216 ~/.zshrc \u4E2D\u5220\u9664: export ${key}=...`));
|
|
553
|
+
warn(`${key} \u9700\u624B\u52A8\u4ECE ~/.bashrc \u6216 ~/.zshrc \u79FB\u9664`);
|
|
636
554
|
}
|
|
637
555
|
}
|
|
638
556
|
return { removed, skipped };
|
|
639
557
|
}
|
|
640
|
-
async function removeEnvVar(key) {
|
|
641
|
-
if (process.platform === "win32") {
|
|
642
|
-
const result = await run("powershell", [
|
|
643
|
-
"-Command",
|
|
644
|
-
`[Environment]::SetEnvironmentVariable('${key}', $null, 'User')`
|
|
645
|
-
]);
|
|
646
|
-
return result.exitCode === 0;
|
|
647
|
-
} else {
|
|
648
|
-
delete process.env[key];
|
|
649
|
-
return false;
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
function maskValue2(val) {
|
|
653
|
-
if (val.length <= 8) return "****";
|
|
654
|
-
return val.slice(0, 4) + "..." + val.slice(-4);
|
|
655
|
-
}
|
|
656
558
|
|
|
657
559
|
// src/cli.ts
|
|
560
|
+
var TOTAL = 7;
|
|
658
561
|
async function runCli() {
|
|
659
562
|
const results = [];
|
|
660
|
-
const env = await detect();
|
|
661
|
-
const components = await selectComponents(env);
|
|
662
|
-
|
|
663
|
-
|
|
563
|
+
const env = await detect(TOTAL);
|
|
564
|
+
const components = await selectComponents(env, TOTAL);
|
|
565
|
+
let scaffoldOpts = null;
|
|
566
|
+
if (components.scaffold) scaffoldOpts = await scaffoldConfig(TOTAL);
|
|
567
|
+
let mcpServers = [];
|
|
568
|
+
if (components.installMcp) mcpServers = await selectMcpServers(TOTAL);
|
|
569
|
+
let skills = [];
|
|
570
|
+
if (components.installSkills) skills = await selectSkills(TOTAL);
|
|
571
|
+
step(6, TOTAL, "\u786E\u8BA4");
|
|
664
572
|
const actions = [];
|
|
665
|
-
if (components.installCli && !env.claudeInstalled) actions.push("\u5B89\u88C5 Claude
|
|
666
|
-
if (
|
|
667
|
-
if (mcpServers.length > 0) actions.push(
|
|
668
|
-
if (skills.length > 0) actions.push(
|
|
669
|
-
if (components.cleanEnv) actions.push(`\u6E05\u7406 ${env.sensitiveEnvVars.length} \u4E2A\
|
|
573
|
+
if (components.installCli && !env.claudeInstalled) actions.push("\u5B89\u88C5 Claude CLI");
|
|
574
|
+
if (scaffoldOpts) actions.push(`\u751F\u6210\u914D\u7F6E (${scaffoldOpts.style})`);
|
|
575
|
+
if (mcpServers.length > 0) actions.push(`${mcpServers.length} \u4E2A MCP`);
|
|
576
|
+
if (skills.length > 0) actions.push(`${skills.length} \u4E2A Skills`);
|
|
577
|
+
if (components.cleanEnv) actions.push(`\u6E05\u7406 ${env.sensitiveEnvVars.length} \u4E2A\u53D8\u91CF`);
|
|
670
578
|
if (actions.length === 0) {
|
|
671
|
-
|
|
579
|
+
info("\u65E0\u64CD\u4F5C");
|
|
672
580
|
return;
|
|
673
581
|
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
console.log();
|
|
679
|
-
console.log(pc7.dim(" Y/\u56DE\u8F66 \u786E\u8BA4 | N \u53D6\u6D88"));
|
|
680
|
-
console.log();
|
|
681
|
-
const confirmed = await p8.confirm({
|
|
682
|
-
message: "\u786E\u8BA4\u6267\u884C\uFF1F",
|
|
683
|
-
initialValue: true
|
|
684
|
-
});
|
|
685
|
-
if (p8.isCancel(confirmed) || !confirmed) {
|
|
686
|
-
p8.cancel("\u5DF2\u53D6\u6D88");
|
|
582
|
+
console.log(pc3.dim(` \u2192 ${actions.join(" \xB7 ")}`));
|
|
583
|
+
const go = await confirm2({ message: "\u5F00\u59CB\u6267\u884C?", default: true });
|
|
584
|
+
if (!go) {
|
|
585
|
+
info("\u5DF2\u53D6\u6D88");
|
|
687
586
|
process.exit(0);
|
|
688
587
|
}
|
|
588
|
+
step(7, TOTAL, "\u6267\u884C\u5B89\u88C5");
|
|
689
589
|
if (components.installCli) {
|
|
690
590
|
const r = await installCli(env.claudeInstalled);
|
|
691
|
-
results.push({
|
|
692
|
-
label: r.skipped ? "Claude Code CLI (\u5DF2\u5B89\u88C5)" : "Claude Code CLI \u5B89\u88C5",
|
|
693
|
-
ok: r.success
|
|
694
|
-
});
|
|
591
|
+
results.push({ label: r.skipped ? "Claude CLI (\u5DF2\u5B89\u88C5)" : "Claude CLI", ok: r.success });
|
|
695
592
|
}
|
|
696
|
-
if (
|
|
697
|
-
|
|
698
|
-
results.push({ label: "\u914D\u7F6E\u6587\u4EF6
|
|
593
|
+
if (scaffoldOpts) {
|
|
594
|
+
await scaffold(process.cwd(), scaffoldOpts);
|
|
595
|
+
results.push({ label: "\u914D\u7F6E\u6587\u4EF6", ok: true });
|
|
699
596
|
}
|
|
700
597
|
if (mcpServers.length > 0) {
|
|
701
598
|
const r = await installMcp(mcpServers);
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
}
|
|
705
|
-
for (const name of r.failed) {
|
|
706
|
-
results.push({ label: `${name} MCP`, ok: false });
|
|
707
|
-
}
|
|
599
|
+
r.installed.forEach((n) => results.push({ label: `${n} MCP`, ok: true }));
|
|
600
|
+
r.failed.forEach((n) => results.push({ label: `${n} MCP`, ok: false }));
|
|
708
601
|
}
|
|
709
602
|
if (skills.length > 0) {
|
|
710
603
|
const r = await installSkills(skills);
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
}
|
|
714
|
-
for (const name of r.failed) {
|
|
715
|
-
results.push({ label: `${name} Skill`, ok: false });
|
|
716
|
-
}
|
|
604
|
+
r.installed.forEach((n) => results.push({ label: `${n} Skill`, ok: true }));
|
|
605
|
+
r.failed.forEach((n) => results.push({ label: `${n} Skill`, ok: false }));
|
|
717
606
|
}
|
|
718
607
|
if (components.cleanEnv) {
|
|
719
|
-
const r = await cleanEnv(env.sensitiveEnvVars);
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
}
|
|
723
|
-
for (const key of r.skipped) {
|
|
724
|
-
results.push({ label: `${key} \u9700\u624B\u52A8\u79FB\u9664`, ok: false });
|
|
725
|
-
}
|
|
608
|
+
const r = await cleanEnv(env.sensitiveEnvVars, TOTAL);
|
|
609
|
+
r.removed.forEach((k) => results.push({ label: `${k} \u5DF2\u79FB\u9664`, ok: true }));
|
|
610
|
+
r.skipped.forEach((k) => results.push({ label: `${k} \u9700\u624B\u52A8`, ok: false }));
|
|
726
611
|
}
|
|
727
|
-
|
|
612
|
+
done(results);
|
|
728
613
|
}
|
|
729
614
|
|
|
730
615
|
// src/index.ts
|
|
731
|
-
|
|
732
|
-
var
|
|
616
|
+
var require2 = createRequire(import.meta.url);
|
|
617
|
+
var { version } = require2("../package.json");
|
|
733
618
|
async function main() {
|
|
734
|
-
banner(
|
|
735
|
-
p9.intro("\u5F00\u59CB\u914D\u7F6E Claude Code \u73AF\u5883");
|
|
619
|
+
banner(version);
|
|
736
620
|
try {
|
|
737
621
|
await runCli();
|
|
738
622
|
} catch (err) {
|
|
739
|
-
if (err instanceof Error) {
|
|
740
|
-
|
|
623
|
+
if (err instanceof Error && err.message.includes("User force closed")) {
|
|
624
|
+
console.log("\n \u5DF2\u9000\u51FA");
|
|
625
|
+
process.exit(0);
|
|
741
626
|
}
|
|
742
|
-
|
|
627
|
+
console.error(err);
|
|
743
628
|
process.exit(1);
|
|
744
629
|
}
|
|
745
|
-
p9.outro("\u611F\u8C22\u4F7F\u7528 ccbot\uFF01");
|
|
746
630
|
}
|
|
747
631
|
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccbot-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Claude Code 环境一键配置工具",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
],
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@
|
|
31
|
+
"@inquirer/prompts": "^8.3.0",
|
|
32
32
|
"execa": "^9.5.2",
|
|
33
33
|
"picocolors": "^1.1.1"
|
|
34
34
|
},
|