mdk-skills 2.1.6 → 2.1.9
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/.claude/profiles.json +11 -5
- package/package.json +1 -1
- package/scripts/cli.js +119 -13
- package/scripts/core.js +17 -0
package/.claude/profiles.json
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"v3-fe-biz-patterns",
|
|
11
11
|
"frontend-design",
|
|
12
12
|
"frontend-code-review",
|
|
13
|
-
"ui-ux-pro-max"
|
|
13
|
+
"ui-ux-pro-max",
|
|
14
|
+
"skill-creator"
|
|
14
15
|
],
|
|
15
16
|
"always_apply": [
|
|
16
17
|
"vue",
|
|
@@ -23,7 +24,12 @@
|
|
|
23
24
|
"id": "react-frontend",
|
|
24
25
|
"name": "React 前端专项",
|
|
25
26
|
"description": "React 技术栈 | 界面设计 | 代码评审 | 通用前端能力",
|
|
26
|
-
"skills": [
|
|
27
|
+
"skills": [
|
|
28
|
+
"frontend-design",
|
|
29
|
+
"frontend-code-review",
|
|
30
|
+
"ui-ux-pro-max",
|
|
31
|
+
"skill-creator"
|
|
32
|
+
],
|
|
27
33
|
"always_apply": [
|
|
28
34
|
"frontend-design",
|
|
29
35
|
"frontend-code-review",
|
|
@@ -34,21 +40,21 @@
|
|
|
34
40
|
"id": "backend-java",
|
|
35
41
|
"name": "Java 后端开发",
|
|
36
42
|
"description": "接口架构设计 | 数据库建模 | Java 后端体系能力",
|
|
37
|
-
"skills": [],
|
|
43
|
+
"skills": ["skill-creator"],
|
|
38
44
|
"always_apply": []
|
|
39
45
|
},
|
|
40
46
|
{
|
|
41
47
|
"id": "backend-python",
|
|
42
48
|
"name": "Python 后端开发",
|
|
43
49
|
"description": "接口架构设计 | 数据层设计 | Python 后端体系能力",
|
|
44
|
-
"skills": [],
|
|
50
|
+
"skills": ["skill-creator"],
|
|
45
51
|
"always_apply": []
|
|
46
52
|
},
|
|
47
53
|
{
|
|
48
54
|
"id": "backend-node",
|
|
49
55
|
"name": "Node.js 后端开发",
|
|
50
56
|
"description": "接口架构设计 | 服务端架构 | Node 后端体系能力",
|
|
51
|
-
"skills": [],
|
|
57
|
+
"skills": ["skill-creator"],
|
|
52
58
|
"always_apply": []
|
|
53
59
|
},
|
|
54
60
|
{
|
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 } = require("./core");
|
|
5
|
+
const { getPackageSkills, getUserSkills, getSkillsSource, backupDir } = require("./core");
|
|
6
6
|
|
|
7
7
|
// npx 运行时:process.cwd() 是用户项目目录
|
|
8
8
|
// __dirname 是包内 scripts/ 目录
|
|
@@ -15,10 +15,11 @@ const projectRoot = (() => {
|
|
|
15
15
|
}
|
|
16
16
|
})();
|
|
17
17
|
const packageDir = path.join(__dirname, "..");
|
|
18
|
+
const skillsSource = getSkillsSource(projectRoot, packageDir);
|
|
18
19
|
const claudeDest = path.join(projectRoot, ".claude");
|
|
19
20
|
const skillsDest = path.join(claudeDest, "skills");
|
|
20
21
|
const settingsPath = path.join(claudeDest, "settings.json");
|
|
21
|
-
const pkgSkillsSource = path.join(
|
|
22
|
+
const pkgSkillsSource = path.join(skillsSource, ".claude", "skills");
|
|
22
23
|
|
|
23
24
|
// ---------- 文件写入 ----------
|
|
24
25
|
|
|
@@ -105,7 +106,7 @@ function installSelectedSkills(selectedNames) {
|
|
|
105
106
|
writeSettings(settings);
|
|
106
107
|
|
|
107
108
|
// 安装 CLAUDE.md(没有才装)
|
|
108
|
-
const mdSource = path.join(
|
|
109
|
+
const mdSource = path.join(skillsSource, "CLAUDE.md");
|
|
109
110
|
const mdDest = path.join(projectRoot, "CLAUDE.md");
|
|
110
111
|
if (fs.existsSync(mdSource) && !fs.existsSync(mdDest)) {
|
|
111
112
|
fs.copyFileSync(mdSource, mdDest);
|
|
@@ -118,7 +119,7 @@ function installSelectedSkills(selectedNames) {
|
|
|
118
119
|
// ---------- 场景选择(场景 → 一键装技能) ----------
|
|
119
120
|
|
|
120
121
|
function loadProfiles() {
|
|
121
|
-
const profilesPath = path.join(
|
|
122
|
+
const profilesPath = path.join(skillsSource, ".claude", "profiles.json");
|
|
122
123
|
if (!fs.existsSync(profilesPath)) return null;
|
|
123
124
|
try {
|
|
124
125
|
return JSON.parse(fs.readFileSync(profilesPath, "utf-8")).profiles;
|
|
@@ -183,7 +184,7 @@ function applyProfile(profile) {
|
|
|
183
184
|
writeSettings(settings);
|
|
184
185
|
|
|
185
186
|
// 安装 CLAUDE.md(没有才装)
|
|
186
|
-
const mdSource = path.join(
|
|
187
|
+
const mdSource = path.join(skillsSource, "CLAUDE.md");
|
|
187
188
|
const mdDest = path.join(projectRoot, "CLAUDE.md");
|
|
188
189
|
if (fs.existsSync(mdSource) && !fs.existsSync(mdDest)) {
|
|
189
190
|
fs.copyFileSync(mdSource, mdDest);
|
|
@@ -277,7 +278,7 @@ async function cmdList() {
|
|
|
277
278
|
}
|
|
278
279
|
|
|
279
280
|
const chalk = (await import("chalk")).default;
|
|
280
|
-
const pkgSkills = getPackageSkills(
|
|
281
|
+
const pkgSkills = getPackageSkills(skillsSource);
|
|
281
282
|
const userSkills = getUserSkills(claudeDest);
|
|
282
283
|
|
|
283
284
|
const skillMap = new Map();
|
|
@@ -323,10 +324,10 @@ async function startInteractiveMenu() {
|
|
|
323
324
|
return;
|
|
324
325
|
}
|
|
325
326
|
|
|
326
|
-
const pkgSkills = getPackageSkills(
|
|
327
|
+
const pkgSkills = getPackageSkills(skillsSource);
|
|
327
328
|
|
|
328
329
|
if (pkgSkills.length === 0) {
|
|
329
|
-
console.log(" ⚠️
|
|
330
|
+
console.log(" ⚠️ 没有可用技能\n");
|
|
330
331
|
return;
|
|
331
332
|
}
|
|
332
333
|
|
|
@@ -373,9 +374,106 @@ async function startInteractiveMenu() {
|
|
|
373
374
|
console.log(`\n ✅ 技能安装完成 ${summary}\n`);
|
|
374
375
|
}
|
|
375
376
|
|
|
377
|
+
// ---------- 本地源连接管理 ----------
|
|
378
|
+
|
|
379
|
+
function cmdConnect(repoPath) {
|
|
380
|
+
if (!repoPath) {
|
|
381
|
+
console.log(" ⚠️ 用法:npx mdk-skills connect <仓库路径>\n");
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
repoPath = path.resolve(repoPath);
|
|
386
|
+
|
|
387
|
+
if (!fs.existsSync(path.join(repoPath, ".claude", "skills"))) {
|
|
388
|
+
console.log(` ❌ 路径 "${repoPath}" 下没有找到 .claude/skills/\n`);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const settings = readSettings();
|
|
393
|
+
settings._skill_source = repoPath;
|
|
394
|
+
writeSettings(settings);
|
|
395
|
+
|
|
396
|
+
console.log(` ✅ 已绑定技能源: ${repoPath}\n`);
|
|
397
|
+
console.log(` 💡 运行 npx mdk-skills 选择场景\n`);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function cmdSync() {
|
|
401
|
+
const settings = readSettings();
|
|
402
|
+
const sourcePath = settings._skill_source;
|
|
403
|
+
|
|
404
|
+
if (!sourcePath) {
|
|
405
|
+
console.log(" ⚠️ 尚未绑定技能源\n");
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (!fs.existsSync(path.join(sourcePath, ".claude"))) {
|
|
410
|
+
console.log(` ❌ 绑定的路径 "${sourcePath}" 已失效\n`);
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// 备份仓库旧内容
|
|
415
|
+
const repoClaude = path.join(sourcePath, ".claude");
|
|
416
|
+
if (fs.existsSync(repoClaude)) {
|
|
417
|
+
backupDir(repoClaude);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// 技能 → 反推到仓库
|
|
421
|
+
const repoSkills = path.join(sourcePath, ".claude", "skills");
|
|
422
|
+
if (!fs.existsSync(repoSkills)) {
|
|
423
|
+
fs.mkdirSync(repoSkills, { recursive: true });
|
|
424
|
+
}
|
|
425
|
+
for (const name of fs.readdirSync(skillsDest)) {
|
|
426
|
+
const src = path.join(skillsDest, name);
|
|
427
|
+
const dest = path.join(repoSkills, name);
|
|
428
|
+
if (fs.existsSync(dest)) {
|
|
429
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
430
|
+
}
|
|
431
|
+
copyDirSync(src, dest);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// profiles.json → 反推
|
|
435
|
+
const projectProfiles = path.join(claudeDest, "profiles.json");
|
|
436
|
+
if (fs.existsSync(projectProfiles)) {
|
|
437
|
+
fs.copyFileSync(projectProfiles, path.join(sourcePath, ".claude", "profiles.json"));
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// settings.json → 反推(过滤掉 _skill_source 和 _active_profile)
|
|
441
|
+
const cleanSettings = { ...settings };
|
|
442
|
+
delete cleanSettings._skill_source;
|
|
443
|
+
delete cleanSettings._active_profile;
|
|
444
|
+
fs.writeFileSync(
|
|
445
|
+
path.join(sourcePath, ".claude", "settings.json"),
|
|
446
|
+
JSON.stringify(cleanSettings, null, 2) + "\n",
|
|
447
|
+
"utf-8",
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
// CLAUDE.md → 反推
|
|
451
|
+
const projectMd = path.join(projectRoot, "CLAUDE.md");
|
|
452
|
+
if (fs.existsSync(projectMd)) {
|
|
453
|
+
fs.copyFileSync(projectMd, path.join(sourcePath, "CLAUDE.md"));
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
console.log(" ✅ 已同步到仓库\n");
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function cmdDisconnect() {
|
|
460
|
+
const settings = readSettings();
|
|
461
|
+
if (!settings._skill_source) {
|
|
462
|
+
console.log(" ⚠️ 当前未绑定任何技能源\n");
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
const oldPath = settings._skill_source;
|
|
467
|
+
delete settings._skill_source;
|
|
468
|
+
writeSettings(settings);
|
|
469
|
+
|
|
470
|
+
console.log(` ✅ 已断开技能源: ${oldPath}\n`);
|
|
471
|
+
console.log(` 💡 恢复为使用 npm 包内置技能\n`);
|
|
472
|
+
}
|
|
473
|
+
|
|
376
474
|
// ---------- 主入口 ----------
|
|
377
475
|
|
|
378
|
-
const COMMANDS = ["list", "
|
|
476
|
+
const COMMANDS = ["list", "connect", "sync", "disconnect"];
|
|
379
477
|
|
|
380
478
|
async function main() {
|
|
381
479
|
const command = process.argv[2];
|
|
@@ -396,21 +494,29 @@ async function main() {
|
|
|
396
494
|
用法:
|
|
397
495
|
npx mdk-skills 场景选择 → 一键安装对应技能
|
|
398
496
|
npx mdk-skills list 查看已安装的技能
|
|
497
|
+
npx mdk-skills connect 绑定本地技能源仓库路径
|
|
498
|
+
npx mdk-skills sync 将项目中的技能修改推送到仓库
|
|
499
|
+
npx mdk-skills disconnect 解绑本地源,恢复使用 npm 包内置技能
|
|
399
500
|
npx mdk-skills --help 显示帮助
|
|
400
501
|
|
|
401
502
|
首次运行选择场景后自动配置技能和 CLAUDE.md
|
|
402
503
|
再次运行可切换场景或进入自定义模式微调
|
|
403
504
|
|
|
404
505
|
示例:
|
|
506
|
+
npx mdk-skills connect D:/dev/mdk-skills
|
|
507
|
+
npx mdk-skills sync
|
|
508
|
+
npx mdk-skills disconnect
|
|
405
509
|
npx mdk-skills
|
|
406
510
|
npx mdk-skills list
|
|
407
511
|
`);
|
|
408
512
|
} else if (command === "list") {
|
|
409
513
|
await cmdList();
|
|
410
|
-
} else if (command === "
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
);
|
|
514
|
+
} else if (command === "connect") {
|
|
515
|
+
cmdConnect(args[0]);
|
|
516
|
+
} else if (command === "sync") {
|
|
517
|
+
cmdSync();
|
|
518
|
+
} else if (command === "disconnect") {
|
|
519
|
+
cmdDisconnect();
|
|
414
520
|
} else {
|
|
415
521
|
console.log(` 未知命令: ${command}\n 可用: ${COMMANDS.join(", ")}\n`);
|
|
416
522
|
process.exit(1);
|
package/scripts/core.js
CHANGED
|
@@ -209,6 +209,22 @@ function getPackageSkills(packageDir) {
|
|
|
209
209
|
});
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
+
/**
|
|
213
|
+
* 解析技能源路径:
|
|
214
|
+
* 优先从 settings.json 的 _skill_source 字段读取(本地开发模式)
|
|
215
|
+
* 没有则回退到包目录(普通用户模式)
|
|
216
|
+
*/
|
|
217
|
+
function getSkillsSource(projectRoot, fallbackDir) {
|
|
218
|
+
const settingsPath = path.join(projectRoot, ".claude", "settings.json");
|
|
219
|
+
if (fs.existsSync(settingsPath)) {
|
|
220
|
+
try {
|
|
221
|
+
const s = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
222
|
+
if (s._skill_source) return s._skill_source;
|
|
223
|
+
} catch {}
|
|
224
|
+
}
|
|
225
|
+
return fallbackDir;
|
|
226
|
+
}
|
|
227
|
+
|
|
212
228
|
/**
|
|
213
229
|
* 获取用户已安装的技能及其 settings 中的 enabled 状态
|
|
214
230
|
*/
|
|
@@ -253,4 +269,5 @@ module.exports = {
|
|
|
253
269
|
installSettings,
|
|
254
270
|
getPackageSkills,
|
|
255
271
|
getUserSkills,
|
|
272
|
+
getSkillsSource,
|
|
256
273
|
};
|