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.
@@ -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
- { name: 'Codex CLI', dir: '.codex/skills', detect: '.codex' },
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(projectDir) {
146
- const rulesDir = resolve(projectDir, '.qoder', 'rules');
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
- 你已加载 superpowers-zh 技能框架(${skillEntries.length} 个 skills)。
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 位于 \`.qoder/skills/\` 目录,每个 skill 有独立的 \`SKILL.md\` 文件。
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 的触发条件时,读取对应的 \`.qoder/skills/<skill-name>/SKILL.md\` 并严格遵循其流程。也可输入 \`/<skill-name>\` 显式调用。
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(projectDir) {
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
- 本项目已安装 superpowers-zh 技能框架(${skillEntries.length} 个 skills)。
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 位于 \`.agents/skills/\` 目录,每个 skill 有独立的 \`SKILL.md\` 文件。
229
+ Skills 位于 \`${skillsRef}\` 目录,每个 skill 有独立的 \`SKILL.md\` 文件。
208
230
 
209
231
  ${skillList}
210
232
 
211
233
  ## 如何使用
212
234
 
213
- 当任务匹配某个 skill 时,读取对应的 \`.agents/skills/<skill-name>/SKILL.md\` 并严格遵循其流程。
235
+ 当任务匹配某个 skill 时,读取对应的 \`${skillsRef}<skill-name>/SKILL.md\` 并严格遵循其流程。
214
236
  `;
215
237
 
216
- // 写入 .agents/rules.md(不覆盖用户已有的 GEMINI.md / AGENTS.md)
217
- const rulePath = resolve(projectDir, '.agents', 'rules.md');
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(projectDir) {
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
- 本项目已安装 superpowers-zh 技能框架(${skillEntries.length} 个 skills)。
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 位于 \`.gemini/skills/\` 目录,每个 skill 有独立的 \`SKILL.md\` 文件。
306
+ Skills 位于 \`${skillsRef}\` 目录,每个 skill 有独立的 \`SKILL.md\` 文件。
283
307
 
284
308
  ${skillList}
285
309
 
286
310
  ## 如何使用
287
311
 
288
- 当任务匹配某个 skill 时,读取对应的 \`.gemini/skills/<skill-name>/SKILL.md\` 并严格遵循其流程。
312
+ 当任务匹配某个 skill 时,读取对应的 \`${skillsRef}<skill-name>/SKILL.md\` 并严格遵循其流程。
289
313
  `;
290
314
 
291
- // 写入 GEMINI.md(如果已存在则追加)
292
- const geminiPath = resolve(projectDir, 'GEMINI.md');
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(projectDir) {
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
- 本项目已安装 superpowers-zh 技能框架(${skillEntries.length} 个 skills)。
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 位于 \`.claude/skills/\` 目录,每个 skill 有独立的 \`SKILL.md\` 文件。
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(projectDir, 'CLAUDE.md');
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 --uninstall 卸载当前目录下的 superpowers-zh
446
- npx superpowers-zh --force 允许在用户主目录(~)安装(默认拒绝)
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
- 自动检测当前项目使用的 AI 编程工具,将 ${countDirs(SKILLS_SRC)} 个 skills 安装到对应目录。
455
- 如果自动检测不到,请用 --tool 指定你的工具,例如:
456
- npx superpowers-zh --tool cursor
457
- npx superpowers-zh --tool trae
538
+ 项目级:把 ${countDirs(SKILLS_SRC)} 个 skills 装到当前项目对应目录(如 .claude/skills)。
539
+ 全局:把 skills 装到用户级目录(如 ~/.claude/skills),一次安装所有项目可用,
540
+ skills 更新时也只需重装一次。项目级优先、全局兜底,二者可共存。
458
541
 
459
- 误装到主目录可以这样清理:
460
- cd ~ && npx superpowers-zh --uninstall
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 dest = resolve(PROJECT_DIR, target.dir);
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
- console.log(` ✅ ${target.name}: ${srcCount} 个 skills -> ${dest}`);
566
+ const scopeTag = isGlobal ? '[全局]' : '[项目]';
567
+ console.log(` ✅ ${target.name} ${scopeTag}: ${srcCount} 个 skills -> ${dest}`);
482
568
 
483
569
  if (target.name === 'Trae') {
484
- generateTraeBootstrapRule(PROJECT_DIR);
570
+ generateTraeBootstrapRule(baseDir);
485
571
  }
486
572
 
487
573
  if (target.name === 'Qoder') {
488
- generateQoderBootstrap(PROJECT_DIR);
574
+ generateQoderBootstrap(baseDir, isGlobal);
489
575
  }
490
576
 
491
577
  if (target.name === 'Antigravity') {
492
- generateAntigravityBootstrap(PROJECT_DIR);
578
+ generateAntigravityBootstrap(baseDir, isGlobal);
493
579
  }
494
580
 
495
581
  if (target.name === 'Aider') {
496
- generateAiderBootstrap(PROJECT_DIR);
582
+ generateAiderBootstrap(baseDir);
497
583
  }
498
584
 
499
585
  if (target.name === 'Gemini CLI') {
500
- generateGeminiBootstrap(PROJECT_DIR);
586
+ generateGeminiBootstrap(baseDir, isGlobal);
501
587
  }
502
588
 
503
589
  if (target.name === 'Hermes Agent') {
504
- generateHermesBootstrap(PROJECT_DIR);
590
+ generateHermesBootstrap(baseDir);
505
591
  }
506
592
 
507
593
  if (target.name === 'Claude Code') {
508
- generateClaudeCodeBootstrap(PROJECT_DIR);
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
- function uninstallForTarget(target, srcSkillNames) {
608
- const dest = resolve(PROJECT_DIR, target.dir);
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
- console.log(`\n superpowers-zh v${PKG.version} — 卸载\n`);
629
- console.log(` 目标项目: ${PROJECT_DIR}\n`);
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 TARGETS) {
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
- console.log(` ✅ ${target.name}: 移除 ${removed} 个 skills <- ${resolve(PROJECT_DIR, target.dir)}`);
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(PROJECT_DIR, '.claude', 'agents');
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 BOOTSTRAP_DELETE) {
671
- const full = resolve(PROJECT_DIR, rel);
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 BOOTSTRAP_CLEAN_SECTION) {
679
- const full = resolve(PROJECT_DIR, rel);
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(' ⚠️ 未在当前目录找到 superpowers-zh 安装痕迹。');
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
- function install(forceToolName, force) {
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
- if (!force && isHomeDir(PROJECT_DIR)) {
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
- 请先 cd 到项目目录:
711
- cd /path/to/your/project
712
- npx superpowers-zh
821
+ 如果你想让 skills 对所有项目生效,用全局安装(推荐):
822
+ npx superpowers-zh --global # 自动检测已装工具
823
+ npx superpowers-zh --global --tool claude
713
824
 
714
- 如果你确实要在主目录安装(不推荐),加 --force:
715
- npx superpowers-zh --force
825
+ 或先 cd 到项目目录做项目级安装:
826
+ cd /path/to/your/project && npx superpowers-zh
716
827
 
717
- 如果你已经在主目录误装过,可以用 --uninstall 清理:
718
- npx superpowers-zh --uninstall
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(` 目标项目: ${PROJECT_DIR}\n`);
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
- installForTarget(target);
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 TARGETS) {
742
- const detects = Array.isArray(target.detect) ? target.detect : [target.detect];
743
- const found = detects.some(d => existsSync(resolve(PROJECT_DIR, d)));
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
- console.log(' ⚠️ 未在当前目录检测到任何已知 AI 编程工具的项目标记。\n');
883
+ const where = isGlobal ? '你的用户主目录(~)' : '当前目录';
884
+ const flag = isGlobal ? '--global ' : '';
885
+ console.log(` ⚠️ 未在${where}检测到任何已知 AI 编程工具的标记。\n`);
755
886
  console.log(' 为避免装错工具,未做任何安装。请用 --tool 显式指定你的工具,例如:\n');
756
- console.log(' npx superpowers-zh --tool claude # Claude Code / Copilot CLI');
757
- console.log(' npx superpowers-zh --tool antigravity # Google Antigravity');
758
- console.log(' npx superpowers-zh --tool trae # Trae');
759
- console.log(' npx superpowers-zh --tool cursor # Cursor\n');
760
- console.log(` 全部可用别名:${Object.keys(TOOL_ALIASES).join(', ')}\n`);
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
- install(undefined, force);
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
  }