diff --git a/cli/assets/templates/platforms/copilot.json b/cli/assets/templates/platforms/copilot.json index e381e69..d1ce349 100644 --- a/cli/assets/templates/platforms/copilot.json +++ b/cli/assets/templates/platforms/copilot.json @@ -4,13 +4,14 @@ "installType": "full", "folderStructure": { "root": ".github", - "skillPath": "prompts/ui-ux-pro-max", - "filename": "PROMPT.md" + "skillPath": "prompts", + "filename": "ui-ux-pro-max.prompt.md", + "dataPath": "prompts/ui-ux-pro-max" }, "scriptPath": "prompts/ui-ux-pro-max/scripts/search.py", "frontmatter": { - "name": "ui-ux-pro-max", - "description": "Comprehensive design guide for web, mobile, and desktop applications. Contains 67 styles, 161 color palettes, 57 font pairings, 99 UX guidelines, and 25 chart types across 22 technology stacks." + "description": "Comprehensive design guide for web, mobile, and desktop applications. Contains 67 styles, 161 color palettes, 57 font pairings, 99 UX guidelines, and 25 chart types across 22 technology stacks.", + "mode": "agent" }, "sections": { "quickReference": false diff --git a/cli/src/commands/uninstall.ts b/cli/src/commands/uninstall.ts index 8b864c1..df460bd 100644 --- a/cli/src/commands/uninstall.ts +++ b/cli/src/commands/uninstall.ts @@ -30,9 +30,18 @@ async function removeSkillDir(baseDir: string, aiType: ConcreteAIType): Promise< // `.github/prompts/`, kiro under `.kiro/steering/`. Also clean the legacy // `/skills/` layout (incl. `.shared/`) so older installs are removed. const parents = new Set(); + // Standalone skill files to remove (platforms with a dataPath keep the + // rendered skill file apart from the data directory — e.g. copilot's + // `.github/prompts/ui-ux-pro-max.prompt.md`). + const skillFiles = new Set(); try { const { folderStructure } = await loadPlatformConfig(aiType); - parents.add(join(folderStructure.root, dirname(folderStructure.skillPath))); + if (folderStructure.dataPath) { + skillFiles.add(join(folderStructure.root, folderStructure.skillPath, folderStructure.filename)); + parents.add(join(folderStructure.root, dirname(folderStructure.dataPath))); + } else { + parents.add(join(folderStructure.root, dirname(folderStructure.skillPath))); + } } catch { // No platform config — fall back to the legacy folders below. } @@ -40,6 +49,18 @@ async function removeSkillDir(baseDir: string, aiType: ConcreteAIType): Promise< parents.add(join(folder, 'skills')); } + for (const skillFile of skillFiles) { + const filePath = join(baseDir, skillFile); + try { + await stat(filePath); + await rm(filePath, { force: true }); + removed.push(skillFile.replaceAll('\\', '/')); + } catch (err: unknown) { + // Skip non-existent files; re-throw permission or other errors + if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err; + } + } + for (const parent of parents) { for (const name of skillNames) { const skillDir = join(baseDir, parent, name); diff --git a/cli/src/types/index.ts b/cli/src/types/index.ts index 299e6ef..8c6c7ce 100755 --- a/cli/src/types/index.ts +++ b/cli/src/types/index.ts @@ -31,6 +31,7 @@ export interface PlatformConfig { root: string; skillPath: string; filename: string; + dataPath?: string; }; scriptPath: string; frontmatter: Record | null; diff --git a/cli/src/utils/template.ts b/cli/src/utils/template.ts index 743e833..d33f37e 100755 --- a/cli/src/utils/template.ts +++ b/cli/src/utils/template.ts @@ -21,6 +21,7 @@ export interface PlatformConfig { root: string; skillPath: string; filename: string; + dataPath?: string; }; scriptPath: string; frontmatter: Record | null; @@ -151,12 +152,22 @@ export async function renderSkillFile(config: PlatformConfig, isGlobal = false): .replace(/\{\{SKILL_OR_WORKFLOW\}\}/g, config.skillOrWorkflow) .replace(/\{\{QUICK_REFERENCE\}\}/g, quickRefWithNewline); + // Rewrite the hardcoded default script path to the platform-specific path + const defaultScriptPath = 'skills/ui-ux-pro-max/scripts/search.py'; + if (config.scriptPath !== defaultScriptPath) { + content = content.replace( + new RegExp(defaultScriptPath.replace(/\//g, '\\/'), 'g'), + config.scriptPath + ); + } + // For global install, rewrite relative script paths to absolute ~/root/ paths if (isGlobal) { const globalPrefix = `~/${config.folderStructure.root}/`; + // Match any platform's script path pattern (skills/, prompts/, steering/, etc.) content = content.replace( - /python3 skills\//g, - `python3 ${globalPrefix}skills/` + new RegExp(`python3 ${config.scriptPath.replace(/\//g, '\\/')}`, 'g'), + `python3 ${globalPrefix}${config.scriptPath}` ); } @@ -272,17 +283,24 @@ export async function generatePlatformFiles( await writeFile(skillFilePath, skillContent, 'utf-8'); createdFolders.push(config.folderStructure.root); - // Copy data and scripts into the skill directory (self-contained) - await copyDataAndScripts(skillDir); + // Copy data and scripts into the data directory (may differ from skill file location) + const dataDir = config.folderStructure.dataPath + ? join(effectiveDir, config.folderStructure.root, config.folderStructure.dataPath) + : skillDir; + await mkdir(dataDir, { recursive: true }); + await copyDataAndScripts(dataDir); // Install the sibling sub-skills (banner-design, brand, design, ...) next to // the orchestrator so all 7 skills are delivered. The skills parent is the // orchestrator's parent dir (skills/ for most platforms, prompts/ for - // copilot, steering/ for kiro) — derived, not hardcoded. + // copilot, steering/ for kiro) — derived, not hardcoded. For platforms with + // a separate dataPath (copilot), the orchestrator's data dir is the anchor. const skillsParentDir = join( effectiveDir, config.folderStructure.root, - dirname(config.folderStructure.skillPath) + config.folderStructure.dataPath + ? dirname(config.folderStructure.dataPath) + : dirname(config.folderStructure.skillPath) ); await copySubSkills(skillsParentDir, force); diff --git a/src/ui-ux-pro-max/templates/platforms/copilot.json b/src/ui-ux-pro-max/templates/platforms/copilot.json index e381e69..d1ce349 100755 --- a/src/ui-ux-pro-max/templates/platforms/copilot.json +++ b/src/ui-ux-pro-max/templates/platforms/copilot.json @@ -4,13 +4,14 @@ "installType": "full", "folderStructure": { "root": ".github", - "skillPath": "prompts/ui-ux-pro-max", - "filename": "PROMPT.md" + "skillPath": "prompts", + "filename": "ui-ux-pro-max.prompt.md", + "dataPath": "prompts/ui-ux-pro-max" }, "scriptPath": "prompts/ui-ux-pro-max/scripts/search.py", "frontmatter": { - "name": "ui-ux-pro-max", - "description": "Comprehensive design guide for web, mobile, and desktop applications. Contains 67 styles, 161 color palettes, 57 font pairings, 99 UX guidelines, and 25 chart types across 22 technology stacks." + "description": "Comprehensive design guide for web, mobile, and desktop applications. Contains 67 styles, 161 color palettes, 57 font pairings, 99 UX guidelines, and 25 chart types across 22 technology stacks.", + "mode": "agent" }, "sections": { "quickReference": false