superpowers-zh 1.1.2 → 1.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.
Files changed (2) hide show
  1. package/bin/superpowers-zh.js +177 -28
  2. package/package.json +4 -1
@@ -1,9 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { existsSync, mkdirSync, cpSync, readdirSync, readFileSync, writeFileSync } from 'fs';
4
- import { resolve, dirname } from 'path';
3
+ import { existsSync, mkdirSync, cpSync, readdirSync, readFileSync, writeFileSync, copyFileSync, statSync } from 'fs';
4
+ import { resolve, dirname, join } from 'path';
5
5
  import { fileURLToPath } from 'url';
6
6
 
7
+ // Node 14/16 兼容:cpSync 在 Node 16.7+ 才可用
8
+ function copyDirSync(src, dest) {
9
+ if (typeof cpSync === 'function') {
10
+ cpSync(src, dest, { recursive: true });
11
+ return;
12
+ }
13
+ // 手动递归复制(兼容 Node 14+)
14
+ mkdirSync(dest, { recursive: true });
15
+ for (const entry of readdirSync(src, { withFileTypes: true })) {
16
+ const srcPath = join(src, entry.name);
17
+ const destPath = join(dest, entry.name);
18
+ if (entry.isDirectory()) {
19
+ copyDirSync(srcPath, destPath);
20
+ } else {
21
+ copyFileSync(srcPath, destPath);
22
+ }
23
+ }
24
+ }
25
+
7
26
  const __dirname = dirname(fileURLToPath(import.meta.url));
8
27
  const PKG = JSON.parse(readFileSync(resolve(__dirname, '..', 'package.json'), 'utf8'));
9
28
  const SKILLS_SRC = resolve(__dirname, '..', 'skills');
@@ -32,32 +51,33 @@ function countDirs(dir) {
32
51
  return readdirSync(dir, { withFileTypes: true }).filter(e => e.isDirectory()).length;
33
52
  }
34
53
 
