Skip to content

Commit fb63548

Browse files
committed
fix(installer): Codex 项目级装到 Codex 从不扫描的目录;CodeArts 补 --global
## Codex:项目级又是「装了完全不生效」 官方 skills 文档(developers.openai.com/codex/skills,现 308 跳到官方新文档站) 给出的扫描目录**完整清单**: $CWD/.agents/skills、$CWD/../.agents/skills、$REPO_ROOT/.agents/skills $HOME/.agents/skills、/etc/codex/skills、内置 skill **没有 .codex/skills。** 两次分别追问确认「.codex/skills 是否曾被扫描」,答案都是 从未出现。而我们项目级正是装到 .codex/skills。 全局(~/.agents/skills)一直是对的 —— 原注释也写明了「不是 ~/.codex/skills」, 说明当初查过全局却没顺手核项目级。改为 .agents/skills,并在安装时清理旧位置 (只清我们装的那些,用户自己放在 .codex/skills 下的不动,已实测)。 与 Antigravity 共用 .agents/skills 是 Agent Skills 开放约定,不是冲突。 ## 这个改动暴露出一个既有 bug:检测有顺序依赖 改完后测试立刻报「检测 .codex/ -> 得到「Antigravity,Codex CLI」,期望「Codex CLI」」。 根因:自动检测是**边装边判**的。Codex 装到 .agents/skills 会创建 .agents/, 循环走到 Antigravity(detect: '.agents')时它就被误判为「项目里有这个工具」, 于是多装一份。这个坑在任何「装了 A 会创建 B 的检测标记」的组合上都会犯。 改为先把所有工具的检测结果一次性算完再开始装 —— 检测必须基于**安装前**的项目 状态。实测:只有 .codex 时只装 Codex;同时有 .codex 与 .agents 时两款都装且 .agents/skills 下仍是 20 个(不重复)。 ## CodeArts:官方已证实用户级路径,补上 --global 原注释只写「用户在 #20 确认」,没有官方出处。已补华为云官方用户指南出处: 项目级:项目根目录的 ./.codeartsdoer/skills/ 个人级:%USERPROFILE%/.codeartsdoer/skills 即 ~/.codeartsdoer/skills 既然已证实,--global 从拒绝名单移出并加落盘断言。实测装 20 个到 ~/.codeartsdoer/skills、卸载后 HOME 零残留。仍是 skills-only —— 其 bootstrap 约定未证实,不猜。 ## 顺带核实 - Cursor:官方 skills 文档确认 .cursor/skills/<name>/SKILL.md ✅ - OpenCode:官方 skills 文档确认项目级与全局都对 ✅(唯二全对的之一) - Kimi / Pi:不在 TARGETS 里,走 plugin manifest 与扩展分发;已确认 docs 没有 承诺 --tool kimi/pi,installer 也正确拒绝这两个名字,无虚假承诺 audit 168 pass / 0 warn / 0 fail;verify-release 115 pass / 0 fail。
1 parent 0e3fbc4 commit fb63548

5 files changed

Lines changed: 78 additions & 17 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ AI:在开始实现之前,我需要了解几个关键问题:
143143
| [Windsurf](https://windsurf.com) | IDE | `npx superpowers-zh` | `.windsurf/skills/`(全局 `~/.codeium/windsurf/skills/`|
144144
| [Kiro](https://kiro.dev) | IDE | `npx superpowers-zh` | `.kiro/skills/` |
145145
| [Gemini CLI](https://github.com/google-gemini/gemini-cli) | CLI | `npx superpowers-zh` | `.gemini/skills/` |
146-
| [Codex CLI](https://github.com/openai/codex) | CLI | `npx superpowers-zh` | `.codex/skills/` |
146+
| [Codex CLI](https://github.com/openai/codex) | CLI | `npx superpowers-zh` | `.agents/skills/` |
147147
| [Aider](https://aider.chat) | CLI | `npx superpowers-zh` | `.aider/skills/` |
148148
| [Trae](https://trae.ai) | IDE | `npx superpowers-zh` | `.trae/skills/` + `.trae/rules/` |
149149
| [VS Code](https://code.visualstudio.com) (Copilot) | IDE 插件 | `npx superpowers-zh` | `.github/superpowers/` + `.github/instructions/` |

README.zh-Hant.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ AI:在開始實作之前,我需要了解幾個關鍵問題:
143143
| [Windsurf](https://windsurf.com) | IDE | `npx superpowers-zh` | `.windsurf/skills/`(全局 `~/.codeium/windsurf/skills/`|
144144
| [Kiro](https://kiro.dev) | IDE | `npx superpowers-zh` | `.kiro/skills/` |
145145
| [Gemini CLI](https://github.com/google-gemini/gemini-cli) | CLI | `npx superpowers-zh` | `.gemini/skills/` |
146-
| [Codex CLI](https://github.com/openai/codex) | CLI | `npx superpowers-zh` | `.codex/skills/` |
146+
| [Codex CLI](https://github.com/openai/codex) | CLI | `npx superpowers-zh` | `.agents/skills/` |
147147
| [Aider](https://aider.chat) | CLI | `npx superpowers-zh` | `.aider/skills/` |
148148
| [Trae](https://trae.ai) | IDE | `npx superpowers-zh` | `.trae/skills/` + `.trae/rules/` |
149149
| [VS Code](https://code.visualstudio.com) (Copilot) | IDE 外掛 | `npx superpowers-zh` | `.github/superpowers/` + `.github/instructions/` |

bin/superpowers-zh.js

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,15 @@ const TARGETS = [
5858
// Cursor 经官方文档核实(cursor.com/docs/skills):.cursor/skills/<name>/SKILL.md,
5959
// 启动时自动发现并交给 Agent 按上下文选用,也可在对话里打 / 手动点名。无需配置。
6060
{ name: 'Cursor', dir: '.cursor/skills', detect: ['.cursor', '.cursorrules'] },
61-
// Codex 全局:docs 确认 Codex 启动时扫描 ~/.agents/skills/(不是 ~/.codex/skills),
62-
// 直接把每个 skill 复制到 ~/.agents/skills/<skill>/ 正好命中它的扁平扫描。
63-
{ name: 'Codex CLI', dir: '.codex/skills', detect: '.codex', global: { dir: '.agents/skills', detect: '.codex' } },
61+
// Codex 各层级扫的都是 .agents/skills,**从不扫 .codex/skills**。官方文档
62+
// (developers.openai.com/codex/skills,308 跳 learn.chatgpt.com/docs/build-skills)
63+
// 给出的完整清单只有:
64+
// $CWD/.agents/skills、$CWD/../.agents/skills、$REPO_ROOT/.agents/skills
65+
// $HOME/.agents/skills、/etc/codex/skills、以及内置 skill
66+
// 全局一直是对的(~/.agents/skills),但**项目级原来装到 .codex/skills —— Codex
67+
// 不读那里,等于装了不生效**。v1.7.11 改为 .agents/skills,并清理旧位置。
68+
// 与 Antigravity 装在同一目录是预期的:两者共用 .agents/skills 这个开放约定。
69+
{ name: 'Codex CLI', dir: '.agents/skills', detect: '.codex', global: { dir: '.agents/skills', detect: '.codex' } },
6470
// Kiro 的 steering 与 Cline / Kilo 的 rules 同性质:**每轮常驻**。官方文档
6571
// (kiro.dev/docs/steering)明确 `.kiro/steering/` 下的文件默认 inclusion: always,
6672
// "loaded into every Kiro interaction automatically"。
@@ -140,10 +146,14 @@ const TARGETS = [
140146
// 优先级 项目级 > 用户级。v1.7.10 及更早文档写「用户级路径尚未验证」而没有
141147
// --global —— 现已核实,补上。
142148
{ name: 'CodeBuddy', dir: '.codebuddy/skills', detect: ['.codebuddy', 'CODEBUDDY.md'], global: { dir: '.codebuddy/skills', detect: '.codebuddy' } },
143-
// 华为云码道(CodeArts Doer):skills 放 .codeartsdoer/skills/(用户在 #20 确认)。
144-
// 仅 skills-only —— 其 bootstrap/指令文件约定未证实,靠 CodeArts 自身 skill 发现;
145-
// 若不自动触发需在对话里手动点名 skill(docs 已说明)。
146-
{ name: 'CodeArts', dir: '.codeartsdoer/skills', detect: '.codeartsdoer' },
149+
// 华为云码道(CodeArts Doer)。原注释只写「用户在 #20 确认」—— 已补官方出处:
150+
// support.huaweicloud.com/usermanual-codeartssnap/codeartsdoer_ug_0024.html
151+
// 项目级:项目根目录的 ./.codeartsdoer/skills/
152+
// 个人级:%USERPROFILE%/.codeartsdoer/skills ← 即 ~/.codeartsdoer/skills
153+
// 每个 skill 目录根必须有 SKILL.md,自动发现、创建后立刻生效、无需配置。
154+
// 个人级路径既然已证实,v1.7.11 起支持 --global(此前一直在拒绝名单里)。
155+
// 仍是 skills-only —— 其 bootstrap/指令文件约定未证实,不猜路径。
156+
{ name: 'CodeArts', dir: '.codeartsdoer/skills', detect: '.codeartsdoer', global: { dir: '.codeartsdoer/skills', detect: '.codeartsdoer' } },
147157
// Cline / Kilo Code 是 VS Code 扩展,加载的是「rules」而非 skills,且 rules 每轮常驻
148158
// system prompt。因此 skills 放各自的 skills/ 目录(不被自动加载),只在 rules 目录里
149159
// 放一份小索引 —— 见 generateClineBootstrapRule / generateKiloCodeBootstrapRule。
@@ -1058,6 +1068,24 @@ function installForTarget(target, baseDir, isGlobal) {
10581068
generateQwenBootstrap(baseDir, isGlobal);
10591069
}
10601070

1071+
// Codex 项目级旧位置清理:v1.7.10 及更早装到 .codex/skills,而 Codex 从不扫那里。
1072+
// 升级的人通常直接重装不会先卸载,不清的话旧目录留着白占地方、还让人以为在生效。
1073+
if (target.name === 'Codex CLI' && !isGlobal) {
1074+
const legacy = resolve(baseDir, '.codex', 'skills');
1075+
if (existsSync(legacy)) {
1076+
const ours = new Set(scanSkillEntries(SKILLS_SRC).map(s => s.name));
1077+
let n = 0;
1078+
for (const e of readdirSync(legacy, { withFileTypes: true })) {
1079+
if (e.isDirectory() && ours.has(e.name)) { rmSync(resolve(legacy, e.name), { recursive: true, force: true }); n++; }
1080+
}
1081+
if (n > 0) {
1082+
console.log(` 🧹 Codex: 清理旧位置 ${n} 个 skill 目录 <- .codex/skills/`);
1083+
console.log(` (Codex 只扫 .agents/skills,旧版装错了地方)`);
1084+
}
1085+
try { if (readdirSync(legacy).filter(x => x !== '.DS_Store').length === 0) rmSync(legacy, { recursive: true, force: true }); } catch {}
1086+
}
1087+
}
1088+
10611089
if (target.name === 'VS Code') {
10621090
generateVSCodeBootstrap(baseDir);
10631091
}
@@ -1113,7 +1141,7 @@ const BOOTSTRAP_DELETE = [
11131141
// v1.7.9 及更早把 skill 正文直接装进 .kiro/steering/<skill>/,而 steering 每轮常驻 ——
11141142
// 那 335 KB 会一直进 prompt。升级的用户不会重跑旧版卸载,所以这里按老路径也清一遍,
11151143
// 否则新旧两份并存,开销问题原样保留。
1116-
const LEGACY_SKILL_DIRS = ['.kiro/steering'];
1144+
const LEGACY_SKILL_DIRS = ['.kiro/steering', '.codex/skills'];
11171145
const BOOTSTRAP_CLEAN_SECTION = [
11181146
'CLAUDE.md',
11191147
'GEMINI.md',
@@ -1387,10 +1415,19 @@ function install(forceToolName, force, isGlobal) {
13871415
let installed = 0;
13881416
const pool = isGlobal ? GLOBAL_TARGETS : TARGETS;
13891417

1418+
// 先把所有工具的检测结果一次性算完,再开始装。
1419+
// 边装边判会有顺序依赖:Codex 装到 .agents/skills 会创建 .agents/,紧接着
1420+
// Antigravity(detect: '.agents')就被误判为「项目里有」,于是多装一份。
1421+
// 两款共用 .agents/skills 是官方约定,但检测必须基于**安装前**的项目状态。
1422+
const detectedBefore = new Map();
1423+
for (const target of pool) {
1424+
const dm = isGlobal ? target.global.detect : target.detect;
1425+
const ds = Array.isArray(dm) ? dm : [dm];
1426+
detectedBefore.set(target.name, ds.some(d => existsSync(resolve(baseDir, d))));
1427+
}
1428+
13901429
for (const target of pool) {
1391-
const detectMarker = isGlobal ? target.global.detect : target.detect;
1392-
const detects = Array.isArray(detectMarker) ? detectMarker : [detectMarker];
1393-
const found = detects.some(d => existsSync(resolve(baseDir, d)));
1430+
const found = detectedBefore.get(target.name);
13941431
if (found) {
13951432
installForTarget(target, baseDir, isGlobal);
13961433
installed++;

docs/README.codex.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
11
# Superpowers 中文版 — Codex CLI 安装指南
22

3+
## ⚠️ v1.7.10 及更早的项目级安装装错了地方
4+
5+
官方文档(developers.openai.com/codex/skills,现 308 跳 learn.chatgpt.com/docs/build-skills)给出的扫描目录**完整清单**是:
6+
7+
```
8+
$CWD/.agents/skills
9+
$CWD/../.agents/skills
10+
$REPO_ROOT/.agents/skills
11+
$HOME/.agents/skills
12+
/etc/codex/skills
13+
```
14+
15+
**没有 `.codex/skills`** 而 v1.7.10 及更早的 `npx superpowers-zh --tool codex` 正是装到 `.codex/skills` —— Codex 不扫那里,等于装了完全不生效。全局(`~/.agents/skills`)一直是对的,只有项目级错。
16+
17+
v1.7.11 起项目级改装 `.agents/skills`,重装时会自动清掉旧位置里我们装的那些(你自己放在 `.codex/skills` 下的东西不动):
18+
19+
```bash
20+
cd /your/project
21+
npx superpowers-zh --tool codex
22+
```
23+
24+
> 顺带说明:`.agents/skills` 与 Antigravity 共用,这是 Agent Skills 开放约定,不是冲突。装过其中一个,另一个也能读到。
25+
326
在 Codex 中使用 superpowers-zh 的完整指南。
427

528
## 快速安装

scripts/verify-release.sh

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ bad() { FAIL=$((FAIL+1)); FAILURES+=("$1"); printf ' ❌ %s\n' "$1"; }
2727

2828
# 工具别名 -> 期望的 skills 目录(相对项目根)
2929
declare -a SPEC=(
30-
"claude:.claude/skills" "cursor:.cursor/skills" "codex:.codex/skills"
30+
"claude:.claude/skills" "cursor:.cursor/skills" "codex:.agents/skills"
3131
"kiro:.kiro/skills" "deerflow:skills/custom" "trae:.trae/skills"
3232
"antigravity:.agents/skills" "vscode:.github/superpowers" "openclaw:skills"
3333
"windsurf:.windsurf/skills" "gemini:.gemini/skills" "aider:.aider/skills"
@@ -113,9 +113,9 @@ for entry in "${DETECT[@]}"; do
113113
done
114114

115115
echo ""
116-
echo "─── C. --global:10 款应成功,其余应明确拒绝且退出码 1 ───"
117-
declare -a GLOBAL_OK=(claude codex openclaw windsurf opencode qwen qoder crush hermes codebuddy)
118-
declare -a GLOBAL_NO=(cursor kiro trae aider deerflow vscode claw gemini antigravity codearts cline kilocode)
116+
echo "─── C. --global:11 款应成功,其余应明确拒绝且退出码 1 ───"
117+
declare -a GLOBAL_OK=(claude codex openclaw windsurf opencode qwen qoder crush hermes codebuddy codearts)
118+
declare -a GLOBAL_NO=(cursor kiro trae aider deerflow vscode claw gemini antigravity cline kilocode)
119119
# 全局落盘位置断言。原来这里只看退出码 —— 而 Windsurf 的 --global 曾装到
120120
# ~/.windsurf/skills,官方实际读 ~/.codeium/windsurf/skills,退出码照样是 0。
121121
# 「跑通了」不等于「装对了」,必须断言 skill 真的落在官方读的那个目录。
@@ -124,6 +124,7 @@ declare -a GLOBAL_DIR=(
124124
"windsurf:.codeium/windsurf/skills" "opencode:.config/opencode/skills"
125125
"qwen:.qwen/skills" "qoder:.qoder/skills" "crush:.config/crush/skills"
126126
"hermes:.hermes/skills" "codebuddy:.codebuddy/skills"
127+
"codearts:.codeartsdoer/skills"
127128
)
128129
for entry in "${GLOBAL_DIR[@]}"; do
129130
tool="${entry%%:*}"; gdir="${entry#*:}"

0 commit comments

Comments
 (0)