Compare commits

..

52 Commits

Author SHA1 Message Date
Drew Ritter
1a9cd9ec4b Improve visual companion: per-question decisions, cross-platform server docs
- Rewrite "When to Use" with explicit browser vs terminal guidance
- Add per-question decision heuristic instead of session-wide mode
- Add unload step when returning to terminal from visual step
- Remove all ${CLAUDE_PLUGIN_ROOT} references from skill docs
- Add cross-platform server startup: bash path + node fallback with env vars
- Give AI guidance to find plugin dir across Claude Code and Codex

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 18:52:45 -08:00
Drew Ritter
bf6d336950 minor change to unload a page from viz brainstorm after the user makes a decision 2026-02-19 16:53:30 -08:00
Drew Ritter
ce0f9a28be Refactor visual brainstorming: browser displays, terminal commands (#509)
* Refactor visual brainstorming: browser displays, terminal commands

Replaces the blocking TaskOutput/wait-for-feedback.sh pattern with a
non-blocking model where the browser is an interactive display and the
terminal stays available for conversation.

Server changes:
- Write user click events to .events JSONL file (per-screen, cleared on
  new screen push) so Claude reads them on its next turn
- Replace regex-based wrapInFrame with <!-- CONTENT --> placeholder
- Add --foreground flag to start-server.sh for sandbox environments
- Harden startup with nohup/disown and liveness check

UI changes:
- Remove feedback footer (textarea + Send button)
- Add selection indicator bar ("Option X selected — return to terminal")
- Narrow click handler to [data-choice] elements only

Skill changes:
- Rewrite visual-companion.md for non-blocking loop
- Fix visual companion being skipped on Codex (no browser tools needed)
- Make visual companion offer a standalone question (one question rule)

Deletes wait-for-feedback.sh entirely.

* Add visual companion offer to brainstorming checklist for UX topics

The visual companion was a disconnected section at the bottom of SKILL.md
that agents never reached because it wasn't in the mandatory checklist.
Now step 2 evaluates whether the topic involves visual/UX decisions and
offers the companion if so. Non-visual topics (APIs, data models, etc.)
skip the step entirely.

* Add multi-select support to visual companion

Containers with data-multiselect allow toggling multiple selections.
Without it, behavior is unchanged (single-select). Indicator bar shows
count when multiple items are selected.
2026-02-19 16:31:51 -08:00
Drew Ritter
3a254ba002 Remove session scope language from SUBAGENT-STOP
Drop 'top-level sessions only' which may cause the model to treat
using-superpowers as a first-turn-only skill, breaking skill chaining
on follow-up turns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Drew Ritter
192cb7db8e Soften SUBAGENT-STOP to only skip this skill, not suppress all behavior
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Drew Ritter
a014baf5b9 Remove skill override directives from dispatch templates
Let the SUBAGENT-STOP gate in using-superpowers handle skill leakage
instead of per-template directives. This avoids blocking non-superpowers
skills that users may want subagents to use.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Drew Ritter
49bbad7084 Move Codex tool mapping to progressive disclosure reference file
Addresses Jesse's review feedback on PR #450:
- Move inline routing table from using-superpowers to references/codex-tools.md,
  leveraging Codex's native progressive disclosure for companion files
- Narrow SUBAGENT-STOP from "Do not invoke skills" to "Do not invoke
  superpowers skills" so subagents can still use non-superpowers skills

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Drew Ritter
79dbce8b10 Sharpen subagent skill override directive in dispatch templates
Replace verbose scope explanations with a direct override statement
that explicitly claims priority over prior guidance (i.e. the
using-superpowers 1% rule injected by Codex's skill discovery).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Drew Ritter
2e12d4fb34 Document collab feature requirement for Codex subagent skills
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Drew Ritter
5535e2d0b3 Prevent Codex subagent skill leakage via gate check and dispatch routing table
Codex subagents inherit filesystem access and can discover superpowers skills
via native discovery. Without guidance, they activate the 1% rule and invoke
full skill workflows instead of executing their assigned task.

- Add SUBAGENT-STOP gate check above the 1% rule in using-superpowers
- Add Codex dispatch routing table (spawn_agent/wait/close_agent)
- Add scope directives to all 4 subagent dispatch templates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Jesse Vincent
7400d43599 fix: restore polyglot wrapper to fix Windows hook window spawning
Claude Code spawns hook commands with shell:true + windowsHide:true,
but on Windows the execution chain cmd.exe -> bash.exe causes Git
Bash (MSYS2) to allocate its own console window, bypassing the hide
flag. This creates visible terminal windows that steal focus on every
SessionStart event (startup, resume, clear, compact).

The fix:
- Rename session-start.sh to session-start (no extension) so Claude
  Code's .sh auto-detection regex doesn't fire and prepend "bash"
- Restore run-hook.cmd polyglot wrapper to control bash invocation
  on Windows (tries known Git Bash paths, then PATH, then exits
  silently if no bash found)
- On Unix, the polyglot's shell portion runs the script directly

This avoids Claude Code's broken .sh auto-prepend, gives us control
over how bash is invoked on Windows, and gracefully handles missing
bash instead of erroring.

Addresses: #440, #414, #354, #417, #293
Upstream: anthropics/claude-code#14828
2026-02-19 09:35:45 -08:00
Jesse Vincent
cb75011d91 fix: move scope assessment into understanding phase
Testing showed the model skipped scope assessment when it was a
separate step after "Understanding the idea." Inlining it as the
first thing in understanding ensures it fires before detailed questions.
2026-02-19 09:35:45 -08:00
Jesse Vincent
56e22b2afc feat: add project-level scope assessment to brainstorming pipeline
Brainstorming now assesses whether a project is too large for a single
spec and helps decompose into sub-projects. Spec reviewer checks scope.
Writing-plans has a backstop if brainstorming missed it.
2026-02-19 09:35:45 -08:00
Jesse Vincent
a0dc300a6e feat: add architecture and file size checks to review loops
Spec reviewer now checks for unit decomposition with clear boundaries.
Plan reviewer now checks file structure and whether files will grow
too large to reason about.
2026-02-19 09:35:45 -08:00
Jesse Vincent
1e3353b232 feat: add file growth check to code quality reviewer
Focus on whether this implementation grew or created large files,
not pre-existing file sizes in brownfield codebases.
2026-02-19 09:35:45 -08:00
Jesse Vincent
21c7284d54 fix: address review feedback on architecture guidance
- Define DONE_WITH_CONCERNS handling in SDD controller flow
- Make implementer action explicit when file grows beyond plan intent
- Reword writing-plans file size reasoning (avoid tooling-artifact language)
- Add decomposition awareness to code quality reviewer prompt
2026-02-19 09:35:45 -08:00
Jesse Vincent
8d996aa829 feat: add architecture guidance and capability-aware escalation to skills
Brainstorming: design-for-isolation guidance and brownfield codebase awareness
Writing-plans: file structure section requiring decomposition before task definition
Implementer prompt: code organization awareness, structured escalation protocol
  (DONE/DONE_WITH_CONCERNS/BLOCKED/NEEDS_CONTEXT), explicit permission to stop
Subagent-driven-development: provider-agnostic model selection tiers, escalation handling
2026-02-19 09:35:45 -08:00
Jesse Vincent
14df703a51 chore: gitignore triage directory 2026-02-19 09:35:45 -08:00
Jesse Vincent
17f80fd0ce docs: add brainstorm visual companion improvements to release notes 2026-02-19 09:35:45 -08:00
Jesse Vincent
2716e12781 docs: restructure brainstorming skill with progressive disclosure
SKILL.md is now minimal: process, principles, and a prompt that notes
the visual companion is new/token-intensive/slow. All visual companion
details move to visual-companion.md as a progressive disclosure document
read only when the user opts in.

Delete CLAUDE-INSTRUCTIONS.md (content folded into visual-companion.md).
Document fragment vs full-document behavior and --project-dir persistence.
2026-02-19 09:35:45 -08:00
Jesse Vincent
b52af8427c feat: persist brainstorm mockups to .superpowers/ directory
start-server.sh now accepts --project-dir to store session files under
.superpowers/brainstorm/ instead of /tmp. stop-server.sh only deletes
ephemeral /tmp sessions, keeping persistent ones for later review.

Fix test race condition with polling-based server startup wait.
2026-02-19 09:35:45 -08:00
Jesse Vincent
5b00c6eb50 refactor: server-side frame wrapping and helper.js consolidation
Move toggleSelect/send/selectedChoice from frame-template.html inline
script to helper.js so they're auto-injected. Server now detects bare
HTML fragments (no DOCTYPE/html tag) and wraps them in the frame
template automatically. Full documents pass through as before.

Fix dark mode in sendToClaude confirmation (was using hardcoded colors).
Fix test env var bug (BRAINSTORM_SCREEN -> BRAINSTORM_DIR).
Add tests for fragment wrapping, full doc passthrough, and helper.js.
2026-02-19 09:35:45 -08:00
Jesse Vincent
7398af9947 test: rewrite document review test as proper integration test
- Creates test project with spec containing intentional errors
- Runs Claude to actually review using spec-document-reviewer template
- Verifies reviewer catches TODO and "specified later" deferrals
- Checks review format and verdict

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Jesse Vincent
6e6b1ae546 test: add end-to-end tests for document review system
Tests verify:
- Spec document reviewer checks (completeness, TODOs)
- Plan document reviewer checks (spec alignment, task decomposition)
- Review loops exist in brainstorming and writing-plans skills
- Chunk-by-chunk review for plans with 1000-line limit
- Iteration guidance (5 iterations, escalate to human)
- Checkbox syntax on steps only (not task headings)
- Correct directories (docs/superpowers/specs, docs/superpowers/plans)
- Reviewers are advisory
- Same agent fixes issues (preserves context)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Jesse Vincent
8d73d0fee2 fix: remove checkbox from task headings, keep on steps only
The `- [ ] ### Task N:` syntax was unusual and might not render
correctly in all markdown parsers. Now only steps have checkboxes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Jesse Vincent
c9f5a393da docs: add document review system spec and plan
- Spec: docs/superpowers/specs/2026-01-22-document-review-system-design.md
- Plan: docs/superpowers/plans/2026-01-22-document-review-system.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Jesse Vincent
a3d45dc32b docs: update plan header to reference checkbox syntax
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Jesse Vincent
21673839c0 feat: add plan review loop and checkbox syntax to writing-plans skill
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Jesse Vincent
800d6a2405 feat: add plan document reviewer prompt template
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Jesse Vincent
1473d86800 feat: add spec review loop to brainstorming skill
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Jesse Vincent
bdfa38509d feat: add spec document reviewer prompt template
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Jesse Vincent
fd90ed5dd9 feat: enforce subagent-driven-development on capable harnesses
- Subagent-driven-development is now mandatory when harness supports it
- No longer offer choice between subagent-driven and executing-plans
- Executing-plans reserved for harnesses without subagent capability
- Update plan header to reference both execution paths

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Jesse Vincent
fbcf9475e4 feat: enforce brainstorming → writing-plans transition
- Make writing-plans REQUIRED after design approval
- Explicitly forbid platform planning features (EnterPlanMode, etc.)
- Forbid direct implementation without writing-plans skill

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Jesse Vincent
14c17242cc refactor: restructure specs and plans directories
- Specs (brainstorming output) now go to docs/superpowers/specs/
- Plans (writing-plans output) now go to docs/superpowers/plans/
- User preferences for locations override these defaults
- Update all skill references and test files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Jesse Vincent
786aa5cf44 fix: Windows hook execution for Claude Code 2.1.x (#331)
* fix: convert shell scripts from CRLF to LF line endings

Add .gitattributes to enforce LF line endings for shell scripts,
preventing bash errors like "/usr/bin/bash: line 1: : command not found"
when scripts are checked out on Windows with CRLF.

Fixes #317 (SessionStart hook fails due to CRLF line endings)

Files converted:
- hooks/session-start.sh
- lib/brainstorm-server/start-server.sh
- lib/brainstorm-server/stop-server.sh
- lib/brainstorm-server/wait-for-feedback.sh
- skills/systematic-debugging/find-polluter.sh

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: update Windows hook execution for Claude Code 2.1.x

Claude Code 2.1.x changed the Windows execution model: it now auto-detects
.sh files in hook commands and prepends "bash " automatically. This broke
the polyglot wrapper because:

  Before: "run-hook.cmd" session-start.sh  (wrapper executes)
  After:  bash "run-hook.cmd" session-start.sh  (bash can't run .cmd)

Changes:
- hooks.json now calls session-start.sh directly (Claude Code handles bash)
- Added deprecation comment to run-hook.cmd explaining the change
- Updated RELEASE-NOTES.md

Fixes #317, #313, #275, #292

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 09:35:45 -08:00
Jesse Vincent
8ab3eec9bc feat(opencode): use native skills and fix agent reset bug (#226) (#330)
* fix use_skill agent context (#290)

* fix: respect OPENCODE_CONFIG_DIR for personal skills lookup (#297)

* fix: respect OPENCODE_CONFIG_DIR for personal skills lookup

The plugin was hardcoded to look for personal skills in ~/.config/opencode/skills,
ignoring users who set OPENCODE_CONFIG_DIR to a custom path (e.g., for dotfiles management).

Now uses OPENCODE_CONFIG_DIR if set, falling back to the default path.

* fix: update help text to use dynamic paths

Use configDir and personalSkillsDir variables in help text so paths
are accurate when OPENCODE_CONFIG_DIR is set.

* fix: normalize OPENCODE_CONFIG_DIR before use

Handle edge cases where the env var might be:
- Empty or whitespace-only
- Using ~ for home directory (common in .env files)
- A relative path

Now trims, expands ~, and resolves to absolute path.

* feat(opencode): use native skills and fix agent reset bug (#226)

- Replace custom use_skill/find_skills tools with OpenCode's native skill tool
- Use experimental.chat.system.transform hook instead of session.prompt
  (fixes #226 agent reset on first message)
- Symlink skills directory into ~/.config/opencode/skills/superpowers/
- Update installation docs with comprehensive Windows support:
  - Command Prompt, PowerShell, and Git Bash instructions
  - Proper symlink vs junction handling
  - Reinstall safety with cleanup steps
  - Verification commands for each shell

* Add OpenCode native skills changes to release notes

Documents:
- Breaking change: switch to native skill tool
- Fix for agent reset bug (#226)
- Fix for Windows installation (#232)

---------

Co-authored-by: Vinicius da Motta <viniciusmotta8@gmail.com>
Co-authored-by: oribi <oribarilan@gmail.com>
2026-02-19 09:35:45 -08:00
Jesse Vincent
630c0f7b54 Add instruction priority hierarchy to using-superpowers skill
Clarifies that user instructions (CLAUDE.md, direct requests) always
take precedence over Superpowers skills, which in turn override
default system prompt behavior. Ensures users remain in control.

Also updates RELEASE-NOTES.md with unreleased changes including
the visual companion feature.
2026-02-19 09:35:45 -08:00
Jesse Vincent
b3e922c10a Use semantic filenames for visual companion screens
Server now watches directory for new .html files instead of a single
screen file. Claude writes to semantically named files like
platform.html, style.html, layout.html - each screen is a new file.

Benefits:
- No need to read before write (files are always new)
- Semantic filenames describe what's on screen
- History preserved in directory for debugging
- Server serves newest file by mtime automatically

Updated: index.js, start-server.sh, and all documentation.
2026-02-19 09:35:44 -08:00
Jesse Vincent
e5a7c05528 docs: improve terminal UX for visual companion
- Never use cat/heredoc for HTML (dumps noise into terminal)
- Read screen_file first before Write tool to avoid errors
- Remind user of URL on every step, not just first
- Give text summary of what's on screen before they look
2026-02-19 09:35:44 -08:00
Jesse Vincent
9ab744b2a9 refactor: simplify visual companion workflow, improve guidance
Scripts:
- Rename show-and-wait.sh -> wait-for-feedback.sh (just waits, no HTML piping)
- Remove wait-for-event.sh (used hanging tail -f)
- Workflow now: Write tool for HTML, wait-for-feedback.sh to block

Documentation rewrite:
- Broader "when to use" (UI, architecture, complex choices, spatial)
- Always ask user first before starting
- Scale fidelity to the question being asked
- Explain the question on each page
- Iterate before moving on - validate changes address feedback
- Use real content (Unsplash images) when it matters
2026-02-19 09:35:44 -08:00
Jesse Vincent
745ea8c71c feat: add show-and-wait.sh helper, fix race condition
- New show-and-wait.sh combines write + wait into one command
- Uses polling instead of tail -f (which hangs on macOS)
- Docs updated: start watcher BEFORE writing screen to avoid race
- Reduces terminal noise by consolidating operations
2026-02-19 09:35:44 -08:00
Jesse Vincent
d494f5a483 fix: session isolation and blocking wait for visual companion
- Each session gets unique temp directory (/tmp/brainstorm-{pid}-{timestamp})
- Server outputs screen_dir and screen_file in startup JSON
- stop-server.sh takes screen_dir arg and cleans up session directory
- Document blocking TaskOutput pattern: 10-min timeouts, retry up to 3x,
  then prompt user "let me know when you want to continue"
2026-02-19 09:35:44 -08:00
Jesse Vincent
ac3af07af0 feat: add visual companion for brainstorming skill
Adds browser-based mockup display to replace ASCII art during
brainstorming sessions. Key components:

- Frame template with OS-aware light/dark theming
- CSS helpers for options, cards, mockups, split views
- Server lifecycle scripts (start/stop with random high port)
- Event watcher using tail+grep for feedback loop
- Claude instructions for using the visual companion

The skill now asks users if they want browser mockups and only
runs in Claude Code environments.
2026-02-19 09:35:44 -08:00
Jesse Vincent
fd51e8a6b7 feat: add sendToClaude helper and wait-for-event tool
- Add sendToClaude() function to browser helper that shows confirmation
- Add wait-for-event.sh script for watching server output (tail -f | grep -m 1)
- Enables clean event-driven loop: background bash waits for event, completion triggers Claude's turn
2026-02-19 09:35:44 -08:00
Jesse Vincent
7c1ac86878 docs: add visual brainstorming implementation plan 2026-02-19 09:35:44 -08:00
Jesse Vincent
91fbffc994 fix: preserve original event type, use source field for wrapper 2026-02-19 09:35:44 -08:00
Jesse Vincent
3bcf5db8a1 fix: correct visual companion documentation issues 2026-02-19 09:35:44 -08:00
Jesse Vincent
ec46999224 feat: add visual companion to brainstorming skill 2026-02-19 09:35:44 -08:00
Jesse Vincent
e76ffffc1d test: add brainstorm server integration tests 2026-02-19 09:35:44 -08:00
Jesse Vincent
d20bdb8ec4 fix: ensure user-event type is preserved in WebSocket message output
The spread operator order was causing incoming event types to overwrite
the user-event type marker.
2026-02-19 09:35:44 -08:00
Jesse Vincent
fc10bf6586 feat: add browser helper library for event capture 2026-02-19 09:35:44 -08:00
Jesse Vincent
91debf6100 feat: add brainstorm server foundation
Create the initial server for the visual brainstorming companion:
- Express server with WebSocket support for browser communication
- File watcher (chokidar) to detect screen.html changes
- Auto-injects helper.js into served HTML for event capture
- Binds to localhost only (127.0.0.1) for security
- Outputs JSON events to stdout for Claude consumption
2026-02-19 09:35:44 -08:00
28 changed files with 792 additions and 176 deletions

View File

@@ -9,7 +9,7 @@
{
"name": "superpowers",
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
"version": "5.0.0",
"version": "4.3.0",
"source": "./",
"author": {
"name": "Jesse Vincent",

View File

@@ -1,7 +1,7 @@
{
"name": "superpowers",
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
"version": "5.0.0",
"version": "4.3.0",
"author": {
"name": "Jesse Vincent",
"email": "jesse@fsck.com"

View File

@@ -2,7 +2,7 @@
"name": "superpowers",
"displayName": "Superpowers",
"description": "Core skills library: TDD, debugging, collaboration patterns, and proven techniques",
"version": "4.3.1",
"version": "4.3.0",
"author": {
"name": "Jesse Vincent",
"email": "jesse@fsck.com"

View File

@@ -1 +0,0 @@
@../skills/using-superpowers/SKILL.md

View File

@@ -1,6 +0,0 @@
{
"name": "superpowers",
"description": "Core skills library: TDD, debugging, collaboration patterns, and proven techniques",
"version": "5.0.0",
"contextFileName": "GEMINI.md"
}

1
.gitignore vendored
View File

@@ -1,7 +1,6 @@
.worktrees/
.private-journal/
.claude/
.DS_Store
node_modules/
inspo
triage/

View File

@@ -1,120 +1,93 @@
# Superpowers Release Notes
## v5.0.0 (2026-03-09)
## Unreleased
### Breaking Changes
**Specs and plans directory restructured**
- Specs (brainstorming output) now save to `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md`
- Plans (writing-plans output) now save to `docs/superpowers/plans/YYYY-MM-DD-<feature-name>.md`
- Specs (brainstorming output) now go to `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md`
- Plans (writing-plans output) now go to `docs/superpowers/plans/YYYY-MM-DD-<feature-name>.md`
- User preferences for spec/plan locations override these defaults
- All internal skill references, test files, and example paths updated to match
- Migration: move existing files from `docs/plans/` to new locations if desired
**Subagent-driven development mandatory on capable harnesses**
**Brainstorming → writing-plans transition enforced**
Writing-plans no longer offers a choice between subagent-driven and executing-plans. On harnesses with subagent support (Claude Code, Codex), subagent-driven-development is required. Executing-plans is reserved for harnesses without subagent capability, and now tells the user that Superpowers works better on a subagent-capable platform.
- After design approval, brainstorming now requires using writing-plans skill
- Platform planning features (e.g., EnterPlanMode) should not be used
- Direct implementation without writing-plans is not allowed
**Executing-plans no longer batches**
**Subagent-driven development now mandatory on capable harnesses**
Removed the "execute 3 tasks then stop for review" pattern. Plans now execute continuously, stopping only for blockers.
- On harnesses with subagent support (Claude Code), subagent-driven-development is now required after plan approval
- No longer offers a choice between subagent-driven and executing-plans
- Executing-plans is only used on harnesses without subagent capability
**Slash commands deprecated**
**OpenCode: Switched to native skills system**
`/brainstorm`, `/write-plan`, and `/execute-plan` now show deprecation notices pointing users to the corresponding skills. Commands will be removed in the next major release.
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
### New Features
**Visual brainstorming companion**
**Visual companion for brainstorming skill**
Optional browser-based companion for brainstorming sessions. When a topic would benefit from visuals, the brainstorming skill offers to show mockups, diagrams, comparisons, and other content in a browser window alongside terminal conversation.
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.
- `lib/brainstorm-server/` — WebSocket server with browser helper library, session management scripts, and dark/light themed frame template ("Superpowers Brainstorming" with GitHub link)
- `skills/brainstorming/visual-companion.md` — Progressive disclosure guide for server workflow, screen authoring, and feedback collection
- Brainstorming skill adds a visual companion decision point to its process flow: after exploring project context, the skill evaluates whether upcoming questions involve visual content and offers the companion in its own message
- Per-question decision: even after accepting, each question is evaluated for whether browser or terminal is more appropriate
- Integration tests in `tests/brainstorm-server/`
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
**Document review system**
The visual companion is opt-in and falls back gracefully to terminal-only operation.
Automated review loops for spec and plan documents using subagent dispatch:
### Bug Fixes
- `skills/brainstorming/spec-document-reviewer-prompt.md` — Reviewer checks completeness, consistency, architecture, and YAGNI
- `skills/writing-plans/plan-document-reviewer-prompt.md` — Reviewer checks spec alignment, task decomposition, file structure, and file size
- Brainstorming dispatches spec reviewer after writing the design doc
- Writing-plans includes chunk-based plan review loop after each section
- Review loops repeat until approved or escalate after 5 iterations
- End-to-end tests in `tests/claude-code/test-document-review-system.sh`
- Design spec and implementation plan in `docs/superpowers/`
**Fixed Windows hook execution for Claude Code 2.1.x**
**Architecture guidance across the skill pipeline**
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.
Design-for-isolation and file-size-awareness guidance added to brainstorming, writing-plans, and subagent-driven-development:
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).
- **Brainstorming** — New sections: "Design for isolation and clarity" (clear boundaries, well-defined interfaces, independently testable units) and "Working in existing codebases" (follow existing patterns, targeted improvements only)
- **Writing-plans** — New "File Structure" section: map out files and responsibilities before defining tasks. New "Scope Check" backstop: catch multi-subsystem specs that should have been decomposed during brainstorming
- **SDD implementer** — New "Code Organization" section (follow plan's file structure, report concerns about growing files) and "When You're in Over Your Head" escalation guidance
- **SDD code quality reviewer** — Now checks architecture, unit decomposition, plan conformance, and file growth
- **Spec/plan reviewers** — Architecture and file size added to review criteria
- **Scope assessment** — Brainstorming now assesses whether a project is too large for a single spec. Multi-subsystem requests are flagged early and decomposed into sub-projects, each with its own spec → plan → implementation cycle
**Brainstorming visual companion: reduced token cost and improved persistence**
**Subagent-driven development improvements**
The visual companion now generates much smaller HTML per screen. The server automatically wraps bare content fragments in the frame template (header, CSS theme, feedback footer, interactive JS), so Claude writes only the content portion (~30 lines instead of ~260). Full HTML documents are still served as-is when Claude needs complete control.
- **Model selection** — Guidance for choosing model capability by task type: cheap models for mechanical implementation, standard for integration, capable for architecture and review
- **Implementer status protocol** — Subagents now report DONE, DONE_WITH_CONCERNS, BLOCKED, or NEEDS_CONTEXT. Controller handles each status appropriately: re-dispatching with more context, upgrading model capability, breaking tasks apart, or escalating to human
Other improvements:
- `toggleSelect`/`send`/`selectedChoice` moved from inline template script to `helper.js` (auto-injected)
- `start-server.sh --project-dir` persists mockups under `.superpowers/brainstorm/` instead of `/tmp`
- `stop-server.sh` only deletes ephemeral `/tmp` sessions, preserving persistent ones
- Dark mode fix: `sendToClaude` confirmation page now uses CSS variables instead of hardcoded colors
- Skill restructured: SKILL.md is minimal (prompt + pointer); all visual companion details in progressive disclosure doc (`visual-companion.md`)
- Prompt to user now notes the feature is new, token-intensive, and can be slow
- Deleted redundant `CLAUDE-INSTRUCTIONS.md` (content folded into `visual-companion.md`)
- Test fixes: correct env var (`BRAINSTORM_DIR`), polling-based startup wait, new tests for frame wrapping
### Improvements
**Instruction priority hierarchy**
**Instruction priority clarified in using-superpowers**
Added explicit priority ordering to using-superpowers:
Added explicit instruction priority hierarchy to prevent conflicts with user preferences:
1. User's explicit instructions (CLAUDE.md, AGENTS.md, direct requests) — highest priority
2. Superpowers skills — override default system behavior
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
If CLAUDE.md or AGENTS.md says "don't use TDD" and a skill says "always use TDD," the user's instructions win.
**SUBAGENT-STOP gate**
Added `<SUBAGENT-STOP>` block to using-superpowers. Subagents dispatched for specific tasks now skip the skill instead of activating the 1% rule and invoking full skill workflows.
**Multi-platform improvements**
- Codex tool mapping moved to progressive disclosure reference file (`references/codex-tools.md`)
- Platform Adaptation pointer added so non-Claude-Code platforms can find tool equivalents
- Plan headers now address "agentic workers" instead of "Claude" specifically
- Collab feature requirement documented in `docs/README.codex.md`
**Writing-plans template updates**
- Plan steps now use checkbox syntax (`- [ ] **Step N:**`) for progress tracking
- Plan header references both subagent-driven-development and executing-plans with platform-aware routing
---
## v4.3.1 (2026-02-21)
### Added
**Cursor support**
Superpowers now works with Cursor's plugin system. Includes a `.cursor-plugin/plugin.json` manifest and Cursor-specific installation instructions in the README. The SessionStart hook output now includes an `additional_context` field alongside the existing `hookSpecificOutput.additionalContext` for Cursor hook compatibility.
### Fixed
**Windows: Restored polyglot wrapper for reliable hook execution (#518, #504, #491, #487, #466, #440)**
Claude Code's `.sh` auto-detection on Windows was prepending `bash` to the hook command, breaking execution. The fix:
- Renamed `session-start.sh` to `session-start` (extensionless) so auto-detection doesn't interfere
- Restored `run-hook.cmd` polyglot wrapper with multi-location bash discovery (standard Git for Windows paths, then PATH fallback)
- Exits silently if no bash is found rather than erroring
- On Unix, the wrapper runs the script directly via `exec bash`
- Uses POSIX-safe `dirname "$0"` path resolution (works on dash/sh, not just bash)
This fixes SessionStart failures on Windows with spaces in paths, missing WSL, `set -euo pipefail` fragility on MSYS, and backslash mangling.
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.3.0 (2026-02-12)

View File

@@ -1,5 +1,6 @@
---
description: "Deprecated - use the superpowers:brainstorming skill instead"
description: "You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores requirements and design before implementation."
disable-model-invocation: true
---
Tell your human partner that this command is deprecated and will be removed in the next major release. They should ask you to use the "superpowers brainstorming" skill instead.
Invoke the superpowers:brainstorming skill and follow it exactly as presented to you

View File

@@ -1,5 +1,6 @@
---
description: "Deprecated - use the superpowers:executing-plans skill instead"
description: Execute plan in batches with review checkpoints
disable-model-invocation: true
---
Tell your human partner that this command is deprecated and will be removed in the next major release. They should ask you to use the "superpowers executing-plans" skill instead.
Invoke the superpowers:executing-plans skill and follow it exactly as presented to you

View File

@@ -1,5 +1,6 @@
---
description: "Deprecated - use the superpowers:writing-plans skill instead"
description: Create detailed implementation plan with bite-sized tasks
disable-model-invocation: true
---
Tell your human partner that this command is deprecated and will be removed in the next major release. They should ask you to use the "superpowers writing-plans" skill instead.
Invoke the superpowers:writing-plans skill and follow it exactly as presented to you

View File

@@ -1,6 +1,6 @@
# OpenCode Support Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Add full superpowers support for OpenCode.ai with a native JavaScript plugin that shares core functionality with the existing Codex implementation.

View File

@@ -1,6 +1,6 @@
# Visual Brainstorming Companion Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Give Claude a browser-based visual companion for brainstorming sessions - show mockups, prototypes, and interactive choices alongside terminal conversation.

View File

@@ -1,6 +1,6 @@
# Document Review System Implementation Plan
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan.
> **For Claude:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan.
**Goal:** Add spec and plan document review loops to the brainstorming and writing-plans skills.
@@ -285,12 +285,12 @@ Run: `grep -A 20 "Plan Document Header" skills/writing-plans/SKILL.md`
The plan header should note that tasks and steps use checkbox syntax. Update the header comment:
```markdown
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Tasks and steps use checkbox (`- [ ]`) syntax for tracking.
> **For Claude:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Tasks and steps use checkbox (`- [ ]`) syntax for tracking.
```
- [ ] **Step 3:** Verify the change
Run: `grep -A 5 "For agentic workers:" skills/writing-plans/SKILL.md`
Run: `grep -A 5 "For Claude:" skills/writing-plans/SKILL.md`
Expected: Shows updated header with checkbox syntax mention
- [ ] **Step 4:** Commit

View File

@@ -1,6 +1,6 @@
# Visual Brainstorming Refactor Implementation Plan
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
> **For Claude:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Refactor visual brainstorming from blocking TUI feedback model to non-blocking "Browser Displays, Terminal Commands" architecture.

View File

@@ -6,7 +6,7 @@
"hooks": [
{
"type": "command",
"command": "'${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd' session-start",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd session-start",
"async": false
}
]

View File

@@ -40,7 +40,7 @@ exit /b 0
CMDBLOCK
# Unix: run the named script directly
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
SCRIPT_NAME="$1"
shift
exec bash "${SCRIPT_DIR}/${SCRIPT_NAME}" "$@"

View File

@@ -35,27 +35,17 @@ warning_escaped=$(escape_for_json "$warning_message")
session_context="<EXTREMELY_IMPORTANT>\nYou have superpowers.\n\n**Below is the full content of your 'superpowers:using-superpowers' skill - your introduction to using skills. For all other skills, use the 'Skill' tool:**\n\n${using_superpowers_escaped}\n\n${warning_escaped}\n</EXTREMELY_IMPORTANT>"
# Output context injection as JSON.
# Cursor hooks expect additional_context.
# Claude Code hooks expect hookSpecificOutput.additionalContext.
# Claude Code reads BOTH fields without deduplication, so we must only
# emit the field consumed by the current platform to avoid double injection.
if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then
# Claude Code sets CLAUDE_PLUGIN_ROOT — emit only hookSpecificOutput
cat <<EOF
# Keep both shapes for compatibility:
# - Cursor hooks expect additional_context.
# - Claude hooks expect hookSpecificOutput.additionalContext.
cat <<EOF
{
"additional_context": "${session_context}",
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": "${session_context}"
}
}
EOF
else
# Other platforms (Cursor, etc.) — emit only additional_context
cat <<EOF
{
"additional_context": "${session_context}"
}
EOF
fi
exit 0

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>Superpowers Brainstorming</title>
<title>Brainstorm Companion</title>
<style>
/*
* BRAINSTORM COMPANION FRAME TEMPLATE
@@ -195,7 +195,7 @@
</head>
<body>
<div class="header">
<h1><a href="https://github.com/obra/superpowers" style="color: inherit; text-decoration: none;">Superpowers Brainstorming</a></h1>
<h1>Brainstorm Companion</h1>
<div class="status">Connected</div>
</div>

208
lib/skills-core.js Normal file
View File

@@ -0,0 +1,208 @@
import fs from 'fs';
import path from 'path';
import { execSync } from 'child_process';
/**
* Extract YAML frontmatter from a skill file.
* Current format:
* ---
* name: skill-name
* description: Use when [condition] - [what it does]
* ---
*
* @param {string} filePath - Path to SKILL.md file
* @returns {{name: string, description: string}}
*/
function extractFrontmatter(filePath) {
try {
const content = fs.readFileSync(filePath, 'utf8');
const lines = content.split('\n');
let inFrontmatter = false;
let name = '';
let description = '';
for (const line of lines) {
if (line.trim() === '---') {
if (inFrontmatter) break;
inFrontmatter = true;
continue;
}
if (inFrontmatter) {
const match = line.match(/^(\w+):\s*(.*)$/);
if (match) {
const [, key, value] = match;
switch (key) {
case 'name':
name = value.trim();
break;
case 'description':
description = value.trim();
break;
}
}
}
}
return { name, description };
} catch (error) {
return { name: '', description: '' };
}
}
/**
* Find all SKILL.md files in a directory recursively.
*
* @param {string} dir - Directory to search
* @param {string} sourceType - 'personal' or 'superpowers' for namespacing
* @param {number} maxDepth - Maximum recursion depth (default: 3)
* @returns {Array<{path: string, name: string, description: string, sourceType: string}>}
*/
function findSkillsInDir(dir, sourceType, maxDepth = 3) {
const skills = [];
if (!fs.existsSync(dir)) return skills;
function recurse(currentDir, depth) {
if (depth > maxDepth) return;
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(currentDir, entry.name);
if (entry.isDirectory()) {
// Check for SKILL.md in this directory
const skillFile = path.join(fullPath, 'SKILL.md');
if (fs.existsSync(skillFile)) {
const { name, description } = extractFrontmatter(skillFile);
skills.push({
path: fullPath,
skillFile: skillFile,
name: name || entry.name,
description: description || '',
sourceType: sourceType
});
}
// Recurse into subdirectories
recurse(fullPath, depth + 1);
}
}
}
recurse(dir, 0);
return skills;
}
/**
* Resolve a skill name to its file path, handling shadowing
* (personal skills override superpowers skills).
*
* @param {string} skillName - Name like "superpowers:brainstorming" or "my-skill"
* @param {string} superpowersDir - Path to superpowers skills directory
* @param {string} personalDir - Path to personal skills directory
* @returns {{skillFile: string, sourceType: string, skillPath: string} | null}
*/
function resolveSkillPath(skillName, superpowersDir, personalDir) {
// Strip superpowers: prefix if present
const forceSuperpowers = skillName.startsWith('superpowers:');
const actualSkillName = forceSuperpowers ? skillName.replace(/^superpowers:/, '') : skillName;
// Try personal skills first (unless explicitly superpowers:)
if (!forceSuperpowers && personalDir) {
const personalPath = path.join(personalDir, actualSkillName);
const personalSkillFile = path.join(personalPath, 'SKILL.md');
if (fs.existsSync(personalSkillFile)) {
return {
skillFile: personalSkillFile,
sourceType: 'personal',
skillPath: actualSkillName
};
}
}
// Try superpowers skills
if (superpowersDir) {
const superpowersPath = path.join(superpowersDir, actualSkillName);
const superpowersSkillFile = path.join(superpowersPath, 'SKILL.md');
if (fs.existsSync(superpowersSkillFile)) {
return {
skillFile: superpowersSkillFile,
sourceType: 'superpowers',
skillPath: actualSkillName
};
}
}
return null;
}
/**
* Check if a git repository has updates available.
*
* @param {string} repoDir - Path to git repository
* @returns {boolean} - True if updates are available
*/
function checkForUpdates(repoDir) {
try {
// Quick check with 3 second timeout to avoid delays if network is down
const output = execSync('git fetch origin && git status --porcelain=v1 --branch', {
cwd: repoDir,
timeout: 3000,
encoding: 'utf8',
stdio: 'pipe'
});
// Parse git status output to see if we're behind
const statusLines = output.split('\n');
for (const line of statusLines) {
if (line.startsWith('## ') && line.includes('[behind ')) {
return true; // We're behind remote
}
}
return false; // Up to date
} catch (error) {
// Network down, git error, timeout, etc. - don't block bootstrap
return false;
}
}
/**
* Strip YAML frontmatter from skill content, returning just the content.
*
* @param {string} content - Full content including frontmatter
* @returns {string} - Content without frontmatter
*/
function stripFrontmatter(content) {
const lines = content.split('\n');
let inFrontmatter = false;
let frontmatterEnded = false;
const contentLines = [];
for (const line of lines) {
if (line.trim() === '---') {
if (inFrontmatter) {
frontmatterEnded = true;
continue;
}
inFrontmatter = true;
continue;
}
if (frontmatterEnded || !inFrontmatter) {
contentLines.push(line);
}
}
return contentLines.join('\n').trim();
}
export {
extractFrontmatter,
findSkillsInDir,
resolveSkillPath,
checkForUpdates,
stripFrontmatter
};

View File

@@ -26,9 +26,8 @@ You MUST create a task for each of these items and complete them in order:
3. **Ask clarifying questions** — one at a time, understand purpose/constraints/success criteria
4. **Propose 2-3 approaches** — with trade-offs and your recommendation
5. **Present design** — in sections scaled to their complexity, get user approval after each section
6. **Write design doc** — save to `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md` and commit
7. **User reviews written spec** — ask user to review the spec file before proceeding
8. **Transition to implementation** — invoke writing-plans skill to create implementation plan
6. **Write design doc** — save to `docs/plans/YYYY-MM-DD-<topic>-design.md` and commit
7. **Transition to implementation** — invoke writing-plans skill to create implementation plan
## Process Flow
@@ -42,7 +41,6 @@ digraph brainstorming {
"Present design sections" [shape=box];
"User approves design?" [shape=diamond];
"Write design doc" [shape=box];
"User reviews spec?" [shape=diamond];
"Invoke writing-plans skill" [shape=doublecircle];
"Explore project context" -> "Visual questions ahead?";
@@ -54,9 +52,7 @@ digraph brainstorming {
"Present design sections" -> "User approves design?";
"User approves design?" -> "Present design sections" [label="no, revise"];
"User approves design?" -> "Write design doc" [label="yes"];
"Write design doc" -> "User reviews spec?";
"User reviews spec?" -> "Write design doc" [label="changes requested"];
"User reviews spec?" -> "Invoke writing-plans skill" [label="approved"];
"Write design doc" -> "Invoke writing-plans skill";
}
```
@@ -117,13 +113,6 @@ After writing the spec document:
2. If Issues Found: fix, re-dispatch, repeat until Approved
3. If loop exceeds 5 iterations, surface to human for guidance
**User Review Gate:**
After the spec review loop passes, ask the user to review the written spec before proceeding:
> "Spec written and committed to `<path>`. Please review it and let me know if you want to make any changes before we start writing out the implementation plan."
Wait for the user's response. If they request changes, make them and re-run the spec review loop. Only proceed once the user approves.
**Implementation:**
- Invoke the writing-plans skill to create a detailed implementation plan
@@ -143,7 +132,7 @@ Wait for the user's response. If they request changes, make them and re-run the
A browser-based companion for showing mockups, diagrams, and visual options during brainstorming. Available as a tool — not a mode. Accepting the companion means it's available for questions that benefit from visual treatment; it does NOT mean every question goes through the browser.
**Offering the companion:** When you anticipate that upcoming questions will involve visual content (mockups, layouts, diagrams), offer it once for consent:
> "Some of what we're working on might be easier to explain if I can show it to you in a web browser. I can put together mockups, diagrams, comparisons, and other visuals as we go. This feature is still new and can be token-intensive. Want to try it? (Requires opening a local URL)"
> "Some of the upcoming design questions would benefit from visual mockups. I can show those in a browser window so you can see and compare options visually. This feature is still new — it can be token-intensive and a bit slow, but it works well for layout and design questions. Want to try it? (Requires opening a local URL)"
**This offer MUST be its own message.** Do not combine it with clarifying questions, context summaries, or any other content. The message should contain ONLY the offer above and nothing else. Wait for the user's response before continuing. If they decline, proceed with text-only brainstorming.

View File

@@ -32,38 +32,36 @@ The server watches a directory for HTML files and serves the newest one to the b
## Starting a Session
The brainstorm server is a Node.js app in `lib/brainstorm-server/` inside the superpowers plugin directory.
**Finding the server:** Use `$CLAUDE_PLUGIN_ROOT` if it's set. If not, locate the superpowers plugin — check `~/.claude/plugins/cache/` (Claude Code), `~/.agents/skills/superpowers/` (Codex), or similar. The server entry point is `lib/brainstorm-server/start-server.sh`.
**Starting with bash (Mac/Linux, or Windows with Git Bash):**
```bash
# Start server with persistence (mockups saved to project)
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/start-server.sh --project-dir /path/to/project
/path/to/superpowers/lib/brainstorm-server/start-server.sh --project-dir /path/to/project
# Returns: {"type":"server-started","port":52341,"url":"http://localhost:52341",
# "screen_dir":"/path/to/project/.superpowers/brainstorm/12345-1706000000"}
```
**Without bash (Windows/PowerShell):** Run node directly from `lib/brainstorm-server/`:
```
node index.js
```
Set these environment variables before running: `BRAINSTORM_DIR` (session directory you create — e.g., `<project>/.superpowers/brainstorm/<session-id>`), `BRAINSTORM_HOST` (default `127.0.0.1`), `BRAINSTORM_URL_HOST` (default `localhost`).
Save `screen_dir` from the response. Tell user to open the URL.
**Note:** Pass the project root as `--project-dir` so mockups persist in `.superpowers/brainstorm/` and survive server restarts. Without it, files go to `/tmp` and get cleaned up. Remind the user to add `.superpowers/` to `.gitignore` if it's not already there.
**Note:** Pass the project root as `--project-dir` (or set `BRAINSTORM_DIR` under it) so mockups persist in `.superpowers/brainstorm/` and survive server restarts. Without it, files go to `/tmp` and get cleaned up. Remind the user to add `.superpowers/` to `.gitignore` if it's not already there.
**Codex behavior:** In Codex (`CODEX_CI=1`), `start-server.sh` auto-switches to foreground mode by default because background jobs may be reaped. Use `--background` only if your environment reliably preserves detached processes.
**If background processes are reaped in your environment:** run in foreground from a persistent terminal session:
**If background processes are reaped in your environment:** run in foreground from a persistent terminal session. With bash, pass `--foreground`. With node directly, it runs in foreground by default.
```bash
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/start-server.sh --project-dir /path/to/project --foreground
```
In `--foreground` mode, the command stays attached and serves until interrupted.
If the URL is unreachable from your browser (common in remote/containerized setups), bind a non-loopback host:
```bash
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/start-server.sh \
--project-dir /path/to/project \
--host 0.0.0.0 \
--url-host localhost
```
Use `--url-host` to control what hostname is printed in the returned URL JSON.
If the URL is unreachable from your browser (common in remote/containerized setups), bind a non-loopback host by passing `--host 0.0.0.0 --url-host localhost` (bash) or setting `BRAINSTORM_HOST=0.0.0.0` and `BRAINSTORM_URL_HOST=localhost` (node).
## The Loop
@@ -248,13 +246,11 @@ If `.events` doesn't exist, the user didn't interact with the browser — use on
## Cleaning Up
```bash
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/stop-server.sh $SCREEN_DIR
```
Stop the server using `stop-server.sh` in `lib/brainstorm-server/` (same directory as `start-server.sh`), passing the `$SCREEN_DIR`. Or kill the process by pid from `$SCREEN_DIR/.server.pid`.
If the session used `--project-dir`, mockup files persist in `.superpowers/brainstorm/` for later reference. Only `/tmp` sessions get deleted on stop.
## Reference
- Frame template (CSS reference): `${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/frame-template.html`
- Helper script (client-side): `${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/helper.js`
- Frame template (CSS reference): `lib/brainstorm-server/frame-template.html` in the superpowers plugin directory
- Helper script (client-side): `lib/brainstorm-server/helper.js` in the superpowers plugin directory

View File

@@ -7,12 +7,12 @@ description: Use when you have a written implementation plan to execute in a sep
## Overview
Load plan, review critically, execute all tasks, report when complete.
Load plan, review critically, execute tasks in batches, report for review between batches.
**Core principle:** Batch execution with checkpoints for architect review.
**Announce at start:** "I'm using the executing-plans skill to implement this plan."
**Note:** Tell your human partner that Superpowers works much better with access to subagents. The quality of its work will be significantly higher if run on a platform with subagent support (such as Claude Code or Codex). If subagents are available, use superpowers:subagent-driven-development instead of this skill.
## The Process
### Step 1: Load and Review Plan
@@ -21,7 +21,8 @@ Load plan, review critically, execute all tasks, report when complete.
3. If concerns: Raise them with your human partner before starting
4. If no concerns: Create TodoWrite and proceed
### Step 2: Execute Tasks
### Step 2: Execute Batch
**Default: First 3 tasks**
For each task:
1. Mark as in_progress
@@ -29,7 +30,19 @@ For each task:
3. Run verifications as specified
4. Mark as completed
### Step 3: Complete Development
### Step 3: Report
When batch complete:
- Show what was implemented
- Show verification output
- Say: "Ready for feedback."
### Step 4: Continue
Based on feedback:
- Apply changes if needed
- Execute next batch
- Repeat until complete
### Step 5: Complete Development
After all tasks complete and verified:
- Announce: "I'm using the finishing-a-development-branch skill to complete this work."
@@ -39,7 +52,7 @@ After all tasks complete and verified:
## When to Stop and Ask for Help
**STOP executing immediately when:**
- Hit a blocker (missing dependency, test fails, instruction unclear)
- Hit a blocker mid-batch (missing dependency, test fails, instruction unclear)
- Plan has critical gaps preventing starting
- You don't understand an instruction
- Verification fails repeatedly
@@ -59,6 +72,7 @@ After all tasks complete and verified:
- Follow plan steps exactly
- Don't skip verifications
- 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

View File

@@ -19,11 +19,11 @@ This is not negotiable. This is not optional. You cannot rationalize your way ou
Superpowers skills override default system prompt behavior, but **user instructions always take precedence**:
1. **User's explicit instructions** (CLAUDE.md, AGENTS.md, direct requests) — highest priority
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
If CLAUDE.md or AGENTS.md says "don't use TDD" and a skill says "always use TDD," follow the user's instructions. The user is in control.
If CLAUDE.md says "don't use TDD" and a skill says "always use TDD," follow CLAUDE.md. The user is in control.
## How to Access Skills

View File

@@ -49,7 +49,7 @@ This structure informs the task decomposition. Each task should produce self-con
```markdown
# [Feature Name] Implementation Plan
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
> **For Claude:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** [One sentence describing what this builds]

View File

@@ -64,7 +64,7 @@ def analyze_main_session(filepath):
subagent_usage[agent_id]['output_tokens'] += usage.get('output_tokens', 0)
subagent_usage[agent_id]['cache_creation'] += usage.get('cache_creation_input_tokens', 0)
subagent_usage[agent_id]['cache_read'] += usage.get('cache_read_input_tokens', 0)
except Exception:
except:
pass
return main_usage, dict(subagent_usage)

View File

@@ -44,6 +44,7 @@ while [[ $# -gt 0 ]]; do
echo ""
echo "Tests:"
echo " test-plugin-loading.sh Verify plugin installation and structure"
echo " test-skills-core.sh Test skills-core.js library functions"
echo " test-tools.sh Test use_skill and find_skills tools (integration)"
echo " test-priority.sh Test skill priority resolution (integration)"
exit 0
@@ -59,6 +60,7 @@ done
# List of tests to run (no external dependencies)
tests=(
"test-plugin-loading.sh"
"test-skills-core.sh"
)
# Integration tests (require OpenCode)

View File

@@ -30,8 +30,17 @@ else
exit 1
fi
# Test 2: Verify skills directory is populated
echo "Test 2: Checking skills directory..."
# Test 2: Verify lib/skills-core.js is in place
echo "Test 2: Checking skills-core.js..."
if [ -f "$HOME/.config/opencode/superpowers/lib/skills-core.js" ]; then
echo " [PASS] skills-core.js exists"
else
echo " [FAIL] skills-core.js not found"
exit 1
fi
# Test 3: Verify skills directory is populated
echo "Test 3: Checking skills directory..."
skill_count=$(find "$HOME/.config/opencode/superpowers/skills" -name "SKILL.md" | wc -l)
if [ "$skill_count" -gt 0 ]; then
echo " [PASS] Found $skill_count skills installed"

View File

@@ -0,0 +1,440 @@
#!/usr/bin/env bash
# Test: Skills Core Library
# Tests the skills-core.js library functions directly via Node.js
# Does not require OpenCode - tests pure library functionality
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
echo "=== Test: Skills Core Library ==="
# Source setup to create isolated environment
source "$SCRIPT_DIR/setup.sh"
# Trap to cleanup on exit
trap cleanup_test_env EXIT
# Test 1: Test extractFrontmatter function
echo "Test 1: Testing extractFrontmatter..."
# Create test file with frontmatter
test_skill_dir="$TEST_HOME/test-skill"
mkdir -p "$test_skill_dir"
cat > "$test_skill_dir/SKILL.md" <<'EOF'
---
name: test-skill
description: A test skill for unit testing
---
# Test Skill Content
This is the content.
EOF
# Run Node.js test using inline function (avoids ESM path resolution issues in test env)
result=$(node -e "
const path = require('path');
const fs = require('fs');
// Inline the extractFrontmatter function for testing
function extractFrontmatter(filePath) {
try {
const content = fs.readFileSync(filePath, 'utf8');
const lines = content.split('\n');
let inFrontmatter = false;
let name = '';
let description = '';
for (const line of lines) {
if (line.trim() === '---') {
if (inFrontmatter) break;
inFrontmatter = true;
continue;
}
if (inFrontmatter) {
const match = line.match(/^(\w+):\s*(.*)$/);
if (match) {
const [, key, value] = match;
if (key === 'name') name = value.trim();
if (key === 'description') description = value.trim();
}
}
}
return { name, description };
} catch (error) {
return { name: '', description: '' };
}
}
const result = extractFrontmatter('$TEST_HOME/test-skill/SKILL.md');
console.log(JSON.stringify(result));
" 2>&1)
if echo "$result" | grep -q '"name":"test-skill"'; then
echo " [PASS] extractFrontmatter parses name correctly"
else
echo " [FAIL] extractFrontmatter did not parse name"
echo " Result: $result"
exit 1
fi
if echo "$result" | grep -q '"description":"A test skill for unit testing"'; then
echo " [PASS] extractFrontmatter parses description correctly"
else
echo " [FAIL] extractFrontmatter did not parse description"
exit 1
fi
# Test 2: Test stripFrontmatter function
echo ""
echo "Test 2: Testing stripFrontmatter..."
result=$(node -e "
const fs = require('fs');
function stripFrontmatter(content) {
const lines = content.split('\n');
let inFrontmatter = false;
let frontmatterEnded = false;
const contentLines = [];
for (const line of lines) {
if (line.trim() === '---') {
if (inFrontmatter) {
frontmatterEnded = true;
continue;
}
inFrontmatter = true;
continue;
}
if (frontmatterEnded || !inFrontmatter) {
contentLines.push(line);
}
}
return contentLines.join('\n').trim();
}
const content = fs.readFileSync('$TEST_HOME/test-skill/SKILL.md', 'utf8');
const stripped = stripFrontmatter(content);
console.log(stripped);
" 2>&1)
if echo "$result" | grep -q "# Test Skill Content"; then
echo " [PASS] stripFrontmatter preserves content"
else
echo " [FAIL] stripFrontmatter did not preserve content"
echo " Result: $result"
exit 1
fi
if ! echo "$result" | grep -q "name: test-skill"; then
echo " [PASS] stripFrontmatter removes frontmatter"
else
echo " [FAIL] stripFrontmatter did not remove frontmatter"
exit 1
fi
# Test 3: Test findSkillsInDir function
echo ""
echo "Test 3: Testing findSkillsInDir..."
# Create multiple test skills
mkdir -p "$TEST_HOME/skills-dir/skill-a"
mkdir -p "$TEST_HOME/skills-dir/skill-b"
mkdir -p "$TEST_HOME/skills-dir/nested/skill-c"
cat > "$TEST_HOME/skills-dir/skill-a/SKILL.md" <<'EOF'
---
name: skill-a
description: First skill
---
# Skill A
EOF
cat > "$TEST_HOME/skills-dir/skill-b/SKILL.md" <<'EOF'
---
name: skill-b
description: Second skill
---
# Skill B
EOF
cat > "$TEST_HOME/skills-dir/nested/skill-c/SKILL.md" <<'EOF'
---
name: skill-c
description: Nested skill
---
# Skill C
EOF
result=$(node -e "
const fs = require('fs');
const path = require('path');
function extractFrontmatter(filePath) {
try {
const content = fs.readFileSync(filePath, 'utf8');
const lines = content.split('\n');
let inFrontmatter = false;
let name = '';
let description = '';
for (const line of lines) {
if (line.trim() === '---') {
if (inFrontmatter) break;
inFrontmatter = true;
continue;
}
if (inFrontmatter) {
const match = line.match(/^(\w+):\s*(.*)$/);
if (match) {
const [, key, value] = match;
if (key === 'name') name = value.trim();
if (key === 'description') description = value.trim();
}
}
}
return { name, description };
} catch (error) {
return { name: '', description: '' };
}
}
function findSkillsInDir(dir, sourceType, maxDepth = 3) {
const skills = [];
if (!fs.existsSync(dir)) return skills;
function recurse(currentDir, depth) {
if (depth > maxDepth) return;
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(currentDir, entry.name);
if (entry.isDirectory()) {
const skillFile = path.join(fullPath, 'SKILL.md');
if (fs.existsSync(skillFile)) {
const { name, description } = extractFrontmatter(skillFile);
skills.push({
path: fullPath,
skillFile: skillFile,
name: name || entry.name,
description: description || '',
sourceType: sourceType
});
}
recurse(fullPath, depth + 1);
}
}
}
recurse(dir, 0);
return skills;
}
const skills = findSkillsInDir('$TEST_HOME/skills-dir', 'test', 3);
console.log(JSON.stringify(skills, null, 2));
" 2>&1)
skill_count=$(echo "$result" | grep -c '"name":' || echo "0")
if [ "$skill_count" -ge 3 ]; then
echo " [PASS] findSkillsInDir found all skills (found $skill_count)"
else
echo " [FAIL] findSkillsInDir did not find all skills (expected 3, found $skill_count)"
echo " Result: $result"
exit 1
fi
if echo "$result" | grep -q '"name": "skill-c"'; then
echo " [PASS] findSkillsInDir found nested skills"
else
echo " [FAIL] findSkillsInDir did not find nested skill"
exit 1
fi
# Test 4: Test resolveSkillPath function
echo ""
echo "Test 4: Testing resolveSkillPath..."
# Create skills in personal and superpowers locations for testing
mkdir -p "$TEST_HOME/personal-skills/shared-skill"
mkdir -p "$TEST_HOME/superpowers-skills/shared-skill"
mkdir -p "$TEST_HOME/superpowers-skills/unique-skill"
cat > "$TEST_HOME/personal-skills/shared-skill/SKILL.md" <<'EOF'
---
name: shared-skill
description: Personal version
---
# Personal Shared
EOF
cat > "$TEST_HOME/superpowers-skills/shared-skill/SKILL.md" <<'EOF'
---
name: shared-skill
description: Superpowers version
---
# Superpowers Shared
EOF
cat > "$TEST_HOME/superpowers-skills/unique-skill/SKILL.md" <<'EOF'
---
name: unique-skill
description: Only in superpowers
---
# Unique
EOF
result=$(node -e "
const fs = require('fs');
const path = require('path');
function resolveSkillPath(skillName, superpowersDir, personalDir) {
const forceSuperpowers = skillName.startsWith('superpowers:');
const actualSkillName = forceSuperpowers ? skillName.replace(/^superpowers:/, '') : skillName;
if (!forceSuperpowers && personalDir) {
const personalPath = path.join(personalDir, actualSkillName);
const personalSkillFile = path.join(personalPath, 'SKILL.md');
if (fs.existsSync(personalSkillFile)) {
return {
skillFile: personalSkillFile,
sourceType: 'personal',
skillPath: actualSkillName
};
}
}
if (superpowersDir) {
const superpowersPath = path.join(superpowersDir, actualSkillName);
const superpowersSkillFile = path.join(superpowersPath, 'SKILL.md');
if (fs.existsSync(superpowersSkillFile)) {
return {
skillFile: superpowersSkillFile,
sourceType: 'superpowers',
skillPath: actualSkillName
};
}
}
return null;
}
const superpowersDir = '$TEST_HOME/superpowers-skills';
const personalDir = '$TEST_HOME/personal-skills';
// Test 1: Shared skill should resolve to personal
const shared = resolveSkillPath('shared-skill', superpowersDir, personalDir);
console.log('SHARED:', JSON.stringify(shared));
// Test 2: superpowers: prefix should force superpowers
const forced = resolveSkillPath('superpowers:shared-skill', superpowersDir, personalDir);
console.log('FORCED:', JSON.stringify(forced));
// Test 3: Unique skill should resolve to superpowers
const unique = resolveSkillPath('unique-skill', superpowersDir, personalDir);
console.log('UNIQUE:', JSON.stringify(unique));
// Test 4: Non-existent skill
const notfound = resolveSkillPath('not-a-skill', superpowersDir, personalDir);
console.log('NOTFOUND:', JSON.stringify(notfound));
" 2>&1)
if echo "$result" | grep -q 'SHARED:.*"sourceType":"personal"'; then
echo " [PASS] Personal skills shadow superpowers skills"
else
echo " [FAIL] Personal skills not shadowing correctly"
echo " Result: $result"
exit 1
fi
if echo "$result" | grep -q 'FORCED:.*"sourceType":"superpowers"'; then
echo " [PASS] superpowers: prefix forces superpowers resolution"
else
echo " [FAIL] superpowers: prefix not working"
exit 1
fi
if echo "$result" | grep -q 'UNIQUE:.*"sourceType":"superpowers"'; then
echo " [PASS] Unique superpowers skills are found"
else
echo " [FAIL] Unique superpowers skills not found"
exit 1
fi
if echo "$result" | grep -q 'NOTFOUND: null'; then
echo " [PASS] Non-existent skills return null"
else
echo " [FAIL] Non-existent skills should return null"
exit 1
fi
# Test 5: Test checkForUpdates function
echo ""
echo "Test 5: Testing checkForUpdates..."
# Create a test git repo
mkdir -p "$TEST_HOME/test-repo"
cd "$TEST_HOME/test-repo"
git init --quiet
git config user.email "test@test.com"
git config user.name "Test"
echo "test" > file.txt
git add file.txt
git commit -m "initial" --quiet
cd "$SCRIPT_DIR"
# Test checkForUpdates on repo without remote (should return false, not error)
result=$(node -e "
const { execSync } = require('child_process');
function checkForUpdates(repoDir) {
try {
const output = execSync('git fetch origin && git status --porcelain=v1 --branch', {
cwd: repoDir,
timeout: 3000,
encoding: 'utf8',
stdio: 'pipe'
});
const statusLines = output.split('\n');
for (const line of statusLines) {
if (line.startsWith('## ') && line.includes('[behind ')) {
return true;
}
}
return false;
} catch (error) {
return false;
}
}
// Test 1: Repo without remote should return false (graceful error handling)
const result1 = checkForUpdates('$TEST_HOME/test-repo');
console.log('NO_REMOTE:', result1);
// Test 2: Non-existent directory should return false
const result2 = checkForUpdates('$TEST_HOME/nonexistent');
console.log('NONEXISTENT:', result2);
// Test 3: Non-git directory should return false
const result3 = checkForUpdates('$TEST_HOME');
console.log('NOT_GIT:', result3);
" 2>&1)
if echo "$result" | grep -q 'NO_REMOTE: false'; then
echo " [PASS] checkForUpdates handles repo without remote gracefully"
else
echo " [FAIL] checkForUpdates should return false for repo without remote"
echo " Result: $result"
exit 1
fi
if echo "$result" | grep -q 'NONEXISTENT: false'; then
echo " [PASS] checkForUpdates handles non-existent directory"
else
echo " [FAIL] checkForUpdates should return false for non-existent directory"
exit 1
fi
if echo "$result" | grep -q 'NOT_GIT: false'; then
echo " [PASS] checkForUpdates handles non-git directory"
else
echo " [FAIL] checkForUpdates should return false for non-git directory"
exit 1
fi
echo ""
echo "=== All skills-core library tests passed ==="