superpowers-zh 1.6.0 → 1.7.0
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +3 -2
- package/.cursor-plugin/plugin.json +1 -1
- package/README.md +34 -25
- package/README.zh-Hant.md +353 -0
- package/RELEASE-NOTES.zh.md +38 -0
- package/bin/superpowers-zh.js +235 -90
- package/docs/README.codearts.md +49 -0
- package/docs/README.codebuddy.md +54 -0
- package/gemini-extension.json +1 -1
- package/package.json +4 -2
- package/skills/using-superpowers/SKILL.md +19 -72
- package/skills/using-superpowers/references/codex-tools.md +2 -2
- package/assets/sponsors/5cookie-code.png +0 -0
package/bin/superpowers-zh.js
CHANGED
|
@@ -46,24 +46,42 @@ const PROJECT_DIR = process.cwd();
|
|
|
46
46
|
// agents/ 目录已删,但旧版本装过的用户机器上仍有残留文件需要清理。
|
|
47
47
|
const LEGACY_AGENT_FILENAMES = ['code-reviewer.md'];
|
|
48
48
|
|
|
49
|
+
// 每个工具:项目级 dir(相对 cwd)+ 可选 global 配置。
|
|
50
|
+
// global 存在 = 该工具有稳定的「用户级 skills 目录」,可全局安装(所有项目共享):
|
|
51
|
+
// global.dir 用户级 skills 目录(相对 home)
|
|
52
|
+
// global.detect home 下用于自动检测该工具是否安装的标记目录
|
|
53
|
+
// global.boot 可选,用户级 bootstrap 文件(相对 home);无则仅靠 skill 自动发现
|
|
54
|
+
// 无 global 的工具(Cursor/Kiro/Trae/Aider/DeerFlow/VS Code/Hermes/Claw)规则是项目级、
|
|
55
|
+
// 或存在于应用内设置,没有稳定的用户级 skills 加载路径 —— --global 会明确拒绝而非写无效路径。
|
|
49
56
|
const TARGETS = [
|
|
50
|
-
{ name: 'Claude Code', dir: '.claude/skills', detect: '.claude' },
|
|
57
|
+
{ name: 'Claude Code', dir: '.claude/skills', detect: '.claude', global: { dir: '.claude/skills', detect: '.claude', boot: '.claude/CLAUDE.md' } },
|
|
51
58
|
{ name: 'Cursor', dir: '.cursor/skills', detect: ['.cursor', '.cursorrules'] },
|
|
52
|
-
|
|
59
|
+
// Codex 全局:docs 确认 Codex 启动时扫描 ~/.agents/skills/(不是 ~/.codex/skills),
|
|
60
|
+
// 直接把每个 skill 复制到 ~/.agents/skills/<skill>/ 正好命中它的扁平扫描。
|
|
61
|
+
{ name: 'Codex CLI', dir: '.codex/skills', detect: '.codex', global: { dir: '.agents/skills', detect: '.codex' } },
|
|
53
62
|
{ name: 'Kiro', dir: '.kiro/steering', detect: '.kiro' },
|
|
54
63
|
{ name: 'DeerFlow', dir: 'skills/custom', detect: 'deer_flow' },
|
|
55
64
|
{ name: 'Trae', dir: '.trae/skills', detect: '.trae' },
|
|
65
|
+
// Antigravity 无 global:其全局 skills 加载路径未在 docs 证实(全局规则走 ~/.gemini/GEMINI.md),
|
|
66
|
+
// 不确认能生效就不写,避免「装了不生效」。用户用项目级安装。
|
|
56
67
|
{ name: 'Antigravity', dir: '.agents/skills', detect: '.agents' },
|
|
57
68
|
{ name: 'VS Code', dir: '.github/superpowers', detect: '.github/copilot-instructions.md' },
|
|
58
|
-
{ name: 'OpenClaw', dir: 'skills', detect: '.openclaw' },
|
|
59
|
-
{ name: 'Windsurf', dir: '.windsurf/skills', detect: '.windsurf' },
|
|
69
|
+
{ name: 'OpenClaw', dir: 'skills', detect: '.openclaw', global: { dir: '.openclaw/skills', detect: '.openclaw' } },
|
|
70
|
+
{ name: 'Windsurf', dir: '.windsurf/skills', detect: '.windsurf', global: { dir: '.windsurf/skills', detect: '.windsurf' } },
|
|
71
|
+
// Gemini 无 global:其全局加载是「扩展目录」~/.gemini/extensions/*/skills/ + gemini-extension.json,
|
|
72
|
+
// 不是简单复制到 ~/.gemini/skills,通用 --global 覆盖不了。见 docs/README.gemini-cli.md。
|
|
60
73
|
{ name: 'Gemini CLI', dir: '.gemini/skills', detect: 'GEMINI.md' },
|
|
61
74
|
{ name: 'Aider', dir: '.aider/skills', detect: '.aider' },
|
|
62
|
-
{ name: 'OpenCode', dir: '.opencode/skills', detect: '.opencode' },
|
|
63
|
-
{ name: 'Qwen Code', dir: '.qwen/skills', detect: '.qwen' },
|
|
75
|
+
{ name: 'OpenCode', dir: '.opencode/skills', detect: '.opencode', global: { dir: '.config/opencode/skills', detect: '.config/opencode' } },
|
|
76
|
+
{ name: 'Qwen Code', dir: '.qwen/skills', detect: '.qwen', global: { dir: '.qwen/skills', detect: '.qwen' } },
|
|
64
77
|
{ name: 'Hermes Agent', dir: '.hermes/skills', detect: ['.hermes', 'HERMES.md', '.hermes.md'] },
|
|
65
78
|
{ name: 'Claw Code', dir: '.claw/skills', detect: ['.claw', 'CLAW.md'] },
|
|
66
|
-
{ name: 'Qoder', dir: '.qoder/skills', detect: '.qoder' },
|
|
79
|
+
{ name: 'Qoder', dir: '.qoder/skills', detect: '.qoder', global: { dir: '.qoder/skills', detect: '.qoder' } },
|
|
80
|
+
{ name: 'CodeBuddy', dir: '.codebuddy/skills', detect: ['.codebuddy', 'CODEBUDDY.md'] },
|
|
81
|
+
// 华为云码道(CodeArts Doer):skills 放 .codeartsdoer/skills/(用户在 #20 确认)。
|
|
82
|
+
// 仅 skills-only —— 其 bootstrap/指令文件约定未证实,靠 CodeArts 自身 skill 发现;
|
|
83
|
+
// 若不自动触发需在对话里手动点名 skill(docs 已说明)。
|
|
84
|
+
{ name: 'CodeArts', dir: '.codeartsdoer/skills', detect: '.codeartsdoer' },
|
|
67
85
|
];
|
|
68
86
|
|
|
69
87
|
function countDirs(dir) {
|
|
@@ -142,12 +160,14 @@ ${skillTable}
|
|
|
142
160
|
console.log(` ✅ Trae: bootstrap rule -> ${rulePath}`);
|
|
143
161
|
}
|
|
144
162
|
|
|
145
|
-
function generateQoderBootstrap(
|
|
146
|
-
const rulesDir = resolve(
|
|
163
|
+
function generateQoderBootstrap(baseDir, isGlobal) {
|
|
164
|
+
const rulesDir = resolve(baseDir, '.qoder', 'rules');
|
|
147
165
|
mkdirSync(rulesDir, { recursive: true });
|
|
148
166
|
|
|
149
167
|
const skillEntries = scanSkillEntries(SKILLS_SRC);
|
|
150
168
|
const skillTable = skillEntries.map(s => `| ${s.name} | ${s.desc} |`).join('\n');
|
|
169
|
+
const scope = isGlobal ? '你已全局加载 superpowers-zh 技能框架,所有项目共享' : '你已加载 superpowers-zh 技能框架';
|
|
170
|
+
const skillsRef = isGlobal ? '~/.qoder/skills/' : '.qoder/skills/';
|
|
151
171
|
|
|
152
172
|
// Qoder rules schema(来源:社区实际样本,docs.qoder.com/zh/user-guide/rules 没公开)
|
|
153
173
|
// trigger: always_on → "始终生效",适用于所有智能会话和内联对话
|
|
@@ -160,7 +180,7 @@ alwaysApply: true
|
|
|
160
180
|
|
|
161
181
|
# Superpowers-ZH 中文增强版
|
|
162
182
|
|
|
163
|
-
|
|
183
|
+
${scope}(${skillEntries.length} 个 skills)。
|
|
164
184
|
|
|
165
185
|
## 核心规则
|
|
166
186
|
|
|
@@ -171,7 +191,7 @@ alwaysApply: true
|
|
|
171
191
|
|
|
172
192
|
## 可用 Skills
|
|
173
193
|
|
|
174
|
-
Skills 位于
|
|
194
|
+
Skills 位于 \`${skillsRef}\` 目录,每个 skill 有独立的 \`SKILL.md\` 文件。
|
|
175
195
|
|
|
176
196
|
| Skill | 触发条件 |
|
|
177
197
|
|-------|---------|
|
|
@@ -179,7 +199,7 @@ ${skillTable}
|
|
|
179
199
|
|
|
180
200
|
## 如何使用
|
|
181
201
|
|
|
182
|
-
当任务匹配某个 skill 的触发条件时,读取对应的
|
|
202
|
+
当任务匹配某个 skill 的触发条件时,读取对应的 \`${skillsRef}<skill-name>/SKILL.md\` 并严格遵循其流程。也可输入 \`/<skill-name>\` 显式调用。
|
|
183
203
|
`;
|
|
184
204
|
|
|
185
205
|
const rulePath = resolve(rulesDir, 'superpowers-zh.md');
|
|
@@ -187,13 +207,15 @@ ${skillTable}
|
|
|
187
207
|
console.log(` ✅ Qoder: bootstrap rule -> ${rulePath}`);
|
|
188
208
|
}
|
|
189
209
|
|
|
190
|
-
function generateAntigravityBootstrap(
|
|
210
|
+
function generateAntigravityBootstrap(baseDir, isGlobal) {
|
|
191
211
|
const skillEntries = scanSkillEntries(SKILLS_SRC);
|
|
192
212
|
const skillList = skillEntries.map(s => `- **${s.name}**: ${s.desc}`).join('\n');
|
|
213
|
+
const scope = isGlobal ? '已全局安装 superpowers-zh 技能框架,所有项目共享' : '本项目已安装 superpowers-zh 技能框架';
|
|
214
|
+
const skillsRef = isGlobal ? '~/.agents/skills/' : '.agents/skills/';
|
|
193
215
|
|
|
194
216
|
const content = `# Superpowers-ZH 中文增强版
|
|
195
217
|
|
|
196
|
-
|
|
218
|
+
${scope}(${skillEntries.length} 个 skills)。
|
|
197
219
|
|
|
198
220
|
## 核心规则
|
|
199
221
|
|
|
@@ -204,17 +226,17 @@ function generateAntigravityBootstrap(projectDir) {
|
|
|
204
226
|
|
|
205
227
|
## 可用 Skills
|
|
206
228
|
|
|
207
|
-
Skills 位于
|
|
229
|
+
Skills 位于 \`${skillsRef}\` 目录,每个 skill 有独立的 \`SKILL.md\` 文件。
|
|
208
230
|
|
|
209
231
|
${skillList}
|
|
210
232
|
|
|
211
233
|
## 如何使用
|
|
212
234
|
|
|
213
|
-
当任务匹配某个 skill 时,读取对应的
|
|
235
|
+
当任务匹配某个 skill 时,读取对应的 \`${skillsRef}<skill-name>/SKILL.md\` 并严格遵循其流程。
|
|
214
236
|
`;
|
|
215
237
|
|
|
216
|
-
// 写入 .agents/rules.md(不覆盖用户已有的 GEMINI.md / AGENTS.md
|
|
217
|
-
const rulePath = resolve(
|
|
238
|
+
// 写入 .agents/rules.md(不覆盖用户已有的 GEMINI.md / AGENTS.md);全局装到 ~/.agents/rules.md
|
|
239
|
+
const rulePath = resolve(baseDir, '.agents', 'rules.md');
|
|
218
240
|
writeFileSync(rulePath, content, 'utf8');
|
|
219
241
|
console.log(` ✅ Antigravity: bootstrap rule -> ${rulePath}`);
|
|
220
242
|
}
|
|
@@ -262,13 +284,15 @@ ${skillList}
|
|
|
262
284
|
}
|
|
263
285
|
}
|
|
264
286
|
|
|
265
|
-
function generateGeminiBootstrap(
|
|
287
|
+
function generateGeminiBootstrap(baseDir, isGlobal) {
|
|
266
288
|
const skillEntries = scanSkillEntries(SKILLS_SRC);
|
|
267
289
|
const skillList = skillEntries.map(s => `- **${s.name}**: ${s.desc}`).join('\n');
|
|
290
|
+
const scope = isGlobal ? '已全局安装 superpowers-zh 技能框架,所有项目共享' : '本项目已安装 superpowers-zh 技能框架';
|
|
291
|
+
const skillsRef = isGlobal ? '~/.gemini/skills/' : '.gemini/skills/';
|
|
268
292
|
|
|
269
293
|
const content = `# Superpowers-ZH 中文增强版
|
|
270
294
|
|
|
271
|
-
|
|
295
|
+
${scope}(${skillEntries.length} 个 skills)。
|
|
272
296
|
|
|
273
297
|
## 核心规则
|
|
274
298
|
|
|
@@ -279,17 +303,18 @@ function generateGeminiBootstrap(projectDir) {
|
|
|
279
303
|
|
|
280
304
|
## 可用 Skills
|
|
281
305
|
|
|
282
|
-
Skills 位于
|
|
306
|
+
Skills 位于 \`${skillsRef}\` 目录,每个 skill 有独立的 \`SKILL.md\` 文件。
|
|
283
307
|
|
|
284
308
|
${skillList}
|
|
285
309
|
|
|
286
310
|
## 如何使用
|
|
287
311
|
|
|
288
|
-
当任务匹配某个 skill 时,读取对应的
|
|
312
|
+
当任务匹配某个 skill 时,读取对应的 \`${skillsRef}<skill-name>/SKILL.md\` 并严格遵循其流程。
|
|
289
313
|
`;
|
|
290
314
|
|
|
291
|
-
// 写入 GEMINI.md
|
|
292
|
-
const geminiPath = resolve(
|
|
315
|
+
// 写入 GEMINI.md(如果已存在则追加);全局装到 ~/.gemini/GEMINI.md
|
|
316
|
+
const geminiPath = isGlobal ? resolve(baseDir, '.gemini', 'GEMINI.md') : resolve(baseDir, 'GEMINI.md');
|
|
317
|
+
mkdirSync(dirname(geminiPath), { recursive: true });
|
|
293
318
|
if (existsSync(geminiPath)) {
|
|
294
319
|
const existing = readFileSync(geminiPath, 'utf8');
|
|
295
320
|
if (!existing.includes('superpowers-zh')) {
|
|
@@ -360,13 +385,15 @@ ${skillList}
|
|
|
360
385
|
}
|
|
361
386
|
}
|
|
362
387
|
|
|
363
|
-
function generateClaudeCodeBootstrap(
|
|
388
|
+
function generateClaudeCodeBootstrap(baseDir, isGlobal) {
|
|
364
389
|
const skillEntries = scanSkillEntries(SKILLS_SRC);
|
|
365
390
|
const skillList = skillEntries.map(s => `- **${s.name}**: ${s.desc}`).join('\n');
|
|
391
|
+
const scope = isGlobal ? '已全局安装 superpowers-zh 技能框架,所有项目共享' : '本项目已安装 superpowers-zh 技能框架';
|
|
392
|
+
const skillsRef = isGlobal ? '~/.claude/skills/' : '.claude/skills/';
|
|
366
393
|
|
|
367
394
|
const content = `# Superpowers-ZH 中文增强版
|
|
368
395
|
|
|
369
|
-
|
|
396
|
+
${scope}(${skillEntries.length} 个 skills)。
|
|
370
397
|
|
|
371
398
|
## 核心规则
|
|
372
399
|
|
|
@@ -377,7 +404,7 @@ function generateClaudeCodeBootstrap(projectDir) {
|
|
|
377
404
|
|
|
378
405
|
## 可用 Skills
|
|
379
406
|
|
|
380
|
-
Skills 位于
|
|
407
|
+
Skills 位于 \`${skillsRef}\` 目录,每个 skill 有独立的 \`SKILL.md\` 文件。
|
|
381
408
|
|
|
382
409
|
${skillList}
|
|
383
410
|
|
|
@@ -388,7 +415,8 @@ ${skillList}
|
|
|
388
415
|
如果你认为哪怕只有 1% 的可能性某个 skill 适用于你正在做的事情,你必须调用该 skill 检查。
|
|
389
416
|
`;
|
|
390
417
|
|
|
391
|
-
const mdPath = resolve(
|
|
418
|
+
const mdPath = isGlobal ? resolve(baseDir, '.claude', 'CLAUDE.md') : resolve(baseDir, 'CLAUDE.md');
|
|
419
|
+
mkdirSync(dirname(mdPath), { recursive: true });
|
|
392
420
|
if (existsSync(mdPath)) {
|
|
393
421
|
const existing = readFileSync(mdPath, 'utf8');
|
|
394
422
|
if (!existing.includes('superpowers-zh')) {
|
|
@@ -403,6 +431,49 @@ ${skillList}
|
|
|
403
431
|
}
|
|
404
432
|
}
|
|
405
433
|
|
|
434
|
+
// CodeBuddy(腾讯 AI IDE)—— 加载机制类似 Claude Code:项目根 CODEBUDDY.md 作 bootstrap,
|
|
435
|
+
// skills 放 .codebuddy/skills/。仅项目级(其用户级 skills 加载路径未证实,暂不做全局)。
|
|
436
|
+
function generateCodeBuddyBootstrap(baseDir) {
|
|
437
|
+
const skillEntries = scanSkillEntries(SKILLS_SRC);
|
|
438
|
+
const skillList = skillEntries.map(s => `- **${s.name}**: ${s.desc}`).join('\n');
|
|
439
|
+
|
|
440
|
+
const content = `# Superpowers-ZH 中文增强版
|
|
441
|
+
|
|
442
|
+
本项目已安装 superpowers-zh 技能框架(${skillEntries.length} 个 skills)。
|
|
443
|
+
|
|
444
|
+
## 核心规则
|
|
445
|
+
|
|
446
|
+
1. **收到任务时,先检查是否有匹配的 skill** — 哪怕只有 1% 的可能性也要检查
|
|
447
|
+
2. **设计先于编码** — 收到功能需求时,先用 brainstorming skill 做需求分析
|
|
448
|
+
3. **测试先于实现** — 写代码前先写测试(TDD)
|
|
449
|
+
4. **验证先于完成** — 声称完成前必须运行验证命令
|
|
450
|
+
|
|
451
|
+
## 可用 Skills
|
|
452
|
+
|
|
453
|
+
Skills 位于 \`.codebuddy/skills/\` 目录,每个 skill 有独立的 \`SKILL.md\` 文件。
|
|
454
|
+
|
|
455
|
+
${skillList}
|
|
456
|
+
|
|
457
|
+
## 如何使用
|
|
458
|
+
|
|
459
|
+
当任务匹配某个 skill 时,读取对应的 \`.codebuddy/skills/<skill-name>/SKILL.md\` 并严格遵循其流程。
|
|
460
|
+
`;
|
|
461
|
+
|
|
462
|
+
const mdPath = resolve(baseDir, 'CODEBUDDY.md');
|
|
463
|
+
if (existsSync(mdPath)) {
|
|
464
|
+
const existing = readFileSync(mdPath, 'utf8');
|
|
465
|
+
if (!existing.includes('superpowers-zh')) {
|
|
466
|
+
writeFileSync(mdPath, existing.replace(/\s+$/, '') + '\n\n' + wrapWithSentinel(content), 'utf8');
|
|
467
|
+
console.log(` ✅ CodeBuddy: 追加 skills 引用 -> ${mdPath}`);
|
|
468
|
+
} else {
|
|
469
|
+
console.log(` ✅ CodeBuddy: CODEBUDDY.md 已包含 superpowers-zh 引用`);
|
|
470
|
+
}
|
|
471
|
+
} else {
|
|
472
|
+
writeFileSync(mdPath, wrapWithSentinel(content), 'utf8');
|
|
473
|
+
console.log(` ✅ CodeBuddy: bootstrap -> ${mdPath}`);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
406
477
|
// 工具名称别名映射(用户输入 -> TARGETS.name)
|
|
407
478
|
const TOOL_ALIASES = {
|
|
408
479
|
'claude': 'Claude Code',
|
|
@@ -432,6 +503,14 @@ const TOOL_ALIASES = {
|
|
|
432
503
|
'claw-code': 'Claw Code',
|
|
433
504
|
'clawcode': 'Claw Code',
|
|
434
505
|
'qoder': 'Qoder',
|
|
506
|
+
'codebuddy': 'CodeBuddy',
|
|
507
|
+
'codebuddy-code': 'CodeBuddy',
|
|
508
|
+
'codebuddycode': 'CodeBuddy',
|
|
509
|
+
'codebuddy-cn': 'CodeBuddy',
|
|
510
|
+
'codearts': 'CodeArts',
|
|
511
|
+
'codeartsdoer': 'CodeArts',
|
|
512
|
+
'codearts-doer': 'CodeArts',
|
|
513
|
+
'huawei': 'CodeArts',
|
|
435
514
|
};
|
|
436
515
|
|
|
437
516
|
function showHelp() {
|
|
@@ -440,31 +519,37 @@ function showHelp() {
|
|
|
440
519
|
superpowers-zh v${PKG.version} — AI 编程超能力中文版
|
|
441
520
|
|
|
442
521
|
用法:
|
|
443
|
-
npx superpowers-zh
|
|
522
|
+
npx superpowers-zh 项目级:自动检测工具并装到当前目录
|
|
523
|
+
npx superpowers-zh --global 全局:装到 ~/,所有项目共享(推荐多项目用户)
|
|
444
524
|
npx superpowers-zh --tool cursor 指定工具安装(检测不到时使用)
|
|
445
|
-
npx superpowers-zh --
|
|
446
|
-
npx superpowers-zh --
|
|
525
|
+
npx superpowers-zh --global -t claude 全局 + 指定工具
|
|
526
|
+
npx superpowers-zh --uninstall 卸载当前目录(加 --global 卸载全局)
|
|
527
|
+
npx superpowers-zh --force 允许在用户主目录(~)做项目级安装(默认拒绝)
|
|
447
528
|
npx superpowers-zh --help 显示帮助
|
|
448
529
|
npx superpowers-zh --version 显示版本
|
|
449
530
|
|
|
450
531
|
支持的工具名:
|
|
451
532
|
${Object.keys(TOOL_ALIASES).join(', ')}
|
|
452
533
|
|
|
534
|
+
支持全局安装的工具(其余工具规则为项目级,--global 会提示改用项目级):
|
|
535
|
+
${TARGETS.filter(t => t.global).map(t => t.name).join('、')}
|
|
536
|
+
|
|
453
537
|
说明:
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
npx superpowers-zh --tool trae
|
|
538
|
+
项目级:把 ${countDirs(SKILLS_SRC)} 个 skills 装到当前项目对应目录(如 .claude/skills)。
|
|
539
|
+
全局:把 skills 装到用户级目录(如 ~/.claude/skills),一次安装所有项目可用,
|
|
540
|
+
skills 更新时也只需重装一次。项目级优先、全局兜底,二者可共存。
|
|
458
541
|
|
|
459
|
-
|
|
460
|
-
|
|
542
|
+
卸载:
|
|
543
|
+
npx superpowers-zh --uninstall 清理当前项目
|
|
544
|
+
npx superpowers-zh --global --uninstall 清理全局安装
|
|
461
545
|
|
|
462
546
|
项目:https://github.com/jnMetaCode/superpowers-zh
|
|
463
547
|
`);
|
|
464
548
|
}
|
|
465
549
|
|
|
466
|
-
function installForTarget(target) {
|
|
467
|
-
const
|
|
550
|
+
function installForTarget(target, baseDir, isGlobal) {
|
|
551
|
+
const relDir = isGlobal ? target.global.dir : target.dir;
|
|
552
|
+
const dest = resolve(baseDir, relDir);
|
|
468
553
|
const srcCount = countDirs(SKILLS_SRC);
|
|
469
554
|
mkdirSync(dest, { recursive: true });
|
|
470
555
|
copyDirSync(SKILLS_SRC, dest);
|
|
@@ -478,34 +563,39 @@ function installForTarget(target) {
|
|
|
478
563
|
` 3. 或手动克隆复制: 见 https://github.com/jnMetaCode/superpowers-zh#方式二手动安装`
|
|
479
564
|
);
|
|
480
565
|
}
|
|
481
|
-
|
|
566
|
+
const scopeTag = isGlobal ? '[全局]' : '[项目]';
|
|
567
|
+
console.log(` ✅ ${target.name} ${scopeTag}: ${srcCount} 个 skills -> ${dest}`);
|
|
482
568
|
|
|
483
569
|
if (target.name === 'Trae') {
|
|
484
|
-
generateTraeBootstrapRule(
|
|
570
|
+
generateTraeBootstrapRule(baseDir);
|
|
485
571
|
}
|
|
486
572
|
|
|
487
573
|
if (target.name === 'Qoder') {
|
|
488
|
-
generateQoderBootstrap(
|
|
574
|
+
generateQoderBootstrap(baseDir, isGlobal);
|
|
489
575
|
}
|
|
490
576
|
|
|
491
577
|
if (target.name === 'Antigravity') {
|
|
492
|
-
generateAntigravityBootstrap(
|
|
578
|
+
generateAntigravityBootstrap(baseDir, isGlobal);
|
|
493
579
|
}
|
|
494
580
|
|
|
495
581
|
if (target.name === 'Aider') {
|
|
496
|
-
generateAiderBootstrap(
|
|
582
|
+
generateAiderBootstrap(baseDir);
|
|
497
583
|
}
|
|
498
584
|
|
|
499
585
|
if (target.name === 'Gemini CLI') {
|
|
500
|
-
generateGeminiBootstrap(
|
|
586
|
+
generateGeminiBootstrap(baseDir, isGlobal);
|
|
501
587
|
}
|
|
502
588
|
|
|
503
589
|
if (target.name === 'Hermes Agent') {
|
|
504
|
-
generateHermesBootstrap(
|
|
590
|
+
generateHermesBootstrap(baseDir);
|
|
505
591
|
}
|
|
506
592
|
|
|
507
593
|
if (target.name === 'Claude Code') {
|
|
508
|
-
generateClaudeCodeBootstrap(
|
|
594
|
+
generateClaudeCodeBootstrap(baseDir, isGlobal);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if (target.name === 'CodeBuddy') {
|
|
598
|
+
generateCodeBuddyBootstrap(baseDir);
|
|
509
599
|
}
|
|
510
600
|
}
|
|
511
601
|
|
|
@@ -528,6 +618,7 @@ const BOOTSTRAP_CLEAN_SECTION = [
|
|
|
528
618
|
'GEMINI.md',
|
|
529
619
|
'HERMES.md',
|
|
530
620
|
'CONVENTIONS.md',
|
|
621
|
+
'CODEBUDDY.md',
|
|
531
622
|
];
|
|
532
623
|
const BOOTSTRAP_SECTION_MARKERS = [
|
|
533
624
|
'# Superpowers-ZH 中文增强版',
|
|
@@ -604,8 +695,16 @@ function cleanBootstrapSection(filePath) {
|
|
|
604
695
|
return true;
|
|
605
696
|
}
|
|
606
697
|
|
|
607
|
-
|
|
608
|
-
|
|
698
|
+
// 全局安装的 bootstrap 文件(相对 home)— 与 install 全局分支写入的路径对应。
|
|
699
|
+
// 仅 Claude Code(~/.claude/CLAUDE.md,全局记忆已证实)和 Qoder(~/.qoder/rules/,镜像其项目机制)
|
|
700
|
+
// 会写全局 bootstrap;其余全局工具靠 skill 自动发现,无 bootstrap 需清理。
|
|
701
|
+
const GLOBAL_BOOTSTRAP_DELETE = ['.qoder/rules/superpowers-zh.md'];
|
|
702
|
+
const GLOBAL_BOOTSTRAP_CLEAN_SECTION = ['.claude/CLAUDE.md'];
|
|
703
|
+
|
|
704
|
+
function uninstallForTarget(target, srcSkillNames, baseDir, isGlobal) {
|
|
705
|
+
const relDir = isGlobal ? (target.global && target.global.dir) : target.dir;
|
|
706
|
+
if (!relDir) return 0;
|
|
707
|
+
const dest = resolve(baseDir, relDir);
|
|
609
708
|
if (!existsSync(dest)) return 0;
|
|
610
709
|
let removed = 0;
|
|
611
710
|
for (const entry of readdirSync(dest, { withFileTypes: true })) {
|
|
@@ -624,9 +723,10 @@ function uninstallForTarget(target, srcSkillNames) {
|
|
|
624
723
|
return removed;
|
|
625
724
|
}
|
|
626
725
|
|
|
627
|
-
function uninstall() {
|
|
628
|
-
|
|
629
|
-
console.log(
|
|
726
|
+
function uninstall(isGlobal) {
|
|
727
|
+
const baseDir = isGlobal ? homedir() : PROJECT_DIR;
|
|
728
|
+
console.log(`\n superpowers-zh v${PKG.version} — 卸载(${isGlobal ? '全局' : '项目级'})\n`);
|
|
729
|
+
console.log(` 目标: ${baseDir}\n`);
|
|
630
730
|
|
|
631
731
|
if (!existsSync(SKILLS_SRC)) {
|
|
632
732
|
console.error(' ❌ 错误:skills 源目录不存在,无法识别要卸载的 skill 名单。');
|
|
@@ -639,18 +739,20 @@ function uninstall() {
|
|
|
639
739
|
.map(e => e.name)
|
|
640
740
|
);
|
|
641
741
|
|
|
742
|
+
const pool = isGlobal ? GLOBAL_TARGETS : TARGETS;
|
|
642
743
|
let totalSkills = 0;
|
|
643
|
-
for (const target of
|
|
644
|
-
const removed = uninstallForTarget(target, srcSkillNames);
|
|
744
|
+
for (const target of pool) {
|
|
745
|
+
const removed = uninstallForTarget(target, srcSkillNames, baseDir, isGlobal);
|
|
645
746
|
if (removed > 0) {
|
|
646
|
-
|
|
747
|
+
const relDir = isGlobal ? target.global.dir : target.dir;
|
|
748
|
+
console.log(` ✅ ${target.name}: 移除 ${removed} 个 skills <- ${resolve(baseDir, relDir)}`);
|
|
647
749
|
totalSkills += removed;
|
|
648
750
|
}
|
|
649
751
|
}
|
|
650
752
|
|
|
651
753
|
// 清理 .claude/agents 下旧版本装过的 legacy agent(v1.2.x 及之前会装 code-reviewer.md,
|
|
652
754
|
// v1.3.0 起跟随上游 v5.1.0 移除)。即使 agents/ 源目录已删,已装用户跑 --uninstall 仍应能清干净。
|
|
653
|
-
const agentsDest = resolve(
|
|
755
|
+
const agentsDest = resolve(baseDir, '.claude', 'agents');
|
|
654
756
|
if (existsSync(agentsDest)) {
|
|
655
757
|
let agentsRemoved = 0;
|
|
656
758
|
for (const entry of readdirSync(agentsDest)) {
|
|
@@ -666,17 +768,19 @@ function uninstall() {
|
|
|
666
768
|
} catch {}
|
|
667
769
|
}
|
|
668
770
|
|
|
771
|
+
const deleteList = isGlobal ? GLOBAL_BOOTSTRAP_DELETE : BOOTSTRAP_DELETE;
|
|
772
|
+
const cleanList = isGlobal ? GLOBAL_BOOTSTRAP_CLEAN_SECTION : BOOTSTRAP_CLEAN_SECTION;
|
|
669
773
|
let bootstrapsRemoved = 0;
|
|
670
|
-
for (const rel of
|
|
671
|
-
const full = resolve(
|
|
774
|
+
for (const rel of deleteList) {
|
|
775
|
+
const full = resolve(baseDir, rel);
|
|
672
776
|
if (existsSync(full)) {
|
|
673
777
|
rmSync(full);
|
|
674
778
|
console.log(` ✅ 删除 bootstrap: ${full}`);
|
|
675
779
|
bootstrapsRemoved++;
|
|
676
780
|
}
|
|
677
781
|
}
|
|
678
|
-
for (const rel of
|
|
679
|
-
const full = resolve(
|
|
782
|
+
for (const rel of cleanList) {
|
|
783
|
+
const full = resolve(baseDir, rel);
|
|
680
784
|
if (cleanBootstrapSection(full)) {
|
|
681
785
|
console.log(` ✅ 清理 bootstrap: ${full}`);
|
|
682
786
|
bootstrapsRemoved++;
|
|
@@ -684,13 +788,16 @@ function uninstall() {
|
|
|
684
788
|
}
|
|
685
789
|
|
|
686
790
|
if (totalSkills === 0 && bootstrapsRemoved === 0) {
|
|
687
|
-
console.log(
|
|
791
|
+
console.log(` ⚠️ 未在${isGlobal ? '用户主目录' : '当前目录'}找到 superpowers-zh 安装痕迹。`);
|
|
688
792
|
} else {
|
|
689
793
|
console.log(`\n 卸载完成。共移除 ${totalSkills} 个 skill 目录、${bootstrapsRemoved} 个 bootstrap 文件。\n`);
|
|
690
794
|
}
|
|
691
795
|
}
|
|
692
796
|
|
|
693
|
-
|
|
797
|
+
// 支持全局安装的工具(有稳定的用户级 skills 目录)
|
|
798
|
+
const GLOBAL_TARGETS = TARGETS.filter(t => t.global);
|
|
799
|
+
|
|
800
|
+
function install(forceToolName, force, isGlobal) {
|
|
694
801
|
try {
|
|
695
802
|
console.log(`\n superpowers-zh v${PKG.version} — AI 编程超能力中文版\n`);
|
|
696
803
|
|
|
@@ -699,29 +806,34 @@ function install(forceToolName, force) {
|
|
|
699
806
|
process.exit(1);
|
|
700
807
|
}
|
|
701
808
|
|
|
702
|
-
|
|
809
|
+
const baseDir = isGlobal ? homedir() : PROJECT_DIR;
|
|
810
|
+
|
|
811
|
+
// 项目级安装(默认):拒绝在 home 根目录乱装(会污染所有项目)。
|
|
812
|
+
// 全局安装(--global):本就写到 ~/.claude/skills 等用户级目录,是正当行为,跳过该护栏。
|
|
813
|
+
if (!isGlobal && !force && isHomeDir(PROJECT_DIR)) {
|
|
703
814
|
console.error(
|
|
704
815
|
` ⚠️ 当前目录是用户主目录: ${PROJECT_DIR}
|
|
705
816
|
|
|
706
|
-
superpowers-zh
|
|
817
|
+
superpowers-zh 项目级安装应该装到具体项目目录,而不是 ~/。
|
|
707
818
|
在主目录安装会把 skills 和 bootstrap 文件(CLAUDE.md / HERMES.md 等)
|
|
708
819
|
写入你的 home,污染所有项目。
|
|
709
820
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
npx superpowers-zh
|
|
821
|
+
如果你想让 skills 对所有项目生效,用全局安装(推荐):
|
|
822
|
+
npx superpowers-zh --global # 自动检测已装工具
|
|
823
|
+
npx superpowers-zh --global --tool claude
|
|
713
824
|
|
|
714
|
-
|
|
715
|
-
npx superpowers-zh
|
|
825
|
+
或先 cd 到项目目录做项目级安装:
|
|
826
|
+
cd /path/to/your/project && npx superpowers-zh
|
|
716
827
|
|
|
717
|
-
|
|
718
|
-
npx superpowers-zh --
|
|
828
|
+
如果你确实要在主目录做项目级安装(不推荐),加 --force:
|
|
829
|
+
npx superpowers-zh --force
|
|
719
830
|
`);
|
|
720
831
|
process.exit(1);
|
|
721
832
|
}
|
|
722
833
|
|
|
723
834
|
console.log(` 源: ${countDirs(SKILLS_SRC)} 个 skills`);
|
|
724
|
-
console.log(`
|
|
835
|
+
console.log(` 模式: ${isGlobal ? '全局(所有项目共享,装到 ~/)' : '项目级'}`);
|
|
836
|
+
console.log(` 目标: ${baseDir}\n`);
|
|
725
837
|
|
|
726
838
|
// --tool 指定安装
|
|
727
839
|
if (forceToolName) {
|
|
@@ -730,19 +842,36 @@ function install(forceToolName, force) {
|
|
|
730
842
|
console.error(` ❌ 未知工具: ${forceToolName}`);
|
|
731
843
|
process.exit(1);
|
|
732
844
|
}
|
|
733
|
-
|
|
845
|
+
if (isGlobal && !target.global) {
|
|
846
|
+
// 部分工具(如 Gemini CLI 的扩展目录)有专属全局方式,但与通用 --global 复制机制不同,
|
|
847
|
+
// 指向对应 docs;其余工具规则为项目级或存于应用内设置,无稳定用户级路径。
|
|
848
|
+
const docSlug = { 'Gemini CLI': 'gemini-cli', 'Antigravity': 'antigravity', 'Trae': 'trae', 'Aider': 'aider', 'Hermes Agent': 'hermes', 'Kiro': 'kiro' }[target.name];
|
|
849
|
+
console.error(
|
|
850
|
+
` ❌ ${target.name} 不支持通用全局安装(--global)。
|
|
851
|
+
|
|
852
|
+
该工具没有通用 --global 能覆盖的稳定用户级 skills 路径${docSlug ? `(可能有专属全局方式,见 docs/README.${docSlug}.md)` : '(规则为项目级或存于应用内设置)'}。
|
|
853
|
+
请改用项目级安装:
|
|
854
|
+
cd /path/to/your/project && npx superpowers-zh --tool ${forceToolName.toLowerCase().replace(/ .*/, '')}
|
|
855
|
+
|
|
856
|
+
支持通用全局安装的工具:${GLOBAL_TARGETS.map(t => t.name).join('、')}
|
|
857
|
+
`);
|
|
858
|
+
process.exit(1);
|
|
859
|
+
}
|
|
860
|
+
installForTarget(target, baseDir, isGlobal);
|
|
734
861
|
console.log('\n 安装完成!重启你的 AI 编程工具即可生效。\n');
|
|
735
862
|
return;
|
|
736
863
|
}
|
|
737
864
|
|
|
738
865
|
// 自动检测
|
|
739
866
|
let installed = 0;
|
|
867
|
+
const pool = isGlobal ? GLOBAL_TARGETS : TARGETS;
|
|
740
868
|
|
|
741
|
-
for (const target of
|
|
742
|
-
const
|
|
743
|
-
const
|
|
869
|
+
for (const target of pool) {
|
|
870
|
+
const detectMarker = isGlobal ? target.global.detect : target.detect;
|
|
871
|
+
const detects = Array.isArray(detectMarker) ? detectMarker : [detectMarker];
|
|
872
|
+
const found = detects.some(d => existsSync(resolve(baseDir, d)));
|
|
744
873
|
if (found) {
|
|
745
|
-
installForTarget(target);
|
|
874
|
+
installForTarget(target, baseDir, isGlobal);
|
|
746
875
|
installed++;
|
|
747
876
|
}
|
|
748
877
|
}
|
|
@@ -751,13 +880,21 @@ function install(forceToolName, force) {
|
|
|
751
880
|
// 检测落空时不再静默装 Claude Code —— 否则 Antigravity / Trae 等
|
|
752
881
|
// 不会在项目里留下检测目录的工具,会被误装成 Claude(见 issue #33)。
|
|
753
882
|
// 改为明确报错并教用户用 --tool 显式指定。
|
|
754
|
-
|
|
883
|
+
const where = isGlobal ? '你的用户主目录(~)' : '当前目录';
|
|
884
|
+
const flag = isGlobal ? '--global ' : '';
|
|
885
|
+
console.log(` ⚠️ 未在${where}检测到任何已知 AI 编程工具的标记。\n`);
|
|
755
886
|
console.log(' 为避免装错工具,未做任何安装。请用 --tool 显式指定你的工具,例如:\n');
|
|
756
|
-
console.log(
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
887
|
+
console.log(` npx superpowers-zh ${flag}--tool claude # Claude Code / Copilot CLI`);
|
|
888
|
+
if (isGlobal) {
|
|
889
|
+
console.log(` npx superpowers-zh ${flag}--tool codex # Codex CLI`);
|
|
890
|
+
console.log(` npx superpowers-zh ${flag}--tool qoder # Qoder\n`);
|
|
891
|
+
console.log(` 支持全局安装的工具:${GLOBAL_TARGETS.map(t => t.name).join('、')}\n`);
|
|
892
|
+
} else {
|
|
893
|
+
console.log(` npx superpowers-zh ${flag}--tool antigravity # Google Antigravity`);
|
|
894
|
+
console.log(` npx superpowers-zh ${flag}--tool trae # Trae`);
|
|
895
|
+
console.log(` npx superpowers-zh ${flag}--tool cursor # Cursor\n`);
|
|
896
|
+
console.log(` 全部可用别名:${Object.keys(TOOL_ALIASES).join(', ')}\n`);
|
|
897
|
+
}
|
|
761
898
|
process.exit(1);
|
|
762
899
|
}
|
|
763
900
|
|
|
@@ -774,14 +911,19 @@ const versionIdx = args.findIndex(a => a === '--version' || a === '-v');
|
|
|
774
911
|
const toolIdx = args.findIndex(a => a === '--tool' || a === '-t');
|
|
775
912
|
const uninstallIdx = args.findIndex(a => a === '--uninstall' || a === '-u');
|
|
776
913
|
const forceIdx = args.findIndex(a => a === '--force' || a === '-f');
|
|
914
|
+
const globalIdx = args.findIndex(a => a === '--global' || a === '-g');
|
|
777
915
|
const force = forceIdx !== -1;
|
|
916
|
+
const isGlobal = globalIdx !== -1;
|
|
917
|
+
|
|
918
|
+
// 已知无参数值的开关,用于校验未知参数(--tool 后面跟工具名不算未知参数)
|
|
919
|
+
const KNOWN_FLAGS = new Set(['--help', '-h', '--version', '-v', '--uninstall', '-u', '--force', '-f', '--global', '-g', '--tool', '-t']);
|
|
778
920
|
|
|
779
921
|
if (helpIdx !== -1) {
|
|
780
922
|
showHelp();
|
|
781
923
|
} else if (versionIdx !== -1) {
|
|
782
924
|
console.log(PKG.version);
|
|
783
925
|
} else if (uninstallIdx !== -1) {
|
|
784
|
-
uninstall();
|
|
926
|
+
uninstall(isGlobal);
|
|
785
927
|
} else if (toolIdx !== -1) {
|
|
786
928
|
const toolArg = args[toolIdx + 1];
|
|
787
929
|
if (!toolArg) {
|
|
@@ -795,11 +937,14 @@ if (helpIdx !== -1) {
|
|
|
795
937
|
console.error(` 支持的工具: ${Object.keys(TOOL_ALIASES).join(', ')}\n`);
|
|
796
938
|
process.exit(1);
|
|
797
939
|
}
|
|
798
|
-
install(toolName, force);
|
|
799
|
-
} else if (args.length > 0 && args[0].startsWith('-') && forceIdx === -1) {
|
|
800
|
-
console.warn(` 未知参数: ${args[0]}\n`);
|
|
801
|
-
showHelp();
|
|
802
|
-
process.exit(1);
|
|
940
|
+
install(toolName, force, isGlobal);
|
|
803
941
|
} else {
|
|
804
|
-
|
|
942
|
+
// 校验未知参数(--tool 的值已在上面分支处理,走到这里说明没有 --tool)
|
|
943
|
+
const unknown = args.find(a => a.startsWith('-') && !KNOWN_FLAGS.has(a));
|
|
944
|
+
if (unknown) {
|
|
945
|
+
console.warn(` 未知参数: ${unknown}\n`);
|
|
946
|
+
showHelp();
|
|
947
|
+
process.exit(1);
|
|
948
|
+
}
|
|
949
|
+
install(undefined, force, isGlobal);
|
|
805
950
|
}
|