fix(3562): generate Codex skill surface; $gsd-* commands discoverable after install
Closes #3562 Codex CLI 0.130.0 only registers commands from skills/<name>/SKILL.md; it does NOT auto-discover from get-shit-done/workflows/*.md or agents/*.md. Prior installer logic (#3427/#3433) removed the gsd-* skill copies under the assumption that Codex would discover the official skills directly. That assumption does not hold — users ended up with workflows on disk and zero $gsd-* entrypoints after restart. Fix: re-wire copyCommandsAsCodexSkills() (line 5519, already present) into the Codex install dispatch path (line 8090). Generates one ~/.codex/skills/gsd-<name>/SKILL.md per commands/gsd/*.md — same shape the Copilot/Antigravity/Cursor/Windsurf/Augment/Trae installs use. Behaviour change: the pre-existing test in bug-3427-3433-codex-install-shape asserted "does not regenerate gsd-* skill copies". Updated it to assert the new behaviour (regenerate gsd-* with refreshed body, preserve non-gsd user skills). Tests: - New tests/bug-3562-codex-install-skill-surface.test.cjs (4 cases): - skills/gsd-help/SKILL.md exists - SKILL.md has YAML frontmatter with name: gsd-help - >= 10 gsd-* skill directories produced (lower-bound, currently 67) - Pre-existing custom-user-skill directory preserved - tests/bug-3427-3433-codex-install-shape.test.cjs: updated to assert regeneration + body refresh + unrelated-skill preservation. Verified by re-running the issue's repro: `node bin/install.js --codex --global --config-dir <tmp>` now produces 67 gsd-* skills and the target ~/.codex/skills/gsd-help/SKILL.md exists with valid frontmatter. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8088,23 +8088,27 @@ function install(isGlobal, runtime = 'claude', options = {}) {
|
||||
failures.push('command/gsd-*');
|
||||
}
|
||||
} else if (isCodex) {
|
||||
// Codex CLI (0.130.0 at time of #3562) does NOT auto-discover commands
|
||||
// from get-shit-done/workflows/*.md or agents/*.md. It only registers
|
||||
// commands from skills/<name>/SKILL.md. The earlier "Codex discovers
|
||||
// official skills directly" branch left users with workflows on disk and
|
||||
// no $gsd-* entrypoints. Regenerate the skill surface the same way the
|
||||
// other runtimes do — copyCommandsAsCodexSkills() rewrites each
|
||||
// commands/gsd/*.md as ~/.codex/skills/gsd-<name>/SKILL.md and converts
|
||||
// Claude-flavored command frontmatter into Codex skill frontmatter.
|
||||
const skillsDir = path.join(targetDir, 'skills');
|
||||
// Codex now discovers repo/user/admin/system skills from .agents/skills and
|
||||
// warns if a layer mixes redundant hook/skill representations. Legacy
|
||||
// gsd-* copies under ~/.codex/skills are therefore removed and no longer
|
||||
// regenerated.
|
||||
let removedLegacyCodexSkills = 0;
|
||||
const gsdSrc = _stageSkills(_commandsDir);
|
||||
copyCommandsAsCodexSkills(gsdSrc, skillsDir, 'gsd', pathPrefix, runtime);
|
||||
if (fs.existsSync(skillsDir)) {
|
||||
for (const entry of fs.readdirSync(skillsDir, { withFileTypes: true })) {
|
||||
if (!entry.isDirectory() || !entry.name.startsWith('gsd-')) continue;
|
||||
fs.rmSync(path.join(skillsDir, entry.name), { recursive: true, force: true });
|
||||
removedLegacyCodexSkills += 1;
|
||||
const count = fs.readdirSync(skillsDir, { withFileTypes: true })
|
||||
.filter(e => e.isDirectory() && e.name.startsWith('gsd-')).length;
|
||||
if (count > 0) {
|
||||
console.log(` ${green}✓${reset} Installed ${count} skills to skills/`);
|
||||
} else {
|
||||
failures.push('skills/gsd-*');
|
||||
}
|
||||
}
|
||||
if (removedLegacyCodexSkills > 0) {
|
||||
console.log(` ${green}✓${reset} Removed ${removedLegacyCodexSkills} legacy Codex gsd-* skill copies from skills/`);
|
||||
} else {
|
||||
console.log(` ${dim}↳${reset} Skipped Codex skill-copy generation (Codex discovers official skills directly)`);
|
||||
failures.push('skills/gsd-*');
|
||||
}
|
||||
} else if (isCopilot) {
|
||||
const skillsDir = path.join(targetDir, 'skills');
|
||||
|
||||
Reference in New Issue
Block a user