54
+ function scanSkillEntries(skillsDir) {
55
+ const entries = [];
56
+ if (!existsSync(skillsDir)) return entries;
57
+ for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
58
+ if (!entry.isDirectory()) continue;
59
+ const skillFile = resolve(skillsDir, entry.name, 'SKILL.md');
60
+ if (!existsSync(skillFile)) continue;
61
+ const content = readFileSync(skillFile, 'utf8');
62
+ const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---/);
63
+ if (!fmMatch) continue;
64
+ const nameMatch = fmMatch[1].match(/^name:\s*(.+)$/m);
65
+ const descMatch = fmMatch[1].match(/^description:\s*["']?(.+?)["']?\s*$/m);
66
+ if (nameMatch) {
67
+ entries.push({
68
+ name: nameMatch[1].trim(),
69
+ desc: descMatch ? descMatch[1].trim() : '',
70
+ });
71
+ }
72
+ }
73
+ return entries;
74
+ }
75
+
35
76
  function generateTraeBootstrapRule(projectDir) {
36
77
  const rulesDir = resolve(projectDir, '.trae', 'rules');
37
78
  mkdirSync(rulesDir, { recursive: true });
38
79
 
39
- // 扫描已安装的 skills,读取 name description
40
- const skillsDir = resolve(projectDir, '.trae', 'skills');
41
- const skillEntries = [];
42
- if (existsSync(skillsDir)) {
43
- for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
44
- if (!entry.isDirectory()) continue;
45
- const skillFile = resolve(skillsDir, entry.name, 'SKILL.md');
46
- if (!existsSync(skillFile)) continue;
47
- const content = readFileSync(skillFile, 'utf8');
48
- const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---/);
49
- if (!fmMatch) continue;
50
- const nameMatch = fmMatch[1].match(/^name:\s*(.+)$/m);
51
- const descMatch = fmMatch[1].match(/^description:\s*["']?(.+?)["']?\s*$/m);
52
- if (nameMatch) {
53
- skillEntries.push({
54
- name: nameMatch[1].trim(),
55
- desc: descMatch ? descMatch[1].trim() : '',
56
- });
57
- }
58
- }
59
- }
60
-
80
+ const skillEntries = scanSkillEntries(resolve(projectDir, '.trae', 'skills'));
61
81
  const skillTable = skillEntries.map(s => `| ${s.name} | ${s.desc} |`).join('\n');
62
82
 
63
83
  const rule = `---
@@ -93,6 +113,123 @@ ${skillTable}
93
113
  console.log(` ✅ Trae: bootstrap rule -> ${rulePath}`);
94
114
  }
95
115
 
116
+ function generateAntigravityBootstrap(projectDir) {
117
+ const skillEntries = scanSkillEntries(resolve(projectDir, '.antigravity', 'skills'));
118
+ const skillList = skillEntries.map(s => `- **${s.name}**: ${s.desc}`).join('\n');
119
+
120
+ const content = `# Superpowers-ZH 中文增强版
121
+
122
+ 本项目已安装 superpowers-zh 技能框架(${skillEntries.length} 个 skills)。
123
+
124
+ ## 核心规则
125
+
126
+ 1. **收到任务时,先检查是否有匹配的 skill** — 哪怕只有 1% 的可能性也要检查
127
+ 2. **设计先于编码** — 收到功能需求时,先用 brainstorming skill 做需求分析
128
+ 3. **测试先于实现** — 写代码前先写测试(TDD)
129
+ 4. **验证先于完成** — 声称完成前必须运行验证命令
130
+
131
+ ## 可用 Skills
132
+
133
+ Skills 位于 \`.antigravity/skills/\` 目录,每个 skill 有独立的 \`SKILL.md\` 文件。
134
+
135
+ ${skillList}
136
+
137
+ ## 如何使用
138
+
139
+ 当任务匹配某个 skill 时,读取对应的 \`.antigravity/skills/<skill-name>/SKILL.md\` 并严格遵循其流程。
140
+ `;
141
+
142
+ // 写入 .antigravity/rules.md(不覆盖用户已有的 GEMINI.md / AGENTS.md)
143
+ const rulePath = resolve(projectDir, '.antigravity', 'rules.md');
144
+ writeFileSync(rulePath, content, 'utf8');
145
+ console.log(` ✅ Antigravity: bootstrap rule -> ${rulePath}`);
146
+ }
147
+
148
+ function generateAiderBootstrap(projectDir) {
149
+ const skillEntries = scanSkillEntries(resolve(projectDir, '.aider', 'skills'));
150
+ const skillList = skillEntries.map(s => `- **${s.name}**: ${s.desc}`).join('\n');
151
+
152
+ const content = `# Superpowers-ZH 工作方法论
153
+
154
+ 本项目使用 superpowers-zh 技能框架(${skillEntries.length} 个 skills)。
155
+
156
+ ## 核心规则
157
+
158
+ 1. **收到任务时,先检查是否有匹配的 skill** — 哪怕只有 1% 的可能性也要检查
159
+ 2. **设计先于编码** — 收到功能需求时,先用 brainstorming skill 做需求分析
160
+ 3. **测试先于实现** — 写代码前先写测试(TDD)
161
+ 4. **验证先于完成** — 声称完成前必须运行验证命令
162
+
163
+ ## 可用 Skills
164
+
165
+ Skills 位于 \`.aider/skills/\` 目录,每个 skill 有独立的 \`SKILL.md\` 文件。
166
+
167
+ ${skillList}
168
+
169
+ ## 如何使用
170
+
171
+ 当任务匹配某个 skill 时,读取对应的 \`.aider/skills/<skill-name>/SKILL.md\` 并严格遵循其流程。
172
+ `;
173
+
174
+ // 写入 CONVENTIONS.md(Aider 原生支持自动加载此文件)
175
+ // 如果已有 CONVENTIONS.md,追加而不覆盖
176
+ const convPath = resolve(projectDir, 'CONVENTIONS.md');
177
+ if (existsSync(convPath)) {
178
+ const existing = readFileSync(convPath, 'utf8');
179
+ if (!existing.includes('superpowers-zh')) {
180
+ writeFileSync(convPath, existing + '\n\n' + content, 'utf8');
181
+ console.log(` ✅ Aider: 追加 skills 引用 -> ${convPath}`);
182
+ } else {
183
+ console.log(` ✅ Aider: CONVENTIONS.md 已包含 superpowers-zh 引用`);
184
+ }
185
+ } else {
186
+ writeFileSync(convPath, content, 'utf8');
187
+ console.log(` ✅ Aider: bootstrap -> ${convPath}`);
188
+ }
189
+ }
190
+
191
+ function generateGeminiBootstrap(projectDir) {
192
+ const skillEntries = scanSkillEntries(resolve(projectDir, '.gemini', 'skills'));
193
+ const skillList = skillEntries.map(s => `- **${s.name}**: ${s.desc}`).join('\n');
194
+
195
+ const content = `# Superpowers-ZH 中文增强版
196
+
197
+ 本项目已安装 superpowers-zh 技能框架(${skillEntries.length} 个 skills)。
198
+
199
+ ## 核心规则
200
+
201
+ 1. **收到任务时,先检查是否有匹配的 skill** — 哪怕只有 1% 的可能性也要检查
202
+ 2. **设计先于编码** — 收到功能需求时,先用 brainstorming skill 做需求分析
203
+ 3. **测试先于实现** — 写代码前先写测试(TDD)
204
+ 4. **验证先于完成** — 声称完成前必须运行验证命令
205
+
206
+ ## 可用 Skills
207
+
208
+ Skills 位于 \`.gemini/skills/\` 目录,每个 skill 有独立的 \`SKILL.md\` 文件。
209
+
210
+ ${skillList}
211
+
212
+ ## 如何使用
213
+
214
+ 当任务匹配某个 skill 时,读取对应的 \`.gemini/skills/<skill-name>/SKILL.md\` 并严格遵循其流程。
215
+ `;
216
+
217
+ // 写入 GEMINI.md(如果已存在则追加)
218
+ const geminiPath = resolve(projectDir, 'GEMINI.md');
219
+ if (existsSync(geminiPath)) {
220
+ const existing = readFileSync(geminiPath, 'utf8');
221
+ if (!existing.includes('superpowers-zh')) {
222
+ writeFileSync(geminiPath, existing + '\n\n' + content, 'utf8');
223
+ console.log(` ✅ Gemini CLI: 追加 skills 引用 -> ${geminiPath}`);
224
+ } else {
225
+ console.log(` ✅ Gemini CLI: GEMINI.md 已包含 superpowers-zh 引用`);
226
+ }
227
+ } else {
228
+ writeFileSync(geminiPath, content, 'utf8');
229
+ console.log(` ✅ Gemini CLI: bootstrap -> ${geminiPath}`);
230
+ }
231
+ }
232
+
96
233
  function showHelp() {
97
234
  console.log(`
98
235
  superpowers-zh v${PKG.version} — AI 编程超能力中文版
@@ -134,7 +271,7 @@ function install() {
134
271
 
135
272
  if (existsSync(detectPath)) {
136
273
  mkdirSync(dest, { recursive: true });
137
- cpSync(SKILLS_SRC, dest, { recursive: true });
274
+ copyDirSync(SKILLS_SRC, dest);
138
275
  const count = countDirs(dest);
139
276
  console.log(` ✅ ${target.name}: ${count} 个 skills -> ${dest}`);
140
277
  installed++;
@@ -143,10 +280,22 @@ function install() {
143
280
  generateTraeBootstrapRule(PROJECT_DIR);
144
281
  }
145
282
 
283
+ if (target.name === 'Antigravity') {
284
+ generateAntigravityBootstrap(PROJECT_DIR);
285
+ }
286
+
287
+ if (target.name === 'Aider') {
288
+ generateAiderBootstrap(PROJECT_DIR);
289
+ }
290
+
291
+ if (target.name === 'Gemini CLI') {
292
+ generateGeminiBootstrap(PROJECT_DIR);
293
+ }
294
+
146
295
  if (target.name === 'Claude Code' && existsSync(AGENTS_SRC)) {
147
296
  const agentsDest = resolve(PROJECT_DIR, '.claude', 'agents');
148
297
  mkdirSync(agentsDest, { recursive: true });
149
- cpSync(AGENTS_SRC, agentsDest, { recursive: true });
298
+ copyDirSync(AGENTS_SRC, agentsDest);
150
299
  }
151
300
  }
152
301
  }
@@ -154,13 +303,13 @@ function install() {
154
303
  if (installed === 0) {
155
304
  const dest = resolve(PROJECT_DIR, '.claude', 'skills');
156
305
  mkdirSync(dest, { recursive: true });
157
- cpSync(SKILLS_SRC, dest, { recursive: true });
306
+ copyDirSync(SKILLS_SRC, dest);
158
307
  console.log(` ✅ 默认安装: ${countDirs(dest)} 个 skills -> ${dest}`);
159
308
 
160
309
  if (existsSync(AGENTS_SRC)) {
161
310
  const agentsDest = resolve(PROJECT_DIR, '.claude', 'agents');
162
311
  mkdirSync(agentsDest, { recursive: true });
163
- cpSync(AGENTS_SRC, agentsDest, { recursive: true });
312
+ copyDirSync(AGENTS_SRC, agentsDest);
164
313
  console.log(` ✅ 默认安装: agents -> ${agentsDest}`);
165
314
  }
166
315
  }
package/package.json CHANGED
@@ -1,6 +1,9 @@
1
1
  {
2
2
  "name": "superpowers-zh",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
+ "engines": {
5
+ "node": ">=14.0.0"
6
+ },
4
7
  "description": "AI 编程超能力中文增强版 — superpowers(99k+ ⭐)完整汉化 + 6 个中国原创 skills,支持 OpenClaw / Claude Code / Cursor / Windsurf / Kiro / Gemini CLI 等 14 款工具",
5
8
  "type": "module",
6
9
  "main": ".opencode/plugins/superpowers.js",