#!/usr/bin/env node const fs = require('fs'); const path = require('path'); const os = require('os'); const skillsCore = require('../lib/skills-core'); // Paths const homeDir = os.homedir(); const superpowersSkillsDir = path.join(homeDir, '.codex', 'superpowers', 'skills'); const personalSkillsDir = path.join(homeDir, '.codex', 'skills'); const bootstrapFile = path.join(homeDir, '.codex', 'superpowers', '.codex', 'superpowers-bootstrap.md'); const superpowersRepoDir = path.join(homeDir, '.codex', 'superpowers'); // Utility functions function printSkill(skillPath, sourceType) { const skillFile = path.join(skillPath, 'SKILL.md'); const relPath = sourceType === 'personal' ? path.relative(personalSkillsDir, skillPath) : path.relative(superpowersSkillsDir, skillPath); // Print skill name with namespace if (sourceType === 'personal') { console.log(relPath.replace(/\\/g, '/')); // Personal skills are not namespaced } else { console.log(`superpowers:${relPath.replace(/\\/g, '/')}`); // Superpowers skills get superpowers namespace } // Extract and print metadata const { name, description } = skillsCore.extractFrontmatter(skillFile); if (description) console.log(` ${description}`); console.log(''); } // Commands function runFindSkills() { console.log('Available skills:'); console.log('=================='); console.log(''); const foundSkills = new Set(); // Find personal skills first (these take precedence) const personalSkills = skillsCore.findSkillsInDir(personalSkillsDir, 'personal', 2); for (const skill of personalSkills) { const relPath = path.relative(personalSkillsDir, skill.path); foundSkills.add(relPath); printSkill(skill.path, 'personal'); } // Find superpowers skills (only if not already found in personal) const superpowersSkills = skillsCore.findSkillsInDir(superpowersSkillsDir, 'superpowers', 1); for (const skill of superpowersSkills) { const relPath = path.relative(superpowersSkillsDir, skill.path); if (!foundSkills.has(relPath)) { printSkill(skill.path, 'superpowers'); } } console.log('Usage:'); console.log(' superpowers-codex use-skill # Load a specific skill'); console.log(''); console.log('Skill naming:'); console.log(' Superpowers skills: superpowers:skill-name (from ~/.codex/superpowers/skills/)'); console.log(' Personal skills: skill-name (from ~/.codex/skills/)'); console.log(' Personal skills override superpowers skills when names match.'); console.log(''); console.log('Note: All skills are disclosed at session start via bootstrap.'); } function runBootstrap() { console.log('# Superpowers Bootstrap for Codex'); console.log('# ================================'); console.log(''); // Check for updates (with timeout protection) if (skillsCore.checkForUpdates(superpowersRepoDir)) { console.log('## Update Available'); console.log(''); console.log('⚠️ Your superpowers installation is behind the latest version.'); console.log('To update, run: `cd ~/.codex/superpowers && git pull`'); console.log(''); console.log('---'); console.log(''); } // Show the bootstrap instructions if (fs.existsSync(bootstrapFile)) { console.log('## Bootstrap Instructions:'); console.log(''); try { const content = fs.readFileSync(bootstrapFile, 'utf8'); console.log(content); } catch (error) { console.log(`Error reading bootstrap file: ${error.message}`); } console.log(''); console.log('---'); console.log(''); } // Run find-skills to show available skills console.log('## Available Skills:'); console.log(''); runFindSkills(); console.log(''); console.log('---'); console.log(''); // Load the using-superpowers skill automatically console.log('## Auto-loading superpowers:using-superpowers skill:'); console.log(''); runUseSkill('superpowers:using-superpowers'); console.log(''); console.log('---'); console.log(''); console.log('# Bootstrap Complete!'); console.log('# You now have access to all superpowers skills.'); console.log('# Use "superpowers-codex use-skill " to load and apply skills.'); console.log('# Remember: If a skill applies to your task, you MUST use it!'); } function runUseSkill(skillName) { if (!skillName) { console.log('Usage: superpowers-codex use-skill '); console.log('Examples:'); console.log(' superpowers-codex use-skill superpowers:brainstorming # Load superpowers skill'); console.log(' superpowers-codex use-skill brainstorming # Load personal skill (or superpowers if not found)'); console.log(' superpowers-codex use-skill my-custom-skill # Load personal skill'); return; } // Handle namespaced skill names let actualSkillPath; let forceSuperpowers = false; if (skillName.startsWith('superpowers:')) { // Remove the superpowers: namespace prefix actualSkillPath = skillName.substring('superpowers:'.length); forceSuperpowers = true; } else { actualSkillPath = skillName; } // Remove "skills/" prefix if present if (actualSkillPath.startsWith('skills/')) { actualSkillPath = actualSkillPath.substring('skills/'.length); } // Function to find skill file function findSkillFile(searchPath) { // Check for exact match with SKILL.md const skillMdPath = path.join(searchPath, 'SKILL.md'); if (fs.existsSync(skillMdPath)) { return skillMdPath; } // Check for direct SKILL.md file if (searchPath.endsWith('SKILL.md') && fs.existsSync(searchPath)) { return searchPath; } return null; } let skillFile = null; // If superpowers: namespace was used, only check superpowers skills if (forceSuperpowers) { if (fs.existsSync(superpowersSkillsDir)) { const superpowersPath = path.join(superpowersSkillsDir, actualSkillPath); skillFile = findSkillFile(superpowersPath); } } else { // First check personal skills directory (takes precedence) if (fs.existsSync(personalSkillsDir)) { const personalPath = path.join(personalSkillsDir, actualSkillPath); skillFile = findSkillFile(personalPath); if (skillFile) { console.log(`# Loading personal skill: ${actualSkillPath}`); console.log(`# Source: ${skillFile}`); console.log(''); } } // If not found in personal, check superpowers skills if (!skillFile && fs.existsSync(superpowersSkillsDir)) { const superpowersPath = path.join(superpowersSkillsDir, actualSkillPath); skillFile = findSkillFile(superpowersPath); if (skillFile) { console.log(`# Loading superpowers skill: superpowers:${actualSkillPath}`); console.log(`# Source: ${skillFile}`); console.log(''); } } } // If still not found, error if (!skillFile) { console.log(`Error: Skill not found: ${actualSkillPath}`); console.log(''); console.log('Available skills:'); runFindSkills(); return; } // Extract frontmatter and content using shared core functions let content, frontmatter; try { const fullContent = fs.readFileSync(skillFile, 'utf8'); const { name, description } = skillsCore.extractFrontmatter(skillFile); content = skillsCore.stripFrontmatter(fullContent); frontmatter = { name, description }; } catch (error) { console.log(`Error reading skill file: ${error.message}`); return; } // Display skill header with clean info const displayName = forceSuperpowers ? `superpowers:${actualSkillPath}` : (skillFile.includes(personalSkillsDir) ? actualSkillPath : `superpowers:${actualSkillPath}`); const skillDirectory = path.dirname(skillFile); console.log(`# ${frontmatter.name || displayName}`); if (frontmatter.description) { console.log(`# ${frontmatter.description}`); } console.log(`# Skill-specific tools and reference files live in ${skillDirectory}`); console.log('# ============================================'); console.log(''); // Display the skill content (without frontmatter) console.log(content); } // Main CLI const command = process.argv[2]; const arg = process.argv[3]; switch (command) { case 'bootstrap': runBootstrap(); break; case 'use-skill': runUseSkill(arg); break; case 'find-skills': runFindSkills(); break; default: console.log('Superpowers for Codex'); console.log('Usage:'); console.log(' superpowers-codex bootstrap # Run complete bootstrap with all skills'); console.log(' superpowers-codex use-skill # Load a specific skill'); console.log(' superpowers-codex find-skills # List all available skills'); console.log(''); console.log('Examples:'); console.log(' superpowers-codex bootstrap'); console.log(' superpowers-codex use-skill superpowers:brainstorming'); console.log(' superpowers-codex use-skill my-custom-skill'); break; }