mirror of
https://github.com/obra/superpowers.git
synced 2026-04-21 00:49:06 +08:00
Compare commits
5 Commits
claude/rev
...
v3.5.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a01a0dcc1 | ||
|
|
8c7826c34d | ||
|
|
4ae8fc8713 | ||
|
|
94089bdce5 | ||
|
|
9297fd24d5 |
@@ -9,7 +9,7 @@
|
||||
{
|
||||
"name": "superpowers",
|
||||
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
|
||||
"version": "3.4.0",
|
||||
"version": "3.5.1",
|
||||
"source": "./",
|
||||
"author": {
|
||||
"name": "Jesse Vincent",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "superpowers",
|
||||
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
|
||||
"version": "3.4.1",
|
||||
"version": "3.5.1",
|
||||
"author": {
|
||||
"name": "Jesse Vincent",
|
||||
"email": "jesse@fsck.com"
|
||||
|
||||
@@ -21,6 +21,61 @@ export const SuperpowersPlugin = async ({ client, directory }) => {
|
||||
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 }]
|
||||
}
|
||||
});
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
tool: {
|
||||
use_skill: tool({
|
||||
@@ -132,72 +187,27 @@ export const SuperpowersPlugin = async ({ client, directory }) => {
|
||||
}
|
||||
})
|
||||
},
|
||||
"chat.message": async (input, output) => {
|
||||
// Only inject on first message of session (or every message if needed)
|
||||
if (!output.message.system || output.message.system.length === 0) {
|
||||
const usingSuperpowersPath = skillsCore.resolveSkillPath('using-superpowers', superpowersSkillsDir, personalSkillsDir);
|
||||
event: async ({ event }) => {
|
||||
// Extract sessionID from various event structures
|
||||
const getSessionID = () => {
|
||||
return event.properties?.info?.id ||
|
||||
event.properties?.sessionID ||
|
||||
event.session?.id;
|
||||
};
|
||||
|
||||
if (usingSuperpowersPath) {
|
||||
const fullContent = fs.readFileSync(usingSuperpowersPath.skillFile, 'utf8');
|
||||
const usingSuperpowersContent = skillsCore.stripFrontmatter(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 → \`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`;
|
||||
|
||||
output.message.system = `<EXTREMELY_IMPORTANT>
|
||||
You have superpowers.
|
||||
|
||||
${usingSuperpowersContent}
|
||||
|
||||
${toolMapping}
|
||||
</EXTREMELY_IMPORTANT>`;
|
||||
// Inject bootstrap at session creation (before first user message)
|
||||
if (event.type === 'session.created') {
|
||||
const sessionID = getSessionID();
|
||||
if (sessionID) {
|
||||
await injectBootstrap(sessionID, false);
|
||||
}
|
||||
}
|
||||
},
|
||||
event: async ({ event }) => {
|
||||
// Re-inject bootstrap after context compaction to maintain superpowers
|
||||
|
||||
// Re-inject bootstrap after context compaction (compact version to save tokens)
|
||||
if (event.type === 'session.compacted') {
|
||||
const usingSuperpowersPath = skillsCore.resolveSkillPath('using-superpowers', superpowersSkillsDir, personalSkillsDir);
|
||||
|
||||
if (usingSuperpowersPath) {
|
||||
const fullContent = fs.readFileSync(usingSuperpowersPath.skillFile, 'utf8');
|
||||
const content = skillsCore.stripFrontmatter(fullContent);
|
||||
|
||||
const toolMapping = `**Tool Mapping:** TodoWrite->update_plan, Task->@mention, Skill->use_skill
|
||||
|
||||
**Skills naming (priority order):** project: > personal > superpowers:`;
|
||||
|
||||
try {
|
||||
await client.session.prompt({
|
||||
path: { id: event.properties.sessionID },
|
||||
body: {
|
||||
noReply: true,
|
||||
parts: [{
|
||||
type: "text",
|
||||
text: `<EXTREMELY_IMPORTANT>
|
||||
You have superpowers.
|
||||
|
||||
${content}
|
||||
|
||||
${toolMapping}
|
||||
</EXTREMELY_IMPORTANT>`
|
||||
}]
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
// Silent failure - bootstrap will be missing but session continues
|
||||
console.error('Failed to re-inject superpowers after compaction:', err.message);
|
||||
}
|
||||
const sessionID = getSessionID();
|
||||
if (sessionID) {
|
||||
await injectBootstrap(sessionID, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
# Superpowers Release Notes
|
||||
|
||||
## [Unreleased]
|
||||
## v3.5.1 (2025-11-24)
|
||||
|
||||
### Changed
|
||||
|
||||
- **OpenCode Bootstrap Refactor**: Switched from `chat.message` hook to `session.created` event for bootstrap injection
|
||||
- Bootstrap now injects at session creation via `session.prompt()` with `noReply: true`
|
||||
- Explicitly tells the model that using-superpowers is already loaded to prevent redundant skill loading
|
||||
- Consolidated bootstrap content generation into shared `getBootstrapContent()` helper
|
||||
- Cleaner single-implementation approach (removed fallback pattern)
|
||||
|
||||
---
|
||||
|
||||
## v3.5.0 (2025-11-23)
|
||||
|
||||
### Added
|
||||
|
||||
@@ -12,7 +24,8 @@
|
||||
- Three-tier skill priority: project > personal > superpowers
|
||||
- Project-local skills support (`.opencode/skills/`)
|
||||
- Shared core module (`lib/skills-core.js`) for code reuse with Codex
|
||||
- Installation guide in `.opencode/INSTALL.md`
|
||||
- Automated test suite with proper isolation (`tests/opencode/`)
|
||||
- Platform-specific documentation (`docs/README.opencode.md`, `docs/README.codex.md`)
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -21,6 +34,12 @@
|
||||
- Single source of truth for skill discovery and parsing
|
||||
- Codex successfully loads ES modules via Node.js interop
|
||||
|
||||
- **Improved Documentation**: Rewrote README to explain problem/solution clearly
|
||||
- Removed duplicate sections and conflicting information
|
||||
- Added complete workflow description (brainstorm → plan → execute → finish)
|
||||
- Simplified platform installation instructions
|
||||
- Emphasized skill-checking protocol over automatic activation claims
|
||||
|
||||
---
|
||||
|
||||
## v3.4.1 (2025-10-31)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
# Bisection script to find which test creates unwanted files/state
|
||||
# Usage: ./find-polluter.sh <file_or_dir_to_check> <test_pattern>
|
||||
# Example: ./find-polluter.sh '.git' 'src/**/*.test.ts'
|
||||
|
||||
Reference in New Issue
Block a user