Skip to content

Commit 266dfc3

Browse files
committed
fix: detect plugin-managed superpowers in doctor
1 parent 966d6cb commit 266dfc3

5 files changed

Lines changed: 62 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
All notable changes to @rpamis/comet will be documented in this file.
44

5+
## What's Changed [0.4.0-beta.16] - 2026-08-05
6+
7+
### Fixed
8+
9+
- **Doctor Superpowers detection**: `comet doctor` now recognizes Claude Code plugin-managed Superpowers installs, so users with Superpowers under the plugin cache no longer receive a misleading install warning.
10+
511
## What's Changed [0.4.0-beta.15] - 2026-08-05
612

713
### Added

app/commands/doctor.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
getPlatformSkillsDirs,
3939
type Platform,
4040
} from '../../platform/install/platforms.js';
41+
import { hasSkills } from '../../platform/install/detect.js';
4142
import { resolveCanonicalSkillRootOwners } from '../../platform/install/skill-root-owner.js';
4243
import type { InstallScope } from '../../platform/install/types.js';
4344
import { inspectClassicChangeReadOnly } from '../../domains/comet-classic/classic-diagnostics.js';
@@ -610,6 +611,15 @@ async function checkSuperpowers(
610611
const detected: string[] = [];
611612
for (const base of getScopeBases(projectPath, scope, context)) {
612613
for (const platform of PLATFORMS) {
614+
if (
615+
await hasSkills(base.baseDir, platform, 'superpowers', [platform], base.scope, {
616+
includeGlobalFallback: false,
617+
includePluginFallback: base.scope === 'global',
618+
})
619+
) {
620+
detected.push(`${platform.name} ${base.scope}`);
621+
continue;
622+
}
613623
for (const skillsDir of getPlatformSkillsDirs(platform, base.scope)) {
614624
for (const sentinel of SUPERPOWERS_SENTINELS) {
615625
if (await fileExists(path.join(base.baseDir, skillsDir, 'skills', sentinel))) {

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@rpamis/comet",
3-
"version": "0.4.0-beta.15",
3+
"version": "0.4.0-beta.16",
44
"description": "Agent Skill Harness For Turning Ideas Into Evaluated Workflows",
55
"keywords": [
66
"comet",

test/app/doctor.test.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,6 +1184,49 @@ describe('doctor command', () => {
11841184
);
11851185
});
11861186

1187+
it('detects Claude plugin-managed Superpowers installs', async () => {
1188+
const fakeHome = path.join(tmpDir, 'plugin-home');
1189+
const pluginSkillsDir = path.join(
1190+
fakeHome,
1191+
'.claude',
1192+
'plugins',
1193+
'cache',
1194+
'claude-plugins-official',
1195+
'superpowers',
1196+
'6.2.0',
1197+
'skills',
1198+
);
1199+
await fs.mkdir(path.join(pluginSkillsDir, 'using-superpowers'), { recursive: true });
1200+
await fs.writeFile(
1201+
path.join(pluginSkillsDir, 'using-superpowers', 'SKILL.md'),
1202+
'# using-superpowers\n',
1203+
'utf8',
1204+
);
1205+
1206+
const previousClaudeConfigDir = process.env.CLAUDE_CONFIG_DIR;
1207+
process.env.CLAUDE_CONFIG_DIR = path.join(fakeHome, '.claude');
1208+
try {
1209+
const log = vi.spyOn(console, 'log').mockImplementation(() => undefined);
1210+
let output: string;
1211+
try {
1212+
await doctorCommand(tmpDir, { homeDir: fakeHome });
1213+
output = log.mock.calls.map((call) => call.join(' ')).join('\n');
1214+
} finally {
1215+
log.mockRestore();
1216+
}
1217+
1218+
expect(output).toContain('Superpowers: detected');
1219+
expect(output).toContain('Claude Code global');
1220+
expect(output).not.toContain('Superpowers: not detected');
1221+
} finally {
1222+
if (previousClaudeConfigDir === undefined) {
1223+
delete process.env.CLAUDE_CONFIG_DIR;
1224+
} else {
1225+
process.env.CLAUDE_CONFIG_DIR = previousClaudeConfigDir;
1226+
}
1227+
}
1228+
});
1229+
11871230
it('reports partial Comet installs with an update command instead of a raw missing dump', async () => {
11881231
await fs.mkdir(path.join(tmpDir, '.claude', 'skills', 'comet'), {
11891232
recursive: true,

0 commit comments

Comments
 (0)