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.
- package/bin/superpowers-zh.js +177 -28
- package/package.json +4 -1
package/bin/superpowers-zh.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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",
|