Skip to content

Commit 792d508

Browse files
committed
fix: detect Codex plugin superpowers
1 parent 1148910 commit 792d508

2 files changed

Lines changed: 71 additions & 12 deletions

File tree

src/core/detect.ts

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,7 @@ const SUPERPOWERS_SKILLS = [
1414
'subagent-driven-development',
1515
];
1616

17-
function getBaseDir(scope: InstallScope, projectPath: string): string {
18-
return scope === 'global' ? os.homedir() : projectPath;
19-
}
20-
21-
/**
22-
* Check if superpowers are installed via Claude Code plugin system.
23-
* Looks in ~/.claude/plugins/cache/{marketplace}/superpowers/{version}/skills/
24-
*/
25-
async function hasPluginSuperpowers(): Promise<boolean> {
26-
const claudeDir = process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), '.claude');
27-
const pluginsCacheDir = path.join(claudeDir, 'plugins', 'cache');
28-
17+
async function hasSuperpowersInPluginCache(pluginsCacheDir: string): Promise<boolean> {
2918
const marketplaceEntries = await readDir(pluginsCacheDir);
3019
for (const marketplace of marketplaceEntries) {
3120
const superpowersDir = path.join(pluginsCacheDir, marketplace, 'superpowers');
@@ -40,9 +29,37 @@ async function hasPluginSuperpowers(): Promise<boolean> {
4029
}
4130
}
4231
}
32+
4333
return false;
4434
}
4535

36+
function getBaseDir(scope: InstallScope, projectPath: string): string {
37+
return scope === 'global' ? os.homedir() : projectPath;
38+
}
39+
40+
/**
41+
* Check if superpowers are installed via Claude Code plugin system.
42+
* Looks in ~/.claude/plugins/cache/{marketplace}/superpowers/{version}/skills/
43+
*/
44+
async function hasPluginSuperpowers(): Promise<boolean> {
45+
const claudeDir = process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), '.claude');
46+
const pluginsCacheDir = path.join(claudeDir, 'plugins', 'cache');
47+
48+
return hasSuperpowersInPluginCache(pluginsCacheDir);
49+
}
50+
51+
/**
52+
* Check if superpowers are installed via Codex plugin system.
53+
* Looks in ~/.codex/plugins/cache/{marketplace}/superpowers/{version}/skills/
54+
*/
55+
async function hasCodexPluginSuperpowers(): Promise<boolean> {
56+
const codexDir =
57+
process.env.CODEX_HOME || process.env.CODEX_CONFIG_DIR || path.join(os.homedir(), '.codex');
58+
const pluginsCacheDir = path.join(codexDir, 'plugins', 'cache');
59+
60+
return hasSuperpowersInPluginCache(pluginsCacheDir);
61+
}
62+
4663
/**
4764
* Check if superpowers are installed via OpenCode plugin system.
4865
* Checks multiple locations:
@@ -189,6 +206,11 @@ async function hasSkills(
189206
if (await hasPluginSuperpowers()) return true;
190207
}
191208

209+
// Check Codex plugin cache for plugin-installed superpowers
210+
if (component === 'superpowers' && platform.id === 'codex') {
211+
if (await hasCodexPluginSuperpowers()) return true;
212+
}
213+
192214
// Check OpenCode plugin system for plugin-installed superpowers
193215
if (component === 'superpowers' && platform.id === 'opencode') {
194216
if (await hasOpenCodePluginSuperpowers()) return true;
@@ -201,6 +223,7 @@ export {
201223
detectPlatforms,
202224
hasSkills,
203225
hasPluginSuperpowers,
226+
hasCodexPluginSuperpowers,
204227
hasOpenCodePluginSuperpowers,
205228
getBaseDir,
206229
};

test/ts/detect.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,42 @@ describe('detect', () => {
245245
delete process.env.CLAUDE_CONFIG_DIR;
246246
}
247247
});
248+
249+
it('detects plugin-installed superpowers for codex platform', async () => {
250+
const origEnv = process.env.CODEX_HOME;
251+
const pluginDir = path.join(tmpDir, '.codex');
252+
process.env.CODEX_HOME = pluginDir;
253+
254+
try {
255+
const skillsDir = path.join(
256+
pluginDir,
257+
'plugins',
258+
'cache',
259+
'openai-curated',
260+
'superpowers',
261+
'c6ea566d',
262+
'skills',
263+
);
264+
await fs.mkdir(skillsDir, { recursive: true });
265+
await fs.mkdir(path.join(skillsDir, 'brainstorming'));
266+
await fs.mkdir(path.join(skillsDir, 'using-superpowers'));
267+
268+
// No skills in the normal project location.
269+
await fs.mkdir(path.join(tmpDir, '.codex', 'skills'), { recursive: true });
270+
271+
const codexPlatform = PLATFORMS.find((platform) => platform.id === 'codex');
272+
expect(codexPlatform).toBeDefined();
273+
if (!codexPlatform) return;
274+
275+
expect(await hasSkills(tmpDir, codexPlatform, 'superpowers')).toBe(true);
276+
} finally {
277+
if (origEnv !== undefined) {
278+
process.env.CODEX_HOME = origEnv;
279+
} else {
280+
delete process.env.CODEX_HOME;
281+
}
282+
}
283+
});
248284
});
249285

250286
describe('hasPluginSuperpowers', () => {

0 commit comments

Comments
 (0)