@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 CHANGED
@@ -25,39 +25,21 @@ open → design → build → verify → archive
25
25
  ## 安装
26
26
 
27
27
  ```bash
28
- cd <你的项目目录>
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
- npx @house365/comate init -g # 装到 ~/.agents/skills/
34
+ cd your-project
35
+ comate init
36
36
  ```
37
37
 
38
- `init` 会一并装齐两个依赖(OpenSpec CLI、Superpowers),已装的自动跳过,可重复执行。
38
+ `init` 会装好 comate 及其依赖(OpenSpec CLI、Superpowers),并创建 `openspec/` 项目结构。支持 Claude Code、Codex、Cursor 等 70+ agent。可重复执行,已装的自动跳过。
39
39
 
40
- 项目安装的目标目录就是**你执行命令时所在的目录**。init 会先打印完整路径,并在目录看起来不像项目(没有 `.git`、`package.json` 等标志)或就是你的主目录时中止,避免装错地方——确实要装在当前目录就加 `--force`。
40
+ 装完输入 `/comate` 开始使用,`comate doctor` 可自检。
41
41
 
42
- 只装 comate 本身、不碰依赖:
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, args.slice(1)));
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-skills init [-g] [--openspec-init] [--force]
24
- 安装 comate 及依赖 (OpenSpec CLI、Superpowers)。已装的自动跳过,可重复执行。
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
- 安装后在 agent 中输入 /comate 开始使用。`);
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: pick a scope, then install what's missing.
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
- // Same convention as the bare `comate-skills` command: no flag means project,
17
- // -g means global. No prompt — the flag already says it.
18
- export function resolveScope(argv) {
19
- return argv.includes('-g') || argv.includes('--global') ? 'global' : 'project';
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, argv) {
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
- if (scope === 'global') {
55
- console.log(`\n安装范围: 全局 -> ${join(home, '.agents', 'skills')}\n`);
56
- } else {
57
- const cwd = process.cwd();
58
- const target = inspectTarget(cwd, home);
59
- console.log(`\n安装范围: 项目 -> ${join(cwd, '.agents', 'skills')}`);
60
-
61
- if (target.kind === 'home' && !force) {
62
- console.error(`
63
- 这是你的用户主目录。装到这里通常不是你想要的——想让所有项目都能用,请加 -g:
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
- // 1. OpenSpec CLI — a PATH command, so global regardless of skill scope.
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(scope)) {
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 args = ['add', 'obra/superpowers', '-y', ...(scope === 'global' ? ['-g'] : [])];
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', ...(scope === 'global' ? ['-g'] : [])];
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 init — opt-in: it writes openspec/ into the user's project and
125
- // edits agent config files, a bigger side effect than the installs above.
126
- if (withOpenSpecInit) {
127
- console.log('\n→ 初始化 OpenSpec 项目结构 (openspec init)');
128
- const r2 = run({ command: 'openspec', args: ['init', '.'], shell: process.platform === 'win32' }, NPM_TIMEOUT_MS);
129
- results.push(['openspec init', r2.ok ? 'installed' : 'failed', r2.ok ? '' : r2.reason]);
130
- } else if (!existsSync('openspec')) {
131
- results.push(['openspec init', 'skipped', '未初始化项目结构,需要时加 --openspec-init']);
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, scope);
114
+ return report(results);
135
115
  }
136
116
 
137
- function report(results, scope) {
117
+ function report(results) {
138
118
  const mark = { installed: '✓', skipped: '·', failed: '✗' };
139
- console.log('\n' + '─'.repeat(58));
119
+ console.log('');
140
120
  for (const [name, status, note] of results) {
141
- console.log(` ${mark[status]} ${name.padEnd(16)} ${status.padEnd(10)} ${note}`);
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} 项失败。修复后可重跑 comate-skills init(已安装的会自动跳过)。`);
126
+ console.error(`\n${failed.length} 项失败,修好后重跑 comate init。`);
148
127
  return 1;
149
128
  }
150
- // Absolute path: the user should not have to work out which directory this
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",
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": [