harveyz-skill 0.7.0 → 0.8.1
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/CHANGELOG.md +11 -0
- package/package.json +2 -1
- package/skills/meta/contribute-skill/SKILL.md +301 -0
- package/skills-index.json +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.1] - 2026-05-24
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- `contribute-skill`:SKILL.md description 字段内含 ASCII 双引号导致 YAML 解析失败
|
|
14
|
+
|
|
15
|
+
## [0.8.0] - 2026-05-24
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- `contribute-skill`(`meta` bundle):在其他项目中将本地 skill 目录贡献到 harveyz-skill 仓库,自动完成 SKILL.md 格式规范化、skills-index.json 注册登记、双向目录同步、分支创建与 commit
|
|
19
|
+
- 新增 `meta` bundle,用于对 harveyz-skill 仓库本身的元操作
|
|
20
|
+
|
|
10
21
|
## [0.7.0] - 2026-05-24
|
|
11
22
|
|
|
12
23
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "harveyz-skill",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Skill manager for Claude Code, Cursor, and Codex",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"skills/writing/mermaid-diagram/",
|
|
32
32
|
"skills/design/sync-design-html/",
|
|
33
33
|
"skills/analysis/git-cleanup/",
|
|
34
|
+
"skills/meta/contribute-skill/",
|
|
34
35
|
"tools/p-launch/",
|
|
35
36
|
"hooks/check-similar-branch/"
|
|
36
37
|
],
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: contribute-skill
|
|
3
|
+
description: '将其他项目的 skill 目录贡献、导入、同步或注册到 harveyz-skill 仓库,自动完成 SKILL.md 格式规范化、skills-index.json 注册登记、双向目录同步。只要用户想把某个现有 skill 添加、贡献、推送、迁移、导入、加进或同步到 harvey-skill 或 harveyz-skill,都应触发此技能。注意:方向是从其他项目流向 harveyz-skill;安装或复制 harvey-skill 中已有的 skill 到本地项目不触发此技能。'
|
|
4
|
+
user_invocable: true
|
|
5
|
+
version: "1.0.0"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# contribute-skill
|
|
9
|
+
|
|
10
|
+
将当前项目的某个 skill 目录贡献进 `harveyz-skill` 仓库,完成格式规范化、注册登记、双向同步的完整流程。
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 执行协议(9 步)
|
|
15
|
+
|
|
16
|
+
### Step 1 — 识别源 skill 目录
|
|
17
|
+
|
|
18
|
+
按优先级识别要贡献的 skill:
|
|
19
|
+
|
|
20
|
+
1. **上下文推断**:从对话中当前提到的 skill 名、文件路径、`SKILL.md` 内容直接推断
|
|
21
|
+
2. **用户显式指定**:用户明确说明路径或名称
|
|
22
|
+
3. **扫描列出**:若上下文不明确,执行以下命令并列出候选供用户选择:
|
|
23
|
+
```bash
|
|
24
|
+
# 先确定源项目根目录
|
|
25
|
+
SOURCE_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
26
|
+
ls "${SOURCE_ROOT}/.claude/skills/"
|
|
27
|
+
```
|
|
28
|
+
若 `.claude/skills/` 目录不存在,提示用户:「当前项目下未找到 .claude/skills/ 目录,请手动输入要贡献的 skill 路径。」
|
|
29
|
+
|
|
30
|
+
验证:确认该目录存在且包含 `SKILL.md`,否则停止并报错。
|
|
31
|
+
|
|
32
|
+
将 `$SOURCE_ROOT` 记为 `<源项目根目录>`,后续所有步骤中的 `<当前项目路径>` 均指此路径。
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
### Step 2 — 定位 harveyz-skill 仓库
|
|
37
|
+
|
|
38
|
+
**配置缓存路径:** `~/.claude/skills/contribute-skill/.config`
|
|
39
|
+
|
|
40
|
+
格式:
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"harveyzSkillPath": "/absolute/path/to/harveyz-skill"
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**查找逻辑(按优先级):**
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
1. 读取 ~/.claude/skills/contribute-skill/.config
|
|
51
|
+
└── 若存在:
|
|
52
|
+
├── 且 <path>/skills-index.json 存在 → 直接使用,跳过后续步骤
|
|
53
|
+
└── 且路径无效(skills-index.json 不存在)→ 删除 .config,继续步骤 2
|
|
54
|
+
|
|
55
|
+
2. 尝试默认路径:~/Projects/harveyz-skill
|
|
56
|
+
└── 若 ~/Projects/harveyz-skill/skills-index.json 存在 → 使用此路径
|
|
57
|
+
|
|
58
|
+
3. 搜索:
|
|
59
|
+
find ~ -name "skills-index.json" -path "*/harveyz-skill/*" -maxdepth 6 2>/dev/null | head -1
|
|
60
|
+
└── 若找到 → 取其父目录
|
|
61
|
+
|
|
62
|
+
4. 以上均失败 → 询问用户手动输入路径
|
|
63
|
+
|
|
64
|
+
找到后:写入 ~/.claude/skills/contribute-skill/.config,后续调用直接读取
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
### Step 3 — 确定目标名称
|
|
70
|
+
|
|
71
|
+
1. 读取源 `SKILL.md` frontmatter 中的 `name:` 字段
|
|
72
|
+
2. 展示给用户确认:
|
|
73
|
+
```
|
|
74
|
+
目标目录名:<name>
|
|
75
|
+
确认使用此名称?(回车确认 / 输入新名称)
|
|
76
|
+
```
|
|
77
|
+
3. 目标路径将为:`<harveyzSkillPath>/skills/<bundle-category>/<name>/`(category 在 Step 4 确定)
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
### Step 4 — 交互选 bundle
|
|
82
|
+
|
|
83
|
+
读取 harveyz-skill 的 `skills-index.json`,列出 `bundleMeta` 中所有现有 bundle(以实际内容为准):
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
现有 bundle:
|
|
87
|
+
1. <bundle-name> — <bundle-description>
|
|
88
|
+
2. <bundle-name> — <bundle-description>
|
|
89
|
+
... (动态读取,不要使用硬编码列表)
|
|
90
|
+
N. [新建 bundle]
|
|
91
|
+
|
|
92
|
+
请选择目标 bundle(输入编号):
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
若用户选择新建 bundle:
|
|
96
|
+
```
|
|
97
|
+
请输入新 bundle 名称(英文,如 deploy):
|
|
98
|
+
请输入 bundle 描述(如 部署工具):
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
选定 bundle 后,明确展示并让用户确认目标子目录名:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
目标子目录名(skills/ 下的一级目录):<bundle 名>
|
|
105
|
+
确认使用此名称作为目录名?(回车确认 / 输入新名称,如 superpowers-fork)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
目录名确认后,将 `<bundle-category>` 定为该值,用于构建目标路径 `skills/<bundle-category>/<name>/`。注意目录名与 bundle 名可以不同(如目录名 `superpowers-fork` 对应 bundle `brainstorming`)。
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
### Step 5 — 确认摘要
|
|
113
|
+
|
|
114
|
+
展示完整操作预览,**等待用户明确确认后再执行**:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
即将执行以下操作:
|
|
118
|
+
|
|
119
|
+
[复制]
|
|
120
|
+
源:<当前项目路径>/.claude/skills/<name>/
|
|
121
|
+
(列出目录中所有文件)
|
|
122
|
+
目标:<harveyzSkillPath>/skills/<bundle-category>/<name>/
|
|
123
|
+
|
|
124
|
+
[注册]
|
|
125
|
+
skills-index.json 新增:{"path": "<bundle-category>/<name>", "bundle": "<bundle>"}
|
|
126
|
+
(若新建 bundle)bundleMeta 新增:{"<bundle>": "<description>"}
|
|
127
|
+
|
|
128
|
+
[同步回源]
|
|
129
|
+
格式化后完整目录 → <当前项目路径>/.claude/skills/<name>/
|
|
130
|
+
|
|
131
|
+
确认继续?(y/n)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
用户输入 `n` 则中止,不做任何修改。
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
### Step 6a — 格式规范化
|
|
139
|
+
|
|
140
|
+
读取源 `SKILL.md`,对照 harveyz-skill 规范检查并修复:
|
|
141
|
+
|
|
142
|
+
**必检字段:**
|
|
143
|
+
|
|
144
|
+
| 字段 | 规范 | 缺失时处理 |
|
|
145
|
+
|------|------|-----------|
|
|
146
|
+
| `name` | 必须存在,值与目录名一致 | 自动补填目录名,无需确认 |
|
|
147
|
+
| `description` | 必须含触发短语,2-3 句 | 根据 skill 内容补写;展示 diff 让用户确认 |
|
|
148
|
+
| `version` | semver 格式,如 `"1.0.0"` | 自动补填 `"1.0.0"`,无需确认 |
|
|
149
|
+
| `user_invocable` | 显式声明 `true` 或 `false` | 自动补填 `true`,无需确认 |
|
|
150
|
+
| frontmatter 包裹 | 标准 `---` YAML 块 | 自动修正格式,无需确认 |
|
|
151
|
+
|
|
152
|
+
**修复策略:**
|
|
153
|
+
- 可自动确定的字段(`name`、`version`、`user_invocable`、frontmatter 格式):直接修复,无需用户确认
|
|
154
|
+
- 涉及内容重写的字段(`description`):以 diff 形式展示修改前后,等用户确认后再应用
|
|
155
|
+
|
|
156
|
+
**若 `SKILL.md` 格式严重损坏**(无法解析 frontmatter):停止执行,报告具体问题,让用户手动修复后重试。
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
### Step 6b — 执行复制与注册
|
|
161
|
+
|
|
162
|
+
按序执行以下操作:
|
|
163
|
+
|
|
164
|
+
**1. 复制 skill 目录**
|
|
165
|
+
```bash
|
|
166
|
+
# 将源目录完整复制为目标路径
|
|
167
|
+
cp -r <源目录>/ <harveyzSkillPath>/skills/<bundle-category>/<name>/
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**2. 用格式化后的 SKILL.md 覆盖目标目录中的 SKILL.md**
|
|
171
|
+
(将 Step 6a 规范化后的内容写入目标路径)
|
|
172
|
+
|
|
173
|
+
**3. 更新 `<harveyzSkillPath>/skills-index.json`**
|
|
174
|
+
|
|
175
|
+
在 `skills[]` 数组末尾新增:
|
|
176
|
+
```json
|
|
177
|
+
{ "path": "<bundle-category>/<name>", "bundle": "<bundle>" }
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
若新建 bundle,在 `bundleMeta` 中新增:
|
|
181
|
+
```json
|
|
182
|
+
"<bundle>": "<用户输入的描述>"
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**4. 运行生成脚本**
|
|
186
|
+
```bash
|
|
187
|
+
cd <harveyzSkillPath> && node scripts/generate-npmignore.js
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
> `generate-npmignore.js` 会更新 `package.json` 的 `files[]` 字段和 `.npmignore`,将新注册的 skill 路径加入分发列表。
|
|
191
|
+
|
|
192
|
+
若脚本执行失败:报告错误,**不执行 git commit**,保留已复制文件供用户检查。
|
|
193
|
+
|
|
194
|
+
**边界情况:目标路径已存在同名 skill**
|
|
195
|
+
```
|
|
196
|
+
目标路径已存在:skills/<bundle-category>/<name>/
|
|
197
|
+
选择操作:
|
|
198
|
+
1. 覆盖(替换已有 skill)
|
|
199
|
+
2. 重命名(输入新目录名)
|
|
200
|
+
3. 中止
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
### Step 7 — 同步回源仓库
|
|
206
|
+
|
|
207
|
+
将 harveyz-skill 中目标 skill 目录的**完整内容**同步回源项目:
|
|
208
|
+
|
|
209
|
+
**前置检查:若源目录有未提交变更,先提示用户确认**
|
|
210
|
+
```bash
|
|
211
|
+
cd <源项目根目录>
|
|
212
|
+
git status --short .claude/skills/<name>/
|
|
213
|
+
```
|
|
214
|
+
若有未提交修改,提示:「源目录有未提交的修改,同步将覆盖这些改动,是否继续?(y/n)」。用户拒绝则跳过 Step 7。
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
# 检测差异
|
|
218
|
+
diff -rq <harveyzSkillPath>/skills/<bundle-category>/<name>/ <源项目根目录>/.claude/skills/<name>/
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
- **若无差异**:跳过,不产生 commit,提示用户"源目录内容已是最新,无需同步"
|
|
222
|
+
- **若有差异**:
|
|
223
|
+
```bash
|
|
224
|
+
# 复制目录内容(不含目录本身)到源目录,覆盖同名文件
|
|
225
|
+
cp -r <harveyzSkillPath>/skills/<bundle-category>/<name>/. <源项目根目录>/.claude/skills/<name>/
|
|
226
|
+
```
|
|
227
|
+
然后在**源项目**当前分支执行:
|
|
228
|
+
```bash
|
|
229
|
+
cd <源项目根目录>
|
|
230
|
+
git add .claude/skills/<name>/
|
|
231
|
+
git commit -m "chore: sync skill format from harveyz-skill"
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**边界情况:源项目无 git 仓库**
|
|
235
|
+
跳过 commit 步骤,仅提示用户"文件已同步,但源项目不是 git 仓库,请手动提交"。
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
### Step 8 — 在 harveyz-skill 创建分支并 commit
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
cd <harveyzSkillPath>
|
|
243
|
+
|
|
244
|
+
# 创建 feature 分支(处理分支已存在的情况)
|
|
245
|
+
if git show-ref --quiet refs/heads/feature/contribute-<name>; then
|
|
246
|
+
echo "分支 feature/contribute-<name> 已存在,是否切换到该分支继续?(y/n)"
|
|
247
|
+
# 若用户确认 → git checkout feature/contribute-<name>
|
|
248
|
+
# 若用户拒绝 → 中止操作
|
|
249
|
+
else
|
|
250
|
+
git checkout -b feature/contribute-<name>
|
|
251
|
+
fi
|
|
252
|
+
|
|
253
|
+
# 暂存所有变更
|
|
254
|
+
git add skills/<bundle-category>/<name>/
|
|
255
|
+
git add skills-index.json
|
|
256
|
+
git add package.json
|
|
257
|
+
git add .npmignore
|
|
258
|
+
|
|
259
|
+
# 提交
|
|
260
|
+
git commit -m "feat: contribute <name> from <source-project-name>"
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
### Step 9 — 报告
|
|
266
|
+
|
|
267
|
+
输出两个仓库的操作摘要:
|
|
268
|
+
|
|
269
|
+
```
|
|
270
|
+
✓ harveyz-skill
|
|
271
|
+
- 新增 skill:skills/<bundle-category>/<name>/
|
|
272
|
+
- 已注册到 bundle:<bundle>
|
|
273
|
+
- 分支:feature/contribute-<name>
|
|
274
|
+
- 下一步:git push origin feature/contribute-<name>,然后创建 PR → staging
|
|
275
|
+
|
|
276
|
+
✓ 源项目(<project-name>)
|
|
277
|
+
- 已同步格式化内容:.claude/skills/<name>/
|
|
278
|
+
- commit:chore: sync skill format from harveyz-skill
|
|
279
|
+
(或:无变化,跳过 commit)
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## 边界情况汇总
|
|
285
|
+
|
|
286
|
+
| 情况 | 处理 |
|
|
287
|
+
|------|------|
|
|
288
|
+
| 目标路径已存在同名 skill | 询问覆盖 / 重命名 / 中止 |
|
|
289
|
+
| 源 SKILL.md 格式严重损坏 | 停止,报告问题,等用户修复后重试 |
|
|
290
|
+
| `generate-npmignore.js` 失败 | 报告错误,不 commit,保留文件 |
|
|
291
|
+
| `.config` 路径失效 | 清除 .config,重新触发路径查找 |
|
|
292
|
+
| 源项目无 git 仓库 | 跳过源项目 commit,提示用户手动处理 |
|
|
293
|
+
| 源目录与目标同步后无差异 | 跳过 Step 7 的 commit |
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## 不在范围内
|
|
298
|
+
|
|
299
|
+
- 批量贡献多个 skill(每次只处理一个)
|
|
300
|
+
- 自动 push 或创建 PR(用户手动决定)
|
|
301
|
+
- 删除或更新已贡献的 skill
|
package/skills-index.json
CHANGED
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"task": "任务管理(pm-task-dispatch + task-close)",
|
|
15
15
|
"web-fetch": "网页抓取工具(article-fetcher)",
|
|
16
16
|
"writing": "写作工具(mermaid-diagram)",
|
|
17
|
-
"design": "设计同步工具(sync-design-html)"
|
|
17
|
+
"design": "设计同步工具(sync-design-html)",
|
|
18
|
+
"meta": "元操作工具(对 harveyz-skill 仓库本身的管理)"
|
|
18
19
|
},
|
|
19
20
|
"skills": [
|
|
20
21
|
{ "path": "analysis/skill-analyzer", "bundle": "analysis" },
|
|
@@ -31,7 +32,8 @@
|
|
|
31
32
|
{ "path": "web-fetch/article-fetcher", "bundle": "web-fetch" },
|
|
32
33
|
{ "path": "writing/mermaid-diagram", "bundle": "writing" },
|
|
33
34
|
{ "path": "design/sync-design-html", "bundle": "design" },
|
|
34
|
-
{ "path": "analysis/git-cleanup", "bundle": "analysis" }
|
|
35
|
+
{ "path": "analysis/git-cleanup", "bundle": "analysis" },
|
|
36
|
+
{ "path": "meta/contribute-skill", "bundle": "meta" }
|
|
35
37
|
],
|
|
36
38
|
"hooks": [
|
|
37
39
|
{
|