@house365/comate 0.9.24 → 0.9.26
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/LICENSE +21 -21
- package/README.md +102 -102
- package/bin/cleanup-duplicate-superpowers.mjs +119 -0
- package/bin/cli.mjs +7 -1
- package/bin/init.mjs +25 -5
- package/bin/update.mjs +6 -5
- package/docs/COMATE_MANUAL.md +695 -695
- package/package.json +55 -55
- package/skills/comate/SKILL.md +309 -309
- package/skills/comate/reference/decision-points.md +101 -101
- package/skills/comate/reference/dirty-worktree.md +58 -58
- package/skills/comate/reference/prerequisites.md +88 -88
- package/skills/comate-archive/SKILL.md +63 -63
- package/skills/comate-build/SKILL.md +227 -227
- package/skills/comate-design/SKILL.md +156 -156
- package/skills/comate-gate/SKILL.md +262 -212
- package/skills/comate-gate/scaffold/docs/README.md +36 -36
- package/skills/comate-gate/scaffold/docs/architecture/README.md +31 -31
- package/skills/comate-gate/scaffold/docs/knowledge-base/README.md +41 -41
- package/skills/comate-gate/scaffold/docs/knowledge-base/integrations/_TEMPLATE/README.md +49 -49
- package/skills/comate-gate/scaffold/docs/knowledge-base/integrations/_TEMPLATE/api-snapshot.md +47 -47
- package/skills/comate-gate/scaffold/docs/knowledge-base/requirements/_templates/PRD.md +95 -95
- package/skills/comate-grill/SKILL.md +185 -185
- package/skills/comate-kb-integration/scripts/fetch_rendered_doc.py +84 -84
- package/skills/comate-open/SKILL.md +176 -176
- package/skills/comate-verify/SKILL.md +145 -145
- package/docs/multica-integration.md +0 -400
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Jian Liang
|
|
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.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jian Liang
|
|
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
CHANGED
|
@@ -1,110 +1,110 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
<img src="comate.png" alt="comate" width="600">
|
|
3
|
-
</div>
|
|
4
|
-
|
|
5
|
-
# comate
|
|
6
|
-
|
|
7
|
-
**SDD (规约驱动开发)** 的 AI 开发编排器。
|
|
8
|
-
|
|
9
|
-
comate 践行 **Specification-Driven Development (SDD)** 理念,通过五阶段工作流(gate → open → design → build → verify → archive)确保每个变更都有完整的规约与设计(fix 预设除外)。底层集成 **OpenSpec**(提案、规约生命周期、归档)和 **Superpowers**(技术设计、规划、执行、收尾),并提供 PRD 门禁、决策澄清、知识库对接等编排能力。
|
|
10
|
-
|
|
11
|
-
## 五阶段
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
[原始 PRD] ─→ /comate-gate ─┐ (阶段 0:门禁+拆分)
|
|
15
|
-
▼
|
|
16
|
-
/comate ──自动探测阶段──────→ open → design → build → verify → archive
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
| 阶段 | skill | 职责 |
|
|
20
|
-
|------|-------|------|
|
|
21
|
-
| gate | `/comate-gate` | (阶段 0,可选)对原始 PRD 做质量门禁 + 拆分成 N 个 change |
|
|
22
|
-
| open | `/comate-open` | 探索想法,创建 change 结构并初始化 `.comate.yaml` |
|
|
23
|
-
| design | `/comate-design` | 技术设计与方案 brainstorming |
|
|
24
|
-
| build | `/comate-build` | 按任务实现并提交 |
|
|
25
|
-
| verify | `/comate-verify` | 验证、出报告、处理分支 |
|
|
26
|
-
| archive | `/comate-archive` | 同步增量规约并归档 |
|
|
27
|
-
|
|
28
|
-
预设路径:`/comate-fix`(快速小改动,覆盖 bug 修复与文案/配置小调整两种模式)。
|
|
29
|
-
|
|
30
|
-
工具 skill:
|
|
31
|
-
- `/comate-grill`(决策点穷追式澄清)——对计划/设计/PRD 的模糊点逐个深挖,每问附推荐答案、一次一问,直到歧义清零。comate-gate 在阻断问题多、有依赖链时会自动提供「深度澄清」选项调用它;也可单独 `/comate-grill <话题>` 挑战自己的计划草稿。
|
|
32
|
-
- `/comate-kb-integration`(第三方对接档案生成)——从官方文档 URL 抓取并按 `docs/knowledge-base/integrations/_TEMPLATE/` 规范产出对接档案(`<service-id>/README.md` + `api-snapshot.md`),自动追加根索引一行。是知识库 integrations scaffold 的配套建档工具;遇 JS 动态渲染文档站自动降级 Playwright 无头抓取。
|
|
33
|
-
|
|
34
|
-
**阶段 0(PRD 门禁与拆分)**:需求若来自一份**原始 PRD**,先过 `/comate-gate`——它审阅 PRD 质量、百分制评分、建阻断台账,门禁通过前禁止建任何 change;通过后按依赖/独立性判定把 PRD 拆成 1 或 N 个 change(粒度由用户定),逐个交给 `/comate-open`。门禁状态钉在 PRD 同级 `<PRD>.gate.yaml`,PRD 通过后被改会自动失效需重跑。需求来自对话时无需此阶段,直接从 open 起步。
|
|
35
|
-
|
|
36
|
-
## 安装
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
npm install -g @house365/comate
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
到项目目录初始化:
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
cd your-project
|
|
46
|
-
comate init
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
`init` 会装好 comate 及其依赖(OpenSpec CLI、Superpowers),创建 `openspec/` 项目结构,并铺出 `docs/` 知识库骨架(`docs/knowledge-base/requirements/` 放 PRD + PRD 模板、`docs/architecture/` 架构规范占位、integrations 对接模板)——`/comate-gate` 从这里读 PRD。支持 Claude Code、Codex、Cursor 等 70+ agent。可重复执行,已装的自动跳过,已有的 docs 文件不覆盖。
|
|
50
|
-
|
|
51
|
-
skills 装到用户级(`~/.agents/skills`),装一次所有项目共用;`openspec/` 是项目自己的规约,建在当前目录,所以 `init` 需要在项目目录下运行。
|
|
52
|
-
|
|
53
|
-
装完输入 `/comate` 开始使用,`comate doctor` 可自检。
|
|
54
|
-
|
|
55
|
-
## 更新
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
npm install -g @house365/comate@latest
|
|
59
|
-
cd your-project && comate init
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
两步都要跑:`npm` 只换 CLI 本身,skills 是 `comate init` 铺到 `~/.agents/skills` 的,npm 不管。这里的 `@latest` 不能省——本地已装时,不带 tag 的 `npm install -g` 可能认为已满足而不去 registry 取新版。
|
|
63
|
-
|
|
64
|
-
## 用法
|
|
65
|
-
|
|
66
|
-
输入 `/comate` 自动探测当前阶段并分派,或直接调用某个阶段 skill。状态记录在每个 change 的 `openspec/changes/<name>/.comate.yaml` 中,支持上下文压缩后断点恢复。
|
|
67
|
-
|
|
68
|
-
## Token 用量:`comate usage`
|
|
69
|
-
|
|
70
|
-
查看**当前项目**的 token 消耗与估算成本(封装 [ccusage](https://github.com/ryoppippi/ccusage),随 comate 一起装):
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
comate usage # 本项目按会话(session)统计
|
|
74
|
-
comate usage daily # 本项目按天
|
|
75
|
-
comate usage --global # 全部项目(不做项目隔离)
|
|
76
|
-
comate usage --json -s 2026-08-01 # 其余参数原样透传给 ccusage
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
默认只统计当前工作目录这一个项目:Claude Code 数据按 `~/.claude/projects/<项目>/` 隔离,Codex 数据按会话记录里的 `cwd` 过滤,两者都不会混入其它项目的用量。加 `--global` 看全量,或用 `comate usage codex ...` 单看某个 agent。
|
|
80
|
-
|
|
81
|
-
> 粒度到项目/会话级;不做 open/design/build 阶段级归因(那需要在状态机打时间戳,属后续增强)。
|
|
82
|
-
|
|
83
|
-
## 目录结构
|
|
84
|
-
|
|
85
|
-
```
|
|
86
|
-
skills/
|
|
87
|
-
comate/ 主编排器:SKILL.md + 脚本 + 参考文档 + 测试
|
|
88
|
-
scripts/ comate.sh(CLI)、comate-lib.sh(共享库)
|
|
89
|
-
reference/ 决策点、脏工作树协议、前置条件
|
|
90
|
-
tests/ bats 测试
|
|
91
|
-
comate-open/ design/ build/ verify/ archive/ 各阶段 skill
|
|
92
|
-
comate-gate/ 阶段 0:PRD 门禁与拆分
|
|
93
|
-
comate-fix/ 预设路径 skill(bug + 小调整)
|
|
94
|
-
comate-grill/ 决策点穷追式澄清工具
|
|
95
|
-
comate-kb-integration/ 第三方对接档案生成工具(知识库配套)
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="comate.png" alt="comate" width="600">
|
|
3
|
+
</div>
|
|
4
|
+
|
|
5
|
+
# comate
|
|
6
|
+
|
|
7
|
+
**SDD (规约驱动开发)** 的 AI 开发编排器。
|
|
8
|
+
|
|
9
|
+
comate 践行 **Specification-Driven Development (SDD)** 理念,通过五阶段工作流(gate → open → design → build → verify → archive)确保每个变更都有完整的规约与设计(fix 预设除外)。底层集成 **OpenSpec**(提案、规约生命周期、归档)和 **Superpowers**(技术设计、规划、执行、收尾),并提供 PRD 门禁、决策澄清、知识库对接等编排能力。
|
|
10
|
+
|
|
11
|
+
## 五阶段
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
[原始 PRD] ─→ /comate-gate ─┐ (阶段 0:门禁+拆分)
|
|
15
|
+
▼
|
|
16
|
+
/comate ──自动探测阶段──────→ open → design → build → verify → archive
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
| 阶段 | skill | 职责 |
|
|
20
|
+
|------|-------|------|
|
|
21
|
+
| gate | `/comate-gate` | (阶段 0,可选)对原始 PRD 做质量门禁 + 拆分成 N 个 change |
|
|
22
|
+
| open | `/comate-open` | 探索想法,创建 change 结构并初始化 `.comate.yaml` |
|
|
23
|
+
| design | `/comate-design` | 技术设计与方案 brainstorming |
|
|
24
|
+
| build | `/comate-build` | 按任务实现并提交 |
|
|
25
|
+
| verify | `/comate-verify` | 验证、出报告、处理分支 |
|
|
26
|
+
| archive | `/comate-archive` | 同步增量规约并归档 |
|
|
27
|
+
|
|
28
|
+
预设路径:`/comate-fix`(快速小改动,覆盖 bug 修复与文案/配置小调整两种模式)。
|
|
29
|
+
|
|
30
|
+
工具 skill:
|
|
31
|
+
- `/comate-grill`(决策点穷追式澄清)——对计划/设计/PRD 的模糊点逐个深挖,每问附推荐答案、一次一问,直到歧义清零。comate-gate 在阻断问题多、有依赖链时会自动提供「深度澄清」选项调用它;也可单独 `/comate-grill <话题>` 挑战自己的计划草稿。
|
|
32
|
+
- `/comate-kb-integration`(第三方对接档案生成)——从官方文档 URL 抓取并按 `docs/knowledge-base/integrations/_TEMPLATE/` 规范产出对接档案(`<service-id>/README.md` + `api-snapshot.md`),自动追加根索引一行。是知识库 integrations scaffold 的配套建档工具;遇 JS 动态渲染文档站自动降级 Playwright 无头抓取。
|
|
33
|
+
|
|
34
|
+
**阶段 0(PRD 门禁与拆分)**:需求若来自一份**原始 PRD**,先过 `/comate-gate`——它审阅 PRD 质量、百分制评分、建阻断台账,门禁通过前禁止建任何 change;通过后按依赖/独立性判定把 PRD 拆成 1 或 N 个 change(粒度由用户定),逐个交给 `/comate-open`。门禁状态钉在 PRD 同级 `<PRD>.gate.yaml`,PRD 通过后被改会自动失效需重跑。需求来自对话时无需此阶段,直接从 open 起步。
|
|
35
|
+
|
|
36
|
+
## 安装
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install -g @house365/comate
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
到项目目录初始化:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
cd your-project
|
|
46
|
+
comate init
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`init` 会装好 comate 及其依赖(OpenSpec CLI、Superpowers),创建 `openspec/` 项目结构,并铺出 `docs/` 知识库骨架(`docs/knowledge-base/requirements/` 放 PRD + PRD 模板、`docs/architecture/` 架构规范占位、integrations 对接模板)——`/comate-gate` 从这里读 PRD。支持 Claude Code、Codex、Cursor 等 70+ agent。可重复执行,已装的自动跳过,已有的 docs 文件不覆盖。
|
|
50
|
+
|
|
51
|
+
skills 装到用户级(`~/.agents/skills`),装一次所有项目共用;`openspec/` 是项目自己的规约,建在当前目录,所以 `init` 需要在项目目录下运行。
|
|
52
|
+
|
|
53
|
+
装完输入 `/comate` 开始使用,`comate doctor` 可自检。
|
|
54
|
+
|
|
55
|
+
## 更新
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install -g @house365/comate@latest
|
|
59
|
+
cd your-project && comate init
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
两步都要跑:`npm` 只换 CLI 本身,skills 是 `comate init` 铺到 `~/.agents/skills` 的,npm 不管。这里的 `@latest` 不能省——本地已装时,不带 tag 的 `npm install -g` 可能认为已满足而不去 registry 取新版。
|
|
63
|
+
|
|
64
|
+
## 用法
|
|
65
|
+
|
|
66
|
+
输入 `/comate` 自动探测当前阶段并分派,或直接调用某个阶段 skill。状态记录在每个 change 的 `openspec/changes/<name>/.comate.yaml` 中,支持上下文压缩后断点恢复。
|
|
67
|
+
|
|
68
|
+
## Token 用量:`comate usage`
|
|
69
|
+
|
|
70
|
+
查看**当前项目**的 token 消耗与估算成本(封装 [ccusage](https://github.com/ryoppippi/ccusage),随 comate 一起装):
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
comate usage # 本项目按会话(session)统计
|
|
74
|
+
comate usage daily # 本项目按天
|
|
75
|
+
comate usage --global # 全部项目(不做项目隔离)
|
|
76
|
+
comate usage --json -s 2026-08-01 # 其余参数原样透传给 ccusage
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
默认只统计当前工作目录这一个项目:Claude Code 数据按 `~/.claude/projects/<项目>/` 隔离,Codex 数据按会话记录里的 `cwd` 过滤,两者都不会混入其它项目的用量。加 `--global` 看全量,或用 `comate usage codex ...` 单看某个 agent。
|
|
80
|
+
|
|
81
|
+
> 粒度到项目/会话级;不做 open/design/build 阶段级归因(那需要在状态机打时间戳,属后续增强)。
|
|
82
|
+
|
|
83
|
+
## 目录结构
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
skills/
|
|
87
|
+
comate/ 主编排器:SKILL.md + 脚本 + 参考文档 + 测试
|
|
88
|
+
scripts/ comate.sh(CLI)、comate-lib.sh(共享库)
|
|
89
|
+
reference/ 决策点、脏工作树协议、前置条件
|
|
90
|
+
tests/ bats 测试
|
|
91
|
+
comate-open/ design/ build/ verify/ archive/ 各阶段 skill
|
|
92
|
+
comate-gate/ 阶段 0:PRD 门禁与拆分
|
|
93
|
+
comate-fix/ 预设路径 skill(bug + 小调整)
|
|
94
|
+
comate-grill/ 决策点穷追式澄清工具
|
|
95
|
+
comate-kb-integration/ 第三方对接档案生成工具(知识库配套)
|
|
96
96
|
docs/
|
|
97
97
|
COMATE_BEGINNER_GUIDE.md 面向新手的安装与使用手册
|
|
98
98
|
COMATE_MANUAL.md 完整操作手册
|
|
99
99
|
```
|
|
100
|
-
|
|
101
|
-
## 文档
|
|
102
|
-
|
|
100
|
+
|
|
101
|
+
## 文档
|
|
102
|
+
|
|
103
103
|
文档:
|
|
104
104
|
|
|
105
105
|
- [入门操作手册](docs/COMATE_BEGINNER_GUIDE.md):面向第一次使用 comate 的同学,覆盖安装、`init`、目录、PRD、Skill 流程和常见问题。
|
|
106
106
|
- [完整技术手册](docs/COMATE_MANUAL.md):安装前置、命令参考、阶段详解、状态文件字段、决策阻塞点、故障排除。
|
|
107
|
-
|
|
108
|
-
## License
|
|
109
|
-
|
|
110
|
-
[MIT](LICENSE)
|
|
107
|
+
|
|
108
|
+
## License
|
|
109
|
+
|
|
110
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// 清理重复的 superpowers 安装(当 plugin 版本已存在时)
|
|
3
|
+
import { existsSync, readFileSync, rmSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
|
|
6
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? '';
|
|
7
|
+
|
|
8
|
+
// 检查是否有 Claude Code plugin 安装
|
|
9
|
+
function hasPluginInstall() {
|
|
10
|
+
const pluginRegistry = join(home, '.claude', 'plugins', 'installed_plugins.json');
|
|
11
|
+
if (!existsSync(pluginRegistry)) return false;
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const registry = JSON.parse(readFileSync(pluginRegistry, 'utf8'));
|
|
15
|
+
return Object.keys(registry.plugins || {}).some((key) =>
|
|
16
|
+
key.startsWith('superpowers@') &&
|
|
17
|
+
Array.isArray(registry.plugins[key]) &&
|
|
18
|
+
registry.plugins[key].length > 0
|
|
19
|
+
);
|
|
20
|
+
} catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// 检查并清理 skills CLI 安装的 superpowers
|
|
26
|
+
function cleanupSkillsCliInstall() {
|
|
27
|
+
const skillsRoots = [
|
|
28
|
+
join(home, '.agents', 'skills'),
|
|
29
|
+
join(home, '.claude', 'skills'),
|
|
30
|
+
join(home, '.config', 'skills'),
|
|
31
|
+
join(home, '.cursor', 'skills'),
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const superpowersSkills = ['using-superpowers', 'brainstorming'];
|
|
35
|
+
const removed = [];
|
|
36
|
+
|
|
37
|
+
for (const root of skillsRoots) {
|
|
38
|
+
for (const skill of superpowersSkills) {
|
|
39
|
+
const skillPath = join(root, skill);
|
|
40
|
+
if (existsSync(skillPath)) {
|
|
41
|
+
try {
|
|
42
|
+
rmSync(skillPath, { recursive: true, force: true });
|
|
43
|
+
removed.push(skillPath);
|
|
44
|
+
} catch (err) {
|
|
45
|
+
console.error(`✗ 删除失败: ${skillPath}`);
|
|
46
|
+
console.error(` 错误: ${err.message}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return removed;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 主函数
|
|
56
|
+
export function cleanup() {
|
|
57
|
+
console.log('=== Superpowers 重复安装清理工具 ===\n');
|
|
58
|
+
|
|
59
|
+
// 1. 检查 plugin 安装
|
|
60
|
+
console.log('1. 检查 Claude Code plugin 安装...');
|
|
61
|
+
if (!hasPluginInstall()) {
|
|
62
|
+
console.log(' ✗ 未检测到 Claude Code plugin 版本的 superpowers');
|
|
63
|
+
console.log(' ⚠️ 不建议清理 skills CLI 版本,因为没有其他可用版本\n');
|
|
64
|
+
return 1;
|
|
65
|
+
}
|
|
66
|
+
console.log(' ✓ 检测到 Claude Code plugin 版本\n');
|
|
67
|
+
|
|
68
|
+
// 2. 列出将要删除的目录
|
|
69
|
+
console.log('2. 扫描 skills CLI 安装...');
|
|
70
|
+
const skillsRoots = [
|
|
71
|
+
join(home, '.agents', 'skills'),
|
|
72
|
+
join(home, '.claude', 'skills'),
|
|
73
|
+
join(home, '.config', 'skills'),
|
|
74
|
+
join(home, '.cursor', 'skills'),
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
const superpowersSkills = ['using-superpowers', 'brainstorming'];
|
|
78
|
+
const toRemove = [];
|
|
79
|
+
|
|
80
|
+
for (const root of skillsRoots) {
|
|
81
|
+
for (const skill of superpowersSkills) {
|
|
82
|
+
const skillPath = join(root, skill);
|
|
83
|
+
if (existsSync(skillPath)) {
|
|
84
|
+
toRemove.push(skillPath);
|
|
85
|
+
console.log(` 发现: ${skillPath}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (toRemove.length === 0) {
|
|
91
|
+
console.log(' ✓ 未发现 skills CLI 版本的 superpowers\n');
|
|
92
|
+
console.log('无需清理,已经是最优状态!');
|
|
93
|
+
return 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
console.log(`\n 共找到 ${toRemove.length} 个目录需要清理\n`);
|
|
97
|
+
|
|
98
|
+
// 3. 确认清理
|
|
99
|
+
console.log('3. 执行清理...');
|
|
100
|
+
const removed = cleanupSkillsCliInstall();
|
|
101
|
+
|
|
102
|
+
if (removed.length > 0) {
|
|
103
|
+
console.log(` ✓ 已删除 ${removed.length} 个目录:`);
|
|
104
|
+
for (const path of removed) {
|
|
105
|
+
console.log(` - ${path}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
console.log('\n=== 清理完成 ===');
|
|
110
|
+
console.log('现在只使用 Claude Code plugin 版本的 superpowers');
|
|
111
|
+
console.log('相关 skill 在 Claude 中仍然可用\n');
|
|
112
|
+
|
|
113
|
+
return 0;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// 当作为脚本直接运行时
|
|
117
|
+
if (import.meta.url === `file:///${process.argv[1].replace(/\\/g, '/')}`) {
|
|
118
|
+
process.exit(cleanup());
|
|
119
|
+
}
|
package/bin/cli.mjs
CHANGED
|
@@ -52,7 +52,7 @@ async function checkForUpdates(currentVersion) {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
// comate 自身的子命令(在下方被先取处理,不会透传给 skills CLI)。
|
|
55
|
-
const COMATE_COMMANDS = ['init', 'doctor', 'update', 'usage'];
|
|
55
|
+
const COMATE_COMMANDS = ['init', 'doctor', 'update', 'usage', 'cleanup'];
|
|
56
56
|
|
|
57
57
|
// 允许透传给 skills CLI 的子命令(含别名)。留在这里的都是 skills CLI 真实存在
|
|
58
58
|
// 的命令,未列入的一律视为未知命令并命中 --help。init/update 已被 comate 先取,
|
|
@@ -93,6 +93,7 @@ const HELP_TEXT = `comate — SDD (规约驱动开发) 的 AI 开发编排器
|
|
|
93
93
|
comate doctor 健康检查
|
|
94
94
|
comate update 更新 comate 到最新版本
|
|
95
95
|
comate usage 查看本项目 token 用量(--global 看全部;参数透传给 ccusage)
|
|
96
|
+
comate cleanup 清理重复的 superpowers 安装(当 plugin 版本已存在时)
|
|
96
97
|
comate --help, -h 显示本帮助
|
|
97
98
|
comate --version, -v 显示版本号
|
|
98
99
|
|
|
@@ -144,6 +145,11 @@ if (args[0] === 'usage') {
|
|
|
144
145
|
process.exit(await usage(args.slice(1), { pkgRoot }));
|
|
145
146
|
}
|
|
146
147
|
|
|
148
|
+
if (args[0] === 'cleanup') {
|
|
149
|
+
const { cleanup } = await import('./cleanup-duplicate-superpowers.mjs');
|
|
150
|
+
process.exit(cleanup());
|
|
151
|
+
}
|
|
152
|
+
|
|
147
153
|
if (args[0] === '--help' || args[0] === '-h' || args[0] === 'help') {
|
|
148
154
|
printHelp();
|
|
149
155
|
process.exit(0);
|
package/bin/init.mjs
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// ponytail: no SKILLS_AGENT_MAP here. The skills CLI detects the running agent
|
|
10
10
|
// on its own, so translating platform ids to agent names would be dead code.
|
|
11
11
|
import { spawnSync } from 'node:child_process';
|
|
12
|
-
import { existsSync, mkdirSync, readdirSync, copyFileSync, statSync, lstatSync, rmSync } from 'node:fs';
|
|
12
|
+
import { existsSync, mkdirSync, readdirSync, copyFileSync, statSync, lstatSync, rmSync, readFileSync } from 'node:fs';
|
|
13
13
|
import { createRequire } from 'node:module';
|
|
14
14
|
import { dirname, join } from 'node:path';
|
|
15
15
|
|
|
@@ -149,9 +149,8 @@ function openSpecState() {
|
|
|
149
149
|
return { status: atLeast(version, MIN_OPENSPEC) ? 'ready' : 'outdated', version };
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
//
|
|
153
|
-
//
|
|
154
|
-
// user-level install and should not count.
|
|
152
|
+
// Detect skills CLI installation (flattens obra/superpowers into one dir per
|
|
153
|
+
// skill) and Claude Code plugin installation (installed_plugins.json registry).
|
|
155
154
|
const SUPERPOWERS_MARKERS = [
|
|
156
155
|
['using-superpowers'],
|
|
157
156
|
['brainstorming'],
|
|
@@ -164,7 +163,28 @@ function superpowersInstalled(scope) {
|
|
|
164
163
|
? ['.agents/skills', '.claude/skills', '.config/skills', '.cursor/skills']
|
|
165
164
|
.map((r) => join(home, r))
|
|
166
165
|
: ['.agents/skills', '.claude/skills', '.cursor/skills', '.codex/skills'];
|
|
167
|
-
|
|
166
|
+
|
|
167
|
+
// Check skills CLI installation
|
|
168
|
+
if (roots.some((root) => SUPERPOWERS_MARKERS.some((m) => existsSync(join(root, ...m))))) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Check Claude Code plugin installation (only for global scope - plugins are user-level)
|
|
173
|
+
if (scope === 'global') {
|
|
174
|
+
const pluginRegistry = join(home, '.claude', 'plugins', 'installed_plugins.json');
|
|
175
|
+
try {
|
|
176
|
+
const registry = JSON.parse(readFileSync(pluginRegistry, 'utf8'));
|
|
177
|
+
// Check if superpowers plugin is installed (any marketplace)
|
|
178
|
+
return Object.keys(registry.plugins || {}).some((key) =>
|
|
179
|
+
key.startsWith('superpowers@') && Array.isArray(registry.plugins[key]) && registry.plugins[key].length > 0
|
|
180
|
+
);
|
|
181
|
+
} catch {
|
|
182
|
+
// File doesn't exist or parse failed - not a plugin install
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return false;
|
|
168
188
|
}
|
|
169
189
|
|
|
170
190
|
// The docs scaffold ships inside the comate skill, so it is present both in dev
|
package/bin/update.mjs
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import { get } from 'node:https';
|
|
3
3
|
import { spawn } from 'node:child_process';
|
|
4
4
|
|
|
5
|
+
import { npmInvocation } from './init.mjs';
|
|
6
|
+
|
|
5
7
|
// Fetch the latest version from npm registry
|
|
6
8
|
function fetchLatestVersion() {
|
|
7
9
|
return new Promise((resolve, reject) => {
|
|
@@ -30,16 +32,15 @@ function fetchLatestVersion() {
|
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
// Run npm install -g with live output
|
|
33
|
-
function runNpmInstall(packageName) {
|
|
35
|
+
export function runNpmInstall(packageName, { spawnFn = spawn, invocation = npmInvocation } = {}) {
|
|
34
36
|
return new Promise((resolve) => {
|
|
35
37
|
console.log(`\n正在更新 ${packageName}...\n`);
|
|
36
38
|
|
|
37
|
-
const
|
|
38
|
-
const npmCmd = isWindows ? 'npm.cmd' : 'npm';
|
|
39
|
+
const { command, args, shell } = invocation(['install', '-g', packageName]);
|
|
39
40
|
|
|
40
|
-
const child =
|
|
41
|
+
const child = spawnFn(command, args, {
|
|
41
42
|
stdio: 'inherit',
|
|
42
|
-
shell:
|
|
43
|
+
...(shell ? { shell: true } : {}),
|
|
43
44
|
});
|
|
44
45
|
|
|
45
46
|
child.on('close', (code) => {
|