@house365/comate 0.1.3 → 0.1.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.
- package/README.md +7 -25
- package/bin/cli.mjs +9 -11
- package/bin/doctor.mjs +44 -0
- package/bin/init-run.mjs +43 -69
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -25,39 +25,21 @@ open → design → build → verify → archive
|
|
|
25
25
|
## 安装
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
|
|
29
|
-
npx @house365/comate init # 装到 ./.agents/skills/
|
|
28
|
+
npm install -g @house365/comate
|
|
30
29
|
```
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
到项目目录初始化:
|
|
33
32
|
|
|
34
33
|
```bash
|
|
35
|
-
|
|
34
|
+
cd your-project
|
|
35
|
+
comate init
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
`init`
|
|
38
|
+
`init` 会装好 comate 及其依赖(OpenSpec CLI、Superpowers),并创建 `openspec/` 项目结构。支持 Claude Code、Codex、Cursor 等 70+ agent。可重复执行,已装的自动跳过。
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
装完输入 `/comate` 开始使用,`comate doctor` 可自检。
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
npx @house365/comate # 装到当前项目 ./.agents/skills/
|
|
46
|
-
npx @house365/comate -g # 装到用户全局
|
|
47
|
-
npx @house365/comate --list # 只看有哪些 skill,不安装
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
需要同时创建 `openspec/` 项目结构时加 `--openspec-init`。
|
|
51
|
-
|
|
52
|
-
支持 Claude Code、Codex、Cursor 等 70+ agent(底层复用 [`skills`](https://www.npmjs.com/package/skills) CLI,自动探测当前 agent)。
|
|
53
|
-
|
|
54
|
-
装完跑一次健康检查:
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
bash .agents/skills/comate/scripts/comate.sh doctor
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
依赖详情见 [docs/COMATE_MANUAL.md](docs/COMATE_MANUAL.md) 第 2 节。
|
|
42
|
+
想装到用户全局、所有项目共用,加 `-g`。
|
|
61
43
|
|
|
62
44
|
## 用法
|
|
63
45
|
|
package/bin/cli.mjs
CHANGED
|
@@ -13,24 +13,22 @@ const args = process.argv.slice(2);
|
|
|
13
13
|
|
|
14
14
|
if (args[0] === 'init') {
|
|
15
15
|
const { init } = await import('./init-run.mjs');
|
|
16
|
-
process.exit(await init(pkgRoot
|
|
16
|
+
process.exit(await init(pkgRoot));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (args[0] === 'doctor') {
|
|
20
|
+
const { doctor } = await import('./doctor.mjs');
|
|
21
|
+
process.exit(doctor(args.slice(1)));
|
|
17
22
|
}
|
|
18
23
|
|
|
19
24
|
if (args[0] === '--help' || args[0] === '-h') {
|
|
20
25
|
console.log(`comate — OpenSpec + Superpowers 规约驱动的开发编排器
|
|
21
26
|
|
|
22
27
|
用法:
|
|
23
|
-
comate
|
|
24
|
-
|
|
25
|
-
项目安装装到当前目录,执行前会打印完整路径并确认这像个项目目录。
|
|
26
|
-
-g, --global 安装到用户全局目录 (默认: 当前项目)
|
|
27
|
-
--openspec-init 同时运行 openspec init 创建项目结构
|
|
28
|
-
-f, --force 跳过目录检查,就装在当前目录
|
|
29
|
-
|
|
30
|
-
comate-skills [add|list|remove|update ...]
|
|
31
|
-
直接透传给 skills CLI。不带子命令时安装本包全部 skill。
|
|
28
|
+
comate init 在当前项目安装 comate、依赖和 openspec/ 结构
|
|
29
|
+
comate doctor 健康检查
|
|
32
30
|
|
|
33
|
-
|
|
31
|
+
装好后在 agent 中输入 /comate 开始使用。`);
|
|
34
32
|
process.exit(0);
|
|
35
33
|
}
|
|
36
34
|
|
package/bin/doctor.mjs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// `comate doctor` — run the installed comate.sh health check.
|
|
2
|
+
//
|
|
3
|
+
// ponytail: comate.sh already implements every check. This only locates the
|
|
4
|
+
// installed copy so the user doesn't have to remember the path.
|
|
5
|
+
import { spawnSync } from 'node:child_process';
|
|
6
|
+
import { existsSync } from 'node:fs';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
|
|
9
|
+
// Where the skills CLI puts things. The project copy comes first so it wins
|
|
10
|
+
// over a global one left from an earlier `comate -g` install.
|
|
11
|
+
function skillRoots() {
|
|
12
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? '';
|
|
13
|
+
const dirs = ['.agents/skills', '.claude/skills', '.cursor/skills', '.codex/skills'];
|
|
14
|
+
return [...dirs.map((d) => join(process.cwd(), d)), ...dirs.map((d) => join(home, d))];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function findComateScript(roots = skillRoots()) {
|
|
18
|
+
for (const root of roots) {
|
|
19
|
+
const script = join(root, 'comate', 'scripts', 'comate.sh');
|
|
20
|
+
if (existsSync(script)) return script;
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function doctor(argv) {
|
|
26
|
+
const script = findComateScript();
|
|
27
|
+
if (!script) {
|
|
28
|
+
console.error('找不到已安装的 comate。先运行: comate init');
|
|
29
|
+
return 1;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// comate.sh resolves sibling skills relative to the skills root, so run it
|
|
33
|
+
// from there rather than from wherever the user happens to be.
|
|
34
|
+
const skillsRoot = join(script, '..', '..', '..');
|
|
35
|
+
const { status, error } = spawnSync('bash', [script, 'doctor', ...argv], {
|
|
36
|
+
cwd: skillsRoot,
|
|
37
|
+
stdio: 'inherit',
|
|
38
|
+
});
|
|
39
|
+
if (error) {
|
|
40
|
+
console.error(`无法执行 bash — comate 的脚本需要 bash。${error.message}`);
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
return status ?? 1;
|
|
44
|
+
}
|
package/bin/init-run.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// The `init` flow:
|
|
1
|
+
// The `init` flow: install whatever the current project is missing.
|
|
2
2
|
import { existsSync } from 'node:fs';
|
|
3
3
|
import { join, resolve } from 'node:path';
|
|
4
4
|
|
|
@@ -13,16 +13,12 @@ import {
|
|
|
13
13
|
superpowersInstalled,
|
|
14
14
|
} from './init.mjs';
|
|
15
15
|
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// A project install lands in cwd, and `npx` runs wherever the user happens to
|
|
23
|
-
// be — so cwd is a guess, not a decision. Report it, and refuse the two cases
|
|
24
|
-
// that are almost certainly a mistake: the home directory (that's what -g is
|
|
25
|
-
// for) and a directory with no project marker at all.
|
|
16
|
+
// `comate init` initialises the current project — no flags. Global installs are
|
|
17
|
+
// still reachable through the bare `comate -g` passthrough to the skills CLI.
|
|
18
|
+
//
|
|
19
|
+
// cwd is where the install lands, so refuse the two cases that are almost
|
|
20
|
+
// certainly a mistake: the home directory, and a directory with no project
|
|
21
|
+
// marker at all.
|
|
26
22
|
const PROJECT_MARKERS = [
|
|
27
23
|
'.git',
|
|
28
24
|
'package.json',
|
|
@@ -44,44 +40,25 @@ export function inspectTarget(dir, home) {
|
|
|
44
40
|
return marker ? { kind: 'project', marker } : { kind: 'bare' };
|
|
45
41
|
}
|
|
46
42
|
|
|
47
|
-
export async function init(pkgRoot
|
|
48
|
-
const scope = resolveScope(argv);
|
|
49
|
-
const withOpenSpecInit = argv.includes('--openspec-init');
|
|
50
|
-
const force = argv.includes('-f') || argv.includes('--force');
|
|
43
|
+
export async function init(pkgRoot) {
|
|
51
44
|
const results = [];
|
|
52
|
-
|
|
53
45
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? '';
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
comate-skills init -g
|
|
66
|
-
|
|
67
|
-
确实要装在这里,加 --force。`);
|
|
68
|
-
return 1;
|
|
69
|
-
}
|
|
70
|
-
if (target.kind === 'bare' && !force) {
|
|
71
|
-
console.error(`
|
|
72
|
-
当前目录看不出是个项目(没有 .git / package.json / pyproject.toml 等标志)。
|
|
73
|
-
comate 会把 skill 装进上面这个路径,先确认这是你要的目录:
|
|
74
|
-
|
|
75
|
-
cd <你的项目目录> && npx @house365/comate init # 换个目录
|
|
76
|
-
npx @house365/comate init -g # 装到全局,所有项目可用
|
|
77
|
-
npx @house365/comate init --force # 就装在这里`);
|
|
78
|
-
return 1;
|
|
79
|
-
}
|
|
80
|
-
if (target.kind === 'project') console.log(`检测到项目标志: ${target.marker}`);
|
|
81
|
-
console.log('');
|
|
46
|
+
const cwd = process.cwd();
|
|
47
|
+
|
|
48
|
+
const target = inspectTarget(cwd, home);
|
|
49
|
+
if (target.kind !== 'project') {
|
|
50
|
+
console.error(
|
|
51
|
+
target.kind === 'home'
|
|
52
|
+
? '\n这是主目录,请在项目目录下运行 comate init。'
|
|
53
|
+
: '\n当前目录不像项目(无 .git / package.json 等),请在项目目录下运行 comate init。',
|
|
54
|
+
);
|
|
55
|
+
return 1;
|
|
82
56
|
}
|
|
83
57
|
|
|
84
|
-
|
|
58
|
+
console.log(`\n安装到 ${join(cwd, '.agents', 'skills')}\n`);
|
|
59
|
+
|
|
60
|
+
// 1. OpenSpec CLI — invoked as a PATH command, so it installs globally even
|
|
61
|
+
// though the skills themselves go into this project.
|
|
85
62
|
const os = openSpecState();
|
|
86
63
|
if (os.status === 'ready') {
|
|
87
64
|
results.push(['OpenSpec CLI', 'skipped', `已安装 ${os.version}`]);
|
|
@@ -101,12 +78,11 @@ comate 会把 skill 装进上面这个路径,先确认这是你要的目录:
|
|
|
101
78
|
}
|
|
102
79
|
|
|
103
80
|
// 2. Superpowers — the skills CLI detects the agent itself.
|
|
104
|
-
if (superpowersInstalled(
|
|
81
|
+
if (superpowersInstalled('project')) {
|
|
105
82
|
results.push(['Superpowers', 'skipped', '已安装']);
|
|
106
83
|
} else {
|
|
107
84
|
console.log('\n→ 安装 Superpowers (skills add obra/superpowers)');
|
|
108
|
-
const
|
|
109
|
-
const r = run(skillsInvocation(pkgRoot, args), SKILLS_TIMEOUT_MS);
|
|
85
|
+
const r = run(skillsInvocation(pkgRoot, ['add', 'obra/superpowers', '-y']), SKILLS_TIMEOUT_MS);
|
|
110
86
|
// It clones from GitHub, so a bare exit code hides the usual cause: no
|
|
111
87
|
// network. Say so rather than leaving the user with "exit code 1".
|
|
112
88
|
const note = r.ok
|
|
@@ -117,41 +93,39 @@ comate 会把 skill 装进上面这个路径,先确认这是你要的目录:
|
|
|
117
93
|
|
|
118
94
|
// 3. comate itself.
|
|
119
95
|
console.log('\n→ 安装 comate skills');
|
|
120
|
-
const comateArgs = ['add', pkgRoot, '--skill', '*', '-y'
|
|
96
|
+
const comateArgs = ['add', pkgRoot, '--skill', '*', '-y'];
|
|
121
97
|
const r = run(skillsInvocation(pkgRoot, comateArgs), SKILLS_TIMEOUT_MS);
|
|
122
98
|
results.push(['comate', r.ok ? 'installed' : 'failed', r.ok ? '' : r.reason]);
|
|
123
99
|
|
|
124
|
-
// 4. openspec
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
100
|
+
// 4. openspec/ project structure. Not optional: comate's open and archive
|
|
101
|
+
// phases read it, so an install without it cannot actually run. An existing
|
|
102
|
+
// one is left alone, which covers projects that already keep it elsewhere.
|
|
103
|
+
if (existsSync('openspec')) {
|
|
104
|
+
results.push(['openspec 结构', 'skipped', '已存在']);
|
|
105
|
+
} else {
|
|
106
|
+
console.log('\n→ 初始化 openspec/ 项目结构');
|
|
107
|
+
const r2 = run(
|
|
108
|
+
{ command: 'openspec', args: ['init', '.'], shell: process.platform === 'win32' },
|
|
109
|
+
NPM_TIMEOUT_MS,
|
|
110
|
+
);
|
|
111
|
+
results.push(['openspec 结构', r2.ok ? 'installed' : 'failed', r2.ok ? '' : r2.reason]);
|
|
132
112
|
}
|
|
133
113
|
|
|
134
|
-
return report(results
|
|
114
|
+
return report(results);
|
|
135
115
|
}
|
|
136
116
|
|
|
137
|
-
function report(results
|
|
117
|
+
function report(results) {
|
|
138
118
|
const mark = { installed: '✓', skipped: '·', failed: '✗' };
|
|
139
|
-
console.log('
|
|
119
|
+
console.log('');
|
|
140
120
|
for (const [name, status, note] of results) {
|
|
141
|
-
console.log(` ${mark[status]} ${name.padEnd(
|
|
121
|
+
console.log(` ${mark[status]} ${name.padEnd(14)}${note}`);
|
|
142
122
|
}
|
|
143
|
-
console.log('─'.repeat(58));
|
|
144
123
|
|
|
145
124
|
const failed = results.filter(([, s]) => s === 'failed');
|
|
146
125
|
if (failed.length > 0) {
|
|
147
|
-
console.error(`\n${failed.length}
|
|
126
|
+
console.error(`\n${failed.length} 项失败,修好后重跑 comate init。`);
|
|
148
127
|
return 1;
|
|
149
128
|
}
|
|
150
|
-
|
|
151
|
-
// landed in, which is the whole problem with a cwd-relative install.
|
|
152
|
-
const root = scope === 'global' ? (process.env.HOME ?? process.env.USERPROFILE ?? '~') : process.cwd();
|
|
153
|
-
const doctorPath = join(root, '.agents', 'skills', 'comate', 'scripts', 'comate.sh');
|
|
154
|
-
console.log(`\n完成。健康检查: bash "${doctorPath}" doctor`);
|
|
155
|
-
console.log('在 agent 中输入 /comate 开始使用。');
|
|
129
|
+
console.log('\n完成。在 agent 中输入 /comate 开始使用,或跑 comate doctor 自检。');
|
|
156
130
|
return 0;
|
|
157
131
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@house365/comate",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "comate —— OpenSpec + Superpowers 规约驱动的 AI 开发编排器(Agent Skills)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"registry": "https://registry.npmjs.org"
|
|
10
10
|
},
|
|
11
11
|
"bin": {
|
|
12
|
+
"comate": "bin/cli.mjs",
|
|
12
13
|
"comate-skills": "bin/cli.mjs"
|
|
13
14
|
},
|
|
14
15
|
"files": [
|