skills-manager 0.0.1 → 0.0.3
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.mjs +56 -266
- package/package.json +12 -12
package/dist/index.mjs
CHANGED
|
@@ -1,279 +1,69 @@
|
|
|
1
1
|
import { cac } from "cac";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { join } from "node:path";
|
|
6
|
-
import {
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { mkdir, readdir, writeFile } from "node:fs/promises";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
import { rimraf } from "rimraf";
|
|
7
|
+
import { joinURL } from "ufo";
|
|
7
8
|
|
|
8
|
-
//#region src/skills.ts
|
|
9
|
-
const skills = new Map([
|
|
10
|
-
["antfu", {
|
|
11
|
-
path: "antfu/skills/skills/antfu",
|
|
12
|
-
description: "Anthony Fu 的个人技能集"
|
|
13
|
-
}],
|
|
14
|
-
["nuxt", {
|
|
15
|
-
path: "antfu/skills/skills/nuxt",
|
|
16
|
-
description: "Nuxt.js 框架技能"
|
|
17
|
-
}],
|
|
18
|
-
["pnpm", {
|
|
19
|
-
path: "antfu/skills/skills/pnpm",
|
|
20
|
-
description: "pnpm 包管理器技能"
|
|
21
|
-
}],
|
|
22
|
-
["slidev", {
|
|
23
|
-
path: "antfu/skills/skills/slidev",
|
|
24
|
-
description: "Slidev 演示文稿工具"
|
|
25
|
-
}],
|
|
26
|
-
["tsdown", {
|
|
27
|
-
path: "antfu/skills/skills/tsdown",
|
|
28
|
-
description: "Tsdown 构建工具"
|
|
29
|
-
}],
|
|
30
|
-
["unocss", {
|
|
31
|
-
path: "antfu/skills/skills/unocss",
|
|
32
|
-
description: "UnoCSS 引擎技能"
|
|
33
|
-
}],
|
|
34
|
-
["vite", {
|
|
35
|
-
path: "antfu/skills/skills/vite",
|
|
36
|
-
description: "Vite 构建工具"
|
|
37
|
-
}],
|
|
38
|
-
["vitest", {
|
|
39
|
-
path: "antfu/skills/skills/vitest",
|
|
40
|
-
description: "Vitest 测试框架"
|
|
41
|
-
}],
|
|
42
|
-
["vue-best-practices", {
|
|
43
|
-
path: "antfu/skills/skills/vue-best-practices",
|
|
44
|
-
description: "Vue 最佳实践"
|
|
45
|
-
}],
|
|
46
|
-
["vue-router-best-practices", {
|
|
47
|
-
path: "antfu/skills/skills/vue-router-best-practices",
|
|
48
|
-
description: "Vue Router 最佳实践"
|
|
49
|
-
}],
|
|
50
|
-
["vue-testing-best-practices", {
|
|
51
|
-
path: "antfu/skills/skills/vue-testing-best-practices",
|
|
52
|
-
description: "Vue 测试最佳实践"
|
|
53
|
-
}],
|
|
54
|
-
["vue", {
|
|
55
|
-
path: "antfu/skills/skills/vue",
|
|
56
|
-
description: "Vue.js 框架技能"
|
|
57
|
-
}],
|
|
58
|
-
["vueuse-functions", {
|
|
59
|
-
path: "antfu/skills/skills/vueuse-functions",
|
|
60
|
-
description: "VueUse 函数集合"
|
|
61
|
-
}],
|
|
62
|
-
["web-design-guidelines", {
|
|
63
|
-
path: "antfu/skills/skills/web-design-guidelines",
|
|
64
|
-
description: "Web 设计指南"
|
|
65
|
-
}],
|
|
66
|
-
["mcp-builder", {
|
|
67
|
-
path: "anthropics/skills/skills/mcp-builder",
|
|
68
|
-
description: "MCP 构建器"
|
|
69
|
-
}],
|
|
70
|
-
["skill-creator", {
|
|
71
|
-
path: "anthropics/skills/skills/skill-creator",
|
|
72
|
-
description: "技能创建器"
|
|
73
|
-
}],
|
|
74
|
-
["cloudflare", {
|
|
75
|
-
path: "cloudflare/skills/skills/cloudflare",
|
|
76
|
-
description: "Cloudflare 平台技能"
|
|
77
|
-
}],
|
|
78
|
-
["wrangler", {
|
|
79
|
-
path: "cloudflare/skills/skills/wrangler",
|
|
80
|
-
description: "Wrangler CLI 工具"
|
|
81
|
-
}],
|
|
82
|
-
["agent-browser", {
|
|
83
|
-
path: "vercel-labs/agent-browser/skills/agent-browser",
|
|
84
|
-
description: "Agent 浏览器技能"
|
|
85
|
-
}],
|
|
86
|
-
["javascript-testing-patterns", {
|
|
87
|
-
path: "wshobson/agents/plugins/javascript-typescript/skills/javascript-testing-patterns",
|
|
88
|
-
description: "JavaScript 测试模式"
|
|
89
|
-
}],
|
|
90
|
-
["modern-javascript-patterns", {
|
|
91
|
-
path: "wshobson/agents/plugins/javascript-typescript/skills/modern-javascript-patterns",
|
|
92
|
-
description: "现代 JavaScript 模式"
|
|
93
|
-
}],
|
|
94
|
-
["typescript-advanced-types", {
|
|
95
|
-
path: "wshobson/agents/plugins/javascript-typescript/skills/typescript-advanced-types",
|
|
96
|
-
description: "TypeScript 高级类型"
|
|
97
|
-
}]
|
|
98
|
-
]);
|
|
99
|
-
|
|
100
|
-
//#endregion
|
|
101
|
-
//#region src/utils.ts
|
|
102
|
-
/**
|
|
103
|
-
* 带颜色的控制台输出工具
|
|
104
|
-
*/
|
|
105
|
-
const colors = {
|
|
106
|
-
reset: "\x1B[0m",
|
|
107
|
-
bright: "\x1B[1m",
|
|
108
|
-
dim: "\x1B[2m",
|
|
109
|
-
red: "\x1B[31m",
|
|
110
|
-
green: "\x1B[32m",
|
|
111
|
-
yellow: "\x1B[33m",
|
|
112
|
-
blue: "\x1B[34m",
|
|
113
|
-
magenta: "\x1B[35m",
|
|
114
|
-
cyan: "\x1B[36m",
|
|
115
|
-
white: "\x1B[37m"
|
|
116
|
-
};
|
|
117
|
-
const logger = {
|
|
118
|
-
success(message) {
|
|
119
|
-
console.log(`${colors.green}✅ ${message}${colors.reset}`);
|
|
120
|
-
},
|
|
121
|
-
error(message) {
|
|
122
|
-
console.error(`${colors.red}❌ ${message}${colors.reset}`);
|
|
123
|
-
},
|
|
124
|
-
warn(message) {
|
|
125
|
-
console.warn(`${colors.yellow}⚠️ ${message}${colors.reset}`);
|
|
126
|
-
},
|
|
127
|
-
info(message) {
|
|
128
|
-
console.log(`${colors.blue}ℹ️ ${message}${colors.reset}`);
|
|
129
|
-
},
|
|
130
|
-
text(message) {
|
|
131
|
-
console.log(`${colors.bright}${message}${colors.reset}`);
|
|
132
|
-
},
|
|
133
|
-
dim(message) {
|
|
134
|
-
console.log(`${colors.dim}${message}${colors.reset}`);
|
|
135
|
-
},
|
|
136
|
-
item(message) {
|
|
137
|
-
console.log(` ${colors.cyan}•${colors.reset} ${message}`);
|
|
138
|
-
},
|
|
139
|
-
title(message) {
|
|
140
|
-
console.log(`\n${colors.bright}${colors.cyan}${message}${colors.reset}`);
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
//#endregion
|
|
145
9
|
//#region src/manager.ts
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
logger.title(`正在安装技能: ${skillName}`);
|
|
173
|
-
if (skill.description) logger.dim(`描述: ${skill.description}`);
|
|
174
|
-
logger.dim(`来源: ${skill.path}`);
|
|
175
|
-
const targetDir = this.getSkillPath(skillName);
|
|
176
|
-
if (existsSync(targetDir)) {
|
|
177
|
-
logger.warn(`技能 "${skillName}" 已经安装`);
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
await mkdir(SKILLS_DIR, { recursive: true });
|
|
181
|
-
const emitter = degit(skill.path, {
|
|
182
|
-
force: true,
|
|
183
|
-
verbose: false
|
|
184
|
-
});
|
|
185
|
-
try {
|
|
186
|
-
await emitter.clone(targetDir);
|
|
187
|
-
logger.success(`技能 "${skillName}" 安装成功!`);
|
|
188
|
-
} catch (error) {
|
|
189
|
-
if (existsSync(targetDir)) await rm(targetDir, {
|
|
190
|
-
recursive: true,
|
|
191
|
-
force: true
|
|
192
|
-
});
|
|
193
|
-
throw error;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* 删除技能
|
|
198
|
-
*/
|
|
199
|
-
async remove(skillName) {
|
|
200
|
-
const skillPath = this.getSkillPath(skillName);
|
|
201
|
-
if (!existsSync(skillPath)) throw new Error(`技能 "${skillName}" 未安装`);
|
|
202
|
-
logger.title(`正在删除技能: ${skillName}`);
|
|
203
|
-
await rm(skillPath, {
|
|
204
|
-
recursive: true,
|
|
205
|
-
force: true
|
|
10
|
+
const print = console.log;
|
|
11
|
+
const CLAUDE_SKILLS_DIR = join(homedir(), ".claude", "skills");
|
|
12
|
+
async function list() {
|
|
13
|
+
print(chalk.gray("→"), chalk.gray(CLAUDE_SKILLS_DIR));
|
|
14
|
+
print();
|
|
15
|
+
(await readdir(CLAUDE_SKILLS_DIR, { withFileTypes: true })).forEach((it) => it.isDirectory() && print(chalk.gray("•"), it.name));
|
|
16
|
+
print();
|
|
17
|
+
}
|
|
18
|
+
async function remove(name) {
|
|
19
|
+
await rimraf(join(CLAUDE_SKILLS_DIR, name));
|
|
20
|
+
await list();
|
|
21
|
+
print(chalk.red("-", name));
|
|
22
|
+
print();
|
|
23
|
+
}
|
|
24
|
+
async function add(key, options) {
|
|
25
|
+
const { owner, repo, name, dir } = format(key);
|
|
26
|
+
const files = (await fetchUnGH(owner, repo, options.branch)).filter((file) => file.path.startsWith(dir)).map((file) => ({
|
|
27
|
+
remote: joinURL("https://cdn.jsdelivr.net/gh", owner, repo, file.path),
|
|
28
|
+
local: join(CLAUDE_SKILLS_DIR, name, file.path.slice(dir.length))
|
|
29
|
+
}));
|
|
30
|
+
await rimraf(join(CLAUDE_SKILLS_DIR, name));
|
|
31
|
+
await Promise.all(files.map(async (file) => {
|
|
32
|
+
await fetch(file.remote).then(async (res) => {
|
|
33
|
+
const data = await res.text();
|
|
34
|
+
await mkdir(dirname(file.local), { recursive: true });
|
|
35
|
+
await writeFile(file.local, data);
|
|
206
36
|
});
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
};
|
|
226
|
-
const manager = new SkillManager();
|
|
37
|
+
}));
|
|
38
|
+
await list();
|
|
39
|
+
print(chalk.green("+", name));
|
|
40
|
+
print();
|
|
41
|
+
}
|
|
42
|
+
function format(key) {
|
|
43
|
+
const [owner, repo, ...rest] = key.split("/");
|
|
44
|
+
return {
|
|
45
|
+
owner,
|
|
46
|
+
repo,
|
|
47
|
+
name: rest.at(-1),
|
|
48
|
+
dir: rest.join("/")
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
async function fetchUnGH(owner, repo, branch) {
|
|
52
|
+
const url = joinURL("https://api.zhaojiakun.com", "ungh", "repos", owner, repo, "files", branch);
|
|
53
|
+
return (await fetch(url).then((res) => res.json())).files;
|
|
54
|
+
}
|
|
227
55
|
|
|
228
56
|
//#endregion
|
|
229
57
|
//#region package.json
|
|
230
|
-
var
|
|
58
|
+
var name = "skills-manager";
|
|
59
|
+
var version = "0.0.3";
|
|
231
60
|
|
|
232
61
|
//#endregion
|
|
233
62
|
//#region src/index.ts
|
|
234
|
-
const cli = cac(
|
|
235
|
-
cli.command("add <
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
} catch (error) {
|
|
239
|
-
logger.error(error instanceof Error ? error.message : String(error));
|
|
240
|
-
process.exit(1);
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
cli.command("remove <skill>", "Remove a skill").alias("rm").action(async (skill) => {
|
|
244
|
-
try {
|
|
245
|
-
await manager.remove(skill);
|
|
246
|
-
} catch (error) {
|
|
247
|
-
logger.error(error instanceof Error ? error.message : String(error));
|
|
248
|
-
process.exit(1);
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
cli.command("list", "List installed skills").alias("ls").action(async () => {
|
|
252
|
-
try {
|
|
253
|
-
const installed = await manager.list();
|
|
254
|
-
if (installed.length === 0) logger.warn("未安装任何技能");
|
|
255
|
-
else {
|
|
256
|
-
logger.title(`已安装的技能 (${installed.length}):`);
|
|
257
|
-
installed.forEach((skill) => logger.item(skill));
|
|
258
|
-
}
|
|
259
|
-
} catch (error) {
|
|
260
|
-
logger.error(error instanceof Error ? error.message : String(error));
|
|
261
|
-
process.exit(1);
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
cli.command("available", "List all available skills").alias("avail").action(() => {
|
|
265
|
-
try {
|
|
266
|
-
const available = manager.listAvailable();
|
|
267
|
-
logger.title(`可用的技能 (${available.length}):`);
|
|
268
|
-
available.forEach((skill) => {
|
|
269
|
-
if (skill.description) logger.item(`${skill.name} - ${skill.description}`);
|
|
270
|
-
else logger.item(skill.name);
|
|
271
|
-
});
|
|
272
|
-
} catch (error) {
|
|
273
|
-
logger.error(error instanceof Error ? error.message : String(error));
|
|
274
|
-
process.exit(1);
|
|
275
|
-
}
|
|
276
|
-
});
|
|
63
|
+
const cli = cac(name);
|
|
64
|
+
cli.command("add <key>", "Add skill").option("-b, --branch", "Repo branch", { default: "main" }).action(add);
|
|
65
|
+
cli.command("list", "List skills").alias("ls").action(list);
|
|
66
|
+
cli.command("remove <name>", "Remove skill").alias("rm").action(remove);
|
|
277
67
|
cli.version(version);
|
|
278
68
|
cli.help();
|
|
279
69
|
cli.parse();
|
package/package.json
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skills-manager",
|
|
3
|
-
"
|
|
4
|
-
"version": "0.0.1",
|
|
3
|
+
"version": "0.0.3",
|
|
5
4
|
"description": "",
|
|
6
|
-
"author": "Jiakun Zhao <hi@zhaojiakun.com>",
|
|
7
|
-
"license": "MIT",
|
|
8
5
|
"homepage": "https://github.com/jiakun-zhao/skills-manager#readme",
|
|
9
|
-
"repository": {
|
|
10
|
-
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/jiakun-zhao/skills-manager.git"
|
|
12
|
-
},
|
|
13
6
|
"bugs": {
|
|
14
7
|
"url": "https://github.com/jiakun-zhao/skills-manager/issues"
|
|
15
8
|
},
|
|
16
|
-
"
|
|
17
|
-
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"author": "Jiakun Zhao <hi@zhaojiakun.com>",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/jiakun-zhao/skills-manager.git"
|
|
18
14
|
},
|
|
15
|
+
"bin": "./dist/index.mjs",
|
|
19
16
|
"files": [
|
|
20
17
|
"dist"
|
|
21
18
|
],
|
|
19
|
+
"type": "module",
|
|
22
20
|
"dependencies": {
|
|
23
21
|
"cac": "^6.7.14",
|
|
24
|
-
"
|
|
22
|
+
"chalk": "^5.6.2",
|
|
23
|
+
"rimraf": "^6.1.2",
|
|
24
|
+
"ufo": "^1.6.3"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@jiakun-zhao/eslint-config": "^4.
|
|
27
|
+
"@jiakun-zhao/eslint-config": "^4.3.0",
|
|
28
28
|
"@types/degit": "^2.8.6",
|
|
29
29
|
"@types/node": "^25.2.0",
|
|
30
30
|
"bumpp": "^10.4.0",
|