mirror of
https://github.com/obra/superpowers.git
synced 2026-04-17 03:12:41 +00:00
Compare commits
38 Commits
opencode-n
...
feat/codex
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b2a7efa7d | ||
|
|
ac65720a98 | ||
|
|
f4db4a7ab0 | ||
|
|
70d85021b0 | ||
|
|
9ee2552fe5 | ||
|
|
f2e3cb7650 | ||
|
|
9a6f4da203 | ||
|
|
654106c4ac | ||
|
|
e0effac27c | ||
|
|
ac6d7b878b | ||
|
|
1143f9be3d | ||
|
|
6cc2d8c920 | ||
|
|
038abed026 | ||
|
|
961052e0f9 | ||
|
|
689e2a77fc | ||
|
|
5e0d2f8175 | ||
|
|
06b92f3682 | ||
|
|
9819209bba | ||
|
|
c7816ee2a6 | ||
|
|
b323e35805 | ||
|
|
bb2ff5d309 | ||
|
|
b63d485955 | ||
|
|
fa3f46d4e9 | ||
|
|
f8dbe7b196 | ||
|
|
93cf2ee84f | ||
|
|
1872f50b64 | ||
|
|
8904b7d9dc | ||
|
|
469a6d81eb | ||
|
|
4b6cef98ac | ||
|
|
03087b13b8 | ||
|
|
493ac18dfe | ||
|
|
35d4fbcd0b | ||
|
|
19c70afc99 | ||
|
|
405a025eea | ||
|
|
36fcd57626 | ||
|
|
3964d18670 | ||
|
|
a01a135fe1 | ||
|
|
ac471e69c2 |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "superpowers",
|
||||
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
|
||||
"version": "4.0.3",
|
||||
"version": "4.1.1",
|
||||
"author": {
|
||||
"name": "Jesse Vincent",
|
||||
"email": "jesse@fsck.com"
|
||||
|
||||
@@ -1,35 +1,67 @@
|
||||
# Installing Superpowers for Codex
|
||||
|
||||
Quick setup to enable superpowers skills in Codex.
|
||||
Enable superpowers skills in Codex via native skill discovery. Just clone and symlink.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Git
|
||||
|
||||
## Installation
|
||||
|
||||
1. **Clone superpowers repository**:
|
||||
1. **Clone the superpowers repository:**
|
||||
```bash
|
||||
mkdir -p ~/.codex/superpowers
|
||||
cd ~/.codex/superpowers
|
||||
git clone https://github.com/obra/superpowers.git .
|
||||
git clone https://github.com/obra/superpowers.git ~/.codex/superpowers
|
||||
```
|
||||
|
||||
2. **Create personal skills directory**:
|
||||
2. **Create the skills symlink:**
|
||||
```bash
|
||||
mkdir -p ~/.codex/skills
|
||||
mkdir -p ~/.agents/skills
|
||||
ln -s ~/.codex/superpowers/skills ~/.agents/skills/superpowers
|
||||
```
|
||||
|
||||
3. **Update ~/.codex/AGENTS.md** to include this superpowers section:
|
||||
```markdown
|
||||
## Superpowers System
|
||||
|
||||
<EXTREMELY_IMPORTANT>
|
||||
You have superpowers. Superpowers teach you new skills and capabilities. RIGHT NOW run: `~/.codex/superpowers/.codex/superpowers-codex bootstrap` and follow the instructions it returns.
|
||||
</EXTREMELY_IMPORTANT>
|
||||
**Windows (PowerShell):**
|
||||
```powershell
|
||||
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.agents\skills"
|
||||
cmd /c mklink /J "$env:USERPROFILE\.agents\skills\superpowers" "$env:USERPROFILE\.codex\superpowers\skills"
|
||||
```
|
||||
|
||||
## Verification
|
||||
3. **Restart Codex** (quit and relaunch the CLI) to discover the skills.
|
||||
|
||||
## Migrating from old bootstrap
|
||||
|
||||
If you installed superpowers before native skill discovery, you need to:
|
||||
|
||||
1. **Update the repo:**
|
||||
```bash
|
||||
cd ~/.codex/superpowers && git pull
|
||||
```
|
||||
|
||||
2. **Create the skills symlink** (step 2 above) — this is the new discovery mechanism.
|
||||
|
||||
3. **Remove the old bootstrap block** from `~/.codex/AGENTS.md` — any block referencing `superpowers-codex bootstrap` is no longer needed.
|
||||
|
||||
4. **Restart Codex.**
|
||||
|
||||
## Verify
|
||||
|
||||
Test the installation:
|
||||
```bash
|
||||
~/.codex/superpowers/.codex/superpowers-codex bootstrap
|
||||
ls -la ~/.agents/skills/superpowers
|
||||
```
|
||||
|
||||
You should see skill listings and bootstrap instructions. The system is now ready for use.
|
||||
You should see a symlink (or junction on Windows) pointing to your superpowers skills directory.
|
||||
|
||||
## Updating
|
||||
|
||||
```bash
|
||||
cd ~/.codex/superpowers && git pull
|
||||
```
|
||||
|
||||
Skills update instantly through the symlink.
|
||||
|
||||
## Uninstalling
|
||||
|
||||
```bash
|
||||
rm ~/.agents/skills/superpowers
|
||||
```
|
||||
|
||||
Optionally delete the clone: `rm -rf ~/.codex/superpowers`.
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
# Superpowers Bootstrap for Codex
|
||||
|
||||
<EXTREMELY_IMPORTANT>
|
||||
You have superpowers.
|
||||
|
||||
**Tool for running skills:**
|
||||
- `~/.codex/superpowers/.codex/superpowers-codex use-skill <skill-name>`
|
||||
|
||||
**Tool Mapping for Codex:**
|
||||
When skills reference tools you don't have, substitute your equivalent tools:
|
||||
- `TodoWrite` → `update_plan` (your planning/task tracking tool)
|
||||
- `Task` tool with subagents → Tell the user that subagents aren't available in Codex yet and you'll do the work the subagent would do
|
||||
- `Skill` tool → `~/.codex/superpowers/.codex/superpowers-codex use-skill` command (already available)
|
||||
- `Read`, `Write`, `Edit`, `Bash` → Use your native tools with similar functions
|
||||
|
||||
**Skills naming:**
|
||||
- Superpowers skills: `superpowers:skill-name` (from ~/.codex/superpowers/skills/)
|
||||
- Personal skills: `skill-name` (from ~/.codex/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 `~/.codex/superpowers/.codex/superpowers-codex use-skill` to load it
|
||||
- Announce: "I've read the [Skill Name] skill and I'm using it to [purpose]"
|
||||
- Skills with checklists require `update_plan` todos for each item
|
||||
- NEVER skip mandatory workflows (brainstorming before coding, TDD, systematic debugging)
|
||||
|
||||
**Skills location:**
|
||||
- Superpowers skills: ~/.codex/superpowers/skills/
|
||||
- Personal skills: ~/.codex/skills/ (override superpowers when names match)
|
||||
|
||||
IF A SKILL APPLIES TO YOUR TASK, YOU DO NOT HAVE A CHOICE. YOU MUST USE IT.
|
||||
</EXTREMELY_IMPORTANT>
|
||||
@@ -1,267 +0,0 @@
|
||||
#!/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 <skill-name> # 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 <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 <skill-name>');
|
||||
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 <skill-name> # 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;
|
||||
}
|
||||
17
.gitattributes
vendored
Normal file
17
.gitattributes
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
# Ensure shell scripts always have LF line endings
|
||||
*.sh text eol=lf
|
||||
|
||||
# Ensure the polyglot wrapper keeps LF (it's parsed by both cmd and bash)
|
||||
*.cmd text eol=lf
|
||||
|
||||
# Common text files
|
||||
*.md text eol=lf
|
||||
*.json text eol=lf
|
||||
*.js text eol=lf
|
||||
*.mjs text eol=lf
|
||||
*.ts text eol=lf
|
||||
|
||||
# Explicitly mark binary files
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.gif binary
|
||||
@@ -3,15 +3,13 @@
|
||||
## Prerequisites
|
||||
|
||||
- [OpenCode.ai](https://opencode.ai) installed
|
||||
- Node.js installed
|
||||
- Git installed
|
||||
|
||||
## Installation Steps
|
||||
|
||||
### 1. Install Superpowers
|
||||
### 1. Clone Superpowers
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.config/opencode/superpowers
|
||||
git clone https://github.com/obra/superpowers.git ~/.config/opencode/superpowers
|
||||
```
|
||||
|
||||
@@ -20,32 +18,43 @@ git clone https://github.com/obra/superpowers.git ~/.config/opencode/superpowers
|
||||
Create a symlink so OpenCode discovers the plugin:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.config/opencode/plugin
|
||||
ln -sf ~/.config/opencode/superpowers/.opencode/plugin/superpowers.js ~/.config/opencode/plugin/superpowers.js
|
||||
mkdir -p ~/.config/opencode/plugins
|
||||
rm -f ~/.config/opencode/plugins/superpowers.js
|
||||
ln -s ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js ~/.config/opencode/plugins/superpowers.js
|
||||
```
|
||||
|
||||
### 3. Restart OpenCode
|
||||
### 3. Symlink Skills
|
||||
|
||||
Restart OpenCode. The plugin will automatically inject superpowers context via the chat.message hook.
|
||||
Create a symlink so OpenCode's native skill tool discovers superpowers skills:
|
||||
|
||||
You should see superpowers is active when you ask "do you have superpowers?"
|
||||
```bash
|
||||
mkdir -p ~/.config/opencode/skills
|
||||
rm -rf ~/.config/opencode/skills/superpowers
|
||||
ln -s ~/.config/opencode/superpowers/skills ~/.config/opencode/skills/superpowers
|
||||
```
|
||||
|
||||
### 4. Restart OpenCode
|
||||
|
||||
Restart OpenCode. The plugin will automatically inject superpowers context.
|
||||
|
||||
Verify by asking: "do you have superpowers?"
|
||||
|
||||
## Usage
|
||||
|
||||
### Finding Skills
|
||||
|
||||
Use the `find_skills` tool to list all available skills:
|
||||
Use OpenCode's native `skill` tool to list available skills:
|
||||
|
||||
```
|
||||
use find_skills tool
|
||||
use skill tool to list skills
|
||||
```
|
||||
|
||||
### Loading a Skill
|
||||
|
||||
Use the `use_skill` tool to load a specific skill:
|
||||
Use OpenCode's native `skill` tool to load a specific skill:
|
||||
|
||||
```
|
||||
use use_skill tool with skill_name: "superpowers:brainstorming"
|
||||
use skill tool to load superpowers/brainstorming
|
||||
```
|
||||
|
||||
### Personal Skills
|
||||
@@ -69,36 +78,11 @@ description: Use when [condition] - [what it does]
|
||||
[Your skill content here]
|
||||
```
|
||||
|
||||
Personal skills override superpowers skills with the same name.
|
||||
|
||||
### Project Skills
|
||||
|
||||
Create project-specific skills in your OpenCode project:
|
||||
Create project-specific skills in `.opencode/skills/` within your project.
|
||||
|
||||
```bash
|
||||
# In your OpenCode project
|
||||
mkdir -p .opencode/skills/my-project-skill
|
||||
```
|
||||
|
||||
Create `.opencode/skills/my-project-skill/SKILL.md`:
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: my-project-skill
|
||||
description: Use when [condition] - [what it does]
|
||||
---
|
||||
|
||||
# My Project Skill
|
||||
|
||||
[Your skill content here]
|
||||
```
|
||||
|
||||
**Skill Priority:** Project skills override personal skills, which override superpowers skills.
|
||||
|
||||
**Skill Naming:**
|
||||
- `project:skill-name` - Force project skill lookup
|
||||
- `skill-name` - Searches project → personal → superpowers
|
||||
- `superpowers:skill-name` - Force superpowers skill lookup
|
||||
**Skill Priority:** Project skills > Personal skills > Superpowers skills
|
||||
|
||||
## Updating
|
||||
|
||||
@@ -111,25 +95,25 @@ git pull
|
||||
|
||||
### Plugin not loading
|
||||
|
||||
1. Check plugin file exists: `ls ~/.config/opencode/superpowers/.opencode/plugin/superpowers.js`
|
||||
2. Check OpenCode logs for errors
|
||||
3. Verify Node.js is installed: `node --version`
|
||||
1. Check plugin symlink: `ls -l ~/.config/opencode/plugins/superpowers.js`
|
||||
2. Check source exists: `ls ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js`
|
||||
3. Check OpenCode logs for errors
|
||||
|
||||
### Skills not found
|
||||
|
||||
1. Verify skills directory exists: `ls ~/.config/opencode/superpowers/skills`
|
||||
2. Use `find_skills` tool to see what's discovered
|
||||
3. Check file structure: each skill should have a `SKILL.md` file
|
||||
1. Check skills symlink: `ls -l ~/.config/opencode/skills/superpowers`
|
||||
2. Verify it points to: `~/.config/opencode/superpowers/skills`
|
||||
3. Use `skill` tool to list what's discovered
|
||||
|
||||
### Tool mapping issues
|
||||
### Tool mapping
|
||||
|
||||
When a skill references a Claude Code tool you don't have:
|
||||
- `TodoWrite` → use `update_plan`
|
||||
- `Task` with subagents → use `@mention` syntax to invoke OpenCode subagents
|
||||
- `Skill` → use `use_skill` tool
|
||||
- File operations → use your native tools
|
||||
When skills reference Claude Code tools:
|
||||
- `TodoWrite` → `update_plan`
|
||||
- `Task` with subagents → `@mention` syntax
|
||||
- `Skill` tool → OpenCode's native `skill` tool
|
||||
- File operations → your native tools
|
||||
|
||||
## Getting Help
|
||||
|
||||
- Report issues: https://github.com/obra/superpowers/issues
|
||||
- Documentation: https://github.com/obra/superpowers
|
||||
- Full documentation: https://github.com/obra/superpowers/blob/main/docs/README.opencode.md
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
/**
|
||||
* Superpowers plugin for OpenCode.ai
|
||||
*
|
||||
* Provides custom tools for loading and discovering skills,
|
||||
* with prompt generation for agent configuration.
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { tool } from '@opencode-ai/plugin/tool';
|
||||
import * as skillsCore from '../../lib/skills-core.js';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export const SuperpowersPlugin = async ({ client, directory }) => {
|
||||
const homeDir = os.homedir();
|
||||
const projectSkillsDir = path.join(directory, '.opencode/skills');
|
||||
// Derive superpowers skills dir from plugin location (works for both symlinked and local installs)
|
||||
const superpowersSkillsDir = path.resolve(__dirname, '../../skills');
|
||||
const personalSkillsDir = path.join(homeDir, '.config/opencode/skills');
|
||||
|
||||
// Helper to generate bootstrap content
|
||||
const getBootstrapContent = (compact = false) => {
|
||||
const usingSuperpowersPath = skillsCore.resolveSkillPath('using-superpowers', superpowersSkillsDir, personalSkillsDir);
|
||||
if (!usingSuperpowersPath) return null;
|
||||
|
||||
const fullContent = fs.readFileSync(usingSuperpowersPath.skillFile, 'utf8');
|
||||
const content = skillsCore.stripFrontmatter(fullContent);
|
||||
|
||||
const toolMapping = compact
|
||||
? `**Tool Mapping:** TodoWrite->update_plan, Task->@mention, Skill->use_skill
|
||||
|
||||
**Skills naming (priority order):** project: > personal > superpowers:`
|
||||
: `**Tool Mapping for OpenCode:**
|
||||
When skills reference tools you don't have, substitute OpenCode equivalents:
|
||||
- \`TodoWrite\` → \`update_plan\`
|
||||
- \`Task\` tool with subagents → Use OpenCode's subagent system (@mention)
|
||||
- \`Skill\` tool → \`use_skill\` custom tool
|
||||
- \`Read\`, \`Write\`, \`Edit\`, \`Bash\` → Your native tools
|
||||
|
||||
**Skills naming (priority order):**
|
||||
- Project skills: \`project:skill-name\` (in .opencode/skills/)
|
||||
- Personal skills: \`skill-name\` (in ~/.config/opencode/skills/)
|
||||
- Superpowers skills: \`superpowers:skill-name\`
|
||||
- Project skills override personal, which override superpowers when names match`;
|
||||
|
||||
return `<EXTREMELY_IMPORTANT>
|
||||
You have superpowers.
|
||||
|
||||
**IMPORTANT: The using-superpowers skill content is included below. It is ALREADY LOADED - you are currently following it. Do NOT use the use_skill tool to load "using-superpowers" - that would be redundant. Use use_skill only for OTHER skills.**
|
||||
|
||||
${content}
|
||||
|
||||
${toolMapping}
|
||||
</EXTREMELY_IMPORTANT>`;
|
||||
};
|
||||
|
||||
// Helper to inject bootstrap via session.prompt
|
||||
const injectBootstrap = async (sessionID, compact = false) => {
|
||||
const bootstrapContent = getBootstrapContent(compact);
|
||||
if (!bootstrapContent) return false;
|
||||
|
||||
try {
|
||||
await client.session.prompt({
|
||||
path: { id: sessionID },
|
||||
body: {
|
||||
noReply: true,
|
||||
parts: [{ type: "text", text: bootstrapContent, synthetic: true }]
|
||||
}
|
||||
});
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
tool: {
|
||||
use_skill: tool({
|
||||
description: 'Load and read a specific skill to guide your work. Skills contain proven workflows, mandatory processes, and expert techniques.',
|
||||
args: {
|
||||
skill_name: tool.schema.string().describe('Name of the skill to load (e.g., "superpowers:brainstorming", "my-custom-skill", or "project:my-skill")')
|
||||
},
|
||||
execute: async (args, context) => {
|
||||
const { skill_name } = args;
|
||||
|
||||
// Resolve with priority: project > personal > superpowers
|
||||
// Check for project: prefix first
|
||||
const forceProject = skill_name.startsWith('project:');
|
||||
const actualSkillName = forceProject ? skill_name.replace(/^project:/, '') : skill_name;
|
||||
|
||||
let resolved = null;
|
||||
|
||||
// Try project skills first (if project: prefix or no prefix)
|
||||
if (forceProject || !skill_name.startsWith('superpowers:')) {
|
||||
const projectPath = path.join(projectSkillsDir, actualSkillName);
|
||||
const projectSkillFile = path.join(projectPath, 'SKILL.md');
|
||||
if (fs.existsSync(projectSkillFile)) {
|
||||
resolved = {
|
||||
skillFile: projectSkillFile,
|
||||
sourceType: 'project',
|
||||
skillPath: actualSkillName
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to personal/superpowers resolution
|
||||
if (!resolved && !forceProject) {
|
||||
resolved = skillsCore.resolveSkillPath(skill_name, superpowersSkillsDir, personalSkillsDir);
|
||||
}
|
||||
|
||||
if (!resolved) {
|
||||
return `Error: Skill "${skill_name}" not found.\n\nRun find_skills to see available skills.`;
|
||||
}
|
||||
|
||||
const fullContent = fs.readFileSync(resolved.skillFile, 'utf8');
|
||||
const { name, description } = skillsCore.extractFrontmatter(resolved.skillFile);
|
||||
const content = skillsCore.stripFrontmatter(fullContent);
|
||||
const skillDirectory = path.dirname(resolved.skillFile);
|
||||
|
||||
const skillHeader = `# ${name || skill_name}
|
||||
# ${description || ''}
|
||||
# Supporting tools and docs are in ${skillDirectory}
|
||||
# ============================================`;
|
||||
|
||||
// Insert as user message with noReply for persistence across compaction
|
||||
try {
|
||||
await client.session.prompt({
|
||||
path: { id: context.sessionID },
|
||||
body: {
|
||||
noReply: true,
|
||||
parts: [
|
||||
{ type: "text", text: `Loading skill: ${name || skill_name}`, synthetic: true },
|
||||
{ type: "text", text: `${skillHeader}\n\n${content}`, synthetic: true }
|
||||
]
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
// Fallback: return content directly if message insertion fails
|
||||
return `${skillHeader}\n\n${content}`;
|
||||
}
|
||||
|
||||
return `Launching skill: ${name || skill_name}`;
|
||||
}
|
||||
}),
|
||||
find_skills: tool({
|
||||
description: 'List all available skills in the project, personal, and superpowers skill libraries.',
|
||||
args: {},
|
||||
execute: async (args, context) => {
|
||||
const projectSkills = skillsCore.findSkillsInDir(projectSkillsDir, 'project', 3);
|
||||
const personalSkills = skillsCore.findSkillsInDir(personalSkillsDir, 'personal', 3);
|
||||
const superpowersSkills = skillsCore.findSkillsInDir(superpowersSkillsDir, 'superpowers', 3);
|
||||
|
||||
// Priority: project > personal > superpowers
|
||||
const allSkills = [...projectSkills, ...personalSkills, ...superpowersSkills];
|
||||
|
||||
if (allSkills.length === 0) {
|
||||
return 'No skills found. Install superpowers skills to ~/.config/opencode/superpowers/skills/ or add project skills to .opencode/skills/';
|
||||
}
|
||||
|
||||
let output = 'Available skills:\n\n';
|
||||
|
||||
for (const skill of allSkills) {
|
||||
let namespace;
|
||||
switch (skill.sourceType) {
|
||||
case 'project':
|
||||
namespace = 'project:';
|
||||
break;
|
||||
case 'personal':
|
||||
namespace = '';
|
||||
break;
|
||||
default:
|
||||
namespace = 'superpowers:';
|
||||
}
|
||||
const skillName = skill.name || path.basename(skill.path);
|
||||
|
||||
output += `${namespace}${skillName}\n`;
|
||||
if (skill.description) {
|
||||
output += ` ${skill.description}\n`;
|
||||
}
|
||||
output += ` Directory: ${skill.path}\n\n`;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
})
|
||||
},
|
||||
event: async ({ event }) => {
|
||||
// Extract sessionID from various event structures
|
||||
const getSessionID = () => {
|
||||
return event.properties?.info?.id ||
|
||||
event.properties?.sessionID ||
|
||||
event.session?.id;
|
||||
};
|
||||
|
||||
// Inject bootstrap at session creation (before first user message)
|
||||
if (event.type === 'session.created') {
|
||||
const sessionID = getSessionID();
|
||||
if (sessionID) {
|
||||
await injectBootstrap(sessionID, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Re-inject bootstrap after context compaction (compact version to save tokens)
|
||||
if (event.type === 'session.compacted') {
|
||||
const sessionID = getSessionID();
|
||||
if (sessionID) {
|
||||
await injectBootstrap(sessionID, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
95
.opencode/plugins/superpowers.js
Normal file
95
.opencode/plugins/superpowers.js
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Superpowers plugin for OpenCode.ai
|
||||
*
|
||||
* Injects superpowers bootstrap context via system prompt transform.
|
||||
* Skills are discovered via OpenCode's native skill tool from symlinked directory.
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
// Simple frontmatter extraction (avoid dependency on skills-core for bootstrap)
|
||||
const extractAndStripFrontmatter = (content) => {
|
||||
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
||||
if (!match) return { frontmatter: {}, content };
|
||||
|
||||
const frontmatterStr = match[1];
|
||||
const body = match[2];
|
||||
const frontmatter = {};
|
||||
|
||||
for (const line of frontmatterStr.split('\n')) {
|
||||
const colonIdx = line.indexOf(':');
|
||||
if (colonIdx > 0) {
|
||||
const key = line.slice(0, colonIdx).trim();
|
||||
const value = line.slice(colonIdx + 1).trim().replace(/^["']|["']$/g, '');
|
||||
frontmatter[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return { frontmatter, content: body };
|
||||
};
|
||||
|
||||
// Normalize a path: trim whitespace, expand ~, resolve to absolute
|
||||
const normalizePath = (p, homeDir) => {
|
||||
if (!p || typeof p !== 'string') return null;
|
||||
let normalized = p.trim();
|
||||
if (!normalized) return null;
|
||||
if (normalized.startsWith('~/')) {
|
||||
normalized = path.join(homeDir, normalized.slice(2));
|
||||
} else if (normalized === '~') {
|
||||
normalized = homeDir;
|
||||
}
|
||||
return path.resolve(normalized);
|
||||
};
|
||||
|
||||
export const SuperpowersPlugin = async ({ client, directory }) => {
|
||||
const homeDir = os.homedir();
|
||||
const superpowersSkillsDir = path.resolve(__dirname, '../../skills');
|
||||
const envConfigDir = normalizePath(process.env.OPENCODE_CONFIG_DIR, homeDir);
|
||||
const configDir = envConfigDir || path.join(homeDir, '.config/opencode');
|
||||
|
||||
// Helper to generate bootstrap content
|
||||
const getBootstrapContent = () => {
|
||||
// Try to load using-superpowers skill
|
||||
const skillPath = path.join(superpowersSkillsDir, 'using-superpowers', 'SKILL.md');
|
||||
if (!fs.existsSync(skillPath)) return null;
|
||||
|
||||
const fullContent = fs.readFileSync(skillPath, 'utf8');
|
||||
const { content } = extractAndStripFrontmatter(fullContent);
|
||||
|
||||
const toolMapping = `**Tool Mapping for OpenCode:**
|
||||
When skills reference tools you don't have, substitute OpenCode equivalents:
|
||||
- \`TodoWrite\` → \`update_plan\`
|
||||
- \`Task\` tool with subagents → Use OpenCode's subagent system (@mention)
|
||||
- \`Skill\` tool → OpenCode's native \`skill\` tool
|
||||
- \`Read\`, \`Write\`, \`Edit\`, \`Bash\` → Your native tools
|
||||
|
||||
**Skills location:**
|
||||
Superpowers skills are in \`${configDir}/skills/superpowers/\`
|
||||
Use OpenCode's native \`skill\` tool to list and load skills.`;
|
||||
|
||||
return `<EXTREMELY_IMPORTANT>
|
||||
You have superpowers.
|
||||
|
||||
**IMPORTANT: The using-superpowers skill content is included below. It is ALREADY LOADED - you are currently following it. Do NOT use the skill tool to load "using-superpowers" again - that would be redundant.**
|
||||
|
||||
${content}
|
||||
|
||||
${toolMapping}
|
||||
</EXTREMELY_IMPORTANT>`;
|
||||
};
|
||||
|
||||
return {
|
||||
// Use system prompt transform to inject bootstrap (fixes #226 agent reset bug)
|
||||
'experimental.chat.system.transform': async (_input, output) => {
|
||||
const bootstrap = getBootstrapContent();
|
||||
if (bootstrap) {
|
||||
(output.system ||= []).push(bootstrap);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
13
README.md
13
README.md
@@ -44,18 +44,7 @@ Then install the plugin from this marketplace:
|
||||
|
||||
### Verify Installation
|
||||
|
||||
Check that commands appear:
|
||||
|
||||
```bash
|
||||
/help
|
||||
```
|
||||
|
||||
```
|
||||
# Should see:
|
||||
# /superpowers:brainstorm - Interactive design refinement
|
||||
# /superpowers:write-plan - Create implementation plan
|
||||
# /superpowers:execute-plan - Execute plan in batches
|
||||
```
|
||||
Start a new session and ask Claude to help with something that would trigger a skill (e.g., "help me plan this feature" or "let's debug this issue"). Claude should automatically invoke the relevant superpowers skill.
|
||||
|
||||
### Codex
|
||||
|
||||
|
||||
111
RELEASE-NOTES.md
111
RELEASE-NOTES.md
@@ -1,5 +1,116 @@
|
||||
# Superpowers Release Notes
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
**OpenCode: Switched to native skills system**
|
||||
|
||||
Superpowers for OpenCode now uses OpenCode's native `skill` tool instead of custom `use_skill`/`find_skills` tools. This is a cleaner integration that works with OpenCode's built-in skill discovery.
|
||||
|
||||
**Migration required:** Skills must be symlinked to `~/.config/opencode/skills/superpowers/` (see updated installation docs).
|
||||
|
||||
### Fixes
|
||||
|
||||
**OpenCode: Fixed agent reset on session start (#226)**
|
||||
|
||||
The previous bootstrap injection method using `session.prompt({ noReply: true })` caused OpenCode to reset the selected agent to "build" on first message. Now uses `experimental.chat.system.transform` hook which modifies the system prompt directly without side effects.
|
||||
|
||||
**OpenCode: Fixed Windows installation (#232)**
|
||||
|
||||
- Removed dependency on `skills-core.js` (eliminates broken relative imports when file is copied instead of symlinked)
|
||||
- Added comprehensive Windows installation docs for cmd.exe, PowerShell, and Git Bash
|
||||
- Documented proper symlink vs junction usage for each platform
|
||||
|
||||
**Fixed Windows hook execution for Claude Code 2.1.x**
|
||||
|
||||
Claude Code 2.1.x changed how hooks execute on Windows: it now auto-detects `.sh` files in commands and prepends `bash `. This broke the polyglot wrapper pattern because `bash "run-hook.cmd" session-start.sh` tries to execute the .cmd file as a bash script.
|
||||
|
||||
Fix: hooks.json now calls session-start.sh directly. Claude Code 2.1.x handles the bash invocation automatically. Also added .gitattributes to enforce LF line endings for shell scripts (fixes CRLF issues on Windows checkout).
|
||||
|
||||
**Windows: SessionStart hook runs async to prevent terminal freeze**
|
||||
|
||||
The synchronous SessionStart hook blocked the TUI from entering raw mode on Windows, freezing terminal input. The pure-bash `escape_for_json` function is O(n^2) on Windows Git Bash, taking 60+ seconds. Running the hook async prevents the freeze while still injecting superpowers context.
|
||||
|
||||
### New Features
|
||||
|
||||
**Visual companion for brainstorming skill**
|
||||
|
||||
Added optional browser-based visual companion for brainstorming sessions. When users have a browser available, brainstorming can display interactive screens showing current phase, questions, and design decisions in a more readable format than terminal output.
|
||||
|
||||
Components:
|
||||
- `lib/brainstorm-server/` - WebSocket server for real-time updates
|
||||
- `skills/brainstorming/visual-companion.md` - Integration guide
|
||||
- Helper scripts for session management with proper isolation
|
||||
- Browser helper library for event capture
|
||||
|
||||
The visual companion is opt-in and falls back gracefully to terminal-only operation.
|
||||
|
||||
### Improvements
|
||||
|
||||
**Instruction priority clarified in using-superpowers**
|
||||
|
||||
Added explicit instruction priority hierarchy to prevent conflicts with user preferences:
|
||||
|
||||
1. User's explicit instructions (CLAUDE.md, direct requests) — highest priority
|
||||
2. Superpowers skills — override default system behavior where they conflict
|
||||
3. Default system prompt — lowest priority
|
||||
|
||||
This ensures users remain in control. If CLAUDE.md says "don't use TDD" and a skill says "always use TDD," CLAUDE.md wins.
|
||||
|
||||
---
|
||||
|
||||
## v4.1.1 (2026-01-23)
|
||||
|
||||
### Fixes
|
||||
|
||||
**OpenCode: Standardized on `plugins/` directory per official docs (#343)**
|
||||
|
||||
OpenCode's official documentation uses `~/.config/opencode/plugins/` (plural). Our docs previously used `plugin/` (singular). While OpenCode accepts both forms, we've standardized on the official convention to avoid confusion.
|
||||
|
||||
Changes:
|
||||
- Renamed `.opencode/plugin/` to `.opencode/plugins/` in repo structure
|
||||
- Updated all installation docs (INSTALL.md, README.opencode.md) across all platforms
|
||||
- Updated test scripts to match
|
||||
|
||||
**OpenCode: Fixed symlink instructions (#339, #342)**
|
||||
|
||||
- Added explicit `rm` before `ln -s` (fixes "file already exists" errors on reinstall)
|
||||
- Added missing skills symlink step that was absent from INSTALL.md
|
||||
- Updated from deprecated `use_skill`/`find_skills` to native `skill` tool references
|
||||
|
||||
---
|
||||
|
||||
## v4.1.0 (2026-01-23)
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
**OpenCode: Switched to native skills system**
|
||||
|
||||
Superpowers for OpenCode now uses OpenCode's native `skill` tool instead of custom `use_skill`/`find_skills` tools. This is a cleaner integration that works with OpenCode's built-in skill discovery.
|
||||
|
||||
**Migration required:** Skills must be symlinked to `~/.config/opencode/skills/superpowers/` (see updated installation docs).
|
||||
|
||||
### Fixes
|
||||
|
||||
**OpenCode: Fixed agent reset on session start (#226)**
|
||||
|
||||
The previous bootstrap injection method using `session.prompt({ noReply: true })` caused OpenCode to reset the selected agent to "build" on first message. Now uses `experimental.chat.system.transform` hook which modifies the system prompt directly without side effects.
|
||||
|
||||
**OpenCode: Fixed Windows installation (#232)**
|
||||
|
||||
- Removed dependency on `skills-core.js` (eliminates broken relative imports when file is copied instead of symlinked)
|
||||
- Added comprehensive Windows installation docs for cmd.exe, PowerShell, and Git Bash
|
||||
- Documented proper symlink vs junction usage for each platform
|
||||
|
||||
**Claude Code: Fixed Windows hook execution for Claude Code 2.1.x**
|
||||
|
||||
Claude Code 2.1.x changed how hooks execute on Windows: it now auto-detects `.sh` files in commands and prepends `bash `. This broke the polyglot wrapper pattern because `bash "run-hook.cmd" session-start.sh` tries to execute the .cmd file as a bash script.
|
||||
|
||||
Fix: hooks.json now calls session-start.sh directly. Claude Code 2.1.x handles the bash invocation automatically. Also added .gitattributes to enforce LF line endings for shell scripts (fixes CRLF issues on Windows checkout).
|
||||
|
||||
---
|
||||
|
||||
## v4.0.3 (2025-12-26)
|
||||
|
||||
### Improvements
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Superpowers for Codex
|
||||
|
||||
Complete guide for using Superpowers with OpenAI Codex.
|
||||
Guide for using Superpowers with OpenAI Codex via native skill discovery.
|
||||
|
||||
## Quick Install
|
||||
|
||||
@@ -14,63 +14,59 @@ Fetch and follow instructions from https://raw.githubusercontent.com/obra/superp
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- OpenAI Codex access
|
||||
- Shell access to install files
|
||||
- OpenAI Codex CLI
|
||||
- Git
|
||||
|
||||
### Installation Steps
|
||||
### Steps
|
||||
|
||||
#### 1. Clone Superpowers
|
||||
1. Clone the repo:
|
||||
```bash
|
||||
git clone https://github.com/obra/superpowers.git ~/.codex/superpowers
|
||||
```
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.codex/superpowers
|
||||
git clone https://github.com/obra/superpowers.git ~/.codex/superpowers
|
||||
2. Create the skills symlink:
|
||||
```bash
|
||||
mkdir -p ~/.agents/skills
|
||||
ln -s ~/.codex/superpowers/skills ~/.agents/skills/superpowers
|
||||
```
|
||||
|
||||
3. Restart Codex.
|
||||
|
||||
### Windows
|
||||
|
||||
Use a junction instead of a symlink (works without Developer Mode):
|
||||
|
||||
```powershell
|
||||
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.agents\skills"
|
||||
cmd /c mklink /J "$env:USERPROFILE\.agents\skills\superpowers" "$env:USERPROFILE\.codex\superpowers\skills"
|
||||
```
|
||||
|
||||
#### 2. Install Bootstrap
|
||||
## How It Works
|
||||
|
||||
The bootstrap file is included in the repository at `.codex/superpowers-bootstrap.md`. Codex will automatically use it from the cloned location.
|
||||
|
||||
#### 3. Verify Installation
|
||||
|
||||
Tell Codex:
|
||||
Codex has native skill discovery — it scans `~/.agents/skills/` at startup, parses SKILL.md frontmatter, and loads skills on demand. Superpowers skills are made visible through a single symlink:
|
||||
|
||||
```
|
||||
Run ~/.codex/superpowers/.codex/superpowers-codex find-skills to show available skills
|
||||
~/.agents/skills/superpowers/ → ~/.codex/superpowers/skills/
|
||||
```
|
||||
|
||||
You should see a list of available skills with descriptions.
|
||||
The `using-superpowers` skill is discovered automatically and enforces skill usage discipline — no additional configuration needed.
|
||||
|
||||
## Usage
|
||||
|
||||
### Finding Skills
|
||||
|
||||
```
|
||||
Run ~/.codex/superpowers/.codex/superpowers-codex find-skills
|
||||
```
|
||||
|
||||
### Loading a Skill
|
||||
|
||||
```
|
||||
Run ~/.codex/superpowers/.codex/superpowers-codex use-skill superpowers:brainstorming
|
||||
```
|
||||
|
||||
### Bootstrap All Skills
|
||||
|
||||
```
|
||||
Run ~/.codex/superpowers/.codex/superpowers-codex bootstrap
|
||||
```
|
||||
|
||||
This loads the complete bootstrap with all skill information.
|
||||
Skills are discovered automatically. Codex activates them when:
|
||||
- You mention a skill by name (e.g., "use brainstorming")
|
||||
- The task matches a skill's description
|
||||
- The `using-superpowers` skill directs Codex to use one
|
||||
|
||||
### Personal Skills
|
||||
|
||||
Create your own skills in `~/.codex/skills/`:
|
||||
Create your own skills in `~/.agents/skills/`:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.codex/skills/my-skill
|
||||
mkdir -p ~/.agents/skills/my-skill
|
||||
```
|
||||
|
||||
Create `~/.codex/skills/my-skill/SKILL.md`:
|
||||
Create `~/.agents/skills/my-skill/SKILL.md`:
|
||||
|
||||
```markdown
|
||||
---
|
||||
@@ -83,71 +79,42 @@ description: Use when [condition] - [what it does]
|
||||
[Your skill content here]
|
||||
```
|
||||
|
||||
Personal skills override superpowers skills with the same name.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Codex CLI Tool
|
||||
|
||||
**Location:** `~/.codex/superpowers/.codex/superpowers-codex`
|
||||
|
||||
A Node.js CLI script that provides three commands:
|
||||
- `bootstrap` - Load complete bootstrap with all skills
|
||||
- `use-skill <name>` - Load a specific skill
|
||||
- `find-skills` - List all available skills
|
||||
|
||||
### Shared Core Module
|
||||
|
||||
**Location:** `~/.codex/superpowers/lib/skills-core.js`
|
||||
|
||||
The Codex implementation uses the shared `skills-core` module (ES module format) for skill discovery and parsing. This is the same module used by the OpenCode plugin, ensuring consistent behavior across platforms.
|
||||
|
||||
### Tool Mapping
|
||||
|
||||
Skills written for Claude Code are adapted for Codex with these mappings:
|
||||
|
||||
- `TodoWrite` → `update_plan`
|
||||
- `Task` with subagents → Tell user subagents aren't available, do work directly
|
||||
- `Skill` tool → `~/.codex/superpowers/.codex/superpowers-codex use-skill`
|
||||
- File operations → Native Codex tools
|
||||
The `description` field is how Codex decides when to activate a skill automatically — write it as a clear trigger condition.
|
||||
|
||||
## Updating
|
||||
|
||||
```bash
|
||||
cd ~/.codex/superpowers
|
||||
git pull
|
||||
cd ~/.codex/superpowers && git pull
|
||||
```
|
||||
|
||||
Skills update instantly through the symlink.
|
||||
|
||||
## Uninstalling
|
||||
|
||||
```bash
|
||||
rm ~/.agents/skills/superpowers
|
||||
```
|
||||
|
||||
**Windows (PowerShell):**
|
||||
```powershell
|
||||
Remove-Item "$env:USERPROFILE\.agents\skills\superpowers"
|
||||
```
|
||||
|
||||
Optionally delete the clone: `rm -rf ~/.codex/superpowers` (Windows: `Remove-Item -Recurse -Force "$env:USERPROFILE\.codex\superpowers"`).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Skills not found
|
||||
### Skills not showing up
|
||||
|
||||
1. Verify installation: `ls ~/.codex/superpowers/skills`
|
||||
2. Check CLI works: `~/.codex/superpowers/.codex/superpowers-codex find-skills`
|
||||
3. Verify skills have SKILL.md files
|
||||
1. Verify the symlink: `ls -la ~/.agents/skills/superpowers`
|
||||
2. Check skills exist: `ls ~/.codex/superpowers/skills`
|
||||
3. Restart Codex — skills are discovered at startup
|
||||
|
||||
### CLI script not executable
|
||||
### Windows junction issues
|
||||
|
||||
```bash
|
||||
chmod +x ~/.codex/superpowers/.codex/superpowers-codex
|
||||
```
|
||||
|
||||
### Node.js errors
|
||||
|
||||
The CLI script requires Node.js. Verify:
|
||||
|
||||
```bash
|
||||
node --version
|
||||
```
|
||||
|
||||
Should show v14 or higher (v18+ recommended for ES module support).
|
||||
Junctions normally work without special permissions. If creation fails, try running PowerShell as administrator.
|
||||
|
||||
## Getting Help
|
||||
|
||||
- Report issues: https://github.com/obra/superpowers/issues
|
||||
- Main documentation: https://github.com/obra/superpowers
|
||||
- Blog post: https://blog.fsck.com/2025/10/27/skills-for-openai-codex/
|
||||
|
||||
## Note
|
||||
|
||||
Codex support is experimental and may require refinement based on user feedback. If you encounter issues, please report them on GitHub.
|
||||
|
||||
@@ -7,7 +7,7 @@ Complete guide for using Superpowers with [OpenCode.ai](https://opencode.ai).
|
||||
Tell OpenCode:
|
||||
|
||||
```
|
||||
Clone https://github.com/obra/superpowers to ~/.config/opencode/superpowers, then create directory ~/.config/opencode/plugin, then symlink ~/.config/opencode/superpowers/.opencode/plugin/superpowers.js to ~/.config/opencode/plugin/superpowers.js, then restart opencode.
|
||||
Clone https://github.com/obra/superpowers to ~/.config/opencode/superpowers, then create directory ~/.config/opencode/plugins, then symlink ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js to ~/.config/opencode/plugins/superpowers.js, then symlink ~/.config/opencode/superpowers/skills to ~/.config/opencode/skills/superpowers, then restart opencode.
|
||||
```
|
||||
|
||||
## Manual Installation
|
||||
@@ -15,59 +15,175 @@ Clone https://github.com/obra/superpowers to ~/.config/opencode/superpowers, the
|
||||
### Prerequisites
|
||||
|
||||
- [OpenCode.ai](https://opencode.ai) installed
|
||||
- Node.js installed
|
||||
- Git installed
|
||||
|
||||
### Installation Steps
|
||||
|
||||
#### 1. Install Superpowers
|
||||
### macOS / Linux
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.config/opencode/superpowers
|
||||
# 1. Install Superpowers (or update existing)
|
||||
if [ -d ~/.config/opencode/superpowers ]; then
|
||||
cd ~/.config/opencode/superpowers && git pull
|
||||
else
|
||||
git clone https://github.com/obra/superpowers.git ~/.config/opencode/superpowers
|
||||
fi
|
||||
|
||||
# 2. Create directories
|
||||
mkdir -p ~/.config/opencode/plugins ~/.config/opencode/skills
|
||||
|
||||
# 3. Remove old symlinks/directories if they exist
|
||||
rm -f ~/.config/opencode/plugins/superpowers.js
|
||||
rm -rf ~/.config/opencode/skills/superpowers
|
||||
|
||||
# 4. Create symlinks
|
||||
ln -s ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js ~/.config/opencode/plugins/superpowers.js
|
||||
ln -s ~/.config/opencode/superpowers/skills ~/.config/opencode/skills/superpowers
|
||||
|
||||
# 5. Restart OpenCode
|
||||
```
|
||||
|
||||
#### Verify Installation
|
||||
|
||||
```bash
|
||||
ls -l ~/.config/opencode/plugins/superpowers.js
|
||||
ls -l ~/.config/opencode/skills/superpowers
|
||||
```
|
||||
|
||||
Both should show symlinks pointing to the superpowers directory.
|
||||
|
||||
### Windows
|
||||
|
||||
**Prerequisites:**
|
||||
- Git installed
|
||||
- Either **Developer Mode** enabled OR **Administrator privileges**
|
||||
- Windows 10: Settings → Update & Security → For developers
|
||||
- Windows 11: Settings → System → For developers
|
||||
|
||||
Pick your shell below: [Command Prompt](#command-prompt) | [PowerShell](#powershell) | [Git Bash](#git-bash)
|
||||
|
||||
#### Command Prompt
|
||||
|
||||
Run as Administrator, or with Developer Mode enabled:
|
||||
|
||||
```cmd
|
||||
:: 1. Install Superpowers
|
||||
git clone https://github.com/obra/superpowers.git "%USERPROFILE%\.config\opencode\superpowers"
|
||||
|
||||
:: 2. Create directories
|
||||
mkdir "%USERPROFILE%\.config\opencode\plugins" 2>nul
|
||||
mkdir "%USERPROFILE%\.config\opencode\skills" 2>nul
|
||||
|
||||
:: 3. Remove existing links (safe for reinstalls)
|
||||
del "%USERPROFILE%\.config\opencode\plugins\superpowers.js" 2>nul
|
||||
rmdir "%USERPROFILE%\.config\opencode\skills\superpowers" 2>nul
|
||||
|
||||
:: 4. Create plugin symlink (requires Developer Mode or Admin)
|
||||
mklink "%USERPROFILE%\.config\opencode\plugins\superpowers.js" "%USERPROFILE%\.config\opencode\superpowers\.opencode\plugins\superpowers.js"
|
||||
|
||||
:: 5. Create skills junction (works without special privileges)
|
||||
mklink /J "%USERPROFILE%\.config\opencode\skills\superpowers" "%USERPROFILE%\.config\opencode\superpowers\skills"
|
||||
|
||||
:: 6. Restart OpenCode
|
||||
```
|
||||
|
||||
#### PowerShell
|
||||
|
||||
Run as Administrator, or with Developer Mode enabled:
|
||||
|
||||
```powershell
|
||||
# 1. Install Superpowers
|
||||
git clone https://github.com/obra/superpowers.git "$env:USERPROFILE\.config\opencode\superpowers"
|
||||
|
||||
# 2. Create directories
|
||||
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.config\opencode\plugins"
|
||||
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.config\opencode\skills"
|
||||
|
||||
# 3. Remove existing links (safe for reinstalls)
|
||||
Remove-Item "$env:USERPROFILE\.config\opencode\plugins\superpowers.js" -Force -ErrorAction SilentlyContinue
|
||||
Remove-Item "$env:USERPROFILE\.config\opencode\skills\superpowers" -Force -ErrorAction SilentlyContinue
|
||||
|
||||
# 4. Create plugin symlink (requires Developer Mode or Admin)
|
||||
New-Item -ItemType SymbolicLink -Path "$env:USERPROFILE\.config\opencode\plugins\superpowers.js" -Target "$env:USERPROFILE\.config\opencode\superpowers\.opencode\plugins\superpowers.js"
|
||||
|
||||
# 5. Create skills junction (works without special privileges)
|
||||
New-Item -ItemType Junction -Path "$env:USERPROFILE\.config\opencode\skills\superpowers" -Target "$env:USERPROFILE\.config\opencode\superpowers\skills"
|
||||
|
||||
# 6. Restart OpenCode
|
||||
```
|
||||
|
||||
#### Git Bash
|
||||
|
||||
Note: Git Bash's native `ln` command copies files instead of creating symlinks. Use `cmd //c mklink` instead (the `//c` is Git Bash syntax for `/c`).
|
||||
|
||||
```bash
|
||||
# 1. Install Superpowers
|
||||
git clone https://github.com/obra/superpowers.git ~/.config/opencode/superpowers
|
||||
|
||||
# 2. Create directories
|
||||
mkdir -p ~/.config/opencode/plugins ~/.config/opencode/skills
|
||||
|
||||
# 3. Remove existing links (safe for reinstalls)
|
||||
rm -f ~/.config/opencode/plugins/superpowers.js 2>/dev/null
|
||||
rm -rf ~/.config/opencode/skills/superpowers 2>/dev/null
|
||||
|
||||
# 4. Create plugin symlink (requires Developer Mode or Admin)
|
||||
cmd //c "mklink \"$(cygpath -w ~/.config/opencode/plugins/superpowers.js)\" \"$(cygpath -w ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js)\""
|
||||
|
||||
# 5. Create skills junction (works without special privileges)
|
||||
cmd //c "mklink /J \"$(cygpath -w ~/.config/opencode/skills/superpowers)\" \"$(cygpath -w ~/.config/opencode/superpowers/skills)\""
|
||||
|
||||
# 6. Restart OpenCode
|
||||
```
|
||||
|
||||
#### 2. Register the Plugin
|
||||
#### WSL Users
|
||||
|
||||
OpenCode discovers plugins from `~/.config/opencode/plugin/`. Create a symlink:
|
||||
If running OpenCode inside WSL, use the [macOS / Linux](#macos--linux) instructions instead.
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.config/opencode/plugin
|
||||
ln -sf ~/.config/opencode/superpowers/.opencode/plugin/superpowers.js ~/.config/opencode/plugin/superpowers.js
|
||||
#### Verify Installation
|
||||
|
||||
**Command Prompt:**
|
||||
```cmd
|
||||
dir /AL "%USERPROFILE%\.config\opencode\plugins"
|
||||
dir /AL "%USERPROFILE%\.config\opencode\skills"
|
||||
```
|
||||
|
||||
Alternatively, for project-local installation:
|
||||
|
||||
```bash
|
||||
# In your OpenCode project
|
||||
mkdir -p .opencode/plugin
|
||||
ln -sf ~/.config/opencode/superpowers/.opencode/plugin/superpowers.js .opencode/plugin/superpowers.js
|
||||
**PowerShell:**
|
||||
```powershell
|
||||
Get-ChildItem "$env:USERPROFILE\.config\opencode\plugins" | Where-Object { $_.LinkType }
|
||||
Get-ChildItem "$env:USERPROFILE\.config\opencode\skills" | Where-Object { $_.LinkType }
|
||||
```
|
||||
|
||||
#### 3. Restart OpenCode
|
||||
Look for `<SYMLINK>` or `<JUNCTION>` in the output.
|
||||
|
||||
Restart OpenCode to load the plugin. Superpowers will automatically activate.
|
||||
#### Troubleshooting Windows
|
||||
|
||||
**"You do not have sufficient privilege" error:**
|
||||
- Enable Developer Mode in Windows Settings, OR
|
||||
- Right-click your terminal → "Run as Administrator"
|
||||
|
||||
**"Cannot create a file when that file already exists":**
|
||||
- Run the removal commands (step 3) first, then retry
|
||||
|
||||
**Symlinks not working after git clone:**
|
||||
- Run `git config --global core.symlinks true` and re-clone
|
||||
|
||||
## Usage
|
||||
|
||||
### Finding Skills
|
||||
|
||||
Use the `find_skills` tool to list all available skills:
|
||||
Use OpenCode's native `skill` tool to list all available skills:
|
||||
|
||||
```
|
||||
use find_skills tool
|
||||
use skill tool to list skills
|
||||
```
|
||||
|
||||
### Loading a Skill
|
||||
|
||||
Use the `use_skill` tool to load a specific skill:
|
||||
Use OpenCode's native `skill` tool to load a specific skill:
|
||||
|
||||
```
|
||||
use use_skill tool with skill_name: "superpowers:brainstorming"
|
||||
use skill tool to load superpowers/brainstorming
|
||||
```
|
||||
|
||||
Skills are automatically inserted into the conversation and persist across context compaction.
|
||||
|
||||
### Personal Skills
|
||||
|
||||
Create your own skills in `~/.config/opencode/skills/`:
|
||||
@@ -111,66 +227,48 @@ description: Use when [condition] - [what it does]
|
||||
[Your skill content here]
|
||||
```
|
||||
|
||||
## Skill Priority
|
||||
## Skill Locations
|
||||
|
||||
Skills are resolved with this priority order:
|
||||
OpenCode discovers skills from these locations:
|
||||
|
||||
1. **Project skills** (`.opencode/skills/`) - Highest priority
|
||||
2. **Personal skills** (`~/.config/opencode/skills/`)
|
||||
3. **Superpowers skills** (`~/.config/opencode/superpowers/skills/`)
|
||||
|
||||
You can force resolution to a specific level:
|
||||
- `project:skill-name` - Force project skill
|
||||
- `skill-name` - Search project → personal → superpowers
|
||||
- `superpowers:skill-name` - Force superpowers skill
|
||||
3. **Superpowers skills** (`~/.config/opencode/skills/superpowers/`) - via symlink
|
||||
|
||||
## Features
|
||||
|
||||
### Automatic Context Injection
|
||||
|
||||
The plugin automatically injects superpowers context via the chat.message hook on every session. No manual configuration needed.
|
||||
The plugin automatically injects superpowers context via the `experimental.chat.system.transform` hook. This adds the "using-superpowers" skill content to the system prompt on every request.
|
||||
|
||||
### Message Insertion Pattern
|
||||
### Native Skills Integration
|
||||
|
||||
When you load a skill with `use_skill`, it's inserted as a user message with `noReply: true`. This ensures skills persist throughout long conversations, even when OpenCode compacts context.
|
||||
|
||||
### Compaction Resilience
|
||||
|
||||
The plugin listens for `session.compacted` events and automatically re-injects the core superpowers bootstrap to maintain functionality after context compaction.
|
||||
Superpowers uses OpenCode's native `skill` tool for skill discovery and loading. Skills are symlinked into `~/.config/opencode/skills/superpowers/` so they appear alongside your personal and project skills.
|
||||
|
||||
### Tool Mapping
|
||||
|
||||
Skills written for Claude Code are automatically adapted for OpenCode. The plugin provides mapping instructions:
|
||||
Skills written for Claude Code are automatically adapted for OpenCode. The bootstrap provides mapping instructions:
|
||||
|
||||
- `TodoWrite` → `update_plan`
|
||||
- `Task` with subagents → OpenCode's `@mention` system
|
||||
- `Skill` tool → `use_skill` custom tool
|
||||
- `Skill` tool → OpenCode's native `skill` tool
|
||||
- File operations → Native OpenCode tools
|
||||
|
||||
## Architecture
|
||||
|
||||
### Plugin Structure
|
||||
|
||||
**Location:** `~/.config/opencode/superpowers/.opencode/plugin/superpowers.js`
|
||||
**Location:** `~/.config/opencode/superpowers/.opencode/plugins/superpowers.js`
|
||||
|
||||
**Components:**
|
||||
- Two custom tools: `use_skill`, `find_skills`
|
||||
- chat.message hook for initial context injection
|
||||
- event handler for session.compacted re-injection
|
||||
- Uses shared `lib/skills-core.js` module (also used by Codex)
|
||||
- `experimental.chat.system.transform` hook for bootstrap injection
|
||||
- Reads and injects the "using-superpowers" skill content
|
||||
|
||||
### Shared Core Module
|
||||
### Skills
|
||||
|
||||
**Location:** `~/.config/opencode/superpowers/lib/skills-core.js`
|
||||
**Location:** `~/.config/opencode/skills/superpowers/` (symlink to `~/.config/opencode/superpowers/skills/`)
|
||||
|
||||
**Functions:**
|
||||
- `extractFrontmatter()` - Parse skill metadata
|
||||
- `stripFrontmatter()` - Remove metadata from content
|
||||
- `findSkillsInDir()` - Recursive skill discovery
|
||||
- `resolveSkillPath()` - Skill resolution with shadowing
|
||||
- `checkForUpdates()` - Git update detection
|
||||
|
||||
This module is shared between OpenCode and Codex implementations for code reuse.
|
||||
Skills are discovered by OpenCode's native skill system. Each skill has a `SKILL.md` file with YAML frontmatter.
|
||||
|
||||
## Updating
|
||||
|
||||
@@ -185,28 +283,28 @@ Restart OpenCode to load the updates.
|
||||
|
||||
### Plugin not loading
|
||||
|
||||
1. Check plugin file exists: `ls ~/.config/opencode/superpowers/.opencode/plugin/superpowers.js`
|
||||
2. Check symlink: `ls -l ~/.config/opencode/plugin/superpowers.js`
|
||||
1. Check plugin exists: `ls ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js`
|
||||
2. Check symlink/junction: `ls -l ~/.config/opencode/plugins/` (macOS/Linux) or `dir /AL %USERPROFILE%\.config\opencode\plugins` (Windows)
|
||||
3. Check OpenCode logs: `opencode run "test" --print-logs --log-level DEBUG`
|
||||
4. Look for: `service=plugin path=file:///.../superpowers.js loading plugin`
|
||||
4. Look for plugin loading message in logs
|
||||
|
||||
### Skills not found
|
||||
|
||||
1. Verify skills directory: `ls ~/.config/opencode/superpowers/skills`
|
||||
2. Use `find_skills` tool to see what's discovered
|
||||
3. Check skill structure: each skill needs a `SKILL.md` file
|
||||
1. Verify skills symlink: `ls -l ~/.config/opencode/skills/superpowers` (should point to superpowers/skills/)
|
||||
2. Use OpenCode's `skill` tool to list available skills
|
||||
3. Check skill structure: each skill needs a `SKILL.md` file with valid frontmatter
|
||||
|
||||
### Tools not working
|
||||
### Windows: Module not found error
|
||||
|
||||
1. Verify plugin loaded: Check OpenCode logs for plugin loading message
|
||||
2. Check Node.js version: The plugin requires Node.js for ES modules
|
||||
3. Test plugin manually: `node --input-type=module -e "import('file://~/.config/opencode/plugin/superpowers.js').then(m => console.log(Object.keys(m)))"`
|
||||
If you see `Cannot find module` errors on Windows:
|
||||
- **Cause:** Git Bash `ln -sf` copies files instead of creating symlinks
|
||||
- **Fix:** Use `mklink /J` directory junctions instead (see Windows installation steps)
|
||||
|
||||
### Context not injecting
|
||||
### Bootstrap not appearing
|
||||
|
||||
1. Check if chat.message hook is working
|
||||
2. Verify using-superpowers skill exists
|
||||
3. Check OpenCode version (requires recent version with plugin support)
|
||||
1. Verify using-superpowers skill exists: `ls ~/.config/opencode/superpowers/skills/using-superpowers/SKILL.md`
|
||||
2. Check OpenCode version supports `experimental.chat.system.transform` hook
|
||||
3. Restart OpenCode after plugin changes
|
||||
|
||||
## Getting Help
|
||||
|
||||
@@ -216,19 +314,17 @@ Restart OpenCode to load the updates.
|
||||
|
||||
## Testing
|
||||
|
||||
The implementation includes an automated test suite at `tests/opencode/`:
|
||||
Verify your installation:
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
./tests/opencode/run-tests.sh --integration --verbose
|
||||
# Check plugin loads
|
||||
opencode run --print-logs "hello" 2>&1 | grep -i superpowers
|
||||
|
||||
# Run specific test
|
||||
./tests/opencode/run-tests.sh --test test-tools.sh
|
||||
# Check skills are discoverable
|
||||
opencode run "use skill tool to list all skills" 2>&1 | grep -i superpowers
|
||||
|
||||
# Check bootstrap injection
|
||||
opencode run "what superpowers do you have?"
|
||||
```
|
||||
|
||||
Tests verify:
|
||||
- Plugin loading
|
||||
- Skills-core library functionality
|
||||
- Tool execution (use_skill, find_skills)
|
||||
- Skill priority resolution
|
||||
- Proper isolation with temp HOME
|
||||
The agent should mention having superpowers and be able to list skills from `superpowers/`.
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" session-start.sh"
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh",
|
||||
"async": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,30 @@
|
||||
: << 'CMDBLOCK'
|
||||
@echo off
|
||||
REM Polyglot wrapper: runs .sh scripts cross-platform
|
||||
REM ============================================================================
|
||||
REM DEPRECATED: This polyglot wrapper is no longer used as of Claude Code 2.1.x
|
||||
REM ============================================================================
|
||||
REM
|
||||
REM Claude Code 2.1.x changed the Windows execution model for hooks:
|
||||
REM
|
||||
REM Before (2.0.x): Hooks ran with shell:true, using the system default shell.
|
||||
REM This wrapper provided cross-platform compatibility by
|
||||
REM being both a valid .cmd file (Windows) and bash script.
|
||||
REM
|
||||
REM After (2.1.x): Claude Code now auto-detects .sh files in hook commands
|
||||
REM and prepends "bash " on Windows. This broke the wrapper
|
||||
REM because the command:
|
||||
REM "run-hook.cmd" session-start.sh
|
||||
REM became:
|
||||
REM bash "run-hook.cmd" session-start.sh
|
||||
REM ...and bash cannot execute a .cmd file.
|
||||
REM
|
||||
REM The fix: hooks.json now calls session-start.sh directly. Claude Code 2.1.x
|
||||
REM handles the bash invocation automatically on Windows.
|
||||
REM
|
||||
REM This file is kept for reference and potential backward compatibility.
|
||||
REM ============================================================================
|
||||
REM
|
||||
REM Original purpose: Polyglot wrapper to run .sh scripts cross-platform
|
||||
REM Usage: run-hook.cmd <script-name> [args...]
|
||||
REM The script should be in the same directory as this wrapper
|
||||
|
||||
|
||||
@@ -17,23 +17,17 @@ fi
|
||||
# Read using-superpowers content
|
||||
using_superpowers_content=$(cat "${PLUGIN_ROOT}/skills/using-superpowers/SKILL.md" 2>&1 || echo "Error reading using-superpowers skill")
|
||||
|
||||
# Escape outputs for JSON using pure bash
|
||||
# Escape string for JSON embedding using bash parameter substitution.
|
||||
# Each ${s//old/new} is a single C-level pass - orders of magnitude
|
||||
# faster than the character-by-character loop this replaces.
|
||||
escape_for_json() {
|
||||
local input="$1"
|
||||
local output=""
|
||||
local i char
|
||||
for (( i=0; i<${#input}; i++ )); do
|
||||
char="${input:$i:1}"
|
||||
case "$char" in
|
||||
$'\\') output+='\\' ;;
|
||||
'"') output+='\"' ;;
|
||||
$'\n') output+='\n' ;;
|
||||
$'\r') output+='\r' ;;
|
||||
$'\t') output+='\t' ;;
|
||||
*) output+="$char" ;;
|
||||
esac
|
||||
done
|
||||
printf '%s' "$output"
|
||||
local s="$1"
|
||||
s="${s//\\/\\\\}"
|
||||
s="${s//\"/\\\"}"
|
||||
s="${s//$'\n'/\\n}"
|
||||
s="${s//$'\r'/\\r}"
|
||||
s="${s//$'\t'/\\t}"
|
||||
printf '%s' "$s"
|
||||
}
|
||||
|
||||
using_superpowers_escaped=$(escape_for_json "$using_superpowers_content")
|
||||
|
||||
@@ -74,3 +74,11 @@ After all tasks complete and verified:
|
||||
- Reference skills when plan says to
|
||||
- Between batches: just report and wait
|
||||
- Stop when blocked, don't guess
|
||||
- Never start implementation on main/master branch without explicit user consent
|
||||
|
||||
## Integration
|
||||
|
||||
**Required workflow skills:**
|
||||
- **superpowers:using-git-worktrees** - REQUIRED: Set up isolated workspace before starting
|
||||
- **superpowers:writing-plans** - Creates the plan this skill executes
|
||||
- **superpowers:finishing-a-development-branch** - Complete development after all tasks
|
||||
|
||||
@@ -199,6 +199,7 @@ Done!
|
||||
## Red Flags
|
||||
|
||||
**Never:**
|
||||
- Start implementation on main/master branch without explicit user consent
|
||||
- Skip reviews (spec compliance OR code quality)
|
||||
- Proceed with unfixed issues
|
||||
- Dispatch multiple implementation subagents in parallel (conflicts)
|
||||
@@ -229,6 +230,7 @@ Done!
|
||||
## Integration
|
||||
|
||||
**Required workflow skills:**
|
||||
- **superpowers:using-git-worktrees** - REQUIRED: Set up isolated workspace before starting
|
||||
- **superpowers:writing-plans** - Creates the plan this skill executes
|
||||
- **superpowers:requesting-code-review** - Code review template for reviewer subagents
|
||||
- **superpowers:finishing-a-development-branch** - Complete development after all tasks
|
||||
|
||||
@@ -210,8 +210,9 @@ Ready to implement auth feature
|
||||
|
||||
**Called by:**
|
||||
- **brainstorming** (Phase 4) - REQUIRED when design is approved and implementation follows
|
||||
- **subagent-driven-development** - REQUIRED before executing any tasks
|
||||
- **executing-plans** - REQUIRED before executing any tasks
|
||||
- Any skill needing isolated workspace
|
||||
|
||||
**Pairs with:**
|
||||
- **finishing-a-development-branch** - REQUIRED for cleanup after work complete
|
||||
- **executing-plans** or **subagent-driven-development** - Work happens in this worktree
|
||||
|
||||
@@ -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, `~/.agents/skills/` for Codex)**
|
||||
|
||||
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).
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ echo "Test 1: Skill loading..."
|
||||
|
||||
output=$(run_claude "What is the subagent-driven-development skill? Describe its key steps briefly." 30)
|
||||
|
||||
if assert_contains "$output" "subagent-driven-development" "Skill is recognized"; then
|
||||
if assert_contains "$output" "subagent-driven-development\|Subagent-Driven Development\|Subagent Driven" "Skill is recognized"; then
|
||||
: # pass
|
||||
else
|
||||
exit 1
|
||||
@@ -136,4 +136,30 @@ fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Test 8: Verify worktree requirement
|
||||
echo "Test 8: Worktree requirement..."
|
||||
|
||||
output=$(run_claude "What workflow skills are required before using subagent-driven-development? List any prerequisites or required skills." 30)
|
||||
|
||||
if assert_contains "$output" "using-git-worktrees\|worktree" "Mentions worktree requirement"; then
|
||||
: # pass
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Test 9: Verify main branch warning
|
||||
echo "Test 9: Main branch red flag..."
|
||||
|
||||
output=$(run_claude "In subagent-driven-development, is it okay to start implementation directly on the main branch?" 30)
|
||||
|
||||
if assert_contains "$output" "worktree\|feature.*branch\|not.*main\|never.*main\|avoid.*main\|don't.*main\|consent\|permission" "Warns against main branch"; then
|
||||
: # pass
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
echo "=== All subagent-driven-development skill tests passed ==="
|
||||
|
||||
@@ -18,13 +18,13 @@ cp -r "$REPO_ROOT/lib" "$HOME/.config/opencode/superpowers/"
|
||||
cp -r "$REPO_ROOT/skills" "$HOME/.config/opencode/superpowers/"
|
||||
|
||||
# Copy plugin directory
|
||||
mkdir -p "$HOME/.config/opencode/superpowers/.opencode/plugin"
|
||||
cp "$REPO_ROOT/.opencode/plugin/superpowers.js" "$HOME/.config/opencode/superpowers/.opencode/plugin/"
|
||||
mkdir -p "$HOME/.config/opencode/superpowers/.opencode/plugins"
|
||||
cp "$REPO_ROOT/.opencode/plugins/superpowers.js" "$HOME/.config/opencode/superpowers/.opencode/plugins/"
|
||||
|
||||
# Register plugin via symlink
|
||||
mkdir -p "$HOME/.config/opencode/plugin"
|
||||
ln -sf "$HOME/.config/opencode/superpowers/.opencode/plugin/superpowers.js" \
|
||||
"$HOME/.config/opencode/plugin/superpowers.js"
|
||||
mkdir -p "$HOME/.config/opencode/plugins"
|
||||
ln -sf "$HOME/.config/opencode/superpowers/.opencode/plugins/superpowers.js" \
|
||||
"$HOME/.config/opencode/plugins/superpowers.js"
|
||||
|
||||
# Create test skills in different locations for testing
|
||||
|
||||
@@ -57,8 +57,8 @@ PROJECT_SKILL_MARKER_67890
|
||||
EOF
|
||||
|
||||
echo "Setup complete: $TEST_HOME"
|
||||
echo "Plugin installed to: $HOME/.config/opencode/superpowers/.opencode/plugin/superpowers.js"
|
||||
echo "Plugin registered at: $HOME/.config/opencode/plugin/superpowers.js"
|
||||
echo "Plugin installed to: $HOME/.config/opencode/superpowers/.opencode/plugins/superpowers.js"
|
||||
echo "Plugin registered at: $HOME/.config/opencode/plugins/superpowers.js"
|
||||
echo "Test project at: $TEST_HOME/test-project"
|
||||
|
||||
# Helper function for cleanup (call from tests or trap)
|
||||
|
||||
@@ -15,15 +15,15 @@ trap cleanup_test_env EXIT
|
||||
|
||||
# Test 1: Verify plugin file exists and is registered
|
||||
echo "Test 1: Checking plugin registration..."
|
||||
if [ -L "$HOME/.config/opencode/plugin/superpowers.js" ]; then
|
||||
if [ -L "$HOME/.config/opencode/plugins/superpowers.js" ]; then
|
||||
echo " [PASS] Plugin symlink exists"
|
||||
else
|
||||
echo " [FAIL] Plugin symlink not found at $HOME/.config/opencode/plugin/superpowers.js"
|
||||
echo " [FAIL] Plugin symlink not found at $HOME/.config/opencode/plugins/superpowers.js"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify symlink target exists
|
||||
if [ -f "$(readlink -f "$HOME/.config/opencode/plugin/superpowers.js")" ]; then
|
||||
if [ -f "$(readlink -f "$HOME/.config/opencode/plugins/superpowers.js")" ]; then
|
||||
echo " [PASS] Plugin symlink target exists"
|
||||
else
|
||||
echo " [FAIL] Plugin symlink target does not exist"
|
||||
@@ -60,7 +60,7 @@ fi
|
||||
|
||||
# Test 5: Verify plugin JavaScript syntax (basic check)
|
||||
echo "Test 5: Checking plugin JavaScript syntax..."
|
||||
plugin_file="$HOME/.config/opencode/superpowers/.opencode/plugin/superpowers.js"
|
||||
plugin_file="$HOME/.config/opencode/superpowers/.opencode/plugins/superpowers.js"
|
||||
if node --check "$plugin_file" 2>/dev/null; then
|
||||
echo " [PASS] Plugin JavaScript syntax is valid"
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user