@workskills/getskill 1.0.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.
Files changed (5) hide show
  1. package/EXAMPLES.md +265 -0
  2. package/LICENSE +21 -0
  3. package/README.md +257 -0
  4. package/index.js +578 -0
  5. package/package.json +58 -0
package/EXAMPLES.md ADDED
@@ -0,0 +1,265 @@
1
+ # GetSkill 使用示例
2
+
3
+ ## 场景 1: 首次使用(未安装 Git)
4
+
5
+ ### Windows 用户
6
+
7
+ ```bash
8
+ # 第一次运行安装命令
9
+ $ getskill install commit-helper
10
+
11
+ 检测到系统未安装 Git,正在准备安装...
12
+
13
+ Windows 系统检测到未安装 Git
14
+ 正在下载 Git 安装程序...
15
+
16
+ 下载进度: 100%
17
+ 下载完成!
18
+
19
+ Git 安装程序已下载到: C:\Users\...\AppData\Local\Temp\git-installer.exe
20
+
21
+ 正在启动安装程序,请按照提示完成安装...
22
+ 安装完成后,请重新运行此命令。
23
+
24
+ # Git 安装完成后,再次运行
25
+ $ getskill install commit-helper
26
+
27
+ 获取技能信息: commit-helper...
28
+ 克隆仓库: https://github.com/workskills/commit-helper.git...
29
+ 仓库克隆成功: C:\Users\...\\.claude\skills-cache\commit-helper
30
+
31
+ 技能已安装到 skills 目录:
32
+ - C:\Users\...\.claude\skills\commit-helper.md
33
+
34
+ Git 仓库缓存: C:\Users\...\.claude\skills-cache\commit-helper
35
+ ```
36
+
37
+ ### macOS 用户
38
+
39
+ ```bash
40
+ $ getskill install commit-helper
41
+
42
+ 检测到系统未安装 Git,正在准备安装...
43
+
44
+ macOS 系统检测到未安装 Git
45
+ 请使用以下命令安装 Git:
46
+
47
+ brew install git
48
+
49
+ 如果未安装 Homebrew,请访问: https://brew.sh/
50
+
51
+ # 安装 Git
52
+ $ brew install git
53
+
54
+ # 再次运行
55
+ $ getskill install commit-helper
56
+ ✓ 安装成功
57
+ ```
58
+
59
+ ### Linux 用户
60
+
61
+ ```bash
62
+ $ getskill install commit-helper
63
+
64
+ 检测到系统未安装 Git,正在准备安装...
65
+
66
+ Linux 系统检测到未安装 Git
67
+ 请使用系统包管理器安装 Git:
68
+
69
+ Ubuntu/Debian: sudo apt-get install git
70
+ CentOS/RHEL: sudo yum install git
71
+ Fedora: sudo dnf install git
72
+ Arch: sudo pacman -S git
73
+
74
+ # Ubuntu/Debian 用户
75
+ $ sudo apt-get install git
76
+
77
+ # 再次运行
78
+ $ getskill install commit-helper
79
+ ✓ 安装成功
80
+ ```
81
+
82
+ ## 场景 2: 已安装 Git(正常使用)
83
+
84
+ ```bash
85
+ # 搜索技能
86
+ $ getskill search commit
87
+
88
+ 找到 3 个技能:
89
+
90
+ 1. commit-helper
91
+ 描述: 帮助生成规范的 git commit 信息
92
+ Git: https://github.com/workskills/commit-helper.git
93
+ 作者: workskills
94
+
95
+ 2. commit-lint
96
+ 描述: 检查 commit 信息是否符合规范
97
+ Git: https://github.com/workskills/commit-lint.git
98
+ 作者: workskills
99
+
100
+ # 安装技能
101
+ $ getskill install commit-helper
102
+
103
+ 获取技能信息: commit-helper...
104
+ 克隆仓库: https://github.com/workskills/commit-helper.git...
105
+ 仓库克隆成功: ~/.claude/skills-cache/commit-helper
106
+ 已复制: commit-helper.md -> ~/.claude/skills/commit-helper.md
107
+
108
+ 技能已安装到 skills 目录:
109
+ - ~/.claude/skills/commit-helper.md
110
+
111
+ Git 仓库缓存: ~/.claude/skills-cache/commit-helper
112
+
113
+ # 列出已安装的技能
114
+ $ getskill list
115
+
116
+ 本地已安装的技能 (1):
117
+ 1. commit-helper.md
118
+
119
+ # 更新技能
120
+ $ getskill update commit-helper
121
+
122
+ 正在更新技能: commit-helper...
123
+ 更新仓库: commit-helper...
124
+ Already up to date.
125
+ 仓库更新成功: ~/.claude/skills-cache/commit-helper
126
+ 已复制: commit-helper.md -> ~/.claude/skills/commit-helper.md
127
+
128
+ 技能已更新到 skills 目录:
129
+ - ~/.claude/skills/commit-helper.md
130
+
131
+ # 查看目录路径
132
+ $ getskill path
133
+
134
+ 技能目录: ~/.claude/skills
135
+ 缓存目录: ~/.claude/skills-cache
136
+
137
+ # 清理缓存
138
+ $ getskill clean
139
+
140
+ 已清理缓存目录: ~/.claude/skills-cache
141
+ ```
142
+
143
+ ## 场景 3: 编程接口使用
144
+
145
+ ```javascript
146
+ const getskill = require('@workskills/getskill');
147
+
148
+ (async () => {
149
+ try {
150
+ // 检查 Git 是否已安装
151
+ const isGitInstalled = await getskill.checkGitInstalled();
152
+ console.log('Git 已安装:', isGitInstalled);
153
+
154
+ if (!isGitInstalled) {
155
+ console.log('正在引导安装 Git...');
156
+ await getskill.ensureGitInstalled();
157
+ }
158
+
159
+ // 搜索技能
160
+ const results = await getskill.searchSkills('commit');
161
+ console.log('搜索结果:', results);
162
+
163
+ // 安装技能
164
+ const result = await getskill.downloadSkill('commit-helper');
165
+ console.log('安装成功:', result.files);
166
+
167
+ // 更新技能
168
+ await getskill.updateSkill('commit-helper');
169
+ console.log('更新成功');
170
+
171
+ // 列出本地技能
172
+ const localSkills = getskill.listLocalSkills();
173
+ console.log('本地技能:', localSkills);
174
+
175
+ } catch (error) {
176
+ console.error('错误:', error.message);
177
+ }
178
+ })();
179
+ ```
180
+
181
+ ## 场景 4: 批量安装技能
182
+
183
+ ```bash
184
+ # 创建脚本 install-skills.sh
185
+ #!/bin/bash
186
+
187
+ skills=(
188
+ "commit-helper"
189
+ "code-review"
190
+ "test-generator"
191
+ "doc-writer"
192
+ )
193
+
194
+ for skill in "${skills[@]}"; do
195
+ echo "正在安装: $skill"
196
+ getskill install "$skill"
197
+ echo "---"
198
+ done
199
+
200
+ # 运行脚本
201
+ $ chmod +x install-skills.sh
202
+ $ ./install-skills.sh
203
+ ```
204
+
205
+ ## 场景 5: 错误处理
206
+
207
+ ```bash
208
+ # 技能不存在
209
+ $ getskill install non-existent-skill
210
+ 获取技能信息: non-existent-skill...
211
+ 搜索技能失败: Request failed with status code 404
212
+ 执行命令时出错: Request failed with status code 404
213
+
214
+ # Git URL 无效
215
+ $ getskill install invalid-git-skill
216
+ 获取技能信息: invalid-git-skill...
217
+ 克隆仓库: https://invalid-url.git...
218
+ 克隆失败: fatal: repository 'https://invalid-url.git/' not found
219
+ 执行命令时出错: Command failed: git clone...
220
+
221
+ # 网络问题
222
+ $ getskill search commit
223
+ 搜索技能失败: connect ETIMEDOUT
224
+ 执行命令时出错: connect ETIMEDOUT
225
+ ```
226
+
227
+ ## 场景 6: 目录结构查看
228
+
229
+ ```bash
230
+ # 安装几个技能后查看目录结构
231
+ $ tree ~/.claude
232
+
233
+ ~/.claude/
234
+ ├── skills/
235
+ │ ├── commit-helper.md
236
+ │ ├── code-review.md
237
+ │ └── test-generator.md
238
+ └── skills-cache/
239
+ ├── commit-helper/
240
+ │ ├── commit-helper.md
241
+ │ ├── README.md
242
+ │ └── .git/
243
+ ├── code-review/
244
+ │ ├── code-review.md
245
+ │ ├── README.md
246
+ │ └── .git/
247
+ └── test-generator/
248
+ ├── test-generator.md
249
+ ├── README.md
250
+ └── .git/
251
+ ```
252
+
253
+ ## 常见问题
254
+
255
+ ### Q: Git 安装后仍提示未安装?
256
+ A: Windows 用户需要重启终端或系统,以便环境变量生效。
257
+
258
+ ### Q: 如何卸载技能?
259
+ A: 直接删除 `~/.claude/skills/` 目录下的对应 `.md` 文件即可。
260
+
261
+ ### Q: 缓存目录可以删除吗?
262
+ A: 可以使用 `getskill clean` 清理缓存,下次更新技能时会重新克隆。
263
+
264
+ ### Q: 如何手动指定 Git 路径?
265
+ A: 确保 `git` 命令在系统 PATH 中,或修改 `~/.bashrc` / `~/.zshrc` 添加 Git 路径。
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 workskills.store
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,257 @@
1
+ # GetSkill
2
+
3
+ OpenClaw 技能管理工具 - 从 getskill.work 搜索、下载和更新技能文件
4
+
5
+ ## 功能特性
6
+
7
+ - 🔍 从 getskill.work API 搜索技能
8
+ - 📥 通过 Git 克隆技能仓库
9
+ - 🔄 通过 Git pull 更新已安装的技能
10
+ - 🛠️ 自动检测并引导安装 Git(如未安装)
11
+ - 📂 跨平台支持(Windows/macOS/Linux)
12
+ - 💾 自动管理技能文件到 OpenClaw skills 目录
13
+
14
+ ## 工作原理
15
+
16
+ 1. **搜索**: 从 `getskill.work` API 获取技能列表,包含 Git 仓库地址
17
+ 2. **安装**: 使用 `git clone` 克隆技能仓库到缓存目录
18
+ 3. **复制**: 将仓库中的 `.md` 技能文件复制到 OpenClaw skills 目录
19
+ 4. **更新**: 使用 `git pull` 更新仓库,并重新复制文件
20
+
21
+ ## 目录结构
22
+
23
+ ```
24
+ ~/.claude/
25
+ ├── skills/ # OpenClaw 技能文件目录
26
+ │ ├── skill1.md
27
+ │ └── skill2.md
28
+ └── skills-cache/ # Git 仓库缓存
29
+ ├── skill1/
30
+ └── skill2/
31
+ ```
32
+
33
+ ### 平台路径
34
+
35
+ - **Windows**: `%USERPROFILE%\.claude\skills`
36
+ - **macOS**: `~/.claude/skills`
37
+ - **Linux**: `~/.claude/skills`
38
+
39
+ ## 安装
40
+
41
+ ### 全局安装(推荐)
42
+
43
+ ```bash
44
+ npm install -g @workskills/getskill
45
+ ```
46
+
47
+ 安装后,可以在任何位置使用 `getskill` 命令。
48
+
49
+ ### 本地安装
50
+
51
+ ```bash
52
+ npm install @workskills/getskill
53
+ ```
54
+
55
+ 本地安装后,可以通过 npx 运行:
56
+
57
+ ```bash
58
+ npx getskill search <关键词>
59
+ ```
60
+
61
+ ### 从源码安装
62
+
63
+ ```bash
64
+ git clone https://github.com/workskills/getskill.git
65
+ cd getskill
66
+ npm install
67
+ npm link
68
+ ```
69
+
70
+ ## 使用方法
71
+
72
+ ### 搜索技能
73
+
74
+ ```bash
75
+ getskill search <关键词>
76
+ ```
77
+
78
+ 示例输出:
79
+ ```
80
+ 找到 3 个技能:
81
+
82
+ 1. commit-helper
83
+ 描述: 帮助生成规范的 git commit 信息
84
+ Git: https://github.com/workskills/commit-helper.git
85
+ 作者: workskills
86
+
87
+ 2. code-review
88
+ 描述: AI 代码审查助手
89
+ Git: https://github.com/workskills/code-review.git
90
+ 作者: workskills
91
+ ```
92
+
93
+ ### 安装技能
94
+
95
+ ```bash
96
+ getskill install <技能名称>
97
+ ```
98
+
99
+ 示例:
100
+ ```bash
101
+ getskill install commit-helper
102
+ ```
103
+
104
+ 操作流程:
105
+ 1. 调用 API 获取技能详情(包含 git_url)
106
+ 2. 执行 `git clone` 到 `~/.claude/skills-cache/commit-helper`
107
+ 3. 复制 `.md` 文件到 `~/.claude/skills/`
108
+
109
+ ### 更新技能
110
+
111
+ ```bash
112
+ getskill update <技能名称>
113
+ ```
114
+
115
+ 示例:
116
+ ```bash
117
+ getskill update commit-helper
118
+ ```
119
+
120
+ 操作流程:
121
+ 1. 进入缓存目录 `~/.claude/skills-cache/commit-helper`
122
+ 2. 执行 `git pull`
123
+ 3. 重新复制最新的 `.md` 文件
124
+
125
+ ### 列出本地技能
126
+
127
+ ```bash
128
+ getskill list
129
+ ```
130
+
131
+ ### 查看目录路径
132
+
133
+ ```bash
134
+ getskill path
135
+ ```
136
+
137
+ ### 清理缓存
138
+
139
+ ```bash
140
+ getskill clean
141
+ ```
142
+
143
+ 清理所有 Git 仓库缓存(不影响 skills 目录中的文件)
144
+
145
+ ## API 接口规范
146
+
147
+ ### 搜索 API
148
+
149
+ ```
150
+ GET https://getskill.work/api/skills/search?q=<关键词>
151
+ ```
152
+
153
+ 响应格式:
154
+ ```json
155
+ {
156
+ "skills": [
157
+ {
158
+ "id": "commit-helper",
159
+ "name": "commit-helper",
160
+ "description": "帮助生成规范的 git commit 信息",
161
+ "git_url": "https://github.com/workskills/commit-helper.git",
162
+ "author": "workskills",
163
+ "version": "1.0.0"
164
+ }
165
+ ]
166
+ }
167
+ ```
168
+
169
+ ### 详情 API
170
+
171
+ ```
172
+ GET https://getskill.work/api/skills/<技能ID>
173
+ ```
174
+
175
+ 响应格式:
176
+ ```json
177
+ {
178
+ "id": "commit-helper",
179
+ "name": "commit-helper",
180
+ "description": "帮助生成规范的 git commit 信息",
181
+ "git_url": "https://github.com/workskills/commit-helper.git",
182
+ "author": "workskills",
183
+ "version": "1.0.0",
184
+ "files": ["commit-helper.md"],
185
+ "readme": "..."
186
+ }
187
+ ```
188
+
189
+ ## 编程接口
190
+
191
+ ```javascript
192
+ const getskill = require('@workskills/getskill');
193
+
194
+ // 搜索技能
195
+ const results = await getskill.searchSkills('commit');
196
+
197
+ // 安装技能
198
+ const result = await getskill.downloadSkill('commit-helper');
199
+ console.log(result.files); // 已复制的文件列表
200
+
201
+ // 更新技能
202
+ await getskill.updateSkill('commit-helper');
203
+
204
+ // 列出本地技能
205
+ const skills = getskill.listLocalSkills();
206
+
207
+ // 获取目录
208
+ const skillsDir = getskill.getSkillsDirectory();
209
+ const cacheDir = getskill.getSkillsCacheDirectory();
210
+ ```
211
+
212
+ ## 技能仓库规范
213
+
214
+ 技能 Git 仓库应包含:
215
+ - 一个或多个 `.md` 技能文件(非 README)
216
+ - 可选的 `README.md` 说明文档
217
+ - 可选的示例代码或配置文件
218
+
219
+ 示例结构:
220
+ ```
221
+ commit-helper/
222
+ ├── commit-helper.md # 主技能文件(会被复制)
223
+ ├── README.md # 说明文档(不会被复制)
224
+ └── examples/ # 示例(不会被复制)
225
+ ```
226
+
227
+ ## 依赖
228
+
229
+ - Node.js >= 12
230
+ - Git 命令行工具(如未安装,程序会自动引导安装)
231
+
232
+ ## Git 自动检测与安装
233
+
234
+ 首次运行 `install` 或 `update` 命令时,程序会自动检测系统是否已安装 Git:
235
+
236
+ ### Windows
237
+ - **自动下载**: 自动下载 Git 安装程序并启动安装向导
238
+ - **手动安装**: 如果自动下载失败,会提示访问 https://git-scm.com/download/win
239
+
240
+ ### macOS
241
+ - 提示使用 Homebrew 安装:`brew install git`
242
+ - 如未安装 Homebrew,会提示访问 https://brew.sh/
243
+
244
+ ### Linux
245
+ - 提示使用系统包管理器安装:
246
+ - Ubuntu/Debian: `sudo apt-get install git`
247
+ - CentOS/RHEL: `sudo yum install git`
248
+ - Fedora: `sudo dnf install git`
249
+ - Arch: `sudo pacman -S git`
250
+
251
+ ## 许可证
252
+
253
+ MIT
254
+
255
+ ## 作者
256
+
257
+ workskills.store
package/index.js ADDED
@@ -0,0 +1,578 @@
1
+ #!/usr/bin/env node
2
+
3
+ const https = require('https');
4
+ const http = require('http');
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const os = require('os');
8
+ const { exec } = require('child_process');
9
+
10
+ /**
11
+ * 检查 Git 是否已安装
12
+ */
13
+ async function checkGitInstalled() {
14
+ try {
15
+ await executeCommand('git --version');
16
+ return true;
17
+ } catch (error) {
18
+ return false;
19
+ }
20
+ }
21
+
22
+ /**
23
+ * 获取 Git 下载链接(根据操作系统)
24
+ */
25
+ function getGitDownloadUrl() {
26
+ const platform = os.platform();
27
+ const arch = os.arch();
28
+
29
+ switch (platform) {
30
+ case 'win32':
31
+ // Windows
32
+ if (arch === 'x64') {
33
+ return 'https://github.com/git-for-windows/git/releases/download/v2.44.0.windows.1/Git-2.44.0-64-bit.exe';
34
+ } else {
35
+ return 'https://github.com/git-for-windows/git/releases/download/v2.44.0.windows.1/Git-2.44.0-32-bit.exe';
36
+ }
37
+ case 'darwin':
38
+ // macOS - 提示使用 Homebrew
39
+ return 'homebrew'; // 特殊标记
40
+ case 'linux':
41
+ // Linux - 提示使用包管理器
42
+ return 'package-manager'; // 特殊标记
43
+ default:
44
+ return null;
45
+ }
46
+ }
47
+
48
+ /**
49
+ * 下载文件
50
+ */
51
+ function downloadFile(url, destPath) {
52
+ return new Promise((resolve, reject) => {
53
+ const urlObj = new URL(url);
54
+ const protocol = urlObj.protocol === 'https:' ? https : http;
55
+
56
+ const file = fs.createWriteStream(destPath);
57
+
58
+ protocol.get(url, (response) => {
59
+ // 处理重定向
60
+ if (response.statusCode === 301 || response.statusCode === 302) {
61
+ file.close();
62
+ fs.unlinkSync(destPath);
63
+ return downloadFile(response.headers.location, destPath)
64
+ .then(resolve)
65
+ .catch(reject);
66
+ }
67
+
68
+ if (response.statusCode !== 200) {
69
+ file.close();
70
+ fs.unlinkSync(destPath);
71
+ return reject(new Error(`下载失败,状态码: ${response.statusCode}`));
72
+ }
73
+
74
+ const totalSize = parseInt(response.headers['content-length'], 10);
75
+ let downloadedSize = 0;
76
+
77
+ response.on('data', (chunk) => {
78
+ downloadedSize += chunk.length;
79
+ const percent = ((downloadedSize / totalSize) * 100).toFixed(2);
80
+ process.stdout.write(`\r下载进度: ${percent}%`);
81
+ });
82
+
83
+ response.pipe(file);
84
+
85
+ file.on('finish', () => {
86
+ file.close();
87
+ console.log('\n下载完成!');
88
+ resolve(destPath);
89
+ });
90
+ }).on('error', (err) => {
91
+ file.close();
92
+ fs.unlinkSync(destPath);
93
+ reject(err);
94
+ });
95
+ });
96
+ }
97
+
98
+ /**
99
+ * 安装 Git
100
+ */
101
+ async function installGit() {
102
+ const platform = os.platform();
103
+ const downloadUrl = getGitDownloadUrl();
104
+
105
+ console.log('检测到系统未安装 Git,正在准备安装...\n');
106
+
107
+ if (downloadUrl === 'homebrew') {
108
+ console.log('macOS 系统检测到未安装 Git');
109
+ console.log('请使用以下命令安装 Git:\n');
110
+ console.log(' brew install git');
111
+ console.log('\n如果未安装 Homebrew,请访问: https://brew.sh/');
112
+ throw new Error('请先安装 Git 后再运行此命令');
113
+ }
114
+
115
+ if (downloadUrl === 'package-manager') {
116
+ console.log('Linux 系统检测到未安装 Git');
117
+ console.log('请使用系统包管理器安装 Git:\n');
118
+ console.log(' Ubuntu/Debian: sudo apt-get install git');
119
+ console.log(' CentOS/RHEL: sudo yum install git');
120
+ console.log(' Fedora: sudo dnf install git');
121
+ console.log(' Arch: sudo pacman -S git');
122
+ throw new Error('请先安装 Git 后再运行此命令');
123
+ }
124
+
125
+ if (platform === 'win32') {
126
+ console.log('Windows 系统检测到未安装 Git');
127
+ console.log('正在下载 Git 安装程序...\n');
128
+
129
+ const tempDir = os.tmpdir();
130
+ const installerPath = path.join(tempDir, 'git-installer.exe');
131
+
132
+ try {
133
+ await downloadFile(downloadUrl, installerPath);
134
+ console.log(`\nGit 安装程序已下载到: ${installerPath}`);
135
+ console.log('\n正在启动安装程序,请按照提示完成安装...');
136
+ console.log('安装完成后,请重新运行此命令。\n');
137
+
138
+ // 启动安装程序
139
+ exec(`"${installerPath}"`, (error) => {
140
+ if (error) {
141
+ console.error('启动安装程序失败:', error.message);
142
+ }
143
+ });
144
+
145
+ throw new Error('请完成 Git 安装后重新运行此命令');
146
+ } catch (error) {
147
+ console.error('\n下载 Git 安装程序失败:', error.message);
148
+ console.log('\n您可以手动访问以下网址下载 Git:');
149
+ console.log('https://git-scm.com/download/win');
150
+ throw new Error('请先安装 Git 后再运行此命令');
151
+ }
152
+ }
153
+ }
154
+
155
+ /**
156
+ * 确保 Git 已安装
157
+ */
158
+ async function ensureGitInstalled() {
159
+ const isInstalled = await checkGitInstalled();
160
+ if (!isInstalled) {
161
+ await installGit();
162
+ }
163
+ return true;
164
+ }
165
+
166
+ /**
167
+ * 获取 OpenClaw skills 目录路径(根据操作系统)
168
+ */
169
+ function getSkillsDirectory() {
170
+ const platform = os.platform();
171
+ const homeDir = os.homedir();
172
+
173
+ switch (platform) {
174
+ case 'win32':
175
+ // Windows: %USERPROFILE%\.claude\skills
176
+ return path.join(homeDir, '.claude', 'skills');
177
+ case 'darwin':
178
+ // macOS: ~/.claude/skills
179
+ return path.join(homeDir, '.claude', 'skills');
180
+ case 'linux':
181
+ // Linux: ~/.claude/skills
182
+ return path.join(homeDir, '.claude', 'skills');
183
+ default:
184
+ // 默认使用 ~/.claude/skills
185
+ return path.join(homeDir, '.claude', 'skills');
186
+ }
187
+ }
188
+
189
+ /**
190
+ * 确保目录存在
191
+ */
192
+ function ensureDirectoryExists(dirPath) {
193
+ if (!fs.existsSync(dirPath)) {
194
+ fs.mkdirSync(dirPath, { recursive: true });
195
+ }
196
+ }
197
+
198
+ /**
199
+ * HTTP/HTTPS 请求封装
200
+ */
201
+ function request(url, options = {}) {
202
+ return new Promise((resolve, reject) => {
203
+ const urlObj = new URL(url);
204
+ const protocol = urlObj.protocol === 'https:' ? https : http;
205
+
206
+ const reqOptions = {
207
+ hostname: urlObj.hostname,
208
+ port: urlObj.port,
209
+ path: urlObj.pathname + urlObj.search,
210
+ method: options.method || 'GET',
211
+ headers: options.headers || {}
212
+ };
213
+
214
+ const req = protocol.request(reqOptions, (res) => {
215
+ let data = '';
216
+
217
+ res.on('data', (chunk) => {
218
+ data += chunk;
219
+ });
220
+
221
+ res.on('end', () => {
222
+ if (res.statusCode >= 200 && res.statusCode < 300) {
223
+ resolve({
224
+ statusCode: res.statusCode,
225
+ headers: res.headers,
226
+ body: data
227
+ });
228
+ } else {
229
+ reject(new Error(`Request failed with status code ${res.statusCode}`));
230
+ }
231
+ });
232
+ });
233
+
234
+ req.on('error', (err) => {
235
+ reject(err);
236
+ });
237
+
238
+ if (options.body) {
239
+ req.write(options.body);
240
+ }
241
+
242
+ req.end();
243
+ });
244
+ }
245
+
246
+ /**
247
+ * 执行命令
248
+ */
249
+ function executeCommand(command, cwd) {
250
+ return new Promise((resolve, reject) => {
251
+ exec(command, { cwd, maxBuffer: 10 * 1024 * 1024 }, (error, stdout, stderr) => {
252
+ if (error) {
253
+ reject(error);
254
+ } else {
255
+ resolve({ stdout, stderr });
256
+ }
257
+ });
258
+ });
259
+ }
260
+
261
+ /**
262
+ * 搜索技能(从 getskill.work API)
263
+ * @param {string} keyword - 搜索关键词
264
+ * @returns {Promise<Array>} 技能列表(包含 git 地址)
265
+ */
266
+ async function searchSkills(keyword) {
267
+ const url = `https://getskill.work/api/skills/search?q=${encodeURIComponent(keyword)}`;
268
+
269
+ try {
270
+ const response = await request(url);
271
+ const data = JSON.parse(response.body);
272
+ // 返回格式: [{ name, description, git_url, author, ... }]
273
+ return data.skills || [];
274
+ } catch (error) {
275
+ console.error('搜索技能失败:', error.message);
276
+ throw error;
277
+ }
278
+ }
279
+
280
+ /**
281
+ * 获取技能详情(包含 git 地址)
282
+ * @param {string} skillId - 技能ID
283
+ * @returns {Promise<Object>} 技能详情
284
+ */
285
+ async function getSkillDetail(skillId) {
286
+ const url = `https://getskill.work/api/skills/${skillId}`;
287
+
288
+ try {
289
+ const response = await request(url);
290
+ const data = JSON.parse(response.body);
291
+ // 返回格式: { name, description, git_url, files, ... }
292
+ return data;
293
+ } catch (error) {
294
+ console.error('获取技能详情失败:', error.message);
295
+ throw error;
296
+ }
297
+ }
298
+
299
+ /**
300
+ * 获取技能仓库缓存目录
301
+ */
302
+ function getSkillsCacheDirectory() {
303
+ const homeDir = os.homedir();
304
+ return path.join(homeDir, '.claude', 'skills-cache');
305
+ }
306
+
307
+ /**
308
+ * 克隆或更新 Git 仓库
309
+ * @param {string} gitUrl - Git 仓库地址
310
+ * @param {string} skillName - 技能名称
311
+ * @returns {Promise<string>} 本地仓库路径
312
+ */
313
+ async function cloneOrUpdateRepo(gitUrl, skillName) {
314
+ // 首先检查并确保 Git 已安装
315
+ await ensureGitInstalled();
316
+
317
+ const cacheDir = getSkillsCacheDirectory();
318
+ ensureDirectoryExists(cacheDir);
319
+
320
+ const repoPath = path.join(cacheDir, skillName);
321
+
322
+ if (fs.existsSync(repoPath)) {
323
+ // 仓库已存在,执行 git pull
324
+ console.log(`更新仓库: ${skillName}...`);
325
+ try {
326
+ await executeCommand('git pull', repoPath);
327
+ console.log(`仓库更新成功: ${repoPath}`);
328
+ } catch (error) {
329
+ console.error(`更新失败: ${error.message}`);
330
+ throw error;
331
+ }
332
+ } else {
333
+ // 克隆新仓库
334
+ console.log(`克隆仓库: ${gitUrl}...`);
335
+ try {
336
+ await executeCommand(`git clone "${gitUrl}" "${skillName}"`, cacheDir);
337
+ console.log(`仓库克隆成功: ${repoPath}`);
338
+ } catch (error) {
339
+ console.error(`克隆失败: ${error.message}`);
340
+ throw error;
341
+ }
342
+ }
343
+
344
+ return repoPath;
345
+ }
346
+
347
+ /**
348
+ * 从仓库复制技能文件到 skills 目录
349
+ * @param {string} repoPath - 仓库路径
350
+ * @param {string} skillName - 技能名称
351
+ */
352
+ function copySkillFiles(repoPath) {
353
+ const skillsDir = getSkillsDirectory();
354
+ ensureDirectoryExists(skillsDir);
355
+
356
+ // 查找仓库中的 .md 文件
357
+ const files = fs.readdirSync(repoPath);
358
+ const mdFiles = files.filter(file =>
359
+ file.endsWith('.md') &&
360
+ !file.toLowerCase().startsWith('readme')
361
+ );
362
+
363
+ if (mdFiles.length === 0) {
364
+ throw new Error(`在仓库中未找到技能 .md 文件`);
365
+ }
366
+
367
+ const copiedFiles = [];
368
+ mdFiles.forEach(file => {
369
+ const sourcePath = path.join(repoPath, file);
370
+ const targetPath = path.join(skillsDir, file);
371
+
372
+ fs.copyFileSync(sourcePath, targetPath);
373
+ console.log(`已复制: ${file} -> ${targetPath}`);
374
+ copiedFiles.push(targetPath);
375
+ });
376
+
377
+ return copiedFiles;
378
+ }
379
+
380
+ /**
381
+ * 下载技能(通过 Git)
382
+ * @param {string} skillIdOrName - 技能ID或名称
383
+ */
384
+ async function downloadSkill(skillIdOrName) {
385
+ try {
386
+ console.log(`获取技能信息: ${skillIdOrName}...`);
387
+ const skillDetail = await getSkillDetail(skillIdOrName);
388
+
389
+ if (!skillDetail.git_url) {
390
+ throw new Error('技能信息中未包含 git_url');
391
+ }
392
+
393
+ const skillName = skillDetail.name || skillIdOrName;
394
+ const repoPath = await cloneOrUpdateRepo(skillDetail.git_url, skillName);
395
+ const copiedFiles = copySkillFiles(repoPath);
396
+
397
+ return {
398
+ skillName,
399
+ repoPath,
400
+ files: copiedFiles
401
+ };
402
+ } catch (error) {
403
+ console.error(`下载技能失败: ${error.message}`);
404
+ throw error;
405
+ }
406
+ }
407
+
408
+ /**
409
+ * 更新技能(通过 Git)
410
+ * @param {string} skillName - 技能名称
411
+ */
412
+ async function updateSkill(skillName) {
413
+ try {
414
+ console.log(`正在更新技能: ${skillName}...`);
415
+
416
+ const cacheDir = getSkillsCacheDirectory();
417
+ const repoPath = path.join(cacheDir, skillName);
418
+
419
+ if (!fs.existsSync(repoPath)) {
420
+ console.log(`技能仓库不存在,将重新下载...`);
421
+ return await downloadSkill(skillName);
422
+ }
423
+
424
+ // 执行 git pull
425
+ await executeCommand('git pull', repoPath);
426
+ console.log(`Git 仓库已更新`);
427
+
428
+ // 复制文件到 skills 目录
429
+ const copiedFiles = copySkillFiles(repoPath);
430
+
431
+ console.log(`技能 ${skillName} 更新成功!`);
432
+ return {
433
+ skillName,
434
+ repoPath,
435
+ files: copiedFiles
436
+ };
437
+ } catch (error) {
438
+ console.error(`更新技能 ${skillName} 失败:`, error.message);
439
+ throw error;
440
+ }
441
+ }
442
+
443
+ /**
444
+ * 列出本地已安装的技能
445
+ */
446
+ function listLocalSkills() {
447
+ const skillsDir = getSkillsDirectory();
448
+
449
+ if (!fs.existsSync(skillsDir)) {
450
+ console.log('技能目录不存在');
451
+ return [];
452
+ }
453
+
454
+ const files = fs.readdirSync(skillsDir);
455
+ const skillFiles = files.filter(file => file.endsWith('.md'));
456
+
457
+ return skillFiles;
458
+ }
459
+
460
+ /**
461
+ * 命令行接口
462
+ */
463
+ async function cli() {
464
+ const args = process.argv.slice(2);
465
+ const command = args[0];
466
+
467
+ try {
468
+ switch (command) {
469
+ case 'search':
470
+ if (!args[1]) {
471
+ console.error('请提供搜索关键词');
472
+ console.log('用法: getskill search <关键词>');
473
+ process.exit(1);
474
+ }
475
+ const results = await searchSkills(args[1]);
476
+ console.log(`找到 ${results.length} 个技能:\n`);
477
+ results.forEach((skill, index) => {
478
+ console.log(`${index + 1}. ${skill.name}`);
479
+ if (skill.description) {
480
+ console.log(` 描述: ${skill.description}`);
481
+ }
482
+ if (skill.git_url) {
483
+ console.log(` Git: ${skill.git_url}`);
484
+ }
485
+ if (skill.author) {
486
+ console.log(` 作者: ${skill.author}`);
487
+ }
488
+ console.log('');
489
+ });
490
+ break;
491
+
492
+ case 'install':
493
+ case 'get':
494
+ case 'download':
495
+ if (!args[1]) {
496
+ console.error('请提供技能ID或名称');
497
+ console.log('用法: getskill install <技能名称>');
498
+ process.exit(1);
499
+ }
500
+ const result = await downloadSkill(args[1]);
501
+ console.log(`\n技能已安装到 skills 目录:`);
502
+ result.files.forEach(file => console.log(` - ${file}`));
503
+ console.log(`\nGit 仓库缓存: ${result.repoPath}`);
504
+ break;
505
+
506
+ case 'update':
507
+ if (!args[1]) {
508
+ console.error('请提供技能名称');
509
+ console.log('用法: getskill update <技能名称>');
510
+ process.exit(1);
511
+ }
512
+ const updateResult = await updateSkill(args[1]);
513
+ console.log(`\n技能已更新到 skills 目录:`);
514
+ updateResult.files.forEach(file => console.log(` - ${file}`));
515
+ break;
516
+
517
+ case 'list':
518
+ const skills = listLocalSkills();
519
+ console.log(`本地已安装的技能 (${skills.length}):`);
520
+ skills.forEach((skill, index) => {
521
+ console.log(`${index + 1}. ${skill}`);
522
+ });
523
+ break;
524
+
525
+ case 'path':
526
+ console.log(`技能目录: ${getSkillsDirectory()}`);
527
+ console.log(`缓存目录: ${getSkillsCacheDirectory()}`);
528
+ break;
529
+
530
+ case 'clean':
531
+ const cacheDir = getSkillsCacheDirectory();
532
+ if (fs.existsSync(cacheDir)) {
533
+ fs.rmSync(cacheDir, { recursive: true, force: true });
534
+ console.log(`已清理缓存目录: ${cacheDir}`);
535
+ } else {
536
+ console.log('缓存目录不存在');
537
+ }
538
+ break;
539
+
540
+ default:
541
+ console.log('GetSkill - OpenClaw 技能管理工具');
542
+ console.log('');
543
+ console.log('用法:');
544
+ console.log(' getskill search <关键词> - 从 getskill.work 搜索技能');
545
+ console.log(' getskill install <技能名称> - 通过 git clone 安装技能');
546
+ console.log(' getskill update <技能名称> - 通过 git pull 更新技能');
547
+ console.log(' getskill list - 列出本地技能');
548
+ console.log(' getskill path - 显示目录路径');
549
+ console.log(' getskill clean - 清理 git 缓存');
550
+ console.log('');
551
+ console.log(`技能目录: ${getSkillsDirectory()}`);
552
+ console.log(`缓存目录: ${getSkillsCacheDirectory()}`);
553
+ }
554
+ } catch (error) {
555
+ console.error('执行命令时出错:', error.message);
556
+ process.exit(1);
557
+ }
558
+ }
559
+
560
+ // 导出模块函数
561
+ module.exports = {
562
+ searchSkills,
563
+ getSkillDetail,
564
+ downloadSkill,
565
+ updateSkill,
566
+ listLocalSkills,
567
+ getSkillsDirectory,
568
+ getSkillsCacheDirectory,
569
+ cloneOrUpdateRepo,
570
+ copySkillFiles,
571
+ checkGitInstalled,
572
+ ensureGitInstalled
573
+ };
574
+
575
+ // 如果直接运行此文件,执行 CLI
576
+ if (require.main === module) {
577
+ cli();
578
+ }
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@workskills/getskill",
3
+ "version": "1.0.0",
4
+ "description": "Search, install, and update OpenClaw skills from getskill.work with automatic Git integration",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "getskill": "./index.js"
8
+ },
9
+ "scripts": {
10
+ "test": "node verify.js",
11
+ "verify": "node verify.js",
12
+ "start": "node index.js",
13
+ "prepublishOnly": "npm run verify"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/workskills/getskill.git"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/workskills/getskill/issues"
21
+ },
22
+ "homepage": "https://github.com/workskills/getskill#readme",
23
+ "keywords": [
24
+ "openclaw",
25
+ "workskills",
26
+ "skill",
27
+ "skills",
28
+ "search",
29
+ "install",
30
+ "update",
31
+ "git",
32
+ "cli",
33
+ "claude",
34
+ "ai",
35
+ "automation"
36
+ ],
37
+ "author": {
38
+ "name": "workskills.store",
39
+ "url": "https://workskills.store"
40
+ },
41
+ "license": "MIT",
42
+ "engines": {
43
+ "node": ">=12.0.0"
44
+ },
45
+ "os": [
46
+ "darwin",
47
+ "linux",
48
+ "win32"
49
+ ],
50
+ "files": [
51
+ "index.js",
52
+ "README.md",
53
+ "EXAMPLES.md",
54
+ "LICENSE"
55
+ ],
56
+ "dependencies": {},
57
+ "devDependencies": {}
58
+ }