diff --git a/README.md b/README.md index ac596b2..2675aee 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ AI:在开始实现之前,我需要了解几个关键问题: | [Windsurf](https://windsurf.com) | IDE | `npx superpowers-zh` | `.windsurf/skills/`(全局 `~/.codeium/windsurf/skills/`) | | [Kiro](https://kiro.dev) | IDE | `npx superpowers-zh` | `.kiro/skills/` | | [Gemini CLI](https://github.com/google-gemini/gemini-cli) | CLI | `npx superpowers-zh` | `.gemini/skills/` | -| [Codex CLI](https://github.com/openai/codex) | CLI | `npx superpowers-zh` | `.codex/skills/` | +| [Codex CLI](https://github.com/openai/codex) | CLI | `npx superpowers-zh` | `.agents/skills/` | | [Aider](https://aider.chat) | CLI | `npx superpowers-zh` | `.aider/skills/` | | [Trae](https://trae.ai) | IDE | `npx superpowers-zh` | `.trae/skills/` + `.trae/rules/` | | [VS Code](https://code.visualstudio.com) (Copilot) | IDE 插件 | `npx superpowers-zh` | `.github/superpowers/` + `.github/instructions/` | diff --git a/README.zh-Hant.md b/README.zh-Hant.md index 86e1da2..a09ff85 100644 --- a/README.zh-Hant.md +++ b/README.zh-Hant.md @@ -143,7 +143,7 @@ AI:在開始實作之前,我需要了解幾個關鍵問題: | [Windsurf](https://windsurf.com) | IDE | `npx superpowers-zh` | `.windsurf/skills/`(全局 `~/.codeium/windsurf/skills/`) | | [Kiro](https://kiro.dev) | IDE | `npx superpowers-zh` | `.kiro/skills/` | | [Gemini CLI](https://github.com/google-gemini/gemini-cli) | CLI | `npx superpowers-zh` | `.gemini/skills/` | -| [Codex CLI](https://github.com/openai/codex) | CLI | `npx superpowers-zh` | `.codex/skills/` | +| [Codex CLI](https://github.com/openai/codex) | CLI | `npx superpowers-zh` | `.agents/skills/` | | [Aider](https://aider.chat) | CLI | `npx superpowers-zh` | `.aider/skills/` | | [Trae](https://trae.ai) | IDE | `npx superpowers-zh` | `.trae/skills/` + `.trae/rules/` | | [VS Code](https://code.visualstudio.com) (Copilot) | IDE 外掛 | `npx superpowers-zh` | `.github/superpowers/` + `.github/instructions/` | diff --git a/bin/superpowers-zh.js b/bin/superpowers-zh.js index dcd7903..0a20866 100755 --- a/bin/superpowers-zh.js +++ b/bin/superpowers-zh.js @@ -58,9 +58,15 @@ const TARGETS = [ // Cursor 经官方文档核实(cursor.com/docs/skills):.cursor/skills//SKILL.md, // 启动时自动发现并交给 Agent 按上下文选用,也可在对话里打 / 手动点名。无需配置。 { name: 'Cursor', dir: '.cursor/skills', detect: ['.cursor', '.cursorrules'] }, - // Codex 全局:docs 确认 Codex 启动时扫描 ~/.agents/skills/(不是 ~/.codex/skills), - // 直接把每个 skill 复制到 ~/.agents/skills// 正好命中它的扁平扫描。 - { name: 'Codex CLI', dir: '.codex/skills', detect: '.codex', global: { dir: '.agents/skills', detect: '.codex' } }, + // Codex 各层级扫的都是 .agents/skills,**从不扫 .codex/skills**。官方文档 + // (developers.openai.com/codex/skills,308 跳 learn.chatgpt.com/docs/build-skills) + // 给出的完整清单只有: + // $CWD/.agents/skills、$CWD/../.agents/skills、$REPO_ROOT/.agents/skills + // $HOME/.agents/skills、/etc/codex/skills、以及内置 skill + // 全局一直是对的(~/.agents/skills),但**项目级原来装到 .codex/skills —— Codex + // 不读那里,等于装了不生效**。v1.7.11 改为 .agents/skills,并清理旧位置。 + // 与 Antigravity 装在同一目录是预期的:两者共用 .agents/skills 这个开放约定。 + { name: 'Codex CLI', dir: '.agents/skills', detect: '.codex', global: { dir: '.agents/skills', detect: '.codex' } }, // Kiro 的 steering 与 Cline / Kilo 的 rules 同性质:**每轮常驻**。官方文档 // (kiro.dev/docs/steering)明确 `.kiro/steering/` 下的文件默认 inclusion: always, // "loaded into every Kiro interaction automatically"。 @@ -140,10 +146,14 @@ const TARGETS = [ // 优先级 项目级 > 用户级。v1.7.10 及更早文档写「用户级路径尚未验证」而没有 // --global —— 现已核实,补上。 { name: 'CodeBuddy', dir: '.codebuddy/skills', detect: ['.codebuddy', 'CODEBUDDY.md'], global: { dir: '.codebuddy/skills', detect: '.codebuddy' } }, - // 华为云码道(CodeArts Doer):skills 放 .codeartsdoer/skills/(用户在 #20 确认)。 - // 仅 skills-only —— 其 bootstrap/指令文件约定未证实,靠 CodeArts 自身 skill 发现; - // 若不自动触发需在对话里手动点名 skill(docs 已说明)。 - { name: 'CodeArts', dir: '.codeartsdoer/skills', detect: '.codeartsdoer' }, + // 华为云码道(CodeArts Doer)。原注释只写「用户在 #20 确认」—— 已补官方出处: + // support.huaweicloud.com/usermanual-codeartssnap/codeartsdoer_ug_0024.html + // 项目级:项目根目录的 ./.codeartsdoer/skills/ + // 个人级:%USERPROFILE%/.codeartsdoer/skills ← 即 ~/.codeartsdoer/skills + // 每个 skill 目录根必须有 SKILL.md,自动发现、创建后立刻生效、无需配置。 + // 个人级路径既然已证实,v1.7.11 起支持 --global(此前一直在拒绝名单里)。 + // 仍是 skills-only —— 其 bootstrap/指令文件约定未证实,不猜路径。 + { name: 'CodeArts', dir: '.codeartsdoer/skills', detect: '.codeartsdoer', global: { dir: '.codeartsdoer/skills', detect: '.codeartsdoer' } }, // Cline / Kilo Code 是 VS Code 扩展,加载的是「rules」而非 skills,且 rules 每轮常驻 // system prompt。因此 skills 放各自的 skills/ 目录(不被自动加载),只在 rules 目录里 // 放一份小索引 —— 见 generateClineBootstrapRule / generateKiloCodeBootstrapRule。 @@ -1058,6 +1068,24 @@ function installForTarget(target, baseDir, isGlobal) { generateQwenBootstrap(baseDir, isGlobal); } + // Codex 项目级旧位置清理:v1.7.10 及更早装到 .codex/skills,而 Codex 从不扫那里。 + // 升级的人通常直接重装不会先卸载,不清的话旧目录留着白占地方、还让人以为在生效。 + if (target.name === 'Codex CLI' && !isGlobal) { + const legacy = resolve(baseDir, '.codex', 'skills'); + if (existsSync(legacy)) { + const ours = new Set(scanSkillEntries(SKILLS_SRC).map(s => s.name)); + let n = 0; + for (const e of readdirSync(legacy, { withFileTypes: true })) { + if (e.isDirectory() && ours.has(e.name)) { rmSync(resolve(legacy, e.name), { recursive: true, force: true }); n++; } + } + if (n > 0) { + console.log(` 🧹 Codex: 清理旧位置 ${n} 个 skill 目录 <- .codex/skills/`); + console.log(` (Codex 只扫 .agents/skills,旧版装错了地方)`); + } + try { if (readdirSync(legacy).filter(x => x !== '.DS_Store').length === 0) rmSync(legacy, { recursive: true, force: true }); } catch {} + } + } + if (target.name === 'VS Code') { generateVSCodeBootstrap(baseDir); } @@ -1113,7 +1141,7 @@ const BOOTSTRAP_DELETE = [ // v1.7.9 及更早把 skill 正文直接装进 .kiro/steering//,而 steering 每轮常驻 —— // 那 335 KB 会一直进 prompt。升级的用户不会重跑旧版卸载,所以这里按老路径也清一遍, // 否则新旧两份并存,开销问题原样保留。 -const LEGACY_SKILL_DIRS = ['.kiro/steering']; +const LEGACY_SKILL_DIRS = ['.kiro/steering', '.codex/skills']; const BOOTSTRAP_CLEAN_SECTION = [ 'CLAUDE.md', 'GEMINI.md', @@ -1387,10 +1415,19 @@ function install(forceToolName, force, isGlobal) { let installed = 0; const pool = isGlobal ? GLOBAL_TARGETS : TARGETS; + // 先把所有工具的检测结果一次性算完,再开始装。 + // 边装边判会有顺序依赖:Codex 装到 .agents/skills 会创建 .agents/,紧接着 + // Antigravity(detect: '.agents')就被误判为「项目里有」,于是多装一份。 + // 两款共用 .agents/skills 是官方约定,但检测必须基于**安装前**的项目状态。 + const detectedBefore = new Map(); for (const target of pool) { - const detectMarker = isGlobal ? target.global.detect : target.detect; - const detects = Array.isArray(detectMarker) ? detectMarker : [detectMarker]; - const found = detects.some(d => existsSync(resolve(baseDir, d))); + const dm = isGlobal ? target.global.detect : target.detect; + const ds = Array.isArray(dm) ? dm : [dm]; + detectedBefore.set(target.name, ds.some(d => existsSync(resolve(baseDir, d)))); + } + + for (const target of pool) { + const found = detectedBefore.get(target.name); if (found) { installForTarget(target, baseDir, isGlobal); installed++; diff --git a/docs/README.codex.md b/docs/README.codex.md index 38a49b9..e1940ee 100644 --- a/docs/README.codex.md +++ b/docs/README.codex.md @@ -1,5 +1,28 @@ # Superpowers 中文版 — Codex CLI 安装指南 +## ⚠️ v1.7.10 及更早的项目级安装装错了地方 + +官方文档(developers.openai.com/codex/skills,现 308 跳 learn.chatgpt.com/docs/build-skills)给出的扫描目录**完整清单**是: + +``` +$CWD/.agents/skills +$CWD/../.agents/skills +$REPO_ROOT/.agents/skills +$HOME/.agents/skills +/etc/codex/skills +``` + +**没有 `.codex/skills`。** 而 v1.7.10 及更早的 `npx superpowers-zh --tool codex` 正是装到 `.codex/skills` —— Codex 不扫那里,等于装了完全不生效。全局(`~/.agents/skills`)一直是对的,只有项目级错。 + +v1.7.11 起项目级改装 `.agents/skills`,重装时会自动清掉旧位置里我们装的那些(你自己放在 `.codex/skills` 下的东西不动): + +```bash +cd /your/project +npx superpowers-zh --tool codex +``` + +> 顺带说明:`.agents/skills` 与 Antigravity 共用,这是 Agent Skills 开放约定,不是冲突。装过其中一个,另一个也能读到。 + 在 Codex 中使用 superpowers-zh 的完整指南。 ## 快速安装 diff --git a/scripts/verify-release.sh b/scripts/verify-release.sh index 00c4da9..783b98d 100755 --- a/scripts/verify-release.sh +++ b/scripts/verify-release.sh @@ -27,7 +27,7 @@ bad() { FAIL=$((FAIL+1)); FAILURES+=("$1"); printf ' ❌ %s\n' "$1"; } # 工具别名 -> 期望的 skills 目录(相对项目根) declare -a SPEC=( - "claude:.claude/skills" "cursor:.cursor/skills" "codex:.codex/skills" + "claude:.claude/skills" "cursor:.cursor/skills" "codex:.agents/skills" "kiro:.kiro/skills" "deerflow:skills/custom" "trae:.trae/skills" "antigravity:.agents/skills" "vscode:.github/superpowers" "openclaw:skills" "windsurf:.windsurf/skills" "gemini:.gemini/skills" "aider:.aider/skills" @@ -113,9 +113,9 @@ for entry in "${DETECT[@]}"; do done echo "" -echo "─── C. --global:10 款应成功,其余应明确拒绝且退出码 1 ───" -declare -a GLOBAL_OK=(claude codex openclaw windsurf opencode qwen qoder crush hermes codebuddy) -declare -a GLOBAL_NO=(cursor kiro trae aider deerflow vscode claw gemini antigravity codearts cline kilocode) +echo "─── C. --global:11 款应成功,其余应明确拒绝且退出码 1 ───" +declare -a GLOBAL_OK=(claude codex openclaw windsurf opencode qwen qoder crush hermes codebuddy codearts) +declare -a GLOBAL_NO=(cursor kiro trae aider deerflow vscode claw gemini antigravity cline kilocode) # 全局落盘位置断言。原来这里只看退出码 —— 而 Windsurf 的 --global 曾装到 # ~/.windsurf/skills,官方实际读 ~/.codeium/windsurf/skills,退出码照样是 0。 # 「跑通了」不等于「装对了」,必须断言 skill 真的落在官方读的那个目录。 @@ -124,6 +124,7 @@ declare -a GLOBAL_DIR=( "windsurf:.codeium/windsurf/skills" "opencode:.config/opencode/skills" "qwen:.qwen/skills" "qoder:.qoder/skills" "crush:.config/crush/skills" "hermes:.hermes/skills" "codebuddy:.codebuddy/skills" + "codearts:.codeartsdoer/skills" ) for entry in "${GLOBAL_DIR[@]}"; do tool="${entry%%:*}"; gdir="${entry#*:}"