mdk-skills 2.1.5 → 2.1.8
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 -51
- package/package.json +1 -1
- package/scripts/cli.js +107 -13
- package/scripts/core.js +17 -0
package/.claude/profiles.json
CHANGED
|
@@ -1,49 +1,3 @@
|
|
|
1
|
-
// {
|
|
2
|
-
// "version": 1,
|
|
3
|
-
// "profiles": [
|
|
4
|
-
// {
|
|
5
|
-
// "id": "vue3-frontend",
|
|
6
|
-
// "name": "前端 Vue3 开发",
|
|
7
|
-
// "description": "Vue 3 + 业务模式库 + 设计 + 代码审查",
|
|
8
|
-
// "skills": ["vue", "v3-fe-biz-patterns", "frontend-design", "frontend-code-review", "ui-ux-pro-max"],
|
|
9
|
-
// "always_apply": ["vue", "frontend-design", "frontend-code-review", "ui-ux-pro-max"]
|
|
10
|
-
// },
|
|
11
|
-
// {
|
|
12
|
-
// "id": "react-frontend",
|
|
13
|
-
// "name": "前端 React 开发",
|
|
14
|
-
// "description": "设计 + 审查 + 通用前端能力",
|
|
15
|
-
// "skills": ["frontend-design", "frontend-code-review", "ui-ux-pro-max"],
|
|
16
|
-
// "always_apply": ["frontend-design", "frontend-code-review", "ui-ux-pro-max"]
|
|
17
|
-
// },
|
|
18
|
-
// {
|
|
19
|
-
// "id": "backend",
|
|
20
|
-
// "name": "java后端开发",
|
|
21
|
-
// "description": "API 设计、数据库、java 后端技能",
|
|
22
|
-
// "skills": [],
|
|
23
|
-
// "always_apply": []
|
|
24
|
-
// },
|
|
25
|
-
// {
|
|
26
|
-
// "id": "backend",
|
|
27
|
-
// "name": "python后端开发",
|
|
28
|
-
// "description": "API 设计、数据库、python 后端技能",
|
|
29
|
-
// "skills": [],
|
|
30
|
-
// "always_apply": []
|
|
31
|
-
// },
|
|
32
|
-
// {
|
|
33
|
-
// "id": "backend",
|
|
34
|
-
// "name": "nodeJs后端开发",
|
|
35
|
-
// "description": "API 设计、数据库、nodeJs 后端技能",
|
|
36
|
-
// "skills": [],
|
|
37
|
-
// "always_apply": []
|
|
38
|
-
// },
|
|
39
|
-
// {
|
|
40
|
-
// "id": "custom",
|
|
41
|
-
// "name": "自定义选择",
|
|
42
|
-
// "description": "按需勾选每一个技能",
|
|
43
|
-
// "skills": null
|
|
44
|
-
// }
|
|
45
|
-
// ]
|
|
46
|
-
// }
|
|
47
1
|
{
|
|
48
2
|
"version": 1,
|
|
49
3
|
"profiles": [
|
|
@@ -56,7 +10,8 @@
|
|
|
56
10
|
"v3-fe-biz-patterns",
|
|
57
11
|
"frontend-design",
|
|
58
12
|
"frontend-code-review",
|
|
59
|
-
"ui-ux-pro-max"
|
|
13
|
+
"ui-ux-pro-max",
|
|
14
|
+
"skill-creator"
|
|
60
15
|
],
|
|
61
16
|
"always_apply": [
|
|
62
17
|
"vue",
|
|
@@ -69,7 +24,12 @@
|
|
|
69
24
|
"id": "react-frontend",
|
|
70
25
|
"name": "React 前端专项",
|
|
71
26
|
"description": "React 技术栈 | 界面设计 | 代码评审 | 通用前端能力",
|
|
72
|
-
"skills": [
|
|
27
|
+
"skills": [
|
|
28
|
+
"frontend-design",
|
|
29
|
+
"frontend-code-review",
|
|
30
|
+
"ui-ux-pro-max",
|
|
31
|
+
"skill-creator"
|
|
32
|
+
],
|
|
73
33
|
"always_apply": [
|
|
74
34
|
"frontend-design",
|
|
75
35
|
"frontend-code-review",
|
|
@@ -80,21 +40,21 @@
|
|
|
80
40
|
"id": "backend-java",
|
|
81
41
|
"name": "Java 后端开发",
|
|
82
42
|
"description": "接口架构设计 | 数据库建模 | Java 后端体系能力",
|
|
83
|
-
"skills": [],
|
|
43
|
+
"skills": ["skill-creator"],
|
|
84
44
|
"always_apply": []
|
|
85
45
|
},
|
|
86
46
|
{
|
|
87
47
|
"id": "backend-python",
|
|
88
48
|
"name": "Python 后端开发",
|
|
89
49
|
"description": "接口架构设计 | 数据层设计 | Python 后端体系能力",
|
|
90
|
-
"skills": [],
|
|
50
|
+
"skills": ["skill-creator"],
|
|
91
51
|
"always_apply": []
|
|
92
52
|
},
|
|
93
53
|
{
|
|
94
54
|
"id": "backend-node",
|
|
95
55
|
"name": "Node.js 后端开发",
|
|
96
56
|
"description": "接口架构设计 | 服务端架构 | Node 后端体系能力",
|
|
97
|
-
"skills": [],
|
|
57
|
+
"skills": ["skill-creator"],
|
|
98
58
|
"always_apply": []
|
|
99
59
|
},
|
|
100
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 } = 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,94 @@ 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 sync 同步技能\n`);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
async function cmdSync() {
|
|
401
|
+
const settings = readSettings();
|
|
402
|
+
const sourcePath = settings._skill_source;
|
|
403
|
+
|
|
404
|
+
if (!sourcePath) {
|
|
405
|
+
console.log(" ⚠️ 尚未绑定技能源,请先运行 npx mdk-skills connect <路径>\n");
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (!fs.existsSync(path.join(sourcePath, ".claude", "skills"))) {
|
|
410
|
+
console.log(` ❌ 绑定的路径 "${sourcePath}" 已失效或已移动\n`);
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const { backupDir, installSkills, installSettings } = require("./core");
|
|
415
|
+
const logFile = path.join(claudeDest, ".install.log");
|
|
416
|
+
|
|
417
|
+
if (fs.existsSync(claudeDest)) {
|
|
418
|
+
backupDir(claudeDest);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const results = installSkills(
|
|
422
|
+
path.join(sourcePath, ".claude", "skills"),
|
|
423
|
+
skillsDest,
|
|
424
|
+
logFile,
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
installSettings(path.join(sourcePath, ".claude"), claudeDest, logFile);
|
|
428
|
+
|
|
429
|
+
// 复制 CLAUDE.md
|
|
430
|
+
const mdSource = path.join(sourcePath, "CLAUDE.md");
|
|
431
|
+
const mdDest = path.join(projectRoot, "CLAUDE.md");
|
|
432
|
+
if (fs.existsSync(mdSource)) {
|
|
433
|
+
fs.copyFileSync(mdSource, mdDest);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const installed = results.filter((r) => r.action === "installed").length;
|
|
437
|
+
const updated = results.filter((r) => r.action === "updated").length;
|
|
438
|
+
const skipped = results.filter((r) => r.action === "skipped").length;
|
|
439
|
+
|
|
440
|
+
console.log(`\n ✅ 技能同步完成`);
|
|
441
|
+
if (installed > 0) console.log(` 新装 ${installed} 个`);
|
|
442
|
+
if (updated > 0) console.log(` 更新 ${updated} 个`);
|
|
443
|
+
if (skipped > 0) console.log(` 跳过 ${skipped} 个(无变化)`);
|
|
444
|
+
console.log("");
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function cmdDisconnect() {
|
|
448
|
+
const settings = readSettings();
|
|
449
|
+
if (!settings._skill_source) {
|
|
450
|
+
console.log(" ⚠️ 当前未绑定任何技能源\n");
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const oldPath = settings._skill_source;
|
|
455
|
+
delete settings._skill_source;
|
|
456
|
+
writeSettings(settings);
|
|
457
|
+
|
|
458
|
+
console.log(` ✅ 已断开技能源: ${oldPath}\n`);
|
|
459
|
+
console.log(` 💡 恢复为使用 npm 包内置技能\n`);
|
|
460
|
+
}
|
|
461
|
+
|
|
376
462
|
// ---------- 主入口 ----------
|
|
377
463
|
|
|
378
|
-
const COMMANDS = ["list", "
|
|
464
|
+
const COMMANDS = ["list", "connect", "sync", "disconnect"];
|
|
379
465
|
|
|
380
466
|
async function main() {
|
|
381
467
|
const command = process.argv[2];
|
|
@@ -396,21 +482,29 @@ async function main() {
|
|
|
396
482
|
用法:
|
|
397
483
|
npx mdk-skills 场景选择 → 一键安装对应技能
|
|
398
484
|
npx mdk-skills list 查看已安装的技能
|
|
485
|
+
npx mdk-skills connect 绑定本地技能源仓库路径
|
|
486
|
+
npx mdk-skills sync 从绑定的源同步技能
|
|
487
|
+
npx mdk-skills disconnect 解绑本地源,恢复使用 npm 包内置技能
|
|
399
488
|
npx mdk-skills --help 显示帮助
|
|
400
489
|
|
|
401
490
|
首次运行选择场景后自动配置技能和 CLAUDE.md
|
|
402
491
|
再次运行可切换场景或进入自定义模式微调
|
|
403
492
|
|
|
404
493
|
示例:
|
|
494
|
+
npx mdk-skills connect D:/dev/mdk-skills
|
|
495
|
+
npx mdk-skills sync
|
|
496
|
+
npx mdk-skills disconnect
|
|
405
497
|
npx mdk-skills
|
|
406
498
|
npx mdk-skills list
|
|
407
499
|
`);
|
|
408
500
|
} else if (command === "list") {
|
|
409
501
|
await cmdList();
|
|
410
|
-
} else if (command === "
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
);
|
|
502
|
+
} else if (command === "connect") {
|
|
503
|
+
cmdConnect(args[0]);
|
|
504
|
+
} else if (command === "sync") {
|
|
505
|
+
await cmdSync();
|
|
506
|
+
} else if (command === "disconnect") {
|
|
507
|
+
cmdDisconnect();
|
|
414
508
|
} else {
|
|
415
509
|
console.log(` 未知命令: ${command}\n 可用: ${COMMANDS.join(", ")}\n`);
|
|
416
510
|
process.exit(1);
|
package/scripts/core.js
CHANGED
|
@@ -212,6 +212,22 @@ function getPackageSkills(packageDir) {
|
|
|
212
212
|
/**
|
|
213
213
|
* 获取用户已安装的技能及其 settings 中的 enabled 状态
|
|
214
214
|
*/
|
|
215
|
+
/**
|
|
216
|
+
* 解析技能源路径:
|
|
217
|
+
* 优先从 settings.json 的 _skill_source 字段读取(本地开发模式)
|
|
218
|
+
* 没有则回退到包目录(普通用户模式)
|
|
219
|
+
*/
|
|
220
|
+
function getSkillsSource(projectRoot, fallbackDir) {
|
|
221
|
+
const settingsPath = path.join(projectRoot, ".claude", "settings.json");
|
|
222
|
+
if (fs.existsSync(settingsPath)) {
|
|
223
|
+
try {
|
|
224
|
+
const s = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
225
|
+
if (s._skill_source) return s._skill_source;
|
|
226
|
+
} catch {}
|
|
227
|
+
}
|
|
228
|
+
return fallbackDir;
|
|
229
|
+
}
|
|
230
|
+
|
|
215
231
|
function getUserSkills(claudeDest) {
|
|
216
232
|
const skillsDest = path.join(claudeDest, "skills");
|
|
217
233
|
if (!fs.existsSync(skillsDest)) return [];
|
|
@@ -253,4 +269,5 @@ module.exports = {
|
|
|
253
269
|
installSettings,
|
|
254
270
|
getPackageSkills,
|
|
255
271
|
getUserSkills,
|
|
272
|
+
getSkillsSource,
|
|
256
273
|
};
|