diff --git a/.copilot/INSTALL.md b/.copilot/INSTALL.md new file mode 100644 index 000000000..cb7228c10 --- /dev/null +++ b/.copilot/INSTALL.md @@ -0,0 +1,115 @@ +# Installing Superpowers for GitHub Copilot + +Quick setup to enable superpowers skills in GitHub Copilot. + +## Prerequisites + +- GitHub Copilot subscription (Individual, Business, or Enterprise) +- VS Code with GitHub Copilot extension (or other supported IDE) +- Node.js installed (for superpowers-copilot command) + +## Installation + +### 1. Clone superpowers repository + +```bash +mkdir -p ~/.copilot/superpowers +cd ~/.copilot/superpowers +git clone https://github.com/obra/superpowers.git . +``` + +### 2. Create personal skills directory + +```bash +mkdir -p ~/.copilot/skills +``` + +### 3. Make CLI executable + +```bash +chmod +x ~/.copilot/superpowers/.copilot/superpowers-copilot +``` + +### 4. Choose Bootstrap Method + +You have two options for bootstrapping superpowers: + +#### Option A: Using .github/copilot-instructions.md (Recommended) + +Create `.github/copilot-instructions.md` in your project root: + +```bash +mkdir -p /.github +cp ~/.copilot/superpowers/.copilot/templates/copilot-instructions.md.template \ + /.github/copilot-instructions.md +``` + +#### Option B: Using AGENTS.md + +Create `AGENTS.md` in your project root: + +```bash +cp ~/.copilot/superpowers/.copilot/templates/AGENTS.md.template \ + /AGENTS.md +``` + +## Verification + +### Test in VS Code + +1. Open your project in VS Code +2. Open GitHub Copilot Chat (Ctrl+Alt+I or Cmd+Alt+I on Mac) +3. Type: `run the bootstrap command` +4. Copilot should execute: `~/.copilot/superpowers/.copilot/superpowers-copilot bootstrap` +5. You should see skill listings and instructions + +### Test skill loading + +In Copilot Chat: +``` +Load the superpowers:brainstorming skill and help me design a feature +``` + +Copilot should run: +```bash +~/.copilot/superpowers/.copilot/superpowers-copilot use-skill superpowers:brainstorming +``` + +## IDE-Specific Notes + +### VS Code +- Works with Agent Mode and standard Chat +- Use @workspace for full project context +- Slash commands: /tests, /fix, /refactor integrate well with skills + +### IntelliJ IDEA +- Copilot instructions support confirmed +- May require plugin update for full agent features + +### Visual Studio +- Basic instructions support available +- Test with your specific version + +### Other IDEs +- GitHub Copilot is available in Xcode, Vim, Neovim, and JetBrains IDEs +- Custom instructions support may vary by IDE + +## Troubleshooting + +**Skills not loading?** +- Verify .github/copilot-instructions.md or AGENTS.md exists in your project root +- Check "References" section in Copilot chat response to see if instructions file was loaded +- Try reloading VS Code window (Cmd/Ctrl+Shift+P → "Developer: Reload Window") + +**Command not found?** +- Verify Node.js is installed: `node --version` +- Check file is executable: `ls -la ~/.copilot/superpowers/.copilot/superpowers-copilot` +- Try full path in instructions file + +**Skills seem outdated?** +- Update repository: `cd ~/.copilot/superpowers && git pull` + +**Copilot not using skills?** +- Explicitly ask Copilot to use a skill: "Use the superpowers:test-driven-development skill" +- Check that bootstrap instructions include `` tags +- Verify the instructions file is in the correct location diff --git a/.copilot/superpowers-bootstrap.md b/.copilot/superpowers-bootstrap.md new file mode 100644 index 000000000..e12ba9a52 --- /dev/null +++ b/.copilot/superpowers-bootstrap.md @@ -0,0 +1,44 @@ +# Superpowers Bootstrap for GitHub Copilot + + +You have superpowers. + +**Tool for running skills:** +- `~/.copilot/superpowers/.copilot/superpowers-copilot use-skill ` + +**Tool Mapping for GitHub Copilot:** +When skills reference tools you don't have, substitute your equivalent tools: +- `TodoWrite` → Create markdown checklist in `docs/plans/YYYY-MM-DD-task-name.md` with checklist items +- `Task` tool with subagents → Tell the user that parallel subagents require custom agents setup (via `.github/agents/`) or do the work manually +- `Skill` tool → `~/.copilot/superpowers/.copilot/superpowers-copilot use-skill` command (already available) +- `Read`, `Write`, `Edit` → Use your native file operations +- `Bash` → Use @terminal participant or your native shell commands +- `Grep`, `Glob` → Use @workspace semantic search for finding files and code patterns + +**GitHub Copilot Integration Tips:** +- Use `@workspace` to get full project context before applying skills +- Use slash commands to enhance skill workflows: + - `/tests` - Generate tests (pairs well with test-driven-development skill) + - `/fix` - Fix bugs (pairs well with systematic-debugging skill) + - `/refactor` - Refactor code (useful after implementing features) +- Reference files with #file syntax for precise context +- When creating plans, use markdown format with checkboxes for tracking + +**Skills naming:** +- Superpowers skills: `superpowers:skill-name` (from ~/.copilot/superpowers/skills/) +- Personal skills: `skill-name` (from ~/.copilot/skills/) +- Personal skills override superpowers skills when names match + +**Critical Rules:** +- Before ANY task, review the skills list (shown below) +- If a relevant skill exists, you MUST use `~/.copilot/superpowers/.copilot/superpowers-copilot use-skill` to load it +- Announce: "I've read the [Skill Name] skill and I'm using it to [purpose]" +- Skills with checklists: Create markdown checklist in `docs/plans/` directory for tracking progress +- NEVER skip mandatory workflows (brainstorming before coding, TDD, systematic debugging) + +**Skills location:** +- Superpowers skills: ~/.copilot/superpowers/skills/ +- Personal skills: ~/.copilot/skills/ (override superpowers when names match) + +IF A SKILL APPLIES TO YOUR TASK, YOU DO NOT HAVE A CHOICE. YOU MUST USE IT. + diff --git a/.copilot/superpowers-copilot b/.copilot/superpowers-copilot new file mode 100755 index 000000000..5996c75d1 --- /dev/null +++ b/.copilot/superpowers-copilot @@ -0,0 +1,388 @@ +#!/usr/bin/env node + +const fs = require('fs'); +const path = require('path'); +const os = require('os'); +const { execSync } = require('child_process'); + +// Paths +const homeDir = os.homedir(); +const superpowersSkillsDir = path.join(homeDir, '.copilot', 'superpowers', 'skills'); +const personalSkillsDir = path.join(homeDir, '.copilot', 'skills'); +const bootstrapFile = path.join(homeDir, '.copilot', 'superpowers', '.copilot', 'superpowers-bootstrap.md'); +const superpowersRepoDir = path.join(homeDir, '.copilot', 'superpowers'); + +// Utility functions +function checkForUpdates() { + try { + // Quick check with 3 second timeout to avoid delays if network is down + const output = execSync('git fetch origin && git status --porcelain=v1 --branch', { + cwd: superpowersRepoDir, + timeout: 3000, + encoding: 'utf8', + stdio: 'pipe' + }); + + // Parse git status output to see if we're behind + const statusLines = output.split('\n'); + for (const line of statusLines) { + if (line.startsWith('## ') && line.includes('[behind ')) { + return true; // We're behind remote + } + } + return false; // Up to date + } catch (error) { + // Network down, git error, timeout, etc. - don't block bootstrap + return false; + } +} + +function extractFrontmatter(filePath) { + try { + const content = fs.readFileSync(filePath, 'utf8'); + const lines = content.split('\n'); + + let inFrontmatter = false; + let name = ''; + let description = ''; + let whenToUse = ''; + + for (const line of lines) { + if (line.trim() === '---') { + if (inFrontmatter) break; + inFrontmatter = true; + continue; + } + + if (inFrontmatter) { + const match = line.match(/^(\w+):\s*(.*)$/); + if (match) { + const [, key, value] = match; + switch (key) { + case 'name': name = value.trim(); break; + case 'description': description = value.trim(); break; + case 'when_to_use': whenToUse = value.trim(); break; + } + } + } + } + + return { name, description, whenToUse }; + } catch (error) { + return { name: '', description: '', whenToUse: '' }; + } +} + +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, whenToUse } = extractFrontmatter(skillFile); + + if (description) console.log(` ${description}`); + if (whenToUse) console.log(` When to use: ${whenToUse}`); + console.log(''); +} + +function findSkillsInDir(dir, sourceType, maxDepth = 1) { + const skills = []; + + if (!fs.existsSync(dir)) return skills; + + function searchDir(currentDir, currentDepth) { + if (currentDepth > maxDepth) return; + + try { + const entries = fs.readdirSync(currentDir, { withFileTypes: true }); + + for (const entry of entries) { + if (entry.isDirectory()) { + const skillDir = path.join(currentDir, entry.name); + const skillFile = path.join(skillDir, 'SKILL.md'); + + if (fs.existsSync(skillFile)) { + skills.push(skillDir); + } + + // For personal skills, search deeper (category/skill structure) + if (sourceType === 'personal' && currentDepth < maxDepth) { + searchDir(skillDir, currentDepth + 1); + } + } + } + } catch (error) { + // Ignore permission errors or other issues + } + } + + searchDir(dir, 0); + return skills; +} + +// Commands +function runFindSkills() { + console.log('Available skills:'); + console.log('=================='); + console.log(''); + + const foundSkills = new Set(); + + // Find personal skills first (these take precedence) + const personalSkills = findSkillsInDir(personalSkillsDir, 'personal', 2); + for (const skillPath of personalSkills) { + const relPath = path.relative(personalSkillsDir, skillPath); + foundSkills.add(relPath); + printSkill(skillPath, 'personal'); + } + + // Find superpowers skills (only if not already found in personal) + const superpowersSkills = findSkillsInDir(superpowersSkillsDir, 'superpowers', 1); + for (const skillPath of superpowersSkills) { + const relPath = path.relative(superpowersSkillsDir, skillPath); + if (!foundSkills.has(relPath)) { + printSkill(skillPath, 'superpowers'); + } + } + + console.log('Usage:'); + console.log(' superpowers-copilot use-skill # Load a specific skill'); + console.log(''); + console.log('Skill naming:'); + console.log(' Superpowers skills: superpowers:skill-name (from ~/.copilot/superpowers/skills/)'); + console.log(' Personal skills: skill-name (from ~/.copilot/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 GitHub Copilot'); + console.log('# =========================================='); + console.log(''); + + // Check for updates (with timeout protection) + if (checkForUpdates()) { + console.log('## Update Available'); + console.log(''); + console.log('⚠️ Your superpowers installation is behind the latest version.'); + console.log('To update, run: `cd ~/.copilot/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-copilot 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-copilot use-skill '); + console.log('Examples:'); + console.log(' superpowers-copilot use-skill superpowers:brainstorming # Load superpowers skill'); + console.log(' superpowers-copilot use-skill brainstorming # Load personal skill (or superpowers if not found)'); + console.log(' superpowers-copilot 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 + let content, frontmatter; + try { + const fullContent = fs.readFileSync(skillFile, 'utf8'); + const { name, description, whenToUse } = extractFrontmatter(skillFile); + + // Extract just the content after frontmatter + const lines = fullContent.split('\n'); + let inFrontmatter = false; + let frontmatterEnded = false; + const contentLines = []; + + for (const line of lines) { + if (line.trim() === '---') { + if (inFrontmatter) { + frontmatterEnded = true; + continue; + } + inFrontmatter = true; + continue; + } + + if (frontmatterEnded || !inFrontmatter) { + contentLines.push(line); + } + } + + content = contentLines.join('\n').trim(); + frontmatter = { name, description, whenToUse }; + } 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}`); + } + if (frontmatter.whenToUse) { + console.log(`# When to use: ${frontmatter.whenToUse}`); + } + console.log(`# Supporting tools and docs are 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 GitHub Copilot'); + console.log('Usage:'); + console.log(' superpowers-copilot bootstrap # Run complete bootstrap with all skills'); + console.log(' superpowers-copilot use-skill # Load a specific skill'); + console.log(' superpowers-copilot find-skills # List all available skills'); + console.log(''); + console.log('Examples:'); + console.log(' superpowers-copilot bootstrap'); + console.log(' superpowers-copilot use-skill superpowers:brainstorming'); + console.log(' superpowers-copilot use-skill my-custom-skill'); + break; +} diff --git a/.copilot/templates/AGENTS.md.template b/.copilot/templates/AGENTS.md.template new file mode 100644 index 000000000..49e3b4d2a --- /dev/null +++ b/.copilot/templates/AGENTS.md.template @@ -0,0 +1,7 @@ +# Superpowers System + + +You have superpowers. Superpowers teach you new skills and capabilities. + +RIGHT NOW run: `~/.copilot/superpowers/.copilot/superpowers-copilot bootstrap` and follow the instructions it returns. + diff --git a/.copilot/templates/copilot-instructions.md.template b/.copilot/templates/copilot-instructions.md.template new file mode 100644 index 000000000..d7b29dc0c --- /dev/null +++ b/.copilot/templates/copilot-instructions.md.template @@ -0,0 +1,9 @@ +# Superpowers Skills System + + +You have superpowers. Superpowers teach you new skills and capabilities. + +RIGHT NOW run: `~/.copilot/superpowers/.copilot/superpowers-copilot bootstrap` and follow the instructions it returns. + + +Use @workspace to get full project context when applying skills. diff --git a/README.md b/README.md index 6776255a0..f32fac32a 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,12 @@ Read the introduction: [Superpowers for Claude Code](https://blog.fsck.com/2025/ Tell Codex to fetch https://raw.githubusercontent.com/obra/superpowers/refs/heads/main/.codex/INSTALL.md and follow the instructions. +### GitHub Copilot (Experimental) + +**Note:** GitHub Copilot support is experimental and may require refinement based on user feedback. + +See [.copilot/INSTALL.md](.copilot/INSTALL.md) for installation instructions. + ## Quick Start ### Using Slash Commands diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index d6e30691b..be17030bf 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,5 +1,46 @@ # Superpowers Release Notes +## v3.5.0 (2025-11-05) + +### New Features + +**Experimental GitHub Copilot Support** +- Added unified `superpowers-copilot` script with bootstrap/use-skill/find-skills commands +- Cross-platform Node.js implementation (works on Windows, macOS, Linux) +- Namespaced skills: `superpowers:skill-name` for superpowers skills, `skill-name` for personal +- Personal skills override superpowers skills when names match +- Clean skill display: shows name/description without raw frontmatter +- Helpful context: shows supporting files directory for each skill +- Tool mapping for GitHub Copilot: TodoWrite→markdown checklists, subagents→custom agents or manual, etc. +- Integration with Copilot's @workspace, slash commands (/tests, /fix, /refactor) +- Bootstrap integration via `.github/copilot-instructions.md` or `AGENTS.md` +- Complete installation guide and bootstrap instructions specific to GitHub Copilot +- Template files for both bootstrap methods + +**Key differences from Claude Code integration:** +- Single unified script instead of separate tools +- Tool substitution system for Copilot-specific equivalents +- File-based planning with markdown checklists (docs/plans/) +- Custom agents support via `.github/agents/` for specialized tasks +- Semantic search integration using @workspace participant +- Support for multiple IDEs (VS Code primary, IntelliJ, Visual Studio, Xcode, etc.) + +**Key differences from Codex integration:** +- @workspace semantic search instead of traditional grep/glob +- Slash commands for enhanced workflows (/tests, /fix, /refactor) +- Multiple bootstrap options (copilot-instructions.md recommended, AGENTS.md supported) +- Custom agents via `.github/agents/` directory (optional) +- File-based planning approach (markdown checklists in docs/plans/) + +### Files Added +- `.copilot/INSTALL.md` - Installation guide for GitHub Copilot users +- `.copilot/superpowers-bootstrap.md` - Bootstrap instructions with Copilot adaptations +- `.copilot/superpowers-copilot` - Unified Node.js executable with all functionality +- `.copilot/templates/copilot-instructions.md.template` - Template for .github/copilot-instructions.md +- `.copilot/templates/AGENTS.md.template` - Template for AGENTS.md bootstrap + +**Note:** GitHub Copilot support is experimental. The integration provides core superpowers functionality but may require refinement based on user feedback. Tested primarily in VS Code; other IDE support is community-validated. + ## v3.4.1 (2025-10-31) ### Improvements diff --git a/skills/writing-skills/SKILL.md b/skills/writing-skills/SKILL.md index 984ebce57..32d3cf91c 100644 --- a/skills/writing-skills/SKILL.md +++ b/skills/writing-skills/SKILL.md @@ -9,7 +9,7 @@ description: Use when creating new skills, editing existing skills, or verifying **Writing skills IS Test-Driven Development applied to process documentation.** -**Personal skills live in agent-specific directories (`~/.claude/skills` for Claude Code, `~/.codex/skills` for Codex)** +**Personal skills live in agent-specific directories (`~/.claude/skills` for Claude Code, `~/.codex/skills` for Codex, `~/.copilot/skills` for GitHub Copilot)** You write test cases (pressure scenarios with subagents), watch them fail (baseline behavior), write the skill (documentation), watch tests pass (agents comply), and refactor (close loopholes).