opencodekit 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/template/.opencode/AGENTS.md +4 -1
- package/dist/template/.opencode/command/skill-create.md +3 -3
- package/dist/template/.opencode/command/skill-optimize.md +1 -1
- package/dist/template/.opencode/dcp.jsonc +63 -41
- package/dist/template/.opencode/opencode.json +5 -4
- package/dist/template/.opencode/package.json +2 -2
- package/dist/template/.opencode/pickle-thinker.jsonc +11 -0
- package/dist/template/.opencode/plugin/skill.ts +275 -0
- package/dist/template/.opencode/{skills → skill}/accessibility-audit/SKILL.md +5 -0
- package/dist/template/.opencode/{skills → skill}/brainstorming/SKILL.md +2 -2
- package/dist/template/.opencode/{skills → skill}/design-system-audit/SKILL.md +5 -0
- package/dist/template/.opencode/{skills → skill}/executing-plans/SKILL.md +13 -2
- package/dist/template/.opencode/{skills → skill}/frontend-aesthetics/SKILL.md +5 -0
- package/dist/template/.opencode/{skills → skill}/mockup-to-code/SKILL.md +5 -0
- package/dist/template/.opencode/{skills → skill}/requesting-code-review/SKILL.md +16 -6
- package/dist/template/.opencode/{skills → skill}/subagent-driven-development/SKILL.md +38 -17
- package/dist/template/.opencode/{skills → skill}/systematic-debugging/SKILL.md +28 -18
- package/dist/template/.opencode/{skills → skill}/testing-skills-with-subagents/SKILL.md +1 -1
- package/dist/template/.opencode/{skills → skill}/ui-ux-research/SKILL.md +5 -0
- package/dist/template/.opencode/{skills → skill}/visual-analysis/SKILL.md +5 -0
- package/dist/template/.opencode/{skills → skill}/writing-plans/SKILL.md +3 -3
- package/dist/template/.opencode/{skills → skill}/writing-skills/SKILL.md +101 -41
- package/package.json +1 -1
- package/dist/template/.opencode/plugin/superpowers.ts +0 -271
- package/dist/template/.opencode/superpowers/.claude/settings.local.json +0 -141
- package/dist/template/.opencode/superpowers/.claude-plugin/marketplace.json +0 -20
- package/dist/template/.opencode/superpowers/.claude-plugin/plugin.json +0 -13
- package/dist/template/.opencode/superpowers/.codex/INSTALL.md +0 -35
- package/dist/template/.opencode/superpowers/.codex/superpowers-bootstrap.md +0 -33
- package/dist/template/.opencode/superpowers/.codex/superpowers-codex +0 -267
- package/dist/template/.opencode/superpowers/.github/FUNDING.yml +0 -3
- package/dist/template/.opencode/superpowers/.opencode/INSTALL.md +0 -135
- package/dist/template/.opencode/superpowers/.opencode/plugin/superpowers.js +0 -215
- package/dist/template/.opencode/superpowers/LICENSE +0 -21
- package/dist/template/.opencode/superpowers/README.md +0 -165
- package/dist/template/.opencode/superpowers/RELEASE-NOTES.md +0 -493
- package/dist/template/.opencode/superpowers/agents/code-reviewer.md +0 -48
- package/dist/template/.opencode/superpowers/commands/brainstorm.md +0 -5
- package/dist/template/.opencode/superpowers/commands/execute-plan.md +0 -5
- package/dist/template/.opencode/superpowers/commands/write-plan.md +0 -5
- package/dist/template/.opencode/superpowers/docs/README.codex.md +0 -153
- package/dist/template/.opencode/superpowers/docs/README.opencode.md +0 -234
- package/dist/template/.opencode/superpowers/docs/plans/2025-11-22-opencode-support-design.md +0 -294
- package/dist/template/.opencode/superpowers/docs/plans/2025-11-22-opencode-support-implementation.md +0 -1095
- package/dist/template/.opencode/superpowers/hooks/hooks.json +0 -15
- package/dist/template/.opencode/superpowers/hooks/session-start.sh +0 -34
- package/dist/template/.opencode/superpowers/lib/skills-core.js +0 -208
- package/dist/template/.opencode/superpowers/tests/opencode/run-tests.sh +0 -165
- package/dist/template/.opencode/superpowers/tests/opencode/setup.sh +0 -73
- package/dist/template/.opencode/superpowers/tests/opencode/test-plugin-loading.sh +0 -81
- package/dist/template/.opencode/superpowers/tests/opencode/test-priority.sh +0 -198
- package/dist/template/.opencode/superpowers/tests/opencode/test-skills-core.sh +0 -440
- package/dist/template/.opencode/superpowers/tests/opencode/test-tools.sh +0 -104
- /package/dist/template/.opencode/{skills → skill}/condition-based-waiting/SKILL.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/condition-based-waiting/example.ts +0 -0
- /package/dist/template/.opencode/{skills → skill}/defense-in-depth/SKILL.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/dispatching-parallel-agents/SKILL.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/finishing-a-development-branch/SKILL.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/gemini-large-context/SKILL.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/receiving-code-review/SKILL.md +0 -0
- /package/dist/template/.opencode/{skills/requesting-code-review/code-reviewer.md → skill/requesting-code-review/review.md} +0 -0
- /package/dist/template/.opencode/{skills → skill}/root-cause-tracing/SKILL.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/root-cause-tracing/find-polluter.sh +0 -0
- /package/dist/template/.opencode/{skills → skill}/sharing-skills/SKILL.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/systematic-debugging/CREATION-LOG.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/systematic-debugging/test-academic.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/systematic-debugging/test-pressure-1.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/systematic-debugging/test-pressure-2.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/systematic-debugging/test-pressure-3.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/test-driven-development/SKILL.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/testing-anti-patterns/SKILL.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/testing-skills-with-subagents/examples/CLAUDE_MD_TESTING.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/using-git-worktrees/SKILL.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/using-superpowers/SKILL.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/verification-before-completion/SKILL.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/writing-skills/anthropic-best-practices.md +0 -0
- /package/dist/template/.opencode/{skills → skill}/writing-skills/graphviz-conventions.dot +0 -0
- /package/dist/template/.opencode/{skills → skill}/writing-skills/persuasion-principles.md +0 -0
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const os = require('os');
|
|
6
|
-
const skillsCore = require('../lib/skills-core');
|
|
7
|
-
|
|
8
|
-
// Paths
|
|
9
|
-
const homeDir = os.homedir();
|
|
10
|
-
const superpowersSkillsDir = path.join(homeDir, '.codex', 'superpowers', 'skills');
|
|
11
|
-
const personalSkillsDir = path.join(homeDir, '.codex', 'skills');
|
|
12
|
-
const bootstrapFile = path.join(homeDir, '.codex', 'superpowers', '.codex', 'superpowers-bootstrap.md');
|
|
13
|
-
const superpowersRepoDir = path.join(homeDir, '.codex', 'superpowers');
|
|
14
|
-
|
|
15
|
-
// Utility functions
|
|
16
|
-
function printSkill(skillPath, sourceType) {
|
|
17
|
-
const skillFile = path.join(skillPath, 'SKILL.md');
|
|
18
|
-
const relPath = sourceType === 'personal'
|
|
19
|
-
? path.relative(personalSkillsDir, skillPath)
|
|
20
|
-
: path.relative(superpowersSkillsDir, skillPath);
|
|
21
|
-
|
|
22
|
-
// Print skill name with namespace
|
|
23
|
-
if (sourceType === 'personal') {
|
|
24
|
-
console.log(relPath.replace(/\\/g, '/')); // Personal skills are not namespaced
|
|
25
|
-
} else {
|
|
26
|
-
console.log(`superpowers:${relPath.replace(/\\/g, '/')}`); // Superpowers skills get superpowers namespace
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Extract and print metadata
|
|
30
|
-
const { name, description } = skillsCore.extractFrontmatter(skillFile);
|
|
31
|
-
|
|
32
|
-
if (description) console.log(` ${description}`);
|
|
33
|
-
console.log('');
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Commands
|
|
37
|
-
function runFindSkills() {
|
|
38
|
-
console.log('Available skills:');
|
|
39
|
-
console.log('==================');
|
|
40
|
-
console.log('');
|
|
41
|
-
|
|
42
|
-
const foundSkills = new Set();
|
|
43
|
-
|
|
44
|
-
// Find personal skills first (these take precedence)
|
|
45
|
-
const personalSkills = skillsCore.findSkillsInDir(personalSkillsDir, 'personal', 2);
|
|
46
|
-
for (const skill of personalSkills) {
|
|
47
|
-
const relPath = path.relative(personalSkillsDir, skill.path);
|
|
48
|
-
foundSkills.add(relPath);
|
|
49
|
-
printSkill(skill.path, 'personal');
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Find superpowers skills (only if not already found in personal)
|
|
53
|
-
const superpowersSkills = skillsCore.findSkillsInDir(superpowersSkillsDir, 'superpowers', 1);
|
|
54
|
-
for (const skill of superpowersSkills) {
|
|
55
|
-
const relPath = path.relative(superpowersSkillsDir, skill.path);
|
|
56
|
-
if (!foundSkills.has(relPath)) {
|
|
57
|
-
printSkill(skill.path, 'superpowers');
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
console.log('Usage:');
|
|
62
|
-
console.log(' superpowers-codex use-skill <skill-name> # Load a specific skill');
|
|
63
|
-
console.log('');
|
|
64
|
-
console.log('Skill naming:');
|
|
65
|
-
console.log(' Superpowers skills: superpowers:skill-name (from ~/.codex/superpowers/skills/)');
|
|
66
|
-
console.log(' Personal skills: skill-name (from ~/.codex/skills/)');
|
|
67
|
-
console.log(' Personal skills override superpowers skills when names match.');
|
|
68
|
-
console.log('');
|
|
69
|
-
console.log('Note: All skills are disclosed at session start via bootstrap.');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function runBootstrap() {
|
|
73
|
-
console.log('# Superpowers Bootstrap for Codex');
|
|
74
|
-
console.log('# ================================');
|
|
75
|
-
console.log('');
|
|
76
|
-
|
|
77
|
-
// Check for updates (with timeout protection)
|
|
78
|
-
if (skillsCore.checkForUpdates(superpowersRepoDir)) {
|
|
79
|
-
console.log('## Update Available');
|
|
80
|
-
console.log('');
|
|
81
|
-
console.log('⚠️ Your superpowers installation is behind the latest version.');
|
|
82
|
-
console.log('To update, run: `cd ~/.codex/superpowers && git pull`');
|
|
83
|
-
console.log('');
|
|
84
|
-
console.log('---');
|
|
85
|
-
console.log('');
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Show the bootstrap instructions
|
|
89
|
-
if (fs.existsSync(bootstrapFile)) {
|
|
90
|
-
console.log('## Bootstrap Instructions:');
|
|
91
|
-
console.log('');
|
|
92
|
-
try {
|
|
93
|
-
const content = fs.readFileSync(bootstrapFile, 'utf8');
|
|
94
|
-
console.log(content);
|
|
95
|
-
} catch (error) {
|
|
96
|
-
console.log(`Error reading bootstrap file: ${error.message}`);
|
|
97
|
-
}
|
|
98
|
-
console.log('');
|
|
99
|
-
console.log('---');
|
|
100
|
-
console.log('');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Run find-skills to show available skills
|
|
104
|
-
console.log('## Available Skills:');
|
|
105
|
-
console.log('');
|
|
106
|
-
runFindSkills();
|
|
107
|
-
|
|
108
|
-
console.log('');
|
|
109
|
-
console.log('---');
|
|
110
|
-
console.log('');
|
|
111
|
-
|
|
112
|
-
// Load the using-superpowers skill automatically
|
|
113
|
-
console.log('## Auto-loading superpowers:using-superpowers skill:');
|
|
114
|
-
console.log('');
|
|
115
|
-
runUseSkill('superpowers:using-superpowers');
|
|
116
|
-
|
|
117
|
-
console.log('');
|
|
118
|
-
console.log('---');
|
|
119
|
-
console.log('');
|
|
120
|
-
console.log('# Bootstrap Complete!');
|
|
121
|
-
console.log('# You now have access to all superpowers skills.');
|
|
122
|
-
console.log('# Use "superpowers-codex use-skill <skill>" to load and apply skills.');
|
|
123
|
-
console.log('# Remember: If a skill applies to your task, you MUST use it!');
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function runUseSkill(skillName) {
|
|
127
|
-
if (!skillName) {
|
|
128
|
-
console.log('Usage: superpowers-codex use-skill <skill-name>');
|
|
129
|
-
console.log('Examples:');
|
|
130
|
-
console.log(' superpowers-codex use-skill superpowers:brainstorming # Load superpowers skill');
|
|
131
|
-
console.log(' superpowers-codex use-skill brainstorming # Load personal skill (or superpowers if not found)');
|
|
132
|
-
console.log(' superpowers-codex use-skill my-custom-skill # Load personal skill');
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Handle namespaced skill names
|
|
137
|
-
let actualSkillPath;
|
|
138
|
-
let forceSuperpowers = false;
|
|
139
|
-
|
|
140
|
-
if (skillName.startsWith('superpowers:')) {
|
|
141
|
-
// Remove the superpowers: namespace prefix
|
|
142
|
-
actualSkillPath = skillName.substring('superpowers:'.length);
|
|
143
|
-
forceSuperpowers = true;
|
|
144
|
-
} else {
|
|
145
|
-
actualSkillPath = skillName;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Remove "skills/" prefix if present
|
|
149
|
-
if (actualSkillPath.startsWith('skills/')) {
|
|
150
|
-
actualSkillPath = actualSkillPath.substring('skills/'.length);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Function to find skill file
|
|
154
|
-
function findSkillFile(searchPath) {
|
|
155
|
-
// Check for exact match with SKILL.md
|
|
156
|
-
const skillMdPath = path.join(searchPath, 'SKILL.md');
|
|
157
|
-
if (fs.existsSync(skillMdPath)) {
|
|
158
|
-
return skillMdPath;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// Check for direct SKILL.md file
|
|
162
|
-
if (searchPath.endsWith('SKILL.md') && fs.existsSync(searchPath)) {
|
|
163
|
-
return searchPath;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return null;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
let skillFile = null;
|
|
170
|
-
|
|
171
|
-
// If superpowers: namespace was used, only check superpowers skills
|
|
172
|
-
if (forceSuperpowers) {
|
|
173
|
-
if (fs.existsSync(superpowersSkillsDir)) {
|
|
174
|
-
const superpowersPath = path.join(superpowersSkillsDir, actualSkillPath);
|
|
175
|
-
skillFile = findSkillFile(superpowersPath);
|
|
176
|
-
}
|
|
177
|
-
} else {
|
|
178
|
-
// First check personal skills directory (takes precedence)
|
|
179
|
-
if (fs.existsSync(personalSkillsDir)) {
|
|
180
|
-
const personalPath = path.join(personalSkillsDir, actualSkillPath);
|
|
181
|
-
skillFile = findSkillFile(personalPath);
|
|
182
|
-
if (skillFile) {
|
|
183
|
-
console.log(`# Loading personal skill: ${actualSkillPath}`);
|
|
184
|
-
console.log(`# Source: ${skillFile}`);
|
|
185
|
-
console.log('');
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// If not found in personal, check superpowers skills
|
|
190
|
-
if (!skillFile && fs.existsSync(superpowersSkillsDir)) {
|
|
191
|
-
const superpowersPath = path.join(superpowersSkillsDir, actualSkillPath);
|
|
192
|
-
skillFile = findSkillFile(superpowersPath);
|
|
193
|
-
if (skillFile) {
|
|
194
|
-
console.log(`# Loading superpowers skill: superpowers:${actualSkillPath}`);
|
|
195
|
-
console.log(`# Source: ${skillFile}`);
|
|
196
|
-
console.log('');
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// If still not found, error
|
|
202
|
-
if (!skillFile) {
|
|
203
|
-
console.log(`Error: Skill not found: ${actualSkillPath}`);
|
|
204
|
-
console.log('');
|
|
205
|
-
console.log('Available skills:');
|
|
206
|
-
runFindSkills();
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Extract frontmatter and content using shared core functions
|
|
211
|
-
let content, frontmatter;
|
|
212
|
-
try {
|
|
213
|
-
const fullContent = fs.readFileSync(skillFile, 'utf8');
|
|
214
|
-
const { name, description } = skillsCore.extractFrontmatter(skillFile);
|
|
215
|
-
content = skillsCore.stripFrontmatter(fullContent);
|
|
216
|
-
frontmatter = { name, description };
|
|
217
|
-
} catch (error) {
|
|
218
|
-
console.log(`Error reading skill file: ${error.message}`);
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Display skill header with clean info
|
|
223
|
-
const displayName = forceSuperpowers ? `superpowers:${actualSkillPath}` :
|
|
224
|
-
(skillFile.includes(personalSkillsDir) ? actualSkillPath : `superpowers:${actualSkillPath}`);
|
|
225
|
-
|
|
226
|
-
const skillDirectory = path.dirname(skillFile);
|
|
227
|
-
|
|
228
|
-
console.log(`# ${frontmatter.name || displayName}`);
|
|
229
|
-
if (frontmatter.description) {
|
|
230
|
-
console.log(`# ${frontmatter.description}`);
|
|
231
|
-
}
|
|
232
|
-
console.log(`# Supporting tools and docs are in ${skillDirectory}`);
|
|
233
|
-
console.log('# ============================================');
|
|
234
|
-
console.log('');
|
|
235
|
-
|
|
236
|
-
// Display the skill content (without frontmatter)
|
|
237
|
-
console.log(content);
|
|
238
|
-
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Main CLI
|
|
242
|
-
const command = process.argv[2];
|
|
243
|
-
const arg = process.argv[3];
|
|
244
|
-
|
|
245
|
-
switch (command) {
|
|
246
|
-
case 'bootstrap':
|
|
247
|
-
runBootstrap();
|
|
248
|
-
break;
|
|
249
|
-
case 'use-skill':
|
|
250
|
-
runUseSkill(arg);
|
|
251
|
-
break;
|
|
252
|
-
case 'find-skills':
|
|
253
|
-
runFindSkills();
|
|
254
|
-
break;
|
|
255
|
-
default:
|
|
256
|
-
console.log('Superpowers for Codex');
|
|
257
|
-
console.log('Usage:');
|
|
258
|
-
console.log(' superpowers-codex bootstrap # Run complete bootstrap with all skills');
|
|
259
|
-
console.log(' superpowers-codex use-skill <skill-name> # Load a specific skill');
|
|
260
|
-
console.log(' superpowers-codex find-skills # List all available skills');
|
|
261
|
-
console.log('');
|
|
262
|
-
console.log('Examples:');
|
|
263
|
-
console.log(' superpowers-codex bootstrap');
|
|
264
|
-
console.log(' superpowers-codex use-skill superpowers:brainstorming');
|
|
265
|
-
console.log(' superpowers-codex use-skill my-custom-skill');
|
|
266
|
-
break;
|
|
267
|
-
}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
# Installing Superpowers for OpenCode
|
|
2
|
-
|
|
3
|
-
## Prerequisites
|
|
4
|
-
|
|
5
|
-
- [OpenCode.ai](https://opencode.ai) installed
|
|
6
|
-
- Node.js installed
|
|
7
|
-
- Git installed
|
|
8
|
-
|
|
9
|
-
## Installation Steps
|
|
10
|
-
|
|
11
|
-
### 1. Install Superpowers
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
mkdir -p ~/.config/opencode/superpowers
|
|
15
|
-
git clone https://github.com/obra/superpowers.git ~/.config/opencode/superpowers
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
### 2. Register the Plugin
|
|
19
|
-
|
|
20
|
-
Create a symlink so OpenCode discovers the plugin:
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
mkdir -p ~/.config/opencode/plugin
|
|
24
|
-
ln -sf ~/.config/opencode/superpowers/.opencode/plugin/superpowers.js ~/.config/opencode/plugin/superpowers.js
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
### 3. Restart OpenCode
|
|
28
|
-
|
|
29
|
-
Restart OpenCode. The plugin will automatically inject superpowers context via the chat.message hook.
|
|
30
|
-
|
|
31
|
-
You should see superpowers is active when you ask "do you have superpowers?"
|
|
32
|
-
|
|
33
|
-
## Usage
|
|
34
|
-
|
|
35
|
-
### Finding Skills
|
|
36
|
-
|
|
37
|
-
Use the `find_skills` tool to list all available skills:
|
|
38
|
-
|
|
39
|
-
```
|
|
40
|
-
use find_skills tool
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### Loading a Skill
|
|
44
|
-
|
|
45
|
-
Use the `use_skill` tool to load a specific skill:
|
|
46
|
-
|
|
47
|
-
```
|
|
48
|
-
use use_skill tool with skill_name: "superpowers:brainstorming"
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### Personal Skills
|
|
52
|
-
|
|
53
|
-
Create your own skills in `~/.config/opencode/skills/`:
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
mkdir -p ~/.config/opencode/skills/my-skill
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
Create `~/.config/opencode/skills/my-skill/SKILL.md`:
|
|
60
|
-
|
|
61
|
-
```markdown
|
|
62
|
-
---
|
|
63
|
-
name: my-skill
|
|
64
|
-
description: Use when [condition] - [what it does]
|
|
65
|
-
---
|
|
66
|
-
|
|
67
|
-
# My Skill
|
|
68
|
-
|
|
69
|
-
[Your skill content here]
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
Personal skills override superpowers skills with the same name.
|
|
73
|
-
|
|
74
|
-
### Project Skills
|
|
75
|
-
|
|
76
|
-
Create project-specific skills in your OpenCode project:
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
# In your OpenCode project
|
|
80
|
-
mkdir -p .opencode/skills/my-project-skill
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
Create `.opencode/skills/my-project-skill/SKILL.md`:
|
|
84
|
-
|
|
85
|
-
```markdown
|
|
86
|
-
---
|
|
87
|
-
name: my-project-skill
|
|
88
|
-
description: Use when [condition] - [what it does]
|
|
89
|
-
---
|
|
90
|
-
|
|
91
|
-
# My Project Skill
|
|
92
|
-
|
|
93
|
-
[Your skill content here]
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
**Skill Priority:** Project skills override personal skills, which override superpowers skills.
|
|
97
|
-
|
|
98
|
-
**Skill Naming:**
|
|
99
|
-
- `project:skill-name` - Force project skill lookup
|
|
100
|
-
- `skill-name` - Searches project → personal → superpowers
|
|
101
|
-
- `superpowers:skill-name` - Force superpowers skill lookup
|
|
102
|
-
|
|
103
|
-
## Updating
|
|
104
|
-
|
|
105
|
-
```bash
|
|
106
|
-
cd ~/.config/opencode/superpowers
|
|
107
|
-
git pull
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
## Troubleshooting
|
|
111
|
-
|
|
112
|
-
### Plugin not loading
|
|
113
|
-
|
|
114
|
-
1. Check plugin file exists: `ls ~/.config/opencode/superpowers/.opencode/plugin/superpowers.js`
|
|
115
|
-
2. Check OpenCode logs for errors
|
|
116
|
-
3. Verify Node.js is installed: `node --version`
|
|
117
|
-
|
|
118
|
-
### Skills not found
|
|
119
|
-
|
|
120
|
-
1. Verify skills directory exists: `ls ~/.config/opencode/superpowers/skills`
|
|
121
|
-
2. Use `find_skills` tool to see what's discovered
|
|
122
|
-
3. Check file structure: each skill should have a `SKILL.md` file
|
|
123
|
-
|
|
124
|
-
### Tool mapping issues
|
|
125
|
-
|
|
126
|
-
When a skill references a Claude Code tool you don't have:
|
|
127
|
-
- `TodoWrite` → use `update_plan`
|
|
128
|
-
- `Task` with subagents → use `@mention` syntax to invoke OpenCode subagents
|
|
129
|
-
- `Skill` → use `use_skill` tool
|
|
130
|
-
- File operations → use your native tools
|
|
131
|
-
|
|
132
|
-
## Getting Help
|
|
133
|
-
|
|
134
|
-
- Report issues: https://github.com/obra/superpowers/issues
|
|
135
|
-
- Documentation: https://github.com/obra/superpowers
|
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Superpowers plugin for OpenCode.ai
|
|
3
|
-
*
|
|
4
|
-
* Provides custom tools for loading and discovering skills,
|
|
5
|
-
* with prompt generation for agent configuration.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import path from 'path';
|
|
9
|
-
import fs from 'fs';
|
|
10
|
-
import os from 'os';
|
|
11
|
-
import { fileURLToPath } from 'url';
|
|
12
|
-
import { tool } from '@opencode-ai/plugin/tool';
|
|
13
|
-
import * as skillsCore from '../../lib/skills-core.js';
|
|
14
|
-
|
|
15
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
16
|
-
|
|
17
|
-
export const SuperpowersPlugin = async ({ client, directory }) => {
|
|
18
|
-
const homeDir = os.homedir();
|
|
19
|
-
const projectSkillsDir = path.join(directory, '.opencode/skills');
|
|
20
|
-
// Derive superpowers skills dir from plugin location (works for both symlinked and local installs)
|
|
21
|
-
const superpowersSkillsDir = path.resolve(__dirname, '../../skills');
|
|
22
|
-
const personalSkillsDir = path.join(homeDir, '.config/opencode/skills');
|
|
23
|
-
|
|
24
|
-
// Helper to generate bootstrap content
|
|
25
|
-
const getBootstrapContent = (compact = false) => {
|
|
26
|
-
const usingSuperpowersPath = skillsCore.resolveSkillPath('using-superpowers', superpowersSkillsDir, personalSkillsDir);
|
|
27
|
-
if (!usingSuperpowersPath) return null;
|
|
28
|
-
|
|
29
|
-
const fullContent = fs.readFileSync(usingSuperpowersPath.skillFile, 'utf8');
|
|
30
|
-
const content = skillsCore.stripFrontmatter(fullContent);
|
|
31
|
-
|
|
32
|
-
const toolMapping = compact
|
|
33
|
-
? `**Tool Mapping:** TodoWrite->update_plan, Task->@mention, Skill->use_skill
|
|
34
|
-
|
|
35
|
-
**Skills naming (priority order):** project: > personal > superpowers:`
|
|
36
|
-
: `**Tool Mapping for OpenCode:**
|
|
37
|
-
When skills reference tools you don't have, substitute OpenCode equivalents:
|
|
38
|
-
- \`TodoWrite\` → \`update_plan\`
|
|
39
|
-
- \`Task\` tool with subagents → Use OpenCode's subagent system (@mention)
|
|
40
|
-
- \`Skill\` tool → \`use_skill\` custom tool
|
|
41
|
-
- \`Read\`, \`Write\`, \`Edit\`, \`Bash\` → Your native tools
|
|
42
|
-
|
|
43
|
-
**Skills naming (priority order):**
|
|
44
|
-
- Project skills: \`project:skill-name\` (in .opencode/skills/)
|
|
45
|
-
- Personal skills: \`skill-name\` (in ~/.config/opencode/skills/)
|
|
46
|
-
- Superpowers skills: \`superpowers:skill-name\`
|
|
47
|
-
- Project skills override personal, which override superpowers when names match`;
|
|
48
|
-
|
|
49
|
-
return `<EXTREMELY_IMPORTANT>
|
|
50
|
-
You have superpowers.
|
|
51
|
-
|
|
52
|
-
**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.**
|
|
53
|
-
|
|
54
|
-
${content}
|
|
55
|
-
|
|
56
|
-
${toolMapping}
|
|
57
|
-
</EXTREMELY_IMPORTANT>`;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
// Helper to inject bootstrap via session.prompt
|
|
61
|
-
const injectBootstrap = async (sessionID, compact = false) => {
|
|
62
|
-
const bootstrapContent = getBootstrapContent(compact);
|
|
63
|
-
if (!bootstrapContent) return false;
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
await client.session.prompt({
|
|
67
|
-
path: { id: sessionID },
|
|
68
|
-
body: {
|
|
69
|
-
noReply: true,
|
|
70
|
-
parts: [{ type: "text", text: bootstrapContent }]
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
return true;
|
|
74
|
-
} catch (err) {
|
|
75
|
-
return false;
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
return {
|
|
80
|
-
tool: {
|
|
81
|
-
use_skill: tool({
|
|
82
|
-
description: 'Load and read a specific skill to guide your work. Skills contain proven workflows, mandatory processes, and expert techniques.',
|
|
83
|
-
args: {
|
|
84
|
-
skill_name: tool.schema.string().describe('Name of the skill to load (e.g., "superpowers:brainstorming", "my-custom-skill", or "project:my-skill")')
|
|
85
|
-
},
|
|
86
|
-
execute: async (args, context) => {
|
|
87
|
-
const { skill_name } = args;
|
|
88
|
-
|
|
89
|
-
// Resolve with priority: project > personal > superpowers
|
|
90
|
-
// Check for project: prefix first
|
|
91
|
-
const forceProject = skill_name.startsWith('project:');
|
|
92
|
-
const actualSkillName = forceProject ? skill_name.replace(/^project:/, '') : skill_name;
|
|
93
|
-
|
|
94
|
-
let resolved = null;
|
|
95
|
-
|
|
96
|
-
// Try project skills first (if project: prefix or no prefix)
|
|
97
|
-
if (forceProject || !skill_name.startsWith('superpowers:')) {
|
|
98
|
-
const projectPath = path.join(projectSkillsDir, actualSkillName);
|
|
99
|
-
const projectSkillFile = path.join(projectPath, 'SKILL.md');
|
|
100
|
-
if (fs.existsSync(projectSkillFile)) {
|
|
101
|
-
resolved = {
|
|
102
|
-
skillFile: projectSkillFile,
|
|
103
|
-
sourceType: 'project',
|
|
104
|
-
skillPath: actualSkillName
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Fall back to personal/superpowers resolution
|
|
110
|
-
if (!resolved && !forceProject) {
|
|
111
|
-
resolved = skillsCore.resolveSkillPath(skill_name, superpowersSkillsDir, personalSkillsDir);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (!resolved) {
|
|
115
|
-
return `Error: Skill "${skill_name}" not found.\n\nRun find_skills to see available skills.`;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const fullContent = fs.readFileSync(resolved.skillFile, 'utf8');
|
|
119
|
-
const { name, description } = skillsCore.extractFrontmatter(resolved.skillFile);
|
|
120
|
-
const content = skillsCore.stripFrontmatter(fullContent);
|
|
121
|
-
const skillDirectory = path.dirname(resolved.skillFile);
|
|
122
|
-
|
|
123
|
-
const skillHeader = `# ${name || skill_name}
|
|
124
|
-
# ${description || ''}
|
|
125
|
-
# Supporting tools and docs are in ${skillDirectory}
|
|
126
|
-
# ============================================`;
|
|
127
|
-
|
|
128
|
-
// Insert as user message with noReply for persistence across compaction
|
|
129
|
-
try {
|
|
130
|
-
await client.session.prompt({
|
|
131
|
-
path: { id: context.sessionID },
|
|
132
|
-
body: {
|
|
133
|
-
noReply: true,
|
|
134
|
-
parts: [
|
|
135
|
-
{ type: "text", text: `Loading skill: ${name || skill_name}` },
|
|
136
|
-
{ type: "text", text: `${skillHeader}\n\n${content}` }
|
|
137
|
-
]
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
} catch (err) {
|
|
141
|
-
// Fallback: return content directly if message insertion fails
|
|
142
|
-
return `${skillHeader}\n\n${content}`;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return `Launching skill: ${name || skill_name}`;
|
|
146
|
-
}
|
|
147
|
-
}),
|
|
148
|
-
find_skills: tool({
|
|
149
|
-
description: 'List all available skills in the project, personal, and superpowers skill libraries.',
|
|
150
|
-
args: {},
|
|
151
|
-
execute: async (args, context) => {
|
|
152
|
-
const projectSkills = skillsCore.findSkillsInDir(projectSkillsDir, 'project', 3);
|
|
153
|
-
const personalSkills = skillsCore.findSkillsInDir(personalSkillsDir, 'personal', 3);
|
|
154
|
-
const superpowersSkills = skillsCore.findSkillsInDir(superpowersSkillsDir, 'superpowers', 3);
|
|
155
|
-
|
|
156
|
-
// Priority: project > personal > superpowers
|
|
157
|
-
const allSkills = [...projectSkills, ...personalSkills, ...superpowersSkills];
|
|
158
|
-
|
|
159
|
-
if (allSkills.length === 0) {
|
|
160
|
-
return 'No skills found. Install superpowers skills to ~/.config/opencode/superpowers/skills/ or add project skills to .opencode/skills/';
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
let output = 'Available skills:\n\n';
|
|
164
|
-
|
|
165
|
-
for (const skill of allSkills) {
|
|
166
|
-
let namespace;
|
|
167
|
-
switch (skill.sourceType) {
|
|
168
|
-
case 'project':
|
|
169
|
-
namespace = 'project:';
|
|
170
|
-
break;
|
|
171
|
-
case 'personal':
|
|
172
|
-
namespace = '';
|
|
173
|
-
break;
|
|
174
|
-
default:
|
|
175
|
-
namespace = 'superpowers:';
|
|
176
|
-
}
|
|
177
|
-
const skillName = skill.name || path.basename(skill.path);
|
|
178
|
-
|
|
179
|
-
output += `${namespace}${skillName}\n`;
|
|
180
|
-
if (skill.description) {
|
|
181
|
-
output += ` ${skill.description}\n`;
|
|
182
|
-
}
|
|
183
|
-
output += ` Directory: ${skill.path}\n\n`;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return output;
|
|
187
|
-
}
|
|
188
|
-
})
|
|
189
|
-
},
|
|
190
|
-
event: async ({ event }) => {
|
|
191
|
-
// Extract sessionID from various event structures
|
|
192
|
-
const getSessionID = () => {
|
|
193
|
-
return event.properties?.info?.id ||
|
|
194
|
-
event.properties?.sessionID ||
|
|
195
|
-
event.session?.id;
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
// Inject bootstrap at session creation (before first user message)
|
|
199
|
-
if (event.type === 'session.created') {
|
|
200
|
-
const sessionID = getSessionID();
|
|
201
|
-
if (sessionID) {
|
|
202
|
-
await injectBootstrap(sessionID, false);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// Re-inject bootstrap after context compaction (compact version to save tokens)
|
|
207
|
-
if (event.type === 'session.compacted') {
|
|
208
|
-
const sessionID = getSessionID();
|
|
209
|
-
if (sessionID) {
|
|
210
|
-
await injectBootstrap(sessionID, true);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
};
|
|
215
|
-
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 Jesse Vincent
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|