@openschool_01/skills 0.1.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/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # OpenSchool Skills Installer
2
+
3
+ OpenSchool curated skills installer for OpenClaw / 小龙虾 workflows.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ npx @openschool_01/skills install summarize
9
+ ```
10
+
11
+ Install into a specific workspace:
12
+
13
+ ```bash
14
+ npx @openschool_01/skills install excel-xlsx --workspace .
15
+ ```
16
+
17
+ ## What it does
18
+
19
+ - Resolves the requested skill from the bundled OpenSchool registry
20
+ - Installs from ClawHub, GitHub, npm, or curated local packages
21
+ - Writes the skill into your local `skills/` directory
22
+
23
+ ## Supported command
24
+
25
+ ```bash
26
+ openschool-skills install <slug> [--workspace <path>]
27
+ ```
@@ -0,0 +1,372 @@
1
+ #!/usr/bin/env node
2
+ /* eslint-disable @typescript-eslint/no-require-imports */
3
+
4
+ const fs = require("node:fs");
5
+ const os = require("node:os");
6
+ const path = require("node:path");
7
+ const cp = require("node:child_process");
8
+ const https = require("node:https");
9
+ const tar = require("tar");
10
+
11
+ const CLI_ROOT = path.resolve(__dirname, "..");
12
+ const REPO_ROOT = path.resolve(CLI_ROOT, "..", "..");
13
+ const BUNDLED_REGISTRY_PATH = path.join(CLI_ROOT, "registry", "skills-registry.json");
14
+ const WORKSPACE_REGISTRY_PATH = path.join(REPO_ROOT, "registry", "skills-registry.json");
15
+ const NPM_EXECUTABLE = process.platform === "win32" ? "npm.cmd" : "npm";
16
+
17
+ function printHelp() {
18
+ console.log(`
19
+ OpenSchool Skills Installer
20
+
21
+ Usage:
22
+ openschool-skills install <slug> [--workspace <path>]
23
+ openschool-skills --help
24
+
25
+ Examples:
26
+ npx @openschool_01/skills install web-access
27
+ npx @openschool_01/skills install summarize --workspace .
28
+ `);
29
+ }
30
+
31
+ function parseArgs(argv) {
32
+ const [first, ...rest] = argv;
33
+ const command = first === "--help" || first === "-h" ? undefined : first;
34
+ const options = { workspace: process.cwd(), help: false };
35
+ const positionals = [];
36
+
37
+ if (first === "--help" || first === "-h") {
38
+ options.help = true;
39
+ }
40
+
41
+ for (let index = 0; index < rest.length; index += 1) {
42
+ const token = rest[index];
43
+
44
+ if (token === "--workspace" || token === "-w") {
45
+ options.workspace = rest[index + 1] ? path.resolve(rest[index + 1]) : process.cwd();
46
+ index += 1;
47
+ continue;
48
+ }
49
+
50
+ if (token === "--help" || token === "-h") {
51
+ options.help = true;
52
+ continue;
53
+ }
54
+
55
+ positionals.push(token);
56
+ }
57
+
58
+ return { command, options, positionals };
59
+ }
60
+
61
+ function loadRegistry() {
62
+ const registryPath = fs.existsSync(BUNDLED_REGISTRY_PATH)
63
+ ? BUNDLED_REGISTRY_PATH
64
+ : WORKSPACE_REGISTRY_PATH;
65
+
66
+ return JSON.parse(fs.readFileSync(registryPath, "utf8"));
67
+ }
68
+
69
+ function getRegistryEntry(slug) {
70
+ return loadRegistry().find((entry) => entry.slug === slug);
71
+ }
72
+
73
+ function ensureDirectory(directoryPath) {
74
+ fs.mkdirSync(directoryPath, { recursive: true });
75
+ }
76
+
77
+ function quoteShellArg(value) {
78
+ if (!/[\s"]/u.test(value)) {
79
+ return value;
80
+ }
81
+
82
+ return `"${value.replace(/"/g, '\\"')}"`;
83
+ }
84
+
85
+ function runNpmCommand(args, options = {}) {
86
+ if (process.platform === "win32") {
87
+ const command = [NPM_EXECUTABLE, ...args].map((part) => quoteShellArg(String(part))).join(" ");
88
+ return cp.execSync(command, {
89
+ ...options,
90
+ shell: true,
91
+ });
92
+ }
93
+
94
+ return cp.execFileSync(NPM_EXECUTABLE, args, options);
95
+ }
96
+
97
+ function copyDirectory(sourceDir, targetDir) {
98
+ ensureDirectory(targetDir);
99
+
100
+ for (const entry of fs.readdirSync(sourceDir, { withFileTypes: true })) {
101
+ const sourcePath = path.join(sourceDir, entry.name);
102
+ const targetPath = path.join(targetDir, entry.name);
103
+
104
+ if (entry.isDirectory()) {
105
+ copyDirectory(sourcePath, targetPath);
106
+ continue;
107
+ }
108
+
109
+ fs.copyFileSync(sourcePath, targetPath);
110
+ }
111
+ }
112
+
113
+ function writeSourceMeta(targetDir, meta) {
114
+ const metaPath = path.join(targetDir, ".openschool-source.json");
115
+ fs.writeFileSync(metaPath, `${JSON.stringify(meta, null, 2)}\n`, "utf8");
116
+ }
117
+
118
+ function getLocalSkillDirectory(entry) {
119
+ if (!entry.localPackageDir) {
120
+ return null;
121
+ }
122
+
123
+ return path.join(REPO_ROOT, entry.localPackageDir, "skill");
124
+ }
125
+
126
+ function installFromLocalDirectory(entry, workspaceDir) {
127
+ const skillDir = getLocalSkillDirectory(entry);
128
+
129
+ if (!skillDir || !fs.existsSync(skillDir)) {
130
+ throw new Error(`本地技能目录不存在: ${entry.slug}`);
131
+ }
132
+
133
+ const targetDir = path.join(workspaceDir, "skills", entry.slug);
134
+ copyDirectory(skillDir, targetDir);
135
+ writeSourceMeta(targetDir, {
136
+ slug: entry.slug,
137
+ packageName: entry.packageName,
138
+ sourceType: entry.sourceType,
139
+ source: "local-workspace",
140
+ });
141
+
142
+ return { targetDir, source: "local-workspace" };
143
+ }
144
+
145
+ function installFromNpmPackage(entry, workspaceDir) {
146
+ const packageName = entry.upstreamPackageName || entry.packageName;
147
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openschool-skills-"));
148
+ const tarballName = runNpmCommand(["pack", packageName, "--silent"], {
149
+ cwd: tempDir,
150
+ encoding: "utf8",
151
+ stdio: ["ignore", "pipe", "pipe"],
152
+ })
153
+ .trim()
154
+ .split(/\r?\n/)
155
+ .pop();
156
+
157
+ const tarballPath = path.join(tempDir, tarballName);
158
+ const extractDir = path.join(tempDir, "extract");
159
+ ensureDirectory(extractDir);
160
+ tar.x({ file: tarballPath, cwd: extractDir, sync: true });
161
+
162
+ const skillDir = path.join(extractDir, "package", "skill");
163
+
164
+ if (!fs.existsSync(skillDir)) {
165
+ throw new Error(`npm 包 ${packageName} 中未找到 skill/ 目录`);
166
+ }
167
+
168
+ const targetDir = path.join(workspaceDir, "skills", entry.slug);
169
+ copyDirectory(skillDir, targetDir);
170
+ writeSourceMeta(targetDir, {
171
+ slug: entry.slug,
172
+ packageName,
173
+ sourceType: entry.sourceType,
174
+ source: "npm",
175
+ });
176
+
177
+ return { targetDir, source: packageName };
178
+ }
179
+
180
+ function downloadFile(url, destinationPath) {
181
+ return new Promise((resolve, reject) => {
182
+ const request = https.get(url, (response) => {
183
+ if (
184
+ response.statusCode &&
185
+ response.statusCode >= 300 &&
186
+ response.statusCode < 400 &&
187
+ response.headers.location
188
+ ) {
189
+ downloadFile(response.headers.location, destinationPath).then(resolve).catch(reject);
190
+ return;
191
+ }
192
+
193
+ if (response.statusCode !== 200) {
194
+ reject(new Error(`下载失败,状态码: ${response.statusCode}`));
195
+ return;
196
+ }
197
+
198
+ const fileStream = fs.createWriteStream(destinationPath);
199
+ response.pipe(fileStream);
200
+ fileStream.on("finish", () => {
201
+ fileStream.close(resolve);
202
+ });
203
+ fileStream.on("error", reject);
204
+ });
205
+
206
+ request.on("error", reject);
207
+ });
208
+ }
209
+
210
+ function resolveGithubTarballUrl(entry) {
211
+ if (!entry.githubRepo || !entry.githubRef) {
212
+ throw new Error(`技能 ${entry.slug} 缺少 GitHub 源配置`);
213
+ }
214
+
215
+ return `https://codeload.github.com/${entry.githubRepo}/tar.gz/refs/heads/${entry.githubRef}`;
216
+ }
217
+
218
+ function resolveExtractedGitHubSkillDir(extractDir) {
219
+ const topLevel = fs
220
+ .readdirSync(extractDir, { withFileTypes: true })
221
+ .find((entry) => entry.isDirectory());
222
+
223
+ if (!topLevel) {
224
+ throw new Error("无法识别 GitHub 技能压缩包结构");
225
+ }
226
+
227
+ const repoRoot = path.join(extractDir, topLevel.name);
228
+ const skillMarker = path.join(repoRoot, "SKILL.md");
229
+
230
+ if (!fs.existsSync(skillMarker)) {
231
+ throw new Error("GitHub 技能目录中未找到 SKILL.md");
232
+ }
233
+
234
+ return repoRoot;
235
+ }
236
+
237
+ async function installFromGitHub(entry, workspaceDir) {
238
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openschool-github-"));
239
+ const tarballPath = path.join(tempDir, "repo.tar.gz");
240
+ const extractDir = path.join(tempDir, "extract");
241
+ ensureDirectory(extractDir);
242
+
243
+ await downloadFile(resolveGithubTarballUrl(entry), tarballPath);
244
+ tar.x({ file: tarballPath, cwd: extractDir, sync: true });
245
+
246
+ const skillDir = resolveExtractedGitHubSkillDir(extractDir);
247
+ const targetDir = path.join(workspaceDir, "skills", entry.slug);
248
+ copyDirectory(skillDir, targetDir);
249
+ writeSourceMeta(targetDir, {
250
+ slug: entry.slug,
251
+ packageName: entry.packageName,
252
+ sourceType: entry.sourceType,
253
+ source: entry.githubRepo,
254
+ });
255
+
256
+ return { targetDir, source: entry.githubRepo };
257
+ }
258
+
259
+ function installFromClawHub(entry, workspaceDir) {
260
+ const clawhubSlug = entry.clawhubSlug || entry.slug;
261
+ const args = [
262
+ "exec",
263
+ "--yes",
264
+ "--package",
265
+ "clawhub",
266
+ "--",
267
+ "clawhub",
268
+ "install",
269
+ clawhubSlug,
270
+ "--workdir",
271
+ workspaceDir,
272
+ "--no-input",
273
+ ];
274
+
275
+ try {
276
+ runNpmCommand(args, {
277
+ cwd: workspaceDir,
278
+ encoding: "utf8",
279
+ stdio: ["ignore", "pipe", "pipe"],
280
+ });
281
+ } catch (error) {
282
+ const stderr =
283
+ error && typeof error === "object" && "stderr" in error ? String(error.stderr || "").trim() : "";
284
+ const stdout =
285
+ error && typeof error === "object" && "stdout" in error ? String(error.stdout || "").trim() : "";
286
+ const details = stderr || stdout || (error instanceof Error ? error.message : String(error));
287
+ throw new Error(`ClawHub 安装失败: ${details}`);
288
+ }
289
+
290
+ const targetDir = path.join(workspaceDir, "skills", entry.slug);
291
+
292
+ if (!fs.existsSync(targetDir)) {
293
+ throw new Error(`ClawHub 安装完成后未找到技能目录: ${targetDir}`);
294
+ }
295
+
296
+ writeSourceMeta(targetDir, {
297
+ slug: entry.slug,
298
+ packageName: entry.packageName,
299
+ sourceType: entry.sourceType,
300
+ source: entry.clawhubUrl || clawhubSlug,
301
+ });
302
+
303
+ return { targetDir, source: entry.clawhubUrl || clawhubSlug };
304
+ }
305
+
306
+ async function installSkill(entry, workspaceDir) {
307
+ ensureDirectory(path.join(workspaceDir, "skills"));
308
+
309
+ if (entry.sourceType === "unavailable") {
310
+ throw new Error(`技能 ${entry.slug} 还未完成安装接入,请先在站点中查看说明`);
311
+ }
312
+
313
+ const localSkillDir = getLocalSkillDirectory(entry);
314
+ if (localSkillDir && fs.existsSync(localSkillDir)) {
315
+ return installFromLocalDirectory(entry, workspaceDir);
316
+ }
317
+
318
+ if (entry.sourceType === "clawhub") {
319
+ return installFromClawHub(entry, workspaceDir);
320
+ }
321
+
322
+ if (entry.sourceType === "curated-github") {
323
+ return installFromGitHub(entry, workspaceDir);
324
+ }
325
+
326
+ return installFromNpmPackage(entry, workspaceDir);
327
+ }
328
+
329
+ async function main() {
330
+ const { command, options, positionals } = parseArgs(process.argv.slice(2));
331
+
332
+ if (!command || options.help) {
333
+ printHelp();
334
+ process.exit(0);
335
+ }
336
+
337
+ if (command !== "install") {
338
+ console.error(`不支持的命令: ${command}`);
339
+ printHelp();
340
+ process.exit(1);
341
+ }
342
+
343
+ const slug = positionals[0];
344
+
345
+ if (!slug) {
346
+ console.error("请提供技能 slug,例如: web-access");
347
+ process.exit(1);
348
+ }
349
+
350
+ const entry = getRegistryEntry(slug);
351
+
352
+ if (!entry) {
353
+ console.error(`未找到技能: ${slug}`);
354
+ process.exit(1);
355
+ }
356
+
357
+ try {
358
+ const workspaceDir = path.resolve(options.workspace);
359
+ const result = await installSkill(entry, workspaceDir);
360
+
361
+ console.log(`已安装技能: ${slug}`);
362
+ console.log(`来源策略: ${entry.sourceType}`);
363
+ console.log(`写入目录: ${result.targetDir}`);
364
+ console.log("下一步: 重启 OpenClaw / 小龙虾会话,让新技能生效。");
365
+ } catch (error) {
366
+ console.error("安装失败:");
367
+ console.error(error instanceof Error ? error.message : String(error));
368
+ process.exit(1);
369
+ }
370
+ }
371
+
372
+ main();
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@openschool_01/skills",
3
+ "version": "0.1.0",
4
+ "description": "OpenSchool curated skills installer CLI.",
5
+ "license": "MIT",
6
+ "bin": {
7
+ "openschool-skills": "bin/openschool-skills.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "registry",
12
+ "README.md"
13
+ ],
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "scripts": {
18
+ "build": "node ./bin/openschool-skills.js --help"
19
+ },
20
+ "dependencies": {
21
+ "tar": "^7.4.3"
22
+ }
23
+ }
@@ -0,0 +1,288 @@
1
+ [
2
+ {
3
+ "slug": "clawdhub",
4
+ "name": "clawdhub",
5
+ "tagline": "技能市场入口,帮你搜索、安装、更新和发布技能。",
6
+ "category": "starter",
7
+ "badge": "OpenSchool 推荐",
8
+ "status": "已上线",
9
+ "difficulty": "入门",
10
+ "installCommand": "npx @openschool_01/skills install clawdhub",
11
+ "packageName": "OpenSchool 安装器(内部接入 ClawHub)",
12
+ "summary": "适合作为新手接触技能生态的第一步,把技能的搜索、安装和更新入口先统一起来。",
13
+ "outcomes": ["搜索技能", "安装技能", "更新技能", "发布技能"],
14
+ "fitFor": ["第一次装技能", "搭建技能环境", "技能管理入门"],
15
+ "updatedAt": "2026-03-29",
16
+ "prerequisites": ["需联网安装", "本地需要可用的 npm 环境"],
17
+ "sourceType": "clawhub",
18
+ "clawhubSlug": "clawdhub",
19
+ "clawhubUrl": "https://clawhub.ai/steipete/clawdhub"
20
+ },
21
+ {
22
+ "slug": "skill-vetter",
23
+ "name": "skill-vetter",
24
+ "tagline": "安装前先做一轮安全审查,帮助判断来源、权限和潜在风险。",
25
+ "category": "starter",
26
+ "badge": "OpenSchool 推荐",
27
+ "status": "已上线",
28
+ "difficulty": "入门",
29
+ "installCommand": "npx @openschool_01/skills install skill-vetter",
30
+ "packageName": "OpenSchool 安装器(内部接入 ClawHub)",
31
+ "summary": "适合新手在安装技能前先做基础安全检查,降低来源不明和权限过高带来的风险。",
32
+ "outcomes": ["来源检查", "权限检查", "风险识别", "安装前审查"],
33
+ "fitFor": ["第一次装技能", "筛选第三方技能", "降低安装风险"],
34
+ "updatedAt": "2026-03-29",
35
+ "prerequisites": ["需联网安装", "本地需要可用的 npm 环境"],
36
+ "sourceType": "clawhub",
37
+ "clawhubSlug": "skill-vetter",
38
+ "clawhubUrl": "https://clawhub.ai/spclaudehome/skill-vetter"
39
+ },
40
+ {
41
+ "slug": "automation-workflows",
42
+ "name": "automation-workflows",
43
+ "tagline": "识别重复工作,并设计 Zapier、Make、n8n 等自动化流程。",
44
+ "category": "starter",
45
+ "badge": "OpenSchool 推荐",
46
+ "status": "已上线",
47
+ "difficulty": "入门",
48
+ "installCommand": "npx @openschool_01/skills install automation-workflows",
49
+ "packageName": "OpenSchool 安装器(内部接入 ClawHub)",
50
+ "summary": "适合刚开始梳理自动化场景的人,用更清晰的方式把重复工作变成流程。",
51
+ "outcomes": ["发现重复工作", "设计工作流", "连接自动化平台", "流程搭建建议"],
52
+ "fitFor": ["运营自动化", "个人提效", "团队 SOP"],
53
+ "updatedAt": "2026-03-29",
54
+ "prerequisites": ["需联网安装", "本地需要可用的 npm 环境"],
55
+ "sourceType": "clawhub",
56
+ "clawhubSlug": "automation-workflows",
57
+ "clawhubUrl": "https://clawhub.ai/jk-0001/automation-workflows"
58
+ },
59
+ {
60
+ "slug": "openclaw-tavily-search",
61
+ "name": "openclaw-tavily-search",
62
+ "tagline": "当主搜索链路不可用时,继续完成联网检索。",
63
+ "category": "starter",
64
+ "badge": "OpenSchool 推荐",
65
+ "status": "已上线",
66
+ "difficulty": "入门",
67
+ "installCommand": "npx @openschool_01/skills install openclaw-tavily-search",
68
+ "packageName": "OpenSchool 安装器(内部接入 ClawHub)",
69
+ "summary": "适合作为联网搜索的备用能力,在常规检索失效时继续兜底。",
70
+ "outcomes": ["联网兜底", "持续检索", "搜索补充", "可用性提升"],
71
+ "fitFor": ["搜索任务", "联网调研", "信息收集"],
72
+ "updatedAt": "2026-03-29",
73
+ "prerequisites": ["需联网安装", "本地需要可用的 npm 环境"],
74
+ "sourceType": "clawhub",
75
+ "clawhubSlug": "openclaw-tavily-search",
76
+ "clawhubUrl": "https://clawhub.ai/jacky1n7/openclaw-tavily-search"
77
+ },
78
+ {
79
+ "slug": "multi-search-engine",
80
+ "name": "multi-search-engine",
81
+ "tagline": "跨多个搜索源比对结果,提升信息可靠性。",
82
+ "category": "starter",
83
+ "badge": "OpenSchool 推荐",
84
+ "status": "已上线",
85
+ "difficulty": "入门",
86
+ "installCommand": "npx @openschool_01/skills install multi-search-engine",
87
+ "packageName": "OpenSchool 安装器(内部接入 ClawHub)",
88
+ "summary": "适合需要更稳搜索结果的人,通过多引擎对照减少单一来源偏差。",
89
+ "outcomes": ["多源检索", "结果对比", "信息校验", "可靠性提升"],
90
+ "fitFor": ["信息查证", "资料搜集", "多源调研"],
91
+ "updatedAt": "2026-03-29",
92
+ "prerequisites": ["需联网安装", "本地需要可用的 npm 环境"],
93
+ "sourceType": "clawhub",
94
+ "clawhubSlug": "multi-search-engine",
95
+ "clawhubUrl": "https://clawhub.ai/gpyangyoujun/multi-search-engine"
96
+ },
97
+ {
98
+ "slug": "self-improving",
99
+ "name": "self-improving",
100
+ "tagline": "把错误复盘和踩坑经验沉淀成可复用的方法。",
101
+ "category": "starter",
102
+ "badge": "OpenSchool 推荐",
103
+ "status": "已上线",
104
+ "difficulty": "入门",
105
+ "installCommand": "npx @openschool_01/skills install self-improving",
106
+ "packageName": "OpenSchool 安装器(内部接入 ClawHub)",
107
+ "summary": "适合作为长期使用中的自我优化工具,把一次次踩坑变成后续少走弯路的经验。",
108
+ "outcomes": ["错误复盘", "经验沉淀", "持续优化", "方法复用"],
109
+ "fitFor": ["长期迭代", "个人方法库", "流程改进"],
110
+ "updatedAt": "2026-03-29",
111
+ "prerequisites": ["需联网安装", "本地需要可用的 npm 环境"],
112
+ "sourceType": "clawhub",
113
+ "clawhubSlug": "self-improving",
114
+ "clawhubUrl": "https://clawhub.ai/ivangdavila/self-improving"
115
+ },
116
+ {
117
+ "slug": "obsidian",
118
+ "name": "obsidian",
119
+ "tagline": "把长期笔记和知识资产沉淀进 Obsidian。",
120
+ "category": "starter",
121
+ "badge": "OpenSchool 推荐",
122
+ "status": "已上线",
123
+ "difficulty": "入门",
124
+ "installCommand": "npx @openschool_01/skills install obsidian",
125
+ "packageName": "OpenSchool 安装器(内部接入 ClawHub)",
126
+ "summary": "适合想把零散知识长期积累下来的人,让知识管理和工作过程更连贯。",
127
+ "outcomes": ["笔记协作", "知识沉淀", "长期积累", "资产管理"],
128
+ "fitFor": ["知识管理", "长期项目", "笔记工作流"],
129
+ "updatedAt": "2026-03-29",
130
+ "prerequisites": ["需联网安装", "本地需要可用的 npm 环境"],
131
+ "sourceType": "clawhub",
132
+ "clawhubSlug": "obsidian",
133
+ "clawhubUrl": "https://clawhub.ai/steipete/obsidian"
134
+ },
135
+ {
136
+ "slug": "ontology",
137
+ "name": "ontology",
138
+ "tagline": "建立项目、任务、文档之间的结构化关系。",
139
+ "category": "starter",
140
+ "badge": "OpenSchool 推荐",
141
+ "status": "已上线",
142
+ "difficulty": "入门",
143
+ "installCommand": "npx @openschool_01/skills install ontology",
144
+ "packageName": "OpenSchool 安装器(内部接入 ClawHub)",
145
+ "summary": "适合希望把信息关系理清楚的人,让知识图谱和任务结构更清晰。",
146
+ "outcomes": ["结构化关系", "知识图谱", "任务关联", "信息整理"],
147
+ "fitFor": ["复杂项目", "知识管理", "结构化梳理"],
148
+ "updatedAt": "2026-03-29",
149
+ "prerequisites": ["需联网安装", "本地需要可用的 npm 环境"],
150
+ "sourceType": "clawhub",
151
+ "clawhubSlug": "ontology",
152
+ "clawhubUrl": "https://clawhub.ai/oswalpalash/ontology"
153
+ },
154
+ {
155
+ "slug": "markdown-converter",
156
+ "name": "markdown-converter",
157
+ "tagline": "把 PDF、Word、PPT、XLS 等文档转成更易复用的 Markdown。",
158
+ "category": "starter",
159
+ "badge": "OpenSchool 推荐",
160
+ "status": "已上线",
161
+ "difficulty": "入门",
162
+ "installCommand": "npx @openschool_01/skills install markdown-converter",
163
+ "packageName": "OpenSchool 安装器(内部接入 ClawHub)",
164
+ "summary": "适合把各类文件整理成统一 Markdown 工作流的人,方便后续复用和再加工。",
165
+ "outcomes": ["文档转换", "统一格式", "内容复用", "二次加工准备"],
166
+ "fitFor": ["文档处理", "知识整理", "内容迁移"],
167
+ "updatedAt": "2026-03-29",
168
+ "prerequisites": ["需联网安装", "本地需要可用的 npm 环境"],
169
+ "sourceType": "clawhub",
170
+ "clawhubSlug": "markdown-converter",
171
+ "clawhubUrl": "https://clawhub.ai/steipete/markdown-converter"
172
+ },
173
+ {
174
+ "slug": "summarize",
175
+ "name": "summarize",
176
+ "tagline": "快速总结网页、视频、PDF 等内容,方便继续加工。",
177
+ "category": "starter",
178
+ "badge": "OpenSchool 推荐",
179
+ "status": "已上线",
180
+ "difficulty": "入门",
181
+ "installCommand": "npx @openschool_01/skills install summarize",
182
+ "packageName": "OpenSchool 安装器(内部接入 ClawHub)",
183
+ "summary": "适合作为高频总结工具,把信息先快速收拢,再继续整理和输出。",
184
+ "outcomes": ["网页总结", "视频摘要", "PDF 摘要", "二次加工准备"],
185
+ "fitFor": ["资料阅读", "快速理解", "内容提炼"],
186
+ "updatedAt": "2026-03-29",
187
+ "prerequisites": ["需联网安装", "部分场景需要额外 API Key 或本地 CLI"],
188
+ "sourceType": "clawhub",
189
+ "clawhubSlug": "summarize",
190
+ "clawhubUrl": "https://clawhub.ai/steipete/summarize"
191
+ },
192
+ {
193
+ "slug": "web-access",
194
+ "name": "Web Access",
195
+ "tagline": "给小龙虾补上更完整的联网、浏览器交互和站点操作能力。",
196
+ "category": "power",
197
+ "badge": "OpenSchool 严选",
198
+ "status": "已上线",
199
+ "difficulty": "专业",
200
+ "installCommand": "npx @openschool_01/skills install web-access",
201
+ "packageName": "@openschool/skill-web-access",
202
+ "summary": "这是 OpenSchool 收录的高质量联网技能,适合需要真实浏览器环境、登录态访问、动态页面读取和网页交互的任务。",
203
+ "outcomes": ["网页搜索调度", "动态页面读取", "浏览器点击交互", "媒体与截图提取"],
204
+ "fitFor": ["网页调研", "登录态站点操作", "小红书等平台浏览", "需要浏览器自动化的任务"],
205
+ "updatedAt": "2026-03-28",
206
+ "prerequisites": ["Node.js 22+", "Chrome 开启 remote debugging", "适合桌面本机环境"],
207
+ "sourceType": "curated-github",
208
+ "githubRepo": "eze-is/web-access",
209
+ "githubRef": "main",
210
+ "localPackageDir": "packages/skills/web-access"
211
+ },
212
+ {
213
+ "slug": "word-docx",
214
+ "name": "DOCX 文档助手",
215
+ "tagline": "创建、查看和编辑 Word / DOCX 文档,兼顾样式、表格、编号和兼容性。",
216
+ "category": "office",
217
+ "badge": "OpenSchool 推荐",
218
+ "status": "已上线",
219
+ "difficulty": "进阶",
220
+ "installCommand": "npx @openschool_01/skills install word-docx",
221
+ "packageName": "OpenSchool 安装器(内部接入 ClawHub)",
222
+ "summary": "适合需要稳定处理 Word 文档的人,能更可靠地生成、检查和修改 DOCX 文件,尤其适合正式文档、方案和交付稿。",
223
+ "outcomes": ["生成 DOCX 文档", "编辑段落与样式", "处理表格和编号", "兼容性检查"],
224
+ "fitFor": ["方案文档", "交付材料", "正式报告", "需要 Word 结构化输出的工作"],
225
+ "updatedAt": "2026-03-30",
226
+ "prerequisites": ["需联网安装", "本地需要可用的 npm 环境"],
227
+ "sourceType": "clawhub",
228
+ "clawhubSlug": "word-docx",
229
+ "clawhubUrl": "https://clawhub.ai/ivangdavila/word-docx"
230
+ },
231
+ {
232
+ "slug": "powerpoint-pptx",
233
+ "name": "PPT 演示助手",
234
+ "tagline": "创建、查看和编辑 PowerPoint / PPTX,兼顾布局、模板、备注和图表。",
235
+ "category": "office",
236
+ "badge": "OpenSchool 推荐",
237
+ "status": "已上线",
238
+ "difficulty": "进阶",
239
+ "installCommand": "npx @openschool_01/skills install powerpoint-pptx",
240
+ "packageName": "OpenSchool 安装器(内部接入 ClawHub)",
241
+ "summary": "适合要稳定做演示文稿的人,可以围绕版式、模板、占位符、备注和图表来处理 PPTX,比只生成一堆页面更适合正式办公场景。",
242
+ "outcomes": ["生成 PPTX 演示稿", "编辑版式与模板", "处理图表与占位符", "演示稿质量检查"],
243
+ "fitFor": ["汇报演示", "项目提案", "培训材料", "客户汇报 PPT"],
244
+ "updatedAt": "2026-03-30",
245
+ "prerequisites": ["需联网安装", "本地需要可用的 npm 环境"],
246
+ "sourceType": "clawhub",
247
+ "clawhubSlug": "powerpoint-pptx",
248
+ "clawhubUrl": "https://clawhub.ai/ivangdavila/powerpoint-pptx"
249
+ },
250
+ {
251
+ "slug": "excel-xlsx",
252
+ "name": "Excel 表格助手",
253
+ "tagline": "创建、查看和编辑 Excel / XLSX,兼顾公式、日期、格式和模板保留。",
254
+ "category": "office",
255
+ "badge": "OpenSchool 推荐",
256
+ "status": "已上线",
257
+ "difficulty": "进阶",
258
+ "installCommand": "npx @openschool_01/skills install excel-xlsx",
259
+ "packageName": "OpenSchool 安装器(内部接入 ClawHub)",
260
+ "summary": "适合经常处理表格的人,能更稳定地创建和修改 Excel 工作簿,适用于公式、格式、日期类型和模板保留这类办公高频需求。",
261
+ "outcomes": ["生成 XLSX 表格", "处理公式与日期", "保留模板格式", "读取和修改工作簿"],
262
+ "fitFor": ["数据台账", "财务表格", "运营报表", "需要 Excel 结构化输出的工作"],
263
+ "updatedAt": "2026-03-30",
264
+ "prerequisites": ["需联网安装", "本地需要可用的 npm 环境"],
265
+ "sourceType": "clawhub",
266
+ "clawhubSlug": "excel-xlsx",
267
+ "clawhubUrl": "https://clawhub.ai/ivangdavila/excel-xlsx"
268
+ },
269
+ {
270
+ "slug": "pdf-processing",
271
+ "name": "PDF 办公助手",
272
+ "tagline": "从 PDF 中提取文本和表格,填写表单,并合并文档。",
273
+ "category": "office",
274
+ "badge": "OpenSchool 推荐",
275
+ "status": "已上线",
276
+ "difficulty": "进阶",
277
+ "installCommand": "npx @openschool_01/skills install pdf-processing",
278
+ "packageName": "OpenSchool 安装器(内部接入 ClawHub)",
279
+ "summary": "适合日常办公里处理 PDF 的场景,能做提取、表格读取、表单填写和文档合并,比较贴近真实文档流转需求。",
280
+ "outcomes": ["提取 PDF 文本", "识别表格内容", "填写 PDF 表单", "合并 PDF 文档"],
281
+ "fitFor": ["合同和附件处理", "表单回填", "资料提取", "PDF 日常办公流转"],
282
+ "updatedAt": "2026-03-30",
283
+ "prerequisites": ["需联网安装", "本地需要可用的 npm 环境"],
284
+ "sourceType": "clawhub",
285
+ "clawhubSlug": "pdf-processing",
286
+ "clawhubUrl": "https://clawhub.ai/rainshow/pdf-processing"
287
+ }
288
+ ]