Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .trae/INSTALL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Installing Superpowers for Trae

Quick setup to enable superpowers skills in Trae.

## Installation

1. **Clone superpowers repository**:
```bash
mkdir -p ~/.trae/superpowers
cd ~/.trae/superpowers
git clone https://github.com/obra/superpowers.git .
```

2. **Create personal skills directory**:
```bash
mkdir -p ~/.trae/skills
```

3. **Update ~/.trae/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: `~/.trae/superpowers/.trae/superpowers-trae bootstrap` and follow the instructions it returns.
</EXTREMELY_IMPORTANT>
```

## Verification

Test the installation:
```bash
~/.trae/superpowers/.trae/superpowers-trae bootstrap
```

You should see skill listings and bootstrap instructions. The system is now ready for use.
33 changes: 33 additions & 0 deletions .trae/superpowers-bootstrap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Superpowers Bootstrap for Trae

<EXTREMELY_IMPORTANT>
You have superpowers.

**Tool for running skills:**
- `~/.trae/superpowers/.trae/superpowers-trae use-skill <skill-name>`

**Tool Mapping for Trae:**
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 Trae yet and you'll do the work the subagent would do
- `Skill` tool → `~/.trae/superpowers/.trae/superpowers-trae use-skill` command (already available)
- `Read`, `Write`, `Edit`, `Bash` → Use your native tools with similar functions

**Skills naming:**
- Superpowers skills: `superpowers:skill-name` (from ~/.trae/superpowers/skills/)
- Personal skills: `skill-name` (from ~/.trae/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 `~/.trae/superpowers/.trae/superpowers-trae 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: ~/.trae/superpowers/skills/
- Personal skills: ~/.trae/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>
267 changes: 267 additions & 0 deletions .trae/superpowers-trae
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
#!/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, '.trae', 'superpowers', 'skills');
const personalSkillsDir = path.join(homeDir, '.trae', 'skills');
const bootstrapFile = path.join(homeDir, '.trae', 'superpowers', '.trae', 'superpowers-bootstrap.md');
const superpowersRepoDir = path.join(homeDir, '.trae', '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-trae use-skill <skill-name> # Load a specific skill');
console.log('');
console.log('Skill naming:');
console.log(' Superpowers skills: superpowers:skill-name (from ~/.trae/superpowers/skills/)');
console.log(' Personal skills: skill-name (from ~/.trae/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 Trae');
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 ~/.trae/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-trae 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-trae use-skill <skill-name>');
console.log('Examples:');
console.log(' superpowers-trae use-skill superpowers:brainstorming # Load superpowers skill');
console.log(' superpowers-trae use-skill brainstorming # Load personal skill (or superpowers if not found)');
console.log(' superpowers-trae 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 Trae');
console.log('Usage:');
console.log(' superpowers-trae bootstrap # Run complete bootstrap with all skills');
console.log(' superpowers-trae use-skill <skill-name> # Load a specific skill');
console.log(' superpowers-trae find-skills # List all available skills');
console.log('');
console.log('Examples:');
console.log(' superpowers-trae bootstrap');
console.log(' superpowers-trae use-skill superpowers:brainstorming');
console.log(' superpowers-trae use-skill my-custom-skill');
break;
}
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ Fetch and follow instructions from https://raw.githubusercontent.com/obra/superp

**Detailed docs:** [docs/README.opencode.md](docs/README.opencode.md)

### Trae

Tell Trae:

```
Fetch and follow instructions from https://raw.githubusercontent.com/obra/superpowers/refs/heads/main/.trae/INSTALL.md
```

**Detailed docs:** [docs/README.trae.md](docs/README.trae.md)

## The Basic Workflow

1. **brainstorming** - Activates before writing code. Refines rough ideas through questions, explores alternatives, presents design in sections for validation. Saves design document.
Expand Down
Loading