mdk-skills 2.4.19 → 2.4.21
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/package.json +1 -1
- package/scripts/cli.js +104 -130
- package/scripts/core.js +131 -136
- package/scripts/web-ui/server/context.js +62 -58
- package/scripts/web-ui/server/routes/others.js +29 -19
- package/scripts/web-ui/server/routes/profiles.js +16 -12
- package/scripts/web-ui/server/routes/skills.js +139 -125
- package/scripts/web-ui/server/routes/source.js +52 -48
- package/scripts/web-ui/server/utils.js +56 -52
- package/scripts/web-ui/server.js +40 -16
package/package.json
CHANGED
package/scripts/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require("fs");
|
|
4
4
|
const path = require("path");
|
|
5
|
-
const { getPackageSkills, getUserSkills, getSkillsSource, backupDir, listSkillDirs } = require("./core");
|
|
5
|
+
const { getPackageSkills, getUserSkills, getSkillsSource, backupDir, listSkillDirs, copyDir } = require("./core");
|
|
6
6
|
|
|
7
7
|
// npx 运行时:process.cwd() 是用户项目目录
|
|
8
8
|
// __dirname 是包内 scripts/ 目录
|
|
@@ -14,31 +14,44 @@ const projectRoot = (() => {
|
|
|
14
14
|
return process.cwd();
|
|
15
15
|
}
|
|
16
16
|
})();
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
|
|
18
|
+
let skillsSource;
|
|
19
|
+
let claudeDest;
|
|
20
|
+
let skillsDest;
|
|
21
|
+
let settingsPath;
|
|
22
|
+
let pkgSkillsSource;
|
|
23
|
+
|
|
24
|
+
async function pathExists(p) {
|
|
25
|
+
try { await fs.promises.access(p); return true; } catch { return false; }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function initPaths() {
|
|
29
|
+
skillsSource = await getSkillsSource(projectRoot);
|
|
30
|
+
claudeDest = path.join(projectRoot, ".claude");
|
|
31
|
+
skillsDest = path.join(claudeDest, "skills");
|
|
32
|
+
settingsPath = path.join(claudeDest, "settings.json");
|
|
33
|
+
pkgSkillsSource = skillsSource
|
|
34
|
+
? path.join(skillsSource, ".claude", "skills")
|
|
35
|
+
: null;
|
|
36
|
+
}
|
|
24
37
|
|
|
25
38
|
// ---------- 文件写入 ----------
|
|
26
39
|
|
|
27
|
-
function readSettings() {
|
|
28
|
-
if (!
|
|
40
|
+
async function readSettings() {
|
|
41
|
+
if (!(await pathExists(settingsPath)))
|
|
29
42
|
return { skills: {}, always_apply_skills: [] };
|
|
30
43
|
try {
|
|
31
|
-
return JSON.parse(fs.
|
|
44
|
+
return JSON.parse(await fs.promises.readFile(settingsPath, "utf-8"));
|
|
32
45
|
} catch {
|
|
33
46
|
return { skills: {}, always_apply_skills: [] };
|
|
34
47
|
}
|
|
35
48
|
}
|
|
36
49
|
|
|
37
|
-
function writeSettings(settings) {
|
|
38
|
-
if (!
|
|
39
|
-
fs.
|
|
50
|
+
async function writeSettings(settings) {
|
|
51
|
+
if (!(await pathExists(claudeDest))) {
|
|
52
|
+
await fs.promises.mkdir(claudeDest, { recursive: true });
|
|
40
53
|
}
|
|
41
|
-
fs.
|
|
54
|
+
await fs.promises.writeFile(
|
|
42
55
|
settingsPath,
|
|
43
56
|
JSON.stringify(settings, null, 2) + "\n",
|
|
44
57
|
"utf-8",
|
|
@@ -47,52 +60,35 @@ function writeSettings(settings) {
|
|
|
47
60
|
|
|
48
61
|
// ---------- 安装勾选的技能 ----------
|
|
49
62
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
for (const item of fs.readdirSync(src)) {
|
|
54
|
-
const srcPath = path.join(src, item);
|
|
55
|
-
const destPath = path.join(dest, item);
|
|
56
|
-
if (fs.statSync(srcPath).isDirectory()) {
|
|
57
|
-
copyDirSync(srcPath, destPath);
|
|
58
|
-
} else {
|
|
59
|
-
fs.copyFileSync(srcPath, destPath);
|
|
60
|
-
}
|
|
63
|
+
async function installSelectedSkills(selectedNames) {
|
|
64
|
+
if (!(await pathExists(skillsDest))) {
|
|
65
|
+
await fs.promises.mkdir(skillsDest, { recursive: true });
|
|
61
66
|
}
|
|
62
|
-
}
|
|
63
67
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (!fs.existsSync(skillsDest)) {
|
|
67
|
-
fs.mkdirSync(skillsDest, { recursive: true });
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const allPkgSkills = listSkillDirs(pkgSkillsSource); let installedCount = 0;
|
|
68
|
+
const allPkgSkills = await listSkillDirs(pkgSkillsSource);
|
|
69
|
+
let installedCount = 0;
|
|
71
70
|
|
|
72
71
|
for (const name of allPkgSkills) {
|
|
73
72
|
const src = path.join(pkgSkillsSource, name);
|
|
74
73
|
const dest = path.join(skillsDest, name);
|
|
75
74
|
|
|
76
75
|
if (selectedNames.includes(name)) {
|
|
77
|
-
|
|
78
|
-
if (!fs.existsSync(dest)) {
|
|
76
|
+
if (!(await pathExists(dest))) {
|
|
79
77
|
try {
|
|
80
|
-
|
|
78
|
+
await copyDir(src, dest);
|
|
81
79
|
installedCount++;
|
|
82
80
|
} catch (err) {
|
|
83
81
|
console.error(` ❌ 安装技能 "${name}" 失败:`, err.message);
|
|
84
82
|
}
|
|
85
83
|
}
|
|
86
84
|
} else {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
fs.rmSync(dest, { recursive: true, force: true });
|
|
85
|
+
if (await pathExists(dest)) {
|
|
86
|
+
await fs.promises.rm(dest, { recursive: true, force: true });
|
|
90
87
|
}
|
|
91
88
|
}
|
|
92
89
|
}
|
|
93
90
|
|
|
94
|
-
|
|
95
|
-
const settings = readSettings();
|
|
91
|
+
const settings = await readSettings();
|
|
96
92
|
if (!settings.skills) settings.skills = {};
|
|
97
93
|
|
|
98
94
|
for (const name of allPkgSkills) {
|
|
@@ -103,21 +99,19 @@ function installSelectedSkills(selectedNames) {
|
|
|
103
99
|
settings.skills[name].enabled = enabled;
|
|
104
100
|
}
|
|
105
101
|
|
|
106
|
-
writeSettings(settings);
|
|
102
|
+
await writeSettings(settings);
|
|
107
103
|
|
|
108
|
-
// 安装 CLAUDE.md(没有才装)
|
|
109
104
|
const mdSource = path.join(skillsSource, "CLAUDE.md");
|
|
110
105
|
const mdDest = path.join(projectRoot, "CLAUDE.md");
|
|
111
|
-
if (
|
|
112
|
-
fs.
|
|
106
|
+
if (await pathExists(mdSource) && !(await pathExists(mdDest))) {
|
|
107
|
+
await fs.promises.copyFile(mdSource, mdDest);
|
|
113
108
|
console.log(" 📝 CLAUDE.md 已创建\n");
|
|
114
109
|
}
|
|
115
110
|
|
|
116
|
-
// 复制 profiles.json 到项目
|
|
117
111
|
const profilesSource = path.join(skillsSource, ".claude", "profiles.json");
|
|
118
112
|
const profilesDest = path.join(claudeDest, "profiles.json");
|
|
119
|
-
if (
|
|
120
|
-
fs.
|
|
113
|
+
if (await pathExists(profilesSource) && !(await pathExists(profilesDest))) {
|
|
114
|
+
await fs.promises.copyFile(profilesSource, profilesDest);
|
|
121
115
|
}
|
|
122
116
|
|
|
123
117
|
return installedCount;
|
|
@@ -125,55 +119,50 @@ function installSelectedSkills(selectedNames) {
|
|
|
125
119
|
|
|
126
120
|
// ---------- 场景选择(场景 → 一键装技能) ----------
|
|
127
121
|
|
|
128
|
-
function loadProfiles() {
|
|
122
|
+
async function loadProfiles() {
|
|
129
123
|
const profilesPath = path.join(skillsSource, ".claude", "profiles.json");
|
|
130
|
-
if (!
|
|
124
|
+
if (!(await pathExists(profilesPath))) return null;
|
|
131
125
|
try {
|
|
132
|
-
return JSON.parse(fs.
|
|
126
|
+
return JSON.parse(await fs.promises.readFile(profilesPath, "utf-8")).profiles;
|
|
133
127
|
} catch {
|
|
134
128
|
return null;
|
|
135
129
|
}
|
|
136
130
|
}
|
|
137
131
|
|
|
138
|
-
function applyProfile(profile) {
|
|
139
|
-
const pkgSkills = listSkillDirs(pkgSkillsSource);
|
|
140
|
-
const settings = readSettings();
|
|
132
|
+
async function applyProfile(profile) {
|
|
133
|
+
const pkgSkills = await listSkillDirs(pkgSkillsSource);
|
|
134
|
+
const settings = await readSettings();
|
|
141
135
|
|
|
142
|
-
// 确定要启用的技能列表
|
|
143
136
|
let selected;
|
|
144
137
|
if (profile.skills === null) {
|
|
145
|
-
// null 表示"自定义",不做操作,由调用方处理
|
|
146
138
|
return;
|
|
147
139
|
} else if (profile.skills.length === 0) {
|
|
148
140
|
selected = [];
|
|
149
141
|
} else {
|
|
150
|
-
// 只取包内实际存在的技能
|
|
151
142
|
selected = profile.skills.filter((s) => pkgSkills.includes(s));
|
|
152
143
|
}
|
|
153
144
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
fs.mkdirSync(skillsDest, { recursive: true });
|
|
145
|
+
if (!(await pathExists(skillsDest))) {
|
|
146
|
+
await fs.promises.mkdir(skillsDest, { recursive: true });
|
|
157
147
|
}
|
|
158
148
|
for (const name of pkgSkills) {
|
|
159
149
|
const src = path.join(pkgSkillsSource, name);
|
|
160
150
|
const dest = path.join(skillsDest, name);
|
|
161
151
|
if (selected.includes(name)) {
|
|
162
|
-
if (!
|
|
152
|
+
if (!(await pathExists(dest))) {
|
|
163
153
|
try {
|
|
164
|
-
|
|
154
|
+
await copyDir(src, dest);
|
|
165
155
|
} catch (err) {
|
|
166
156
|
console.error(` ❌ 安装技能 "${name}" 失败:`, err.message);
|
|
167
157
|
}
|
|
168
158
|
}
|
|
169
159
|
} else {
|
|
170
|
-
if (
|
|
171
|
-
fs.
|
|
160
|
+
if (await pathExists(dest)) {
|
|
161
|
+
await fs.promises.rm(dest, { recursive: true, force: true });
|
|
172
162
|
}
|
|
173
163
|
}
|
|
174
164
|
}
|
|
175
165
|
|
|
176
|
-
// 更新 settings
|
|
177
166
|
if (!settings.skills) settings.skills = {};
|
|
178
167
|
for (const name of pkgSkills) {
|
|
179
168
|
const enabled = selected.includes(name);
|
|
@@ -181,31 +170,26 @@ function applyProfile(profile) {
|
|
|
181
170
|
settings.skills[name].enabled = enabled;
|
|
182
171
|
}
|
|
183
172
|
|
|
184
|
-
// 更新 always_apply_skills
|
|
185
173
|
if (profile.always_apply) {
|
|
186
174
|
settings.always_apply_skills = profile.always_apply;
|
|
187
175
|
}
|
|
188
176
|
|
|
189
|
-
// 记录当前活动场景
|
|
190
177
|
settings._active_profile = profile.id;
|
|
191
|
-
writeSettings(settings);
|
|
178
|
+
await writeSettings(settings);
|
|
192
179
|
|
|
193
|
-
// 安装 CLAUDE.md(没有才装)
|
|
194
180
|
const mdSource = path.join(skillsSource, "CLAUDE.md");
|
|
195
181
|
const mdDest = path.join(projectRoot, "CLAUDE.md");
|
|
196
|
-
if (
|
|
197
|
-
fs.
|
|
182
|
+
if (await pathExists(mdSource) && !(await pathExists(mdDest))) {
|
|
183
|
+
await fs.promises.copyFile(mdSource, mdDest);
|
|
198
184
|
console.log(" 📝 CLAUDE.md 已创建\n");
|
|
199
185
|
}
|
|
200
186
|
|
|
201
|
-
// 复制 profiles.json 到项目(方便在项目里修改后 sync 推回)
|
|
202
187
|
const profilesSource = path.join(skillsSource, ".claude", "profiles.json");
|
|
203
188
|
const profilesDest = path.join(claudeDest, "profiles.json");
|
|
204
|
-
if (
|
|
205
|
-
fs.
|
|
189
|
+
if (await pathExists(profilesSource)) {
|
|
190
|
+
await fs.promises.copyFile(profilesSource, profilesDest);
|
|
206
191
|
}
|
|
207
192
|
|
|
208
|
-
// 输出结果
|
|
209
193
|
const enabledCount = selected.length;
|
|
210
194
|
const disabledCount = pkgSkills.length - enabledCount;
|
|
211
195
|
console.log(`\n ✅ 已切换到「${profile.name}」`);
|
|
@@ -215,10 +199,10 @@ function applyProfile(profile) {
|
|
|
215
199
|
async function startSceneSelection() {
|
|
216
200
|
const { select } = await import("@inquirer/prompts");
|
|
217
201
|
const chalk = (await import("chalk")).default;
|
|
218
|
-
const profiles = loadProfiles();
|
|
219
|
-
const settings = readSettings();
|
|
202
|
+
const profiles = await loadProfiles();
|
|
203
|
+
const settings = await readSettings();
|
|
220
204
|
const activeProfile = settings._active_profile;
|
|
221
|
-
const hasExistingInstall =
|
|
205
|
+
const hasExistingInstall = await pathExists(claudeDest);
|
|
222
206
|
|
|
223
207
|
const choices = profiles.map((p) => {
|
|
224
208
|
const isActive = p.id === activeProfile;
|
|
@@ -232,7 +216,6 @@ async function startSceneSelection() {
|
|
|
232
216
|
};
|
|
233
217
|
});
|
|
234
218
|
|
|
235
|
-
// 底部加个分隔
|
|
236
219
|
choices.push(
|
|
237
220
|
{ name: chalk.dim("────────────────"), value: "__sep__", description: "" },
|
|
238
221
|
{ name: " 查看技能清单", value: "__list__", description: "列出所有技能状态" },
|
|
@@ -254,7 +237,6 @@ async function startSceneSelection() {
|
|
|
254
237
|
|
|
255
238
|
if (selectedId === "__list__") {
|
|
256
239
|
await cmdList();
|
|
257
|
-
// 看完列表再回到场景选择
|
|
258
240
|
console.log("");
|
|
259
241
|
return startSceneSelection();
|
|
260
242
|
}
|
|
@@ -262,13 +244,11 @@ async function startSceneSelection() {
|
|
|
262
244
|
const profile = profiles.find((p) => p.id === selectedId);
|
|
263
245
|
|
|
264
246
|
if (profile.skills === null) {
|
|
265
|
-
// "自定义选择" → 跳到 checkbox
|
|
266
247
|
await startInteractiveMenu();
|
|
267
248
|
return;
|
|
268
249
|
}
|
|
269
250
|
|
|
270
251
|
if (profile.id === activeProfile) {
|
|
271
|
-
// 选的已经是当前场景,问要不要微调
|
|
272
252
|
const { confirm } = await import("@inquirer/prompts");
|
|
273
253
|
const tweak = await confirm({
|
|
274
254
|
message: "已是当前场景,是否进入自定义模式微调技能?",
|
|
@@ -280,20 +260,20 @@ async function startSceneSelection() {
|
|
|
280
260
|
return;
|
|
281
261
|
}
|
|
282
262
|
|
|
283
|
-
applyProfile(profile);
|
|
263
|
+
await applyProfile(profile);
|
|
284
264
|
}
|
|
285
265
|
|
|
286
266
|
// ---------- 命令:list ----------
|
|
287
267
|
|
|
288
268
|
async function cmdList() {
|
|
289
|
-
if (!
|
|
269
|
+
if (!(await pathExists(claudeDest))) {
|
|
290
270
|
console.log("\n ⚠️ 尚未安装技能,请先运行 npx mdk-skills\n");
|
|
291
271
|
return;
|
|
292
272
|
}
|
|
293
273
|
|
|
294
274
|
const chalk = (await import("chalk")).default;
|
|
295
|
-
const pkgSkills = getPackageSkills(skillsSource);
|
|
296
|
-
const userSkills = getUserSkills(claudeDest);
|
|
275
|
+
const pkgSkills = await getPackageSkills(skillsSource);
|
|
276
|
+
const userSkills = await getUserSkills(claudeDest);
|
|
297
277
|
|
|
298
278
|
const skillMap = new Map();
|
|
299
279
|
for (const s of userSkills) skillMap.set(s.name, s);
|
|
@@ -333,27 +313,25 @@ async function cmdList() {
|
|
|
333
313
|
async function startInteractiveMenu() {
|
|
334
314
|
const { checkbox } = await import("@inquirer/prompts");
|
|
335
315
|
|
|
336
|
-
if (!
|
|
316
|
+
if (!(await pathExists(pkgSkillsSource))) {
|
|
337
317
|
console.log(" ⚠️ 包内没有找到技能文件\n");
|
|
338
318
|
return;
|
|
339
319
|
}
|
|
340
320
|
|
|
341
|
-
const pkgSkills = getPackageSkills(skillsSource);
|
|
321
|
+
const pkgSkills = await getPackageSkills(skillsSource);
|
|
342
322
|
|
|
343
323
|
if (pkgSkills.length === 0) {
|
|
344
324
|
console.log(" ⚠️ 没有可用技能\n");
|
|
345
325
|
return;
|
|
346
326
|
}
|
|
347
327
|
|
|
348
|
-
|
|
349
|
-
const userSkills = getUserSkills(claudeDest);
|
|
328
|
+
const userSkills = await getUserSkills(claudeDest);
|
|
350
329
|
const enabledSet = new Set(
|
|
351
330
|
userSkills.filter((s) => s.enabled).map((s) => s.name),
|
|
352
331
|
);
|
|
353
332
|
const installedSet = new Set(userSkills.map((s) => s.name));
|
|
354
333
|
|
|
355
|
-
|
|
356
|
-
const hasExistingInstall = fs.existsSync(claudeDest);
|
|
334
|
+
const hasExistingInstall = await pathExists(claudeDest);
|
|
357
335
|
const defaultChecked = hasExistingInstall
|
|
358
336
|
? enabledSet
|
|
359
337
|
: new Set(pkgSkills.map((s) => s.name));
|
|
@@ -378,7 +356,7 @@ async function startInteractiveMenu() {
|
|
|
378
356
|
(name) => !selected.includes(name),
|
|
379
357
|
).length;
|
|
380
358
|
|
|
381
|
-
const installed = installSelectedSkills(selected);
|
|
359
|
+
const installed = await installSelectedSkills(selected);
|
|
382
360
|
|
|
383
361
|
const parts = [];
|
|
384
362
|
if (newCount > 0) parts.push(`新装 ${newCount} 个`);
|
|
@@ -390,7 +368,7 @@ async function startInteractiveMenu() {
|
|
|
390
368
|
|
|
391
369
|
// ---------- 本地源连接管理 ----------
|
|
392
370
|
|
|
393
|
-
function cmdConnect(repoPath) {
|
|
371
|
+
async function cmdConnect(repoPath) {
|
|
394
372
|
if (!repoPath) {
|
|
395
373
|
console.log(" ⚠️ 用法:npx mdk-skills connect <仓库路径>\n");
|
|
396
374
|
return;
|
|
@@ -398,20 +376,20 @@ function cmdConnect(repoPath) {
|
|
|
398
376
|
|
|
399
377
|
repoPath = path.resolve(repoPath);
|
|
400
378
|
|
|
401
|
-
if (!
|
|
379
|
+
if (!(await pathExists(path.join(repoPath, ".claude", "skills")))) {
|
|
402
380
|
console.log(` ❌ 路径 "${repoPath}" 下没有找到 .claude/skills/\n`);
|
|
403
381
|
return;
|
|
404
382
|
}
|
|
405
383
|
|
|
406
|
-
const settings = readSettings();
|
|
384
|
+
const settings = await readSettings();
|
|
407
385
|
settings._skill_source = repoPath;
|
|
408
|
-
writeSettings(settings);
|
|
386
|
+
await writeSettings(settings);
|
|
409
387
|
|
|
410
388
|
console.log(` ✅ 技能目录已设置: ${repoPath}\n`);
|
|
411
389
|
}
|
|
412
390
|
|
|
413
|
-
function cmdSync() {
|
|
414
|
-
const settings = readSettings();
|
|
391
|
+
async function cmdSync() {
|
|
392
|
+
const settings = await readSettings();
|
|
415
393
|
const sourcePath = settings._skill_source;
|
|
416
394
|
|
|
417
395
|
if (!sourcePath) {
|
|
@@ -419,58 +397,53 @@ function cmdSync() {
|
|
|
419
397
|
return;
|
|
420
398
|
}
|
|
421
399
|
|
|
422
|
-
if (!
|
|
400
|
+
if (!(await pathExists(path.join(sourcePath, ".claude")))) {
|
|
423
401
|
console.log(` ❌ 绑定的路径 "${sourcePath}" 已失效\n`);
|
|
424
402
|
return;
|
|
425
403
|
}
|
|
426
404
|
|
|
427
|
-
// 备份仓库旧内容
|
|
428
405
|
const repoClaude = path.join(sourcePath, ".claude");
|
|
429
|
-
if (
|
|
430
|
-
backupDir(repoClaude);
|
|
406
|
+
if (await pathExists(repoClaude)) {
|
|
407
|
+
await backupDir(repoClaude);
|
|
431
408
|
}
|
|
432
409
|
|
|
433
|
-
// 技能 → 反推到仓库
|
|
434
410
|
const repoSkills = path.join(sourcePath, ".claude", "skills");
|
|
435
|
-
if (!
|
|
436
|
-
fs.
|
|
411
|
+
if (!(await pathExists(repoSkills))) {
|
|
412
|
+
await fs.promises.mkdir(repoSkills, { recursive: true });
|
|
437
413
|
}
|
|
438
|
-
for (const name of listSkillDirs(skillsDest)) {
|
|
414
|
+
for (const name of await listSkillDirs(skillsDest)) {
|
|
439
415
|
const src = path.join(skillsDest, name);
|
|
440
416
|
const dest = path.join(repoSkills, name);
|
|
441
|
-
if (
|
|
442
|
-
fs.
|
|
417
|
+
if (await pathExists(dest)) {
|
|
418
|
+
await fs.promises.rm(dest, { recursive: true, force: true });
|
|
443
419
|
}
|
|
444
|
-
|
|
420
|
+
await copyDir(src, dest);
|
|
445
421
|
}
|
|
446
422
|
|
|
447
|
-
// profiles.json → 反推
|
|
448
423
|
const projectProfiles = path.join(claudeDest, "profiles.json");
|
|
449
|
-
if (
|
|
450
|
-
fs.
|
|
424
|
+
if (await pathExists(projectProfiles)) {
|
|
425
|
+
await fs.promises.copyFile(projectProfiles, path.join(sourcePath, ".claude", "profiles.json"));
|
|
451
426
|
}
|
|
452
427
|
|
|
453
|
-
// settings.json → 反推(过滤掉 _skill_source 和 _active_profile)
|
|
454
428
|
const cleanSettings = { ...settings };
|
|
455
429
|
delete cleanSettings._skill_source;
|
|
456
430
|
delete cleanSettings._active_profile;
|
|
457
|
-
fs.
|
|
431
|
+
await fs.promises.writeFile(
|
|
458
432
|
path.join(sourcePath, ".claude", "settings.json"),
|
|
459
433
|
JSON.stringify(cleanSettings, null, 2) + "\n",
|
|
460
434
|
"utf-8",
|
|
461
435
|
);
|
|
462
436
|
|
|
463
|
-
// CLAUDE.md → 反推
|
|
464
437
|
const projectMd = path.join(projectRoot, "CLAUDE.md");
|
|
465
|
-
if (
|
|
466
|
-
fs.
|
|
438
|
+
if (await pathExists(projectMd)) {
|
|
439
|
+
await fs.promises.copyFile(projectMd, path.join(sourcePath, "CLAUDE.md"));
|
|
467
440
|
}
|
|
468
441
|
|
|
469
442
|
console.log(" ✅ 已同步到仓库\n");
|
|
470
443
|
}
|
|
471
444
|
|
|
472
|
-
function cmdClearSource() {
|
|
473
|
-
const settings = readSettings();
|
|
445
|
+
async function cmdClearSource() {
|
|
446
|
+
const settings = await readSettings();
|
|
474
447
|
if (!settings._skill_source) {
|
|
475
448
|
console.log(" ⚠️ 当前未设置任何技能目录\n");
|
|
476
449
|
return;
|
|
@@ -478,7 +451,7 @@ function cmdClearSource() {
|
|
|
478
451
|
|
|
479
452
|
const oldPath = settings._skill_source;
|
|
480
453
|
delete settings._skill_source;
|
|
481
|
-
writeSettings(settings);
|
|
454
|
+
await writeSettings(settings);
|
|
482
455
|
|
|
483
456
|
console.log(` ✅ 已清除技能目录设置: ${oldPath}\n`);
|
|
484
457
|
console.log(` 💡 运行 npx mdk-skills ui 重新设置\n`);
|
|
@@ -489,15 +462,16 @@ function cmdClearSource() {
|
|
|
489
462
|
const COMMANDS = ["list", "connect", "sync", "clear-source", "ui"];
|
|
490
463
|
|
|
491
464
|
async function main() {
|
|
465
|
+
await initPaths();
|
|
466
|
+
|
|
492
467
|
const command = process.argv[2];
|
|
493
468
|
const args = process.argv.slice(3);
|
|
494
469
|
|
|
495
470
|
if (!command) {
|
|
496
|
-
const profiles = loadProfiles();
|
|
471
|
+
const profiles = await loadProfiles();
|
|
497
472
|
if (profiles) {
|
|
498
473
|
await startSceneSelection();
|
|
499
474
|
} else {
|
|
500
|
-
// 没有 profiles.json 时回退到原来的 checkbox
|
|
501
475
|
await startInteractiveMenu();
|
|
502
476
|
}
|
|
503
477
|
} else if (command === "--help" || command === "-h") {
|
|
@@ -522,10 +496,10 @@ async function main() {
|
|
|
522
496
|
npx mdk-skills ui
|
|
523
497
|
`);
|
|
524
498
|
} else if (command === "--connect") {
|
|
525
|
-
cmdConnect(args[0]);
|
|
526
|
-
|
|
499
|
+
await cmdConnect(args[0]);
|
|
500
|
+
await initPaths();
|
|
527
501
|
if (skillsSource) {
|
|
528
|
-
const profiles = loadProfiles();
|
|
502
|
+
const profiles = await loadProfiles();
|
|
529
503
|
if (profiles) {
|
|
530
504
|
await startSceneSelection();
|
|
531
505
|
} else {
|
|
@@ -533,12 +507,12 @@ async function main() {
|
|
|
533
507
|
}
|
|
534
508
|
}
|
|
535
509
|
} else if (command === "connect") {
|
|
536
|
-
cmdConnect(args[0]);
|
|
510
|
+
await cmdConnect(args[0]);
|
|
537
511
|
} else if (command === "sync") {
|
|
538
512
|
if (!skillsSource) { console.log(" ⚠️ 未设置技能目录,请先运行 npx mdk-skills ui\n"); return; }
|
|
539
|
-
cmdSync();
|
|
513
|
+
await cmdSync();
|
|
540
514
|
} else if (command === "clear-source") {
|
|
541
|
-
cmdClearSource();
|
|
515
|
+
await cmdClearSource();
|
|
542
516
|
} else if (command === "ui") {
|
|
543
517
|
require("./web-ui/server");
|
|
544
518
|
} else {
|