Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,28 @@ AI:在开始实现之前,我需要了解几个关键问题:

## 快速开始

### 方式一:npm 安装(推荐)
### 📌 先选对路径:marketplace vs npx

> **以下 4 款工具有官方 plugin marketplace——走 marketplace 才是 high-fidelity**(正式注册为 plugin、`/skills` 命令可见、hooks 走标准 `${CLAUDE_PLUGIN_ROOT}` 路径)。`npx superpowers-zh` 对它们是 low-fidelity 路径——v1.4.0 起已补齐 hooks 注册和 `.claude/settings.json` 写入,能让 SessionStart hook 自动触发 `using-superpowers` 注入,但仍是"项目级 loose plugin"。

| 工具 | High-fidelity 路径(**推荐**) | npx low-fidelity 路径 |
|---|---|---|
| **Claude Code** | `/plugin marketplace add jnMetaCode/superpowers-zh`<br>`/plugin install superpowers-zh@superpowers-zh` | `npx superpowers-zh`(v1.4.0+ 已补 hooks) |
| **Codex CLI** | 在 CLI 里输入 `/plugins`,搜 `superpowers` | `npx superpowers-zh --tool codex` |
| **OpenCode** | 见 [上游 OpenCode 安装](https://github.com/obra/superpowers#opencode) | `npx superpowers-zh --tool opencode` |
| **VS Code (Copilot)** | 见 [docs/README.vscode.md](docs/README.vscode.md) | `npx superpowers-zh`(仅复制 skills) |

**其余 13 款工具**(Cursor / Trae / Kiro / Gemini CLI / Hermes Agent / Aider / Antigravity / Windsurf / Qwen Code / Claw Code / OpenClaw / DeerFlow / Hermes)—— 它们本来就只看本地配置文件(rules / steering / instructions),**`npx superpowers-zh` 是它们的 canonical 安装路径**,没有"更高保真"可言。

### 方式一:npm 安装(多工具自适应)

```bash
cd /your/project
npx superpowers-zh
```

自动检测当前项目使用的工具,把 20 个 skills 装到对应位置 + 写工具专属的 bootstrap 文件。**Claude Code v1.4.0+ 还会同时复制 hooks/ 并注册 `.claude/settings.json`** 让 SessionStart hook 自动注入 `using-superpowers`。

> ⚠️ **不要在主目录(`~`)下跑**。v1.2.1 起会拒绝并提示,老版本会把 skills 和 `CLAUDE.md` 等 bootstrap 文件写到你的 home 目录,污染所有项目。如已误装见下文「卸载 / 误装清理」。

### 方式二:手动安装(low-fidelity,仅作备选)
Expand Down
40 changes: 40 additions & 0 deletions RELEASE-NOTES.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,46 @@

---

## v1.4.0 (2026-05-12)

### 🔴 关键修复:Claude Code npx 安装现在会装 hooks + 注册 SessionStart

**背景:** v1.3.0 及之前,`npx superpowers-zh` 装 Claude Code 目标**只**复制 `skills/` 到 `.claude/skills/` 并改 `CLAUDE.md`,**完全没装 hooks**。结果:

- `hooks/hooks.json` 用的 `${CLAUDE_PLUGIN_ROOT}` 只有走 Claude Code plugin marketplace 时才会注入,npx 路径下根本不会展开
- 没有 SessionStart hook → 不会把 `using-superpowers` 元 skill 注入到对话开头
- 仅靠 `CLAUDE.md` 文本(被动)告诉模型 "有 skills",模型可能完全忽略

**用户体感:** skills 静静躺在 `.claude/skills/` 但 AI 从不主动调用,连 `using-superpowers` 指令也不进流程。

**修复(`bin/superpowers-zh.js`):**

- 新增 `installClaudeCodeHooks(projectDir)` —— 复制 `hooks/` 到 `.claude/hooks/`,并把 SessionStart hook 注册到 `.claude/settings.json`,**用绝对路径**替代 `${CLAUDE_PLUGIN_ROOT}`
- 幂等:重复跑 `npx superpowers-zh` 不会重复注册(按 hooks 目录路径去重)
- `--uninstall` 跟随:新增 `uninstallClaudeCodeHooks(projectDir)`,精确摘掉 settings.json 里的 entry + 删除 `.claude/hooks/` 下我们装过的脚本

**新增 marketplace 提示:** 安装时若识别到 Claude Code / Codex CLI / OpenCode / VS Code 这 4 款"有官方 plugin marketplace 的工具",自动打印 marketplace 命令作为 high-fidelity 推荐路径(npx 仍可用但是 low-fidelity)。

### 📚 README 透明度章节

加 "📌 先选对路径:marketplace vs npx" 表格,**诚实标注 17 款工具里有 4 款的 npx 路径是 low-fidelity**:

- Claude Code / Codex CLI / OpenCode / VS Code → marketplace 是 high-fidelity,npx 是 fallback
- 其余 13 款(Cursor / Trae / Kiro / Gemini CLI / Hermes Agent / Aider / Antigravity / Windsurf / Qwen Code / Claw Code / OpenClaw / DeerFlow) → npx 是 canonical(它们本来就只看本地配置文件)

### 影响范围

- ✅ 修复用户社区高频反馈:"npx 装完 skill 不会自动触发"、"using-superpowers 指令不走流程"
- ✅ 不影响上游 marketplace 安装路径(仍按上游正常工作)
- ✅ 向后兼容:v1.3.0 已装的用户重新跑 `npx superpowers-zh` 即可补齐 hooks,无需手动清理

### Refs

- 用户反馈 issue: TBD(社区微信群报告)
- 相关 issue: #19 tracking 上游同步(worktree 部分见 PR #28)

---

## v1.3.0 (2026-05-10)

### 跟上游对齐 (v5.1.0)
Expand Down
155 changes: 155 additions & 0 deletions bin/superpowers-zh.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ function copyDirSync(src, dest) {
const __dirname = dirname(fileURLToPath(import.meta.url));
const PKG = JSON.parse(readFileSync(resolve(__dirname, '..', 'package.json'), 'utf8'));
const SKILLS_SRC = resolve(__dirname, '..', 'skills');
const HOOKS_SRC = resolve(__dirname, '..', 'hooks');
const PROJECT_DIR = process.cwd();

// 历史遗留 agent 文件名 — 用于 --uninstall 清理已装用户机器上的残留。
Expand Down Expand Up @@ -314,7 +315,126 @@ ${skillList}
}
}

// Claude Code 专用:把 hooks/ 复制到 .claude/hooks/,并把 SessionStart hook
// 注册到 .claude/settings.json(用绝对路径替代 ${CLAUDE_PLUGIN_ROOT})。
// 没有这一步,CLAUDE.md 是被动文本——模型可能忽略——而 hook 注入是 superpowers
// 自动触发链路的核心。详见 README "Claude Code 用户必读" 段。
function installClaudeCodeHooks(projectDir) {
if (!existsSync(HOOKS_SRC)) {
console.warn(` ⚠️ Claude Code: 源目录 hooks/ 不存在,跳过 hook 注册`);
return false;
}

const hooksDest = resolve(projectDir, '.claude', 'hooks');
copyDirSync(HOOKS_SRC, hooksDest);
console.log(` ✅ Claude Code: hooks -> ${hooksDest}`);

// 写/合并 .claude/settings.json
const settingsPath = resolve(projectDir, '.claude', 'settings.json');
let settings = {};
if (existsSync(settingsPath)) {
try {
settings = JSON.parse(readFileSync(settingsPath, 'utf8'));
} catch (e) {
console.warn(` ⚠️ .claude/settings.json 解析失败,跳过 hook 注册: ${e.message}`);
return false;
}
}

if (!settings.hooks) settings.hooks = {};
if (!Array.isArray(settings.hooks.SessionStart)) settings.hooks.SessionStart = [];

const cmdPath = resolve(hooksDest, 'run-hook.cmd');
const ourCommand = `"${cmdPath}" session-start`;

// 幂等:若已存在指向我们 hooksDest 的 entry,不重复注册
const alreadyExists = settings.hooks.SessionStart.some(entry =>
Array.isArray(entry.hooks) && entry.hooks.some(h =>
h && typeof h.command === 'string' && h.command.includes(hooksDest)
)
);

if (!alreadyExists) {
settings.hooks.SessionStart.push({
matcher: 'startup|clear|compact',
hooks: [
{ type: 'command', command: ourCommand, async: false }
]
});
}

mkdirSync(resolve(projectDir, '.claude'), { recursive: true });
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
console.log(` ✅ Claude Code: SessionStart hook 注册 -> ${settingsPath}`);
return true;
}

function uninstallClaudeCodeHooks(projectDir) {
const hooksDest = resolve(projectDir, '.claude', 'hooks');
const settingsPath = resolve(projectDir, '.claude', 'settings.json');
let removed = 0;

// 1. 从 settings.json 摘掉指向 hooksDest 的 entry
if (existsSync(settingsPath)) {
try {
const settings = JSON.parse(readFileSync(settingsPath, 'utf8'));
if (settings.hooks && Array.isArray(settings.hooks.SessionStart)) {
const before = settings.hooks.SessionStart.length;
settings.hooks.SessionStart = settings.hooks.SessionStart.filter(entry => {
if (!Array.isArray(entry.hooks)) return true;
return !entry.hooks.some(h =>
h && typeof h.command === 'string' && h.command.includes(hooksDest)
);
});
const dropped = before - settings.hooks.SessionStart.length;
if (dropped > 0) {
if (settings.hooks.SessionStart.length === 0) delete settings.hooks.SessionStart;
if (settings.hooks && Object.keys(settings.hooks).length === 0) delete settings.hooks;
if (Object.keys(settings).length === 0) {
rmSync(settingsPath);
console.log(` ✅ Claude Code: 删除空 settings.json -> ${settingsPath}`);
} else {
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
console.log(` ✅ Claude Code: 从 settings.json 摘掉 ${dropped} 个 hook entry`);
}
removed += dropped;
}
}
} catch (e) {
console.warn(` ⚠️ .claude/settings.json 解析失败,跳过 hook 清理: ${e.message}`);
}
}

// 2. 删 .claude/hooks/ 下我们装过的文件,目录空了就连目录一起删
if (existsSync(hooksDest) && existsSync(HOOKS_SRC)) {
const ourFiles = readdirSync(HOOKS_SRC, { withFileTypes: true })
.filter(e => e.isFile())
.map(e => e.name);
let fileRemoved = 0;
for (const f of ourFiles) {
const fp = resolve(hooksDest, f);
if (existsSync(fp)) {
try { rmSync(fp); fileRemoved++; } catch {}
}
}
if (fileRemoved > 0) {
console.log(` ✅ Claude Code: 移除 ${fileRemoved} 个 hook 脚本 -> ${hooksDest}`);
removed += fileRemoved;
}
try {
const left = readdirSync(hooksDest).filter(n => n !== '.DS_Store');
if (left.length === 0) rmSync(hooksDest, { recursive: true, force: true });
} catch {}
}

return removed;
}

function generateClaudeCodeBootstrap(projectDir) {
// 关键修复 (v1.4.0):先装 hooks——CLAUDE.md 文本是被动的,只有 SessionStart hook
// 才能保证每次会话注入 using-superpowers,让 skill 真正能被自动触发。
installClaudeCodeHooks(projectDir);

const skillEntries = scanSkillEntries(SKILLS_SRC);
const skillList = skillEntries.map(s => `- **${s.name}**: ${s.desc}`).join('\n');

Expand Down Expand Up @@ -458,6 +578,33 @@ function installForTarget(target) {
}
}

// 对走 npx 路径装 Claude Code/Codex CLI/OpenCode/VS Code 的用户提示官方 plugin
// marketplace 才是 high-fidelity 路径。npx 装这些工具是 low-fidelity(v1.4.0 起
// Claude Code 已补 hooks 注册,但 /skills 命令仍可能识别不到,因为没走 plugin 注册)。
const LOW_FIDELITY_TARGETS = ['Claude Code', 'Codex CLI', 'OpenCode', 'VS Code'];

function printMarketplaceHintIfNeeded(installedTargets) {
const lowFidelity = installedTargets.filter(t => LOW_FIDELITY_TARGETS.includes(t));
if (lowFidelity.length === 0) return;

console.log(` 📌 提示:以下工具有官方 plugin marketplace,走那条路径体验更完整:\n`);
if (lowFidelity.includes('Claude Code')) {
console.log(` Claude Code:`);
console.log(` /plugin marketplace add jnMetaCode/superpowers-zh`);
console.log(` /plugin install superpowers-zh@superpowers-zh`);
}
if (lowFidelity.includes('Codex CLI')) {
console.log(` Codex CLI: 在 CLI 内输入 /plugins,搜索 superpowers`);
}
if (lowFidelity.includes('OpenCode')) {
console.log(` OpenCode: 见上游官方安装说明 https://github.com/obra/superpowers#opencode`);
}
if (lowFidelity.includes('VS Code')) {
console.log(` VS Code (Copilot): 见 docs/README.vscode.md`);
}
console.log(`\n npx 安装是 low-fidelity 路径,胜在跨工具一致;上面这些工具的 plugin marketplace 路径才是 high-fidelity。\n`);
}

function isHomeDir(p) {
const home = homedir();
if (!home) return false;
Expand Down Expand Up @@ -596,6 +743,9 @@ function uninstall() {
}
}

// v1.4.0+ 装的 Claude Code SessionStart hook 与 .claude/hooks/ 脚本
uninstallClaudeCodeHooks(PROJECT_DIR);

// 清理 .claude/agents 下旧版本装过的 legacy agent(v1.2.x 及之前会装 code-reviewer.md,
// v1.3.0 起跟随上游 v5.1.0 移除)。即使 agents/ 源目录已删,已装用户跑 --uninstall 仍应能清干净。
const agentsDest = resolve(PROJECT_DIR, '.claude', 'agents');
Expand Down Expand Up @@ -680,18 +830,21 @@ function install(forceToolName, force) {
}
installForTarget(target);
console.log('\n 安装完成!重启你的 AI 编程工具即可生效。\n');
printMarketplaceHintIfNeeded([target.name]);
return;
}

// 自动检测
let installed = 0;
const installedTargets = [];

for (const target of TARGETS) {
const detects = Array.isArray(target.detect) ? target.detect : [target.detect];
const found = detects.some(d => existsSync(resolve(PROJECT_DIR, d)));
if (found) {
installForTarget(target);
installed++;
installedTargets.push(target.name);
}
}

Expand All @@ -708,9 +861,11 @@ function install(forceToolName, force) {
console.log(` ✅ 默认安装: ${countDirs(dest)} 个 skills -> ${dest}`);

generateClaudeCodeBootstrap(PROJECT_DIR);
installedTargets.push('Claude Code');
}

console.log('\n 安装完成!重启你的 AI 编程工具即可生效。\n');
printMarketplaceHintIfNeeded(installedTargets);
} catch (err) {
console.error(` ❌ 安装失败:${err.message}`);
process.exit(1);
Expand Down
Loading