fix: restore short Claude plugin slug and skill installs (#1712)

This commit is contained in:
Affaan Mustafa
2026-05-11 02:10:36 -04:00
committed by GitHub
parent 7b964402ee
commit 8a57679222
25 changed files with 273 additions and 94 deletions

View File

@@ -78,6 +78,56 @@ function dedupeStrings(values) {
return [...new Set((Array.isArray(values) ? values : []).map(value => String(value).trim()).filter(Boolean))];
}
function listSkillDirectoryIds(repoRoot) {
const skillsRoot = path.join(repoRoot, 'skills');
if (!fs.existsSync(skillsRoot) || !fs.statSync(skillsRoot).isDirectory()) {
return [];
}
return fs.readdirSync(skillsRoot, { withFileTypes: true })
.filter(entry => entry.isDirectory())
.map(entry => entry.name)
.sort();
}
function addSyntheticSkillComponents({ repoRoot, modules, components }) {
const moduleIds = new Set(modules.map(module => module.id));
const componentIds = new Set(components.map(component => component.id));
for (const skillId of listSkillDirectoryIds(repoRoot)) {
const componentId = `skill:${skillId}`;
if (componentIds.has(componentId)) {
continue;
}
const moduleId = `skill-${skillId}`;
if (!moduleIds.has(moduleId)) {
modules.push({
id: moduleId,
kind: 'skills',
description: `Single-skill install surface for ${skillId}.`,
paths: [`skills/${skillId}`],
targets: SUPPORTED_INSTALL_TARGETS.slice(),
dependencies: [],
defaultInstall: false,
cost: 'light',
stability: 'stable',
synthetic: true,
});
moduleIds.add(moduleId);
}
components.push({
id: componentId,
family: 'skill',
description: `Install only the ${skillId} skill directory.`,
modules: [moduleId],
synthetic: true,
});
componentIds.add(componentId);
}
}
function readOptionalStringOption(options, key) {
if (
!Object.prototype.hasOwnProperty.call(options, key)
@@ -164,11 +214,13 @@ function loadInstallManifests(options = {}) {
const componentsData = fs.existsSync(componentsPath)
? readJson(componentsPath, 'install-components.json')
: { version: null, components: [] };
const modules = Array.isArray(modulesData.modules) ? modulesData.modules : [];
const modules = Array.isArray(modulesData.modules) ? modulesData.modules.slice() : [];
const profiles = profilesData && typeof profilesData.profiles === 'object'
? profilesData.profiles
: {};
const components = Array.isArray(componentsData.components) ? componentsData.components : [];
const components = Array.isArray(componentsData.components) ? componentsData.components.slice() : [];
addSyntheticSkillComponents({ repoRoot, modules, components });
for (const module of modules) {
readModuleTargetsOrThrow(module);

View File

@@ -8,6 +8,12 @@ function dedupeStrings(values) {
return [...new Set((Array.isArray(values) ? values : []).map(value => String(value).trim()).filter(Boolean))];
}
function normalizeSkillComponentIds(rawValue) {
return dedupeStrings(String(rawValue || '').split(',')).map(value => (
value.startsWith('skill:') ? value : `skill:${value}`
));
}
function parseInstallArgs(argv) {
const args = argv.slice(2);
const parsed = {
@@ -45,6 +51,9 @@ function parseInstallArgs(argv) {
parsed.includeComponentIds.push(componentId.trim());
}
index += 1;
} else if (arg === '--skill' || arg === '--skills') {
parsed.includeComponentIds.push(...normalizeSkillComponentIds(args[index + 1] || ''));
index += 1;
} else if (arg === '--without') {
const componentId = args[index + 1] || '';
if (componentId.trim()) {