skill-flow 1.0.2 → 1.0.4

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 (57) hide show
  1. package/README.md +62 -23
  2. package/README.zh.md +63 -25
  3. package/dist/cli.js +13 -39
  4. package/dist/cli.js.map +1 -1
  5. package/dist/domain/types.d.ts +12 -1
  6. package/dist/services/doctor-service.js +1 -1
  7. package/dist/services/doctor-service.js.map +1 -1
  8. package/dist/services/skill-flow.d.ts +16 -13
  9. package/dist/services/skill-flow.js +158 -5
  10. package/dist/services/skill-flow.js.map +1 -1
  11. package/dist/services/source-service.d.ts +11 -1
  12. package/dist/services/source-service.js +60 -18
  13. package/dist/services/source-service.js.map +1 -1
  14. package/dist/services/workflow-service.d.ts +2 -2
  15. package/dist/services/workflow-service.js +17 -4
  16. package/dist/services/workflow-service.js.map +1 -1
  17. package/dist/services/workspace-bootstrap-service.d.ts +25 -0
  18. package/dist/services/workspace-bootstrap-service.js +148 -0
  19. package/dist/services/workspace-bootstrap-service.js.map +1 -0
  20. package/dist/state/store.js +1 -0
  21. package/dist/state/store.js.map +1 -1
  22. package/dist/tests/skill-flow.test.js +1458 -0
  23. package/dist/tests/skill-flow.test.js.map +1 -1
  24. package/dist/tui/config-app.d.ts +3 -0
  25. package/dist/tui/config-app.js +61 -1
  26. package/dist/tui/config-app.js.map +1 -1
  27. package/dist/tui/find-app.d.ts +1 -1
  28. package/dist/tui/find-app.js +36 -4
  29. package/dist/tui/find-app.js.map +1 -1
  30. package/dist/utils/format.js +1 -1
  31. package/dist/utils/format.js.map +1 -1
  32. package/dist/utils/naming.d.ts +1 -0
  33. package/dist/utils/naming.js +7 -1
  34. package/dist/utils/naming.js.map +1 -1
  35. package/dist/utils/source-id.js +4 -0
  36. package/dist/utils/source-id.js.map +1 -1
  37. package/package.json +10 -1
  38. package/.gstack/browse-network.log +0 -1
  39. package/.gstack/browse.json +0 -7
  40. package/.gstack/qa-reports/base-branch.txt +0 -1
  41. package/.gstack/qa-reports/qa-report-skill-flow-cli-2026-03-22.md +0 -159
  42. package/.gstack/qa-reports/qa-report-skill-manager-2026-03-22.md +0 -60
  43. package/docs/DESIGN.md +0 -407
  44. package/docs/PRD/PRD-1.0.0.md +0 -1862
  45. package/docs/PRD/renew/PRD-0.0.0.md +0 -26
  46. package/docs/PRD/renew/PRD-0.0.1.md +0 -408
  47. package/docs/PRD/renew/PRD-0.0.2.md +0 -705
  48. package/docs/PRD/renew/PRD-0.0.3.md +0 -740
  49. package/docs/PRD/renew/PRD-0.0.4.md +0 -1494
  50. package/docs/README.md +0 -242
  51. package/docs/plan/PLAN_v1.0.0.md +0 -663
  52. package/docs/plan/PLAN_v1.0.1.md +0 -845
  53. package/docs/refrences/README.md +0 -9
  54. package/docs/refrences/agent-skill-paths.md +0 -274
  55. package/docs/refrences/config-state-reconciliation.md +0 -199
  56. package/docs/refrences/naming-dedupe-warning-rules.md +0 -482
  57. package/img/img-1.jpg +0 -0
@@ -1,1862 +0,0 @@
1
- # skill-flow PRD + 工程实施文档(Discovery / Find Skills 修订版)
2
-
3
- > 版本:v1.2
4
- > 文档性质:定型版 PRD + 工程实施规范
5
- > 产出方式:基于 Martin Fowler / Isaac Z. Schlueter / Mitchell Hashimoto 三人视角多轮讨论后收敛
6
- > 平台:macOS(MVP)
7
- > 启动命令:`skill-flow`
8
- > 数据目录:`~/.skillflow/`
9
-
10
- ---
11
-
12
- # 一、三人多轮讨论纪要
13
-
14
- ## 第一轮:先定边界,这到底是不是“包管理器”?
15
-
16
- ### Martin Fowler
17
- “它不是一个下载器。下载只是入口。真正的产品边界应该是:`Source → SkillLeaf → Channel → Deployment`。只要这个边界不清,后面 `config`、`update`、`uninstall` 都会混成文件搬运。”
18
-
19
- ### Isaac Z. Schlueter
20
- “如果没有锁定层,它就不是 manager,只是 installer。你一旦要支持多来源、多技能仓库、多渠道分发,就必须记录用户意图和解析结果,否则更新、回滚、恢复安装都不可靠。”
21
-
22
- ### Mitchell Hashimoto
23
- “CLI 不是把能力堆成命令。真正的主流程只有一个:`add source -> inspect inventory -> choose channels -> apply deployments`。用户不该理解内部状态文件,但状态文件必须非常强。”
24
-
25
- ### 本轮结论
26
-
27
- 1. 产品正式定义为:**一个面向 Agent Skills 生态的 CLI 包管理器与渠道投影器**。
28
- 2. 系统边界只负责:**获取、扫描、校验、索引、锁定、分发、更新、卸载、诊断**。
29
- 3. 系统明确**不负责执行 skill**,也不对 skill 脚本做运行时沙箱承诺。
30
- 4. 数据模型固定为:`Source / SourceSnapshot / SkillLeaf / Channel / Deployment / Manifest / Lock`。
31
-
32
- ---
33
-
34
- ## 第二轮:Source 怎么建模,仓库和 skill 的关系是什么?
35
-
36
- ### Martin Fowler
37
- “仓库不是 skill。仓库是 source root,skill 才是 leaf。否则你没法表达一个仓库里多个技能,也没法做你要的一级/二级树选择。”
38
-
39
- ### Isaac Z. Schlueter
40
- “更新也必须以 source 为单位,而不是 skill 为单位。因为上游版本边界属于 source。你可以按 skill 选择是否部署,但不能按 skill 伪造上游版本。”
41
-
42
- ### Mitchell Hashimoto
43
- “UI 上可以把 source 展示成一级目录,把 skill 展示成二级节点;但内部一定要有稳定的 `sourceId` 和 `skillId`,不能依赖展示名。”
44
-
45
- ### 本轮结论
46
-
47
- 1. **Source 是上游单位**:Git 仓库、ClawHub slug、未来的 well-known URL。
48
- 2. **SkillLeaf 是可安装单位**:一个合法 skill root。
49
- 3. **Source 与 SkillLeaf 是一对多关系**。
50
- 4. “两层结构”正式进入领域模型,而不是只作为 UI 细节。
51
- 5. internal id 与 display label 分离:
52
- - internal:稳定、不可读也没关系
53
- - display:仓库名 / 作者名 / `single`
54
-
55
- ---
56
-
57
- ## 第三轮:Channel 不是路径字符串,而是适配器
58
-
59
- ### Martin Fowler
60
- “Channel 必须是 adapter,不是 path。因为 Claude、OpenCode、Codex、OpenClaw 的发现规则、优先级、兼容路径、以及对 symlink 的容忍度都不一样。”
61
-
62
- ### Isaac Z. Schlueter
63
- “同一个 leaf 投影到不同 channel,可以是不同 strategy。manager 的任务不是追求实现统一,而是追求状态统一。”
64
-
65
- ### Mitchell Hashimoto
66
- “用户界面里可以看到都是‘一个目标’,但产品内部必须知道:Claude 默认是 per-skill symlink,OpenClaw 默认要 copy。”
67
-
68
- ### 本轮结论
69
-
70
- 正式把 Channel 定义为:
71
-
72
- - 一个**目标目录解析器**
73
- - 一个**发现规则集合**
74
- - 一个**分发策略集合**
75
- - 一个**诊断器**
76
-
77
- 而不是一个简单路径。
78
-
79
- ---
80
-
81
- ## 第四轮:锁文件要不要做成“一等公民”?
82
-
83
- ### Isaac Z. Schlueter
84
- “必须,而且不是一个文件,而是两个层级:manifest 记录用户意图,lock 记录解析结果。否则用户选了哪些 channel、哪些 skill,是‘期望状态’;上游实际解析到的 commit/version/hash,是‘已解析状态’。这两个不能混。”
85
-
86
- ### Martin Fowler
87
- “同意。manifest 是 policy,lock 是 materialized view。”
88
-
89
- ### Mitchell Hashimoto
90
- “从 CLI 体验上,这意味着 `config` 改的是 manifest,`apply/update` 刷的是 lock。这样 `doctor` 才能告诉用户:你的意图没变,但当前部署漂移了。”
91
-
92
- ### 本轮结论
93
-
94
- MVP 固定采用双文件状态:
95
-
96
- - `manifest.json`:用户意图
97
- - `lock.json`:解析结果与部署状态
98
-
99
- ---
100
-
101
- ## 第五轮:MVP 里到底支持哪些 Source?
102
-
103
- ### Martin Fowler
104
- “从建模上要预留 `SourceAdapter`,但 MVP 不要把来源铺太大。”
105
-
106
- ### Isaac Z. Schlueter
107
- “Git 一定要是第一优先级,因为它天然有 snapshot。ClawHub 可以做第二优先级,因为它已经有 version/store/lock 语义。”
108
-
109
- ### Mitchell Hashimoto
110
- “`search` 的体验不能太弱,但 GitHub 关键词搜索的结果质量不一定稳定。MVP 里要区分:`add` 支持显式 locator,`search` 则优先做有结构化结果的来源。”
111
-
112
- ### 本轮结论
113
-
114
- MVP Source 范围定为:
115
-
116
- 1. **Git Source**
117
- - 必做
118
- - 支持 GitHub repo / 任意 git URL / 本地 git 路径
119
- 2. **ClawHub Source**
120
- - 必做
121
- - 作为注册表来源
122
- 3. **Well-known Skills Discovery**
123
- - 只预留接口,P1 再做
124
-
125
- ---
126
-
127
- ## 第六轮:分发策略拍板
128
-
129
- ### Martin Fowler
130
- “要遵循渠道现实,不要为了‘统一’牺牲兼容。”
131
-
132
- ### Isaac Z. Schlueter
133
- “中心化 canonical store 没问题,但投影策略必须 per-channel。”
134
-
135
- ### Mitchell Hashimoto
136
- “用户应该默认感知不到复杂性,所以策略要自动选,只在 `doctor` 和 advanced config 里解释。”
137
-
138
- ### 本轮结论
139
-
140
- - Claude Code:**per-skill symlink** 默认,copy 兜底
141
- - OpenCode:**symlink** 默认
142
- - Codex:**symlink** 默认
143
- - 通用 `.agents/skills`:**symlink** 默认
144
- - OpenClaw:**copy** 默认,不走跨根 symlink
145
-
146
- ---
147
-
148
- ## 第七轮:技术栈正式定型
149
-
150
- ### Mitchell Hashimoto
151
- “既然 `config` 是树状 TUI,终端 UI 就不是附属品,而是主界面。Ink 很合适。”
152
-
153
- ### Isaac Z. Schlueter
154
- “如果你选 Node,就选当前 LTS 主线,不要用已进入 maintenance 的版本。”
155
-
156
- ### Martin Fowler
157
- “技术栈要服务模型稳定和 schema 演进,所以 Zod、atomic writes、fixture-based tests 都该是正式要求,不是实现偏好。”
158
-
159
- ### 本轮结论
160
-
161
- 正式技术栈:
162
-
163
- - Runtime:**Node.js 24 LTS**
164
- - Language:**TypeScript 5.x**
165
- - Package manager:**pnpm**
166
- - CLI framework:**oclif**
167
- - TUI:**Ink**
168
- - Schema validation:**Zod**
169
- - Git wrapper:**system git + simple-git**
170
- - Test:**Vitest**
171
- - Distribution:**npm first,Homebrew tap in P1**
172
-
173
- ---
174
-
175
-
176
- ## 第八轮:`find skills` 不是附属命令,而是一条完整 Discovery 工作流
177
-
178
- ### Martin Fowler
179
- “你现在的文档把 install / update / deploy 写清楚了,但 discover / recommend 还不是一等能力。`search` 只是命令,不是领域流程。真正缺的是:搜索结果模型、来源分层、推荐依据、安装前解释、安装后反馈。”
180
-
181
- ### Isaac Z. Schlueter
182
- “只要做 discovery,就必须把 catalog、trust、installed state、install method 纳入状态模型。否则 `search` 出来的只是字符串,不是 package candidate。”
183
-
184
- ### Mitchell Hashimoto
185
- “用户真正的问题通常不是 ‘给我一个 repo URL’,而是 ‘我想做 X,有没有 skill 能解决?哪个值得信?我装过没有?能不能现在直接装?装完要不要刷新客户端?’ 所以 CLI 需要 `find -> inspect -> install/apply` 这条一等路径。”
186
-
187
- ### 本轮结论
188
-
189
- 1. `search` 正式升级为 **Discovery 工作流**,并新增主命令 `find`,`search` 保留为兼容别名。
190
- 2. Discovery 必须有自己的领域输出:`SkillCandidate`,而不是直接返回 source 文本。
191
- 3. PRD 必须补齐:
192
- - Discovery Goals / Non-Goals
193
- - Discovery Source Tiers
194
- - Search Result Schema & Ranking
195
- - Quick Install / Direct Install
196
- - Installed Annotations & Post-Install Feedback
197
- - Channel Feature Compatibility Matrix
198
- - Source Inventory Index
199
- 4. 产品正式从 **manager / installer / deployer** 扩展为 **finder / recommender / installer / deployer / manager**。
200
-
201
- # 二、skill-flow 定型版 PRD
202
-
203
- ## 1. 产品定义
204
-
205
- `skill-flow` 是一个面向 Agent Skills 生态的 macOS CLI。它既是统一的 Skills 包管理器,也是一个 Discovery / Find Skills 入口。它统一管理多来源 skills,把上游内容下载到 `~/.skillflow/source/`,扫描出合法的 `SkillLeaf`,在 `~/.skillflow/skills/` 建立 canonical skill 集合,再将用户选中的 skill 以适配渠道的方式分发到 Claude Code、OpenCode、Codex、OpenClaw 与通用 `.agents/skills`。其核心职责是**索引与投影**,不是执行 skill。
206
-
207
- ## 2. 目标与非目标
208
-
209
- ### 2.1 目标
210
-
211
- MVP 要完成六件事:
212
-
213
- 1. 支持 Git Source 与 ClawHub Source 的添加、扫描、更新、卸载。
214
- 2. 支持“单 source 多 skill”的两层树状模型。
215
- 3. 支持 `skill-flow config` 的树形多选 TUI。
216
- 4. 支持按 channel 投影:Claude Code、OpenCode、Codex、OpenClaw、`.agents/skills`。
217
- 5. 支持 `manifest.json + lock.json` 双层状态。
218
- 6. 支持 `doctor` 做冲突、漂移、路径和兼容性检查。
219
-
220
- ### 2.2 非目标
221
-
222
- MVP 不做以下事情:
223
-
224
- 1. 不执行 skill 中的脚本。
225
- 2. 不修改上游 `SKILL.md`。
226
- 3. 不做 GUI。
227
- 4. 不做通用 project-scope 管理;只有 OpenClaw 因官方工作区模型原因,保留 workspace 渠道。
228
-
229
-
230
- ### 2.3 Discovery 目标
231
-
232
- MVP 的 Discovery 能力要解决五件事:
233
-
234
- 1. 当用户只有“能力诉求”而没有具体来源时,帮助其找到可安装候选。
235
- 2. 区分“已安装 / 未安装 / 已内置 / 已预装”状态,避免重复推荐。
236
- 3. 把来源可信度、安装量、官方属性、支持渠道、风险提示纳入结果展示。
237
- 4. 支持从候选结果直接安装单个 skill 或整个 source。
238
- 5. 在安装完成后给出下一步动作:是否需要刷新、重启、重新扫描或执行 `config`。
239
-
240
- ### 2.4 Discovery 非目标
241
-
242
- MVP Discovery 不做以下事情:
243
-
244
- 1. 不做自然语言生成式推荐排名模型;先采用显式规则排序。
245
- 2. 不承诺全网搜索;优先覆盖结构化来源与本地 inventory。
246
- 3. 不把 commands / agents / plugins 全部纳入统一安装对象;MVP 只管理合法 `SKILL.md` skill。
247
- 4. 不把内部 inventory index 对外承诺为开放标准。
248
-
249
- ## 3. 用户与典型场景
250
-
251
- 目标用户是同时使用多个 AI coding agent 的开发者。他们的高频动作是:
252
-
253
- - 从 GitHub 或 ClawHub 获取 skills
254
- - 统一查看一个 source 里有哪些 skill
255
- - 把其中部分 skill 应用到某个或全部渠道
256
- - 后续更新 source,并同步刷新多个渠道
257
- - 卸载整个 source,或仅取消某个 channel 的启用状态
258
-
259
- ## 4. 领域模型
260
-
261
- ### 4.1 Source
262
-
263
- 一个可更新的上游单位。
264
-
265
- 字段建议:
266
-
267
- - `sourceId`
268
- - `sourceType`
269
- - `locator`
270
- - `displayName`
271
- - `storageRoot`
272
- - `updateStrategy`
273
-
274
- ### 4.2 SourceSnapshot
275
-
276
- Source 在某一时刻的解析快照。
277
-
278
- - git:`remote + branch + commit SHA`
279
- - clawhub:`slug + version + contentHash`
280
- - future well-known:`baseUrl + indexHash/etag`
281
-
282
- ### 4.3 SkillLeaf
283
-
284
- 真正可安装的 skill 单元。满足条件:
285
-
286
- - 存在 `SKILL.md`
287
- - frontmatter 可解析
288
- - `name`
289
- - `description`
290
-
291
- 字段建议:
292
-
293
- - `skillId`
294
- - `sourceId`
295
- - `name`
296
- - `description`
297
- - `relativeRoot`
298
- - `contentHash`
299
- - `hasScripts`
300
- - `hasReferences`
301
- - `hasAssets`
302
- - `riskFlags[]`
303
-
304
-
305
- ### 4.4 SkillCandidate
306
-
307
- Discovery 过程中返回的候选对象,用于连接“搜索结果”和“安装动作”。
308
-
309
- 字段建议:
310
-
311
- - `candidateId`
312
- - `sourceType`
313
- - `sourceLocator`
314
- - `publisher`
315
- - `repo`
316
- - `skillPath`
317
- - `title`
318
- - `summary`
319
- - `verified`
320
- - `official`
321
- - `installCount`
322
- - `stars`
323
- - `alreadyInstalled`
324
- - `installedInChannels[]`
325
- - `supportedChannels[]`
326
- - `installMethods[]`
327
- - `riskFlags[]`
328
- - `score`
329
-
330
- 候选对象不等于 `SkillLeaf`。前者代表“可安装建议”,后者代表“已经被本地解析并纳入索引的技能实体”。
331
-
332
- ### 4.5 Channel
333
-
334
- 一个目标适配器,而不是路径。
335
-
336
- 字段建议:
337
-
338
- - `channelId`
339
- - `displayName`
340
- - `resolvedPath`
341
- - `strategy`
342
- - `pathSource`
343
- - `healthStatus`
344
-
345
- ### 4.6 Deployment
346
-
347
- SkillLeaf 到 Channel 的一次投影关系。
348
-
349
- 字段建议:
350
-
351
- - `deploymentId`
352
- - `skillId`
353
- - `channelId`
354
- - `strategy`
355
- - `targetPath`
356
- - `status`
357
- - `lastAppliedAt`
358
-
359
- ## 5. 文件系统布局
360
-
361
- ```text
362
- ~/.skillflow/
363
- source/
364
- git/
365
- <sourceId>/
366
- clawhub/
367
- <sourceId>/
368
- skills/
369
- <sourceId>/
370
- <skillName>/ -> ../../source/...
371
- state/
372
- manifest.json
373
- lock.json
374
- channels.json
375
- history.ndjson
376
- cache/
377
- tmp/
378
- logs/
379
- ```
380
-
381
- ## 6. Source 策略
382
-
383
- ### 6.1 Git Source(MVP 必做)
384
-
385
- 输入支持:
386
-
387
- - GitHub `owner/repo`
388
- - 任意 git URL
389
- - 本地 git 路径
390
-
391
- ### 6.2 ClawHub Source(MVP 必做)
392
-
393
- 输入支持:
394
-
395
- - `clawhub:<slug>`
396
- - `clawhub:<slug>@<version>`
397
-
398
- MVP 实现:
399
-
400
- - 优先采用 **CLI bridge**:shell-out `clawhub install/update/list`
401
- - 将版本与来源信息同步到 `skill-flow lock`
402
-
403
- ### 6.3 Well-known Skills Discovery(P1)
404
-
405
- 只做接口预留,不进 MVP。
406
-
407
-
408
- ## 6.4 Discovery Source Tiers
409
-
410
- 当执行 `find` 时,来源优先级采用分层策略,而不是把所有来源混在一起:
411
-
412
- ### Tier 0:Installed / Bundled / System
413
-
414
- - 已安装到 `skill-flow` 的 source / skill
415
- - 目标渠道已启用的 skill
416
- - 各渠道自带或预装的 bundled / system skill
417
-
418
- 用途:避免重复推荐,优先提示“你已经有了”。
419
-
420
- ### Tier 1:Official Curated Registry
421
-
422
- - ClawHub 等官方注册表
423
- - 未来可接入的官方 curated catalog
424
-
425
- 用途:默认优先展示,因其通常带版本、发布者和更强的信任信号。
426
-
427
- ### Tier 2:Public Ecosystem Directory / Leaderboard
428
-
429
- - skills.sh 这类目录型来源
430
- - 公开榜单、安装量与聚合索引
431
-
432
- 用途:补齐“广度发现”和“受欢迎技能”的判断。
433
-
434
- ### Tier 3:Direct Git Repositories
435
-
436
- - GitHub / GitLab / 任意 git 仓库
437
- - 已知 repo path 的直接安装
438
-
439
- 用途:作为高覆盖兜底来源,也支撑精准 repo/path 输入。
440
-
441
- ### Tier 4:Manual / Local / Custom URL
442
-
443
- - 本地目录
444
- - 自定义 URL
445
- - 企业内部镜像
446
-
447
- 用途:满足高级用户与私有来源场景。
448
-
449
- `find` 默认按 Tier 0 -> Tier 1 -> Tier 2 -> Tier 3 -> Tier 4 的顺序组织结果与解释。
450
-
451
- ## 7. Source 命名与展示规则
452
-
453
- ### 外显 display 规则
454
-
455
- - Git 仓库:显示仓库名
456
- - 非 Git 且可识别作者:显示作者名
457
- - 无法识别:显示 `single`
458
-
459
- ### 内部 storage 规则
460
-
461
- - Git:`<host>__<owner>__<repo>`
462
- - ClawHub:`clawhub__<slug>`
463
- - Generic single:`single__<hash>`
464
-
465
- ## 8. Skill 扫描与索引规则
466
-
467
- 扫描逻辑:
468
-
469
- 1. 递归搜索包含 `SKILL.md` 的目录
470
- 2. 跳过 `.git`、`node_modules`、构建产物
471
- 3. 解析 frontmatter
472
- 4. 生成 `SkillLeaf` 索引项
473
- 5. 建立 `skills/<sourceId>/<skillName>` canonical 入口
474
-
475
- 校验等级:
476
-
477
- ### 标准校验
478
-
479
- - `SKILL.md` 存在
480
- - YAML 可解析
481
- - `name`
482
- - `description`
483
-
484
- ### 严格校验
485
-
486
- - `name` 与目录名匹配
487
- - 命名合法
488
- - `description` 长度合理
489
- - 相对路径引用可达
490
-
491
- ## 9. Channel 适配与默认策略
492
-
493
- ### 9.1 Claude Code
494
-
495
- - 默认路径:`~/.claude/skills`
496
- - 默认策略:`symlink`
497
- - 兜底策略:`copy`
498
-
499
- ### 9.2 OpenCode
500
-
501
- - 默认路径:`~/.config/opencode/skills`
502
- - 默认策略:`symlink`
503
-
504
- ### 9.3 Codex
505
-
506
- - 默认路径:`~/.agents/skills`
507
- - 默认策略:`symlink`
508
-
509
- ### 9.4 OpenClaw
510
-
511
- - 默认路径:`<workspace>/skills`,备选 `~/.openclaw/skills`
512
- - 默认策略:`copy`
513
-
514
- ### 9.5 通用 `.agents/skills`
515
-
516
- - 默认路径:`~/.agents/skills`
517
- - 默认策略:`symlink`
518
-
519
- ## 10. 命令设计
520
-
521
- 正式命令集:
522
-
523
- ```bash
524
- skill-flow add <source>
525
- skill-flow find [query]
526
- skill-flow search [query] # `find` 的兼容别名
527
- skill-flow install <candidate-or-source>
528
- skill-flow list
529
- skill-flow config
530
- skill-flow update [--all | <sourceId>]
531
- skill-flow uninstall [<sourceId>...]
532
- skill-flow doctor
533
- ```
534
-
535
- ### 10.1 `find`
536
-
537
- `find` 是 Discovery 主命令。它既支持明确 query,也支持无 query 的交互式发现。
538
-
539
- 典型用法:
540
-
541
- ```bash
542
- skill-flow find react performance
543
- skill-flow find postgres backups
544
- skill-flow find
545
- ```
546
-
547
- 行为定义:
548
-
549
- 1. 先检查 Tier 0:本地已安装 / 已启用 / 已内置能力。
550
- 2. 再检查 Tier 1:ClawHub 等官方 registry。
551
- 3. 再检查 Tier 2:目录 / leaderboard / popularity signals。
552
- 4. 最后检查 Tier 3:git 级来源与 repo path。
553
- 5. 返回 `SkillCandidate[]`,而不是直接执行安装。
554
-
555
- ### 10.2 `install`
556
-
557
- `install` 是 Discovery 到安装的快速闭环,支持“直接从候选安装”和“直接从 source / repo path 安装”两种模式。
558
-
559
- 典型用法:
560
-
561
- ```bash
562
- skill-flow install clawhub:publisher/skill@1.2.3
563
- skill-flow install github:vercel-labs/skills --skill react-best-practices
564
- skill-flow install github:openai/skills --path skills/.curated/pdf
565
- ```
566
-
567
- 行为定义:
568
-
569
- 1. 若入参是候选对象,按候选携带的最优安装方法执行。
570
- 2. 若入参是 source,则进入 add / scan / optional apply 流程。
571
- 3. 安装完成后刷新 manifest / lock / inventory index。
572
- 4. 视 channel 给出后续提示,如 `config`、重扫或重启客户端。
573
-
574
- ### 10.3 `add`
575
-
576
- `add` 保留为“把 source 纳入 skill-flow 管理”的正式入口。与 `install` 的区别是:`add` 偏 source-first,`install` 偏 candidate-first。
577
-
578
-
579
- ## 10.4 Discovery 工作流
580
-
581
- 当用户只有“能力诉求”时,`find` 的完整流程如下:
582
-
583
- 1. **Intent Normalize**
584
- 从用户描述抽取 capability、domain、toolchain、约束条件。
585
-
586
- 2. **Query Expansion**
587
- 生成一组用于 registry / directory / git 的查询词,包括领域词、同义词与技术栈词。
588
-
589
- 3. **Tiered Retrieval**
590
- 按来源分层召回候选:已安装 -> registry -> leaderboard -> git。
591
-
592
- 4. **Candidate Enrichment**
593
- 填充安装量、来源、publisher、stars、是否已安装、支持渠道、风险标记。
594
-
595
- 5. **Rule-based Ranking**
596
- 依据显式规则排序,而不是黑盒推荐。
597
-
598
- 6. **Presentation**
599
- 至少展示:名称、用途、来源、安装量/可信信号、安装方式、详情入口。
600
-
601
- 7. **Action**
602
- 用户可选择:
603
- - 立即安装
604
- - 添加为 source 后再配置
605
- - 仅保存为候选
606
- - 忽略
607
-
608
- ## 10.5 Search Result Schema & Ranking
609
-
610
- `find` 返回的每个结果至少要包含:
611
-
612
- - `title`
613
- - `summary`
614
- - `sourceType`
615
- - `sourceLocator`
616
- - `publisher`
617
- - `skillPath`
618
- - `installMethods[]`
619
- - `alreadyInstalled`
620
- - `installedInChannels[]`
621
- - `verified`
622
- - `official`
623
- - `installCount`
624
- - `stars`
625
- - `riskFlags[]`
626
- - `score`
627
-
628
- 默认排序规则:
629
-
630
- 1. Tier 优先级
631
- 2. `alreadyInstalled` 命中时置顶,并标注“已安装”
632
- 3. `official / verified` 优先
633
- 4. 安装量 / 使用量
634
- 5. GitHub stars / repo 活跃度
635
- 6. 精确名称匹配
636
- 7. 描述语义匹配
637
- 8. 新近性
638
-
639
- ### 10.6 Installed Annotation & Post-Install Feedback
640
-
641
- Discovery 与安装结果必须回流到 UX:
642
-
643
- - 搜索结果标出 `already installed`
644
- - 搜索结果标出 `installed in channels: [...]`
645
- - 对 bundled / system / preinstalled 条目标出 `preinstalled`
646
- - 安装完成后给出 channel-specific next steps:
647
- - 需要执行 `config`
648
- - 需要重扫
649
- - 建议重启客户端
650
- - 可热加载,无需重启
651
-
652
- ### 10.7 Non-Skill Artifact Handling
653
-
654
- MVP 扫描器与 Discovery 索引器只管理合法 `SKILL.md` skill root。对同一仓库中的以下对象:
655
-
656
- - `.claude/commands/`
657
- - `agents/`
658
- - `plugins/`
659
- - 其他非 skill 工件
660
-
661
- 统一策略为:
662
-
663
- 1. 默认忽略,不作为可安装 skill。
664
- 2. 若检测到与 skill 高度相似的目录结构,记 warning。
665
- 3. 后续若扩展到 commands / agents 管理,再通过新 artifact kind 建模,而不是复用 `SkillLeaf`。
666
-
667
- ## 11. 状态文件设计
668
-
669
- ### `manifest.json`
670
-
671
- 记录用户意图:
672
-
673
- - sources
674
- - naming policy
675
- - selected skills by channel
676
- - user overrides
677
-
678
- ### `lock.json`
679
-
680
- 记录解析结果:
681
-
682
- - source snapshots
683
- - skill leaf inventory
684
- - deployments
685
- - content hashes
686
- - timestamps
687
- - schemaVersion
688
-
689
- ### `channels.json`
690
-
691
- 记录本机探测与 path override:
692
-
693
- - detected channels
694
- - resolved path
695
- - available strategies
696
- - health flags
697
-
698
-
699
-
700
- ### `inventory-index.json`
701
-
702
- 记录每个 source 解析出的 Discovery 友好索引,供 `find`、`config`、`diff`、`doctor` 快速读取。
703
-
704
- 建议字段:
705
-
706
- - `sourceId`
707
- - `snapshotRef`
708
- - `skills[]`
709
- - `name`
710
- - `description`
711
- - `path`
712
- - `tags`
713
- - `riskFlags`
714
- - `contentHash`
715
- - `generatedAt`
716
-
717
- 说明:
718
-
719
- - 这是 `skill-flow` 的内部缓存格式,不对外承诺为开放标准。
720
- - 它解决大型 source 在反复 `find` / `config` 时的性能问题。
721
-
722
- ### `discovery-cache.json`
723
-
724
- 记录外部来源的候选缓存,降低频繁请求 registry / leaderboard / git API 的成本。
725
-
726
- 建议字段:
727
-
728
- - `query`
729
- - `sourceTier`
730
- - `candidates[]`
731
- - `fetchedAt`
732
- - `expiresAt`
733
- - `etag`
734
-
735
- ### `history.ndjson`
736
-
737
- 记录审计事件:
738
-
739
- - add
740
- - update
741
- - config-apply
742
- - uninstall
743
- - doctor-warning
744
-
745
- ## 12. 冲突与一致性规则
746
-
747
- ### 12.1 同 channel 同名 skill
748
-
749
- 默认阻止,不静默覆盖。
750
-
751
- ### 12.2 目标路径已有非本工具管理文件
752
-
753
- 默认不接管,标记 `foreign-existing`。
754
-
755
- ### 12.3 Source 内同名 leaf
756
-
757
- 扫描时直接判定 source inventory 非法,需要用户缩小范围或忽略。
758
-
759
- ### 12.4 原子性
760
-
761
- 所有 state 文件写入采用:
762
-
763
- - `tmp write`
764
- - `fsync`
765
- - `rename`
766
-
767
- 所有 deployment 采用 staged apply;失败时不提交 lock 的成功状态。
768
-
769
-
770
- ## 12.5 Channel Feature Compatibility Matrix
771
-
772
- 不同渠道对前端元数据和技能语义的支持并不等价。MVP 需要最少维护一张兼容矩阵:
773
-
774
- | 能力 / 字段 | Agent Skills 通用 | Claude Code | OpenCode | Codex | OpenClaw | `skill-flow` 导入策略 |
775
- |---|---|---|---|---|---|---|
776
- | `name` / `description` | 支持 | 支持 | 支持 | 支持 | 支持 | 必填 / 缺失则失败 |
777
- | `references/` / `assets/` / `scripts/` | 支持 | 支持 | 支持 | 支持 | 支持 | 扫描但不执行脚本 |
778
- | `allowed-tools` | 非通用 | 支持 | 未承诺 | 未承诺 | 未承诺 | 保留原样,非支持渠道仅 warning |
779
- | `user-invocable` | 非通用 | 支持 | 未承诺 | 未承诺 | 未承诺 | 保留原样 |
780
- | `disable-model-invocation` | 非通用 | 支持 | 未承诺 | 未承诺 | 未承诺 | 保留原样 |
781
- | `argument-hint` | 非通用 | 支持 | 未承诺 | 未承诺 | 未承诺 | 保留原样 |
782
- | nested discovery | 非通用 | 支持 | 项目向上查找 | repo/user/admin/system | workspace 优先 | 仅在 channel adapter 层处理 |
783
- | commands 兼容 | 非通用 | 与 skills 合流 | 未纳入 MVP | 未纳入 MVP | 未纳入 MVP | 默认忽略 commands |
784
-
785
- 策略说明:
786
-
787
- 1. `skill-flow` 不重写 source 内容。
788
- 2. 对未知 frontmatter 保留原样,不主动删除。
789
- 3. 对渠道已知但不受支持的字段,在 `doctor` 中给 warning。
790
-
791
- ## 13. 安全要求
792
-
793
- MVP 安全要求:
794
-
795
- 1. 永不执行 skill 脚本
796
- 2. 扫描时做 frontmatter 与路径校验
797
- 3. 拒绝 root 外 realpath 投影
798
- 4. 风险标记:
799
- - `has-scripts`
800
- - `invalid-frontmatter`
801
- - `name-dir-mismatch`
802
- - `external-symlink`
803
- - `foreign-existing`
804
- - `openclaw-root-risk`
805
- 5. 默认提示审计,`--yes` 才跳过确认
806
-
807
- ## 14. 技术栈
808
-
809
- ### 14.1 运行时与语言
810
-
811
- - **Node.js 24 LTS**
812
- - **TypeScript 5.x**
813
-
814
- ### 14.2 包管理与构建
815
-
816
- - **pnpm**
817
- - 发布到 **npm**
818
-
819
- ### 14.3 CLI 与 TUI
820
-
821
- - **oclif**
822
- - **Ink**
823
-
824
- ### 14.4 Schema 与状态验证
825
-
826
- - **Zod**
827
-
828
- ### 14.5 Git 访问
829
-
830
- - **system git**
831
- - **simple-git**
832
-
833
- ### 14.6 测试
834
-
835
- - **Vitest**
836
- - fixture-based filesystem integration tests
837
-
838
- ### 14.7 建议工程结构
839
-
840
- ```text
841
- src/
842
- commands/
843
- tui/
844
- domain/
845
- adapters/
846
- source/
847
- channel/
848
- services/
849
- scan/
850
- deploy/
851
- update/
852
- doctor/
853
- state/
854
- utils/
855
- ```
856
-
857
- ## 15. 里程碑
858
-
859
- ### Milestone 1
860
- - Git Source
861
- - 扫描器
862
- - manifest/lock
863
- - list/add/update
864
-
865
- ### Milestone 2
866
- - config TUI
867
- - Claude/OpenCode/Codex/agents 投影
868
- - doctor
869
-
870
- ### Milestone 3
871
- - OpenClaw copy deployment
872
- - ClawHub adapter
873
- - uninstall
874
-
875
- ### Milestone 4
876
- - search
877
- - diff
878
- - schema migration
879
- - alias conflict handling
880
-
881
- ### Milestone 5(P1)
882
- - well-known discovery
883
- - project-scope support
884
- - Homebrew tap
885
- - advanced channel overrides
886
- - external plugin SDK
887
-
888
- ---
889
-
890
- # 三、工程实施文档
891
-
892
- ## 1. 实施目标
893
-
894
- 这一部分不是再讨论“做什么”,而是明确“怎么落地”。目标是让工程团队在没有额外口头补充的情况下,直接进入:
895
-
896
- 1. 仓库初始化
897
- 2. 核心模块搭建
898
- 3. 命令实现
899
- 4. 端到端测试
900
- 5. 首个可发布 MVP
901
-
902
- ---
903
-
904
- ## 2. MVP 工程范围切片
905
-
906
- ### 2.1 必须在首发版本完成
907
-
908
- - Git Source Adapter
909
- - ClawHub Source Adapter(CLI bridge 方案)
910
- - Skill Scanner
911
- - Manifest/Lock/Channels 三类状态文件
912
- - Claude/OpenCode/Codex/Agents 四个 symlink channel
913
- - OpenClaw copy channel
914
- - `add / list / config / update / uninstall / doctor`
915
- - TUI 树状多选界面
916
- - 冲突检测、路径校验、原子写入、日志落盘
917
-
918
- ### 2.2 可以延后到 P1
919
-
920
- - well-known registry adapter
921
- - alias 命名策略
922
- - Homebrew tap 自动发布
923
- - project-scope 管理
924
- - 自定义 channel adapter SDK
925
- - 远程 diff 预览
926
-
927
- ---
928
-
929
- ## 3. 工程仓库建议结构
930
-
931
- ```text
932
- skill-flow/
933
- package.json
934
- pnpm-lock.yaml
935
- tsconfig.json
936
- vitest.config.ts
937
- README.md
938
- src/
939
- index.ts
940
- cli.ts
941
- commands/
942
- add.ts
943
- search.ts
944
- list.ts
945
- config.ts
946
- update.ts
947
- uninstall.ts
948
- doctor.ts
949
- tui/
950
- app.tsx
951
- screens/
952
- channel-select.tsx
953
- skill-tree.tsx
954
- apply-preview.tsx
955
- components/
956
- tree-node.tsx
957
- checkbox.tsx
958
- footer-hints.tsx
959
- status-pill.tsx
960
- domain/
961
- source.ts
962
- snapshot.ts
963
- skill.ts
964
- channel.ts
965
- deployment.ts
966
- errors.ts
967
- adapters/
968
- source/
969
- git.ts
970
- clawhub.ts
971
- registry.ts
972
- channel/
973
- claude.ts
974
- opencode.ts
975
- codex.ts
976
- openclaw.ts
977
- agents.ts
978
- services/
979
- detect/
980
- channels.ts
981
- scan/
982
- scanner.ts
983
- parser.ts
984
- validators.ts
985
- state/
986
- manifest.ts
987
- lock.ts
988
- channels.ts
989
- migrations.ts
990
- deploy/
991
- planner.ts
992
- symlink.ts
993
- copy.ts
994
- applier.ts
995
- source/
996
- resolve.ts
997
- fetch.ts
998
- update.ts
999
- doctor/
1000
- checks.ts
1001
- logging/
1002
- history.ts
1003
- logger.ts
1004
- utils/
1005
- fs.ts
1006
- hash.ts
1007
- path.ts
1008
- prompt.ts
1009
- time.ts
1010
- ids.ts
1011
- fixtures/
1012
- repos/
1013
- channels/
1014
- snapshots/
1015
- tests/
1016
- unit/
1017
- integration/
1018
- e2e/
1019
- ```
1020
-
1021
- 设计原则:
1022
-
1023
- - `commands/` 只做参数解析与 orchestration
1024
- - `domain/` 只放模型和不依赖 IO 的规则
1025
- - `adapters/` 隔离第三方系统差异
1026
- - `services/` 承担业务编排
1027
- - `tui/` 不直接触碰磁盘;通过 service 层读写
1028
-
1029
- ---
1030
-
1031
- ## 4. 命令参数规范
1032
-
1033
- ## 4.1 `skill-flow add`
1034
-
1035
- ```bash
1036
- skill-flow add <source>
1037
- [--name <displayName>]
1038
- [--branch <branch>]
1039
- [--ref <ref>]
1040
- [--channel <channel...>]
1041
- [--yes]
1042
- [--json]
1043
- ```
1044
-
1045
- ### 行为定义
1046
-
1047
- - `<source>` 支持:
1048
- - `owner/repo`
1049
- - `https://...git`
1050
- - `git@...`
1051
- - 本地路径
1052
- - `clawhub:<slug>`
1053
- - `clawhub:<slug>@<version>`
1054
- - 若指定 `--channel`,则在 `add` 后直接触发一次 apply
1055
- - 若指定 `--ref`,优先锁定对应 tag/commit
1056
- - `--yes` 跳过来源确认与风险确认
1057
-
1058
- ## 4.2 `skill-flow search`
1059
-
1060
- ```bash
1061
- skill-flow search <query>
1062
- [--source git|clawhub|all]
1063
- [--limit <n>]
1064
- [--json]
1065
- ```
1066
-
1067
- ### 行为定义
1068
-
1069
- - `--source clawhub`:正式支持
1070
- - `--source git`:MVP 仅做 repo 级搜索或 locator 解析辅助
1071
- - `--source all`:按 adapter 聚合结果
1072
-
1073
- ## 4.3 `skill-flow list`
1074
-
1075
- ```bash
1076
- skill-flow list
1077
- [--sources]
1078
- [--skills]
1079
- [--deployments]
1080
- [--channel <channel>]
1081
- [--source-id <id>]
1082
- [--json]
1083
- ```
1084
-
1085
- ### 行为定义
1086
-
1087
- - 默认输出 `sources + skills + deployment summary`
1088
- - `--skills` 展示 skill leaf 明细
1089
- - `--deployments` 展示按 channel 的启用状态
1090
-
1091
- ## 4.4 `skill-flow config`
1092
-
1093
- ```bash
1094
- skill-flow config
1095
- [--channel <channel...>]
1096
- [--source-id <id>]
1097
- [--non-interactive]
1098
- [--json]
1099
- ```
1100
-
1101
- ### 行为定义
1102
-
1103
- - 默认进入 TUI
1104
- - `--non-interactive` 预留给脚本模式,MVP 可只支持有限 flag 驱动
1105
- - 未传 `--channel` 时先展示 channel 多选
1106
-
1107
- ## 4.5 `skill-flow update`
1108
-
1109
- ```bash
1110
- skill-flow update
1111
- [--all]
1112
- [--source-id <id>...]
1113
- [--apply]
1114
- [--dry-run]
1115
- [--json]
1116
- ```
1117
-
1118
- ### 行为定义
1119
-
1120
- - `--all` 更新所有 source
1121
- - `--apply` 更新完成后重新部署受影响 channel
1122
- - `--dry-run` 仅展示可更新项和变更摘要
1123
-
1124
- ## 4.6 `skill-flow uninstall`
1125
-
1126
- ```bash
1127
- skill-flow uninstall <sourceId...>
1128
- [--yes]
1129
- [--json]
1130
- ```
1131
-
1132
- ### 行为定义
1133
-
1134
- - 卸载 source 及其 canonical skills 与所有 deployments
1135
- - 不删除其他来源产生的同名 skill
1136
-
1137
- ## 4.7 `skill-flow doctor`
1138
-
1139
- ```bash
1140
- skill-flow doctor
1141
- [--channel <channel...>]
1142
- [--source-id <id>...]
1143
- [--fix]
1144
- [--json]
1145
- ```
1146
-
1147
- ### 行为定义
1148
-
1149
- - 默认只检查不修改
1150
- - `--fix` 仅修复确定性问题:断链重建、缺失 state 目录、历史文件 rotate
1151
- - 冲突覆盖不属于自动修复范围
1152
-
1153
- ---
1154
-
1155
- ## 5. 状态文件 Schema
1156
-
1157
- ## 5.1 `manifest.json`
1158
-
1159
- 作用:记录用户意图。
1160
-
1161
- ```json
1162
- {
1163
- "$schema": "https://skill-flow.dev/schema/manifest-v1.json",
1164
- "schemaVersion": 1,
1165
- "sources": [
1166
- {
1167
- "sourceId": "github__vercel-labs__skills",
1168
- "sourceType": "git",
1169
- "locator": "vercel-labs/skills",
1170
- "displayName": "skills",
1171
- "options": {
1172
- "ref": null,
1173
- "branch": "main"
1174
- }
1175
- }
1176
- ],
1177
- "bindings": [
1178
- {
1179
- "channelId": "claude",
1180
- "skillSelections": [
1181
- {
1182
- "sourceId": "github__vercel-labs__skills",
1183
- "skillIds": ["frontend-design", "skill-creator"]
1184
- }
1185
- ]
1186
- }
1187
- ],
1188
- "overrides": {
1189
- "channels": {
1190
- "openclaw": {
1191
- "path": null,
1192
- "strategy": "copy"
1193
- }
1194
- }
1195
- }
1196
- }
1197
- ```
1198
-
1199
- ### 约束
1200
-
1201
- - `schemaVersion` 必填
1202
- - `bindings` 只描述“期望启用哪些 skill 到哪些 channel”
1203
- - 不记录部署是否成功;那是 lock 的职责
1204
-
1205
- ## 5.2 `lock.json`
1206
-
1207
- 作用:记录解析结果与当前落地状态。
1208
-
1209
- ```json
1210
- {
1211
- "$schema": "https://skill-flow.dev/schema/lock-v1.json",
1212
- "schemaVersion": 1,
1213
- "generatedAt": "2026-03-21T12:00:00.000Z",
1214
- "sources": [
1215
- {
1216
- "sourceId": "github__vercel-labs__skills",
1217
- "sourceType": "git",
1218
- "snapshot": {
1219
- "remote": "https://github.com/vercel-labs/skills.git",
1220
- "branch": "main",
1221
- "commit": "abc123"
1222
- },
1223
- "contentHash": "sha256:..."
1224
- }
1225
- ],
1226
- "skills": [
1227
- {
1228
- "skillId": "frontend-design",
1229
- "sourceId": "github__vercel-labs__skills",
1230
- "name": "frontend-design",
1231
- "description": "...",
1232
- "relativeRoot": "skills/frontend-design",
1233
- "canonicalPath": "~/.skillflow/skills/github__vercel-labs__skills/frontend-design",
1234
- "contentHash": "sha256:...",
1235
- "riskFlags": []
1236
- }
1237
- ],
1238
- "deployments": [
1239
- {
1240
- "deploymentId": "dep_001",
1241
- "skillId": "frontend-design",
1242
- "channelId": "claude",
1243
- "strategy": "symlink",
1244
- "targetPath": "~/.claude/skills/frontend-design",
1245
- "status": "applied",
1246
- "lastAppliedAt": "2026-03-21T12:00:00.000Z"
1247
- }
1248
- ]
1249
- }
1250
- ```
1251
-
1252
- ### 约束
1253
-
1254
- - lock 必须可重建本地部署视图
1255
- - `deployments.status` 允许:`planned | applied | stale | broken | removed`
1256
- - `contentHash` 用于 update 后判断是否需要重投影
1257
-
1258
- ## 5.3 `channels.json`
1259
-
1260
- 作用:记录本机探测结果与 override。
1261
-
1262
- ```json
1263
- {
1264
- "$schema": "https://skill-flow.dev/schema/channels-v1.json",
1265
- "schemaVersion": 1,
1266
- "detected": [
1267
- {
1268
- "channelId": "claude",
1269
- "path": "/Users/alice/.claude/skills",
1270
- "pathSource": "default",
1271
- "available": true,
1272
- "preferredStrategy": "symlink"
1273
- },
1274
- {
1275
- "channelId": "openclaw",
1276
- "path": "/Users/alice/.openclaw/workspace/skills",
1277
- "pathSource": "detected-workspace",
1278
- "available": true,
1279
- "preferredStrategy": "copy"
1280
- }
1281
- ]
1282
- }
1283
- ```
1284
-
1285
- ## 5.4 `history.ndjson`
1286
-
1287
- 每行一个事件,方便审计与排障。
1288
-
1289
- ```json
1290
- {"ts":"2026-03-21T12:00:00.000Z","event":"add","sourceId":"github__vercel-labs__skills"}
1291
- {"ts":"2026-03-21T12:01:00.000Z","event":"config-apply","channelId":"claude","count":2}
1292
- ```
1293
-
1294
- ---
1295
-
1296
- ## 6. Domain Model TypeScript Interface
1297
-
1298
- ```ts
1299
- export type SourceType = "git" | "clawhub" | "registry";
1300
- export type ChannelId = "claude" | "opencode" | "codex" | "openclaw" | "agents";
1301
- export type DeployStrategy = "symlink" | "copy";
1302
- export type DeploymentStatus = "planned" | "applied" | "stale" | "broken" | "removed";
1303
-
1304
- export interface Source {
1305
- sourceId: string;
1306
- sourceType: SourceType;
1307
- locator: string;
1308
- displayName: string;
1309
- storageRoot: string;
1310
- updateStrategy: "git-pull" | "registry-sync" | "custom";
1311
- }
1312
-
1313
- export interface SourceSnapshot {
1314
- sourceId: string;
1315
- versionRef: string;
1316
- contentHash: string;
1317
- metadata: Record<string, unknown>;
1318
- }
1319
-
1320
- export interface SkillLeaf {
1321
- skillId: string;
1322
- sourceId: string;
1323
- name: string;
1324
- description: string;
1325
- relativeRoot: string;
1326
- canonicalPath: string;
1327
- contentHash: string;
1328
- riskFlags: string[];
1329
- }
1330
-
1331
- export interface Channel {
1332
- channelId: ChannelId;
1333
- displayName: string;
1334
- resolvedPath: string;
1335
- preferredStrategy: DeployStrategy;
1336
- available: boolean;
1337
- }
1338
-
1339
- export interface Deployment {
1340
- deploymentId: string;
1341
- skillId: string;
1342
- channelId: ChannelId;
1343
- strategy: DeployStrategy;
1344
- targetPath: string;
1345
- status: DeploymentStatus;
1346
- lastAppliedAt?: string;
1347
- }
1348
- ```
1349
-
1350
- ---
1351
-
1352
- ## 7. Adapter 接口规范
1353
-
1354
- ## 7.1 Source Adapter
1355
-
1356
- ```ts
1357
- export interface ResolvedSource {
1358
- sourceType: "git" | "clawhub" | "registry";
1359
- locator: string;
1360
- normalizedId: string;
1361
- metadata?: Record<string, unknown>;
1362
- }
1363
-
1364
- export interface FetchResult {
1365
- source: Source;
1366
- snapshot: SourceSnapshot;
1367
- storageRoot: string;
1368
- }
1369
-
1370
- export interface DiscoveredSkill {
1371
- name: string;
1372
- description: string;
1373
- relativeRoot: string;
1374
- contentHash: string;
1375
- riskFlags: string[];
1376
- }
1377
-
1378
- export interface SourceAdapter {
1379
- kind: "git" | "clawhub" | "registry";
1380
- probe(input: string): boolean;
1381
- resolve(input: string): Promise<ResolvedSource>;
1382
- fetch(source: ResolvedSource): Promise<FetchResult>;
1383
- update(source: Source, snapshot: SourceSnapshot): Promise<FetchResult>;
1384
- scan(storageRoot: string): Promise<DiscoveredSkill[]>;
1385
- }
1386
- ```
1387
-
1388
- ### Git Adapter 额外职责
1389
-
1390
- - 支持 branch/ref/commit
1391
- - 提供远程变化检查
1392
- - 在公开 GitHub 来源下可使用 API 预览树结构,但正式下载仍以 git 为准
1393
-
1394
- ### ClawHub Adapter 额外职责
1395
-
1396
- - shell-out 调用 `clawhub`
1397
- - 读取安装结果与 lock 信息
1398
- - 将 registry version 映射为 `versionRef`
1399
-
1400
- ## 7.2 Channel Adapter
1401
-
1402
- ```ts
1403
- export interface DeploymentPlanItem {
1404
- skillId: string;
1405
- channelId: ChannelId;
1406
- strategy: DeployStrategy;
1407
- canonicalPath: string;
1408
- targetPath: string;
1409
- action: "create" | "replace" | "remove" | "skip";
1410
- reason?: string;
1411
- }
1412
-
1413
- export interface DeploymentPlan {
1414
- channelId: ChannelId;
1415
- items: DeploymentPlanItem[];
1416
- warnings: string[];
1417
- }
1418
-
1419
- export interface DoctorFinding {
1420
- code: string;
1421
- severity: "info" | "warn" | "error";
1422
- message: string;
1423
- target?: string;
1424
- }
1425
-
1426
- export interface ChannelAdapter {
1427
- kind: ChannelId;
1428
- detect(): Promise<Channel | null>;
1429
- plan(skills: SkillLeaf[], channel: Channel): Promise<DeploymentPlan>;
1430
- apply(plan: DeploymentPlan): Promise<Deployment[]>;
1431
- diagnose(channel: Channel): Promise<DoctorFinding[]>;
1432
- }
1433
- ```
1434
-
1435
- ---
1436
-
1437
- ## 8. 关键算法规范
1438
-
1439
- ## 8.1 Skill Scanner 算法
1440
-
1441
- ### 输入
1442
-
1443
- - `sourceRoot`
1444
- - `scanOptions`
1445
-
1446
- ### 伪代码
1447
-
1448
- ```text
1449
- walk(sourceRoot)
1450
- ignore directories: .git, node_modules, dist, build, .next, target
1451
- if currentDir contains SKILL.md:
1452
- parse frontmatter
1453
- validate required fields
1454
- emit SkillLeaf candidate
1455
- do not recurse into nested skill roots unless explicit nested mode enabled
1456
- ```
1457
-
1458
- ### 规则
1459
-
1460
- - 默认不允许“skill 中嵌 skill”自动递归安装
1461
- - 若一个目录命中 `SKILL.md`,把它视为 leaf 边界
1462
- - 生成 `contentHash` 时应基于 leaf root 下所有受管文件
1463
-
1464
- ## 8.2 Deployment Planner 算法
1465
-
1466
- ### 输入
1467
-
1468
- - 目标 channel
1469
- - manifest 中该 channel 的选中 skill 列表
1470
- - 当前 lock 中已存在的 deployments
1471
- - 磁盘实际状态
1472
-
1473
- ### 输出
1474
-
1475
- - `DeploymentPlan`
1476
-
1477
- ### 规则
1478
-
1479
- 1. 先构建 desired set
1480
- 2. 再读取 current set
1481
- 3. 求 diff:
1482
- - desired - current => create
1483
- - current - desired => remove
1484
- - desired ∩ current 且 hash 变化 => replace
1485
- - desired ∩ current 且一致 => skip
1486
- 4. 若遇到 foreign-existing,计划项变为 `skip` 并附 reason
1487
-
1488
- ## 8.3 Copy Deploy 算法(OpenClaw)
1489
-
1490
- ```text
1491
- for each plan item:
1492
- stage copy into SM_HOME/tmp/<deploymentId>
1493
- verify realpath(target parent) within configured root
1494
- rename staged dir -> final target
1495
- fsync parent dir
1496
- ```
1497
-
1498
- ## 8.4 Symlink Deploy 算法
1499
-
1500
- ```text
1501
- for each plan item:
1502
- ensure target parent exists
1503
- if target exists and managed-by-us -> remove/replace
1504
- if target exists and foreign -> skip with warning
1505
- ln -s canonicalPath targetPath
1506
- ```
1507
-
1508
- ## 8.5 Update 算法
1509
-
1510
- ```text
1511
- resolve sources to update
1512
- for each source:
1513
- fetch/update snapshot
1514
- rescan skills
1515
- rebuild canonical entries for changed skills only
1516
- recompute deployments for affected channels
1517
- if --apply then apply plans
1518
- commit new lock atomically
1519
- ```
1520
-
1521
- ---
1522
-
1523
- ## 9. TUI 详细交互规范
1524
-
1525
- ## 9.1 页面流转
1526
-
1527
- ```text
1528
- Start
1529
- -> ChannelSelectScreen
1530
- -> SkillTreeScreen
1531
- -> ApplyPreviewScreen
1532
- -> ApplyResultScreen
1533
- -> Exit
1534
- ```
1535
-
1536
- ## 9.2 `ChannelSelectScreen`
1537
-
1538
- ### 展示字段
1539
-
1540
- - channel 名称
1541
- - 是否检测到
1542
- - 目标路径
1543
- - 默认策略
1544
- - 健康状态
1545
-
1546
- ### 操作键
1547
-
1548
- - `↑ / ↓`:移动
1549
- - `Space`:切换选中
1550
- - `a`:全选 / 全不选
1551
- - `Enter`:进入下一屏
1552
- - `Esc`:退出
1553
-
1554
- ## 9.3 `SkillTreeScreen`
1555
-
1556
- ### 展示结构
1557
-
1558
- - 一级:source display root
1559
- - 二级:skill leaf
1560
-
1561
- ### 状态
1562
-
1563
- - `[ ]`:未选
1564
- - `[-]`:部分选中
1565
- - `[x]`:全部选中
1566
-
1567
- ### 操作键
1568
-
1569
- - `↑ / ↓`:移动
1570
- - `Space`:选中/取消
1571
- - `Tab`:展开/收起一级节点
1572
- - `Enter`:进入预览
1573
- - `Backspace`:返回上一屏
1574
-
1575
- ## 9.4 `ApplyPreviewScreen`
1576
-
1577
- ### 展示字段
1578
-
1579
- - channels 数量
1580
- - skills 数量
1581
- - create / replace / remove / skip 计数
1582
- - warnings 列表
1583
- - conflicts 列表
1584
-
1585
- ### 操作键
1586
-
1587
- - `Enter`:确认应用
1588
- - `Backspace`:返回树选择
1589
- - `q`:取消
1590
-
1591
- ---
1592
-
1593
- ## 10. 错误码规范
1594
-
1595
- 错误码统一形式:`SM_<DOMAIN>_<CODE>`
1596
-
1597
- ### 10.1 Source 相关
1598
-
1599
- - `SM_SOURCE_UNSUPPORTED`:无法识别来源
1600
- - `SM_SOURCE_RESOLVE_FAILED`:来源解析失败
1601
- - `SM_SOURCE_FETCH_FAILED`:下载或拉取失败
1602
- - `SM_SOURCE_UPDATE_CONFLICT`:更新过程中发现本地 source 被手工修改
1603
-
1604
- ### 10.2 Scan 相关
1605
-
1606
- - `SM_SCAN_SKILL_MD_MISSING`:未发现合法 `SKILL.md`
1607
- - `SM_SCAN_FRONTMATTER_INVALID`:frontmatter 无法解析
1608
- - `SM_SCAN_NAME_DIR_MISMATCH`:name 与目录名不一致
1609
- - `SM_SCAN_DUPLICATE_SKILL`:同一 source 内发现重名 skill
1610
-
1611
- ### 10.3 Deployment 相关
1612
-
1613
- - `SM_DEPLOY_TARGET_EXISTS_FOREIGN`:目标路径已存在非受管文件
1614
- - `SM_DEPLOY_BROKEN_SYMLINK`:存在断链
1615
- - `SM_DEPLOY_COPY_OUTSIDE_ROOT`:copy 目标越出受允根目录
1616
- - `SM_DEPLOY_STRATEGY_UNSUPPORTED`:channel 不支持该分发策略
1617
-
1618
- ### 10.4 State 相关
1619
-
1620
- - `SM_STATE_SCHEMA_UNKNOWN`:schemaVersion 不识别
1621
- - `SM_STATE_MIGRATION_FAILED`:状态迁移失败
1622
- - `SM_STATE_LOCK_WRITE_FAILED`:lock 原子写入失败
1623
-
1624
- ### 10.5 Doctor 相关
1625
-
1626
- - `SM_DOCTOR_CHANNEL_UNAVAILABLE`:渠道不可用
1627
- - `SM_DOCTOR_REALPATH_RISK`:realpath 风险
1628
- - `SM_DOCTOR_DRIFT_DETECTED`:manifest/lock/磁盘三者漂移
1629
-
1630
- ---
1631
-
1632
- ## 11. 日志与可观测性
1633
-
1634
- ### 11.1 控制台日志级别
1635
-
1636
- - `info`
1637
- - `warn`
1638
- - `error`
1639
- - `debug`
1640
-
1641
- ### 11.2 日志文件
1642
-
1643
- 建议:
1644
-
1645
- ```text
1646
- ~/.skillflow/logs/
1647
- current.log
1648
- previous.log
1649
- ```
1650
-
1651
- ### 11.3 审计事件
1652
-
1653
- `history.ndjson` 必须可回答这些问题:
1654
-
1655
- - 某个 source 何时被添加
1656
- - 某个 skill 何时被应用到某个 channel
1657
- - 某次 update 改了哪些 snapshot
1658
- - 某次 doctor 发现了什么问题
1659
-
1660
- ---
1661
-
1662
- ## 12. 安全与防御式实现要求
1663
-
1664
- 1. **默认不执行第三方脚本**
1665
- 2. **所有路径操作先做 `realpath` 校验**
1666
- 3. **受管 symlink 通过 sidecar 元数据或 lock 映射识别**
1667
- 4. **删除操作只删除受管目标**
1668
- 5. **copy 部署使用临时目录,完成后 rename 提交**
1669
- 6. **风险 flag 在 UI 和 JSON 输出中都必须可见**
1670
- 7. **外部 CLI bridge(如 ClawHub)必须收集 exit code、stdout、stderr**
1671
-
1672
- ---
1673
-
1674
- ## 13. 测试计划
1675
-
1676
- ## 13.1 单元测试
1677
-
1678
- 覆盖:
1679
-
1680
- - source parser
1681
- - id normalizer
1682
- - frontmatter parser
1683
- - manifest/lock validator
1684
- - planner diff 逻辑
1685
- - 错误码映射
1686
-
1687
- ## 13.2 集成测试
1688
-
1689
- ### 用例 A:Git 单仓多 skill
1690
-
1691
- 1. add git repo
1692
- 2. scan 出 3 个 leaf
1693
- 3. config 到 Claude + Codex
1694
- 4. 验证 symlink 数量与 lock deployments
1695
-
1696
- ### 用例 B:OpenClaw copy
1697
-
1698
- 1. 检测 workspace
1699
- 2. apply 到 openclaw
1700
- 3. 验证复制后的 skill realpath 在 workspace root 内
1701
-
1702
- ### 用例 C:更新后重投影
1703
-
1704
- 1. 初始安装 skill A
1705
- 2. 上游变更 skill A 内容
1706
- 3. update --apply
1707
- 4. lock 中 hash 更新,deployment 状态回到 `applied`
1708
-
1709
- ### 用例 D:foreign-existing
1710
-
1711
- 1. 在目标目录预先创建同名非受管文件夹
1712
- 2. apply
1713
- 3. 返回 `SM_DEPLOY_TARGET_EXISTS_FOREIGN`
1714
-
1715
- ### 用例 E:卸载
1716
-
1717
- 1. 安装 source X
1718
- 2. 投影到多个 channel
1719
- 3. uninstall X
1720
- 4. 验证 source、canonical、deployments 被清理
1721
-
1722
- ## 13.3 E2E 测试
1723
-
1724
- - 在临时 HOME 下运行完整 CLI
1725
- - 验证 state 文件与磁盘结构一致
1726
- - 验证 JSON 模式输出可供脚本消费
1727
-
1728
- ---
1729
-
1730
-
1731
- ## 13.4 Discovery 专项测试
1732
-
1733
- 需要新增以下测试矩阵:
1734
-
1735
- ### 用例 F:`find` 命中已安装技能
1736
-
1737
- - 本地 inventory 已存在 `react-best-practices`
1738
- - 查询 `react performance`
1739
- - 结果首屏应标注 `already installed`
1740
-
1741
- ### 用例 G:registry + leaderboard + git 混合召回
1742
-
1743
- - registry 返回 1 个 verified 候选
1744
- - leaderboard 返回 2 个热门候选
1745
- - git 搜索返回 3 个普通候选
1746
- - 排序应遵守 tier 与 trust 规则
1747
-
1748
- ### 用例 H:repo path 直装
1749
-
1750
- - 输入 `github:openai/skills --path skills/.curated/pdf`
1751
- - 应直接完成 source 导入、定位 leaf、生成 lock
1752
-
1753
- ### 用例 I:非 skill 工件忽略
1754
-
1755
- - source 同时包含 `skills/`、`commands/`、`agents/`
1756
- - 扫描器只纳入 skill,其他仅 warning
1757
-
1758
- ### 用例 J:安装后反馈
1759
-
1760
- - 对需要刷新 / 重启的渠道,安装完成后应给出提示
1761
- - 对可热加载渠道,不应误提示必须重启
1762
-
1763
- ## 14. 发布流程建议
1764
-
1765
- ## 14.1 首发发布
1766
-
1767
- - npm package:`skill-flow`
1768
- - 可执行入口:`bin/skill-flow`
1769
- - README 包含 quickstart 与 channel caveats
1770
-
1771
- ## 14.2 CI 流程
1772
-
1773
- - install
1774
- - lint
1775
- - test
1776
- - build
1777
- - package smoke test
1778
- - draft release
1779
-
1780
- ## 14.3 P1 发布补充
1781
-
1782
- - Homebrew tap
1783
- - shell completion
1784
- - upgrade notice
1785
-
1786
- ---
1787
-
1788
- ## 15. 首个 Sprint 建议拆解
1789
-
1790
- ### Sprint 1(基础骨架)
1791
-
1792
- - 初始化 oclif + TypeScript + pnpm + Vitest
1793
- - 建立 domain model
1794
- - state 文件读写与 schema 验证
1795
- - Git adapter 最小实现
1796
-
1797
- ### Sprint 2(扫描与列表)
1798
-
1799
- - scanner
1800
- - parser
1801
- - list
1802
- - canonical skill 构建
1803
-
1804
- ### Sprint 3(分发与 TUI)
1805
-
1806
- - Channel adapters
1807
- - planner / applier
1808
- - config TUI
1809
- - doctor 初版
1810
-
1811
- ### Sprint 4(更新与卸载)
1812
-
1813
- - update
1814
- - uninstall
1815
- - drift detection
1816
- - e2e 测试
1817
-
1818
- ### Sprint 5(ClawHub 与打磨)
1819
-
1820
- - ClawHub adapter
1821
- - JSON 输出模式
1822
- - 文档与发布流程
1823
-
1824
- ---
1825
-
1826
- ## 16. 最终实施结论
1827
-
1828
- 这份文档的最终工程结论如下:
1829
-
1830
- 1. **先做全局级 manager,再做项目级 manager**。
1831
- 2. **先做 Git + ClawHub 两类 source,再做 registry discovery**。
1832
- 3. **先做 per-channel strategy 自动化,再开放高级 override**。
1833
- 4. **坚持 manifest/lock 双层状态,不做无状态运行**。
1834
- 5. **坚持 OpenClaw 默认 copy,其他主渠道默认 symlink**。
1835
- 6. **坚持状态原子写入、部署 staged apply、删除只删受管内容**。
1836
- 7. **坚持 TUI 作为主配置界面,而不是靠长 flag 拼装体验**。
1837
-
1838
- 这已经足够作为研发启动、任务拆解和首轮工程评审的直接输入文档。
1839
-
1840
-
1841
- ---
1842
-
1843
- ## 附录 A:本次修订重点
1844
-
1845
- v1.2 相比 v1.1 新增或明确了以下内容:
1846
-
1847
- 1. 把 `search` 提升为正式 `find` Discovery 工作流。
1848
- 2. 新增 `SkillCandidate` 领域对象。
1849
- 3. 新增 Discovery Source Tiers 与排序规则。
1850
- 4. 新增 `install` 直装模式,支持 repo path / curated item / registry item。
1851
- 5. 新增 installed annotation 与安装后反馈要求。
1852
- 6. 新增 `inventory-index.json` 与 `discovery-cache.json`。
1853
- 7. 新增 Channel Feature Compatibility Matrix。
1854
- 8. 明确非 skill 工件默认忽略,不纳入 MVP 安装对象。
1855
-
1856
- ## 附录 B:参考资料
1857
-
1858
- - https://andrew.ooo/posts/openclaw-skills-sources-guide/
1859
- - https://github.com/openai/skills/blob/main/skills/.system/skill-installer/SKILL.md
1860
- - https://code.claude.com/docs/en/skills
1861
- - https://github.com/vercel-labs/skills/blob/main/skills/find-skills/SKILL.md
1862
- - https://github.com/alirezarezvani/claude-skills/blob/main/INSTALLATION.md