Compare commits

...

284 Commits

Author SHA1 Message Date
Jesse Vincent
b0519329df 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-08 16:50:24 -08:00
Jesse Vincent
6ca430a0d3 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-08 16:50:24 -08:00
Jesse Vincent
6394555d14 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-08 16:50:24 -08:00
Jesse Vincent
5a3137c24f 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-08 16:50:24 -08:00
Jesse Vincent
03d182bc39 chore: gitignore triage directory 2026-02-08 16:50:12 -08:00
Jesse Vincent
e9b46118db docs: add brainstorm visual companion improvements to release notes 2026-02-08 16:50:12 -08:00
Jesse Vincent
3ed92079c2 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-08 16:50:12 -08:00
Jesse Vincent
b10a3c0995 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-08 16:50:12 -08:00
Jesse Vincent
9133401613 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-08 16:50:12 -08:00
Jesse Vincent
3abf068fed 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-08 16:50:12 -08:00
Jesse Vincent
acb50ce4b3 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-08 16:50:12 -08:00
Jesse Vincent
0d1efaf03d 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-08 16:50:12 -08:00
Jesse Vincent
3c2afcd150 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-08 16:50:12 -08:00
Jesse Vincent
f093a192ab docs: update plan header to reference checkbox syntax
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-08 16:50:12 -08:00
Jesse Vincent
e85234b396 feat: add plan review loop and checkbox syntax to writing-plans skill
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-08 16:50:12 -08:00
Jesse Vincent
2754b1a1c0 feat: add plan document reviewer prompt template
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-08 16:50:12 -08:00
Jesse Vincent
b2d325ae3b feat: add spec review loop to brainstorming skill
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-08 16:50:12 -08:00
Jesse Vincent
7ad7220124 feat: add spec document reviewer prompt template
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-08 16:50:12 -08:00
Jesse Vincent
41ff1a92b0 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-08 16:50:12 -08:00
Jesse Vincent
6915ca4376 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-08 16:50:12 -08:00
Jesse Vincent
2538180beb 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-08 16:50:12 -08:00
Jesse Vincent
3abe1cf4b4 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-08 16:50:12 -08:00
Jesse Vincent
75e037d29b 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-08 16:50:12 -08:00
Jesse Vincent
00fca66a52 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-08 16:50:12 -08:00
Jesse Vincent
e6d3c5ce15 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-08 16:49:15 -08:00
Jesse Vincent
5bacd0fd3c 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-08 16:49:15 -08:00
Jesse Vincent
a1f1c75b23 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-08 16:49:15 -08:00
Jesse Vincent
b7774ec82e 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-08 16:49:15 -08:00
Jesse Vincent
194cca5a47 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-08 16:49:15 -08:00
Jesse Vincent
e2c6be7174 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-08 16:49:15 -08:00
Jesse Vincent
23cb23b5bd 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-08 16:49:15 -08:00
Jesse Vincent
9be148f3b8 docs: add visual brainstorming implementation plan 2026-02-08 16:49:15 -08:00
Jesse Vincent
8360e087ff fix: preserve original event type, use source field for wrapper 2026-02-08 16:49:15 -08:00
Jesse Vincent
f4f62cb1af fix: correct visual companion documentation issues 2026-02-08 16:49:15 -08:00
Jesse Vincent
62b588799b feat: add visual companion to brainstorming skill 2026-02-08 16:49:15 -08:00
Jesse Vincent
6a524af4db test: add brainstorm server integration tests 2026-02-08 16:49:15 -08:00
Jesse Vincent
3ec1c2570b 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-08 16:49:15 -08:00
Jesse Vincent
e532c6dbbe feat: add browser helper library for event capture 2026-02-08 16:49:15 -08:00
Jesse Vincent
e3625b93e1 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-08 16:49:15 -08:00
Jesse Vincent
a98c5dfc9d Release v4.2.0: Windows fixes, Codex native skill discovery, worktree requirements 2026-02-05 17:34:36 -08:00
Drew Ritter
a72e416979 Fix stale Codex skills path in writing-skills SKILL.md
~/.codex/skills/ is deprecated; Codex uses ~/.agents/skills/ via native discovery.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 17:21:25 -08:00
Drew Ritter
8dd31c3da5 Add Windows uninstall instructions and expand migration steps
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 17:21:25 -08:00
Drew Ritter
6a07692da1 Drop installer script and AGENTS.md gatekeeper
Testing showed native skill discovery works without the AGENTS.md
gatekeeper — using-superpowers bootstraps itself via SKILL.md
frontmatter. Install is now just clone + symlink, driven by
INSTALL.md. No Node.js dependency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 17:21:25 -08:00
Drew Ritter
0771fd7cd1 Fix path resolution and symlink removal in Codex installer
Use fileURLToPath() instead of manual URL pathname parsing to correctly
handle paths with spaces and special characters on all platforms.
Replace execSync rm/rmdir with fs.unlinkSync for stale symlink removal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 17:21:25 -08:00
Drew Ritter
bcccc69271 Polish docs from 5-agent review
- INSTALL.md: add prerequisites, Windows note, verify step, clone
  deletion in uninstall
- README.codex.md: fix Windows section (junctions not symlinks),
  add description field guidance, consistent terminology
- install-codex.mjs: accurate link type labels (symlink vs junction)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 17:21:25 -08:00
Drew Ritter
3626ccc53e Rewrite Codex docs for native skill discovery
Replaces bootstrap CLI references with native discovery flow.
Install is now clone + run installer. Documents tool mappings,
personal skills path, and Windows junction fallback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 17:21:25 -08:00
Drew Ritter
47d3df7acc Rewrite INSTALL.md for native skill discovery
Two-step install: clone + run installer. Replaces the old manual
setup that required editing AGENTS.md by hand.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 17:21:25 -08:00
Drew Ritter
d41f951c4a Add minimal Codex installer for native skill discovery
Creates symlink from ~/.agents/skills/superpowers to repo skills dir,
updates ~/.codex/AGENTS.md with gatekeeper block, removes old bootstrap
block if present. Windows junction fallback when symlinks are blocked.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 17:21:25 -08:00
Drew Ritter
b4f56fec1b Remove bootstrap CLI and related files
The bootstrap CLI (superpowers-codex), Windows wrapper, and bootstrap
content file are no longer needed — Codex now has native skill discovery
that replaces this mechanism.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 17:21:25 -08:00
Drew Ritter
1143f9be3d Fix ~/ path expansion on Windows — use $HOME instead
PowerShell doesn't expand ~ when passed as an argument to node,
causing MODULE_NOT_FOUND errors. $HOME expands correctly in both
bash and PowerShell.

Fixes #285

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 12:11:11 -08:00
Drew Ritter
6cc2d8c920 Fix Windows/PowerShell invocation of superpowers-codex
Windows doesn't respect shebangs, so directly invoking the extensionless
superpowers-codex script triggers an "Open with" dialog. Prefix all
invocations with `node` (harmless on Unix, required on Windows) and add
a .cmd wrapper for manual invocation on Windows.

Fixes #285, #243

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 11:54:57 -08:00
Jesse Vincent
038abed026 fix: replace O(n^2) escape_for_json with parameter substitution
The character-by-character loop using ${input:$i:1} was O(n^2) in
bash due to substring copy overhead. On Windows Git Bash this took
60+ seconds, freezing terminal input even with async hooks.

Replaced with bash parameter substitution (${s//old/new}) which runs
each pattern as a single C-level pass. 7x faster on macOS, expected
to be dramatically faster on Windows Git Bash where the original
caused the worst hangs.

Relates to #404, #413
2026-02-05 11:38:06 -08:00
Jesse Vincent
961052e0f9 fix: run SessionStart hook async to prevent Windows terminal freeze
The synchronous SessionStart hook blocked the TUI from entering raw
mode on Windows, freezing all keyboard input. The pure-bash
escape_for_json function is O(n^2) on Git Bash, taking 60+ seconds.

Running the hook async prevents the freeze while still injecting
superpowers context. Multiple users confirmed this workaround.

Fixes #404, #413, #414, #419
2026-02-05 11:33:58 -08:00
Jesse Vincent
689e2a77fc 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-05 11:33:25 -08:00
Jesse Vincent
5e0d2f8175 Simplify installation verification instructions
Remove /help command check and specific slash command list. Skills are
primarily invoked by describing what you want to do, not by running
specific commands.
2026-02-05 11:32:46 -08:00
Jesse Vincent
06b92f3682 Merge pull request #382 from clkao/fix/subagent-worktree-requirement
fix: require worktree setup before subagent-driven-development and executing-plans
2026-01-30 09:51:30 -08:00
Jesse Vincent
9819209bba Merge pull request #361 from deinspanjer/codex-bootstrap-support-collab-subagent
Codex: clarify subagent tool mapping in bootstrap + README
2026-01-30 09:48:29 -08:00
CL Kao
c7816ee2a6 docs: change main branch red flag to require explicit user consent
Instead of prohibiting main branch work entirely, allow it with explicit
user consent. This is more flexible while still ensuring users are aware
of the implications.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 15:12:50 -08:00
CL Kao
b323e35805 docs(executing-plans): add worktree requirement before executing plans
Add Integration section referencing using-git-worktrees skill as required,
consistent with subagent-driven-development skill. Also add reminder to
never start on main/master branch.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 14:48:24 -08:00
CL Kao
bb2ff5d309 docs(using-git-worktrees): add subagent/executing-plans as callers
Update Integration section to show bidirectional relationship:
subagent-driven-development and executing-plans now list
using-git-worktrees as required, so this skill should list
them as callers.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 14:46:45 -08:00
CL Kao
b63d485955 docs(subagent-driven-development): add main branch red flag to Never list
Add explicit warning against starting implementation on main/master
branch without first using a worktree for isolation.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 14:45:04 -08:00
CL Kao
fa3f46d4e9 docs(subagent-driven-development): add using-git-worktrees as required skill
Adds using-git-worktrees as the first required workflow skill in the
Integration section. This makes explicit that an isolated workspace
should be set up before starting subagent-driven development.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 14:43:33 -08:00
CL Kao
f8dbe7b196 test: add Test 9 - main branch red flag warning
TDD: Test verifies that subagent-driven-development skill warns
against starting implementation directly on main/master branch.
Test expects skill to recommend worktree or feature branch instead.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 14:41:39 -08:00
CL Kao
93cf2ee84f test: add worktree requirement test for subagent-driven-development
Add Test 8 to verify that using-git-worktrees is mentioned as a required
skill for subagent-driven-development. This test will initially fail per
TDD approach - the skill file needs to be updated to pass this test.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 14:39:50 -08:00
CL Kao
1872f50b64 fix(tests): handle case variations in skill recognition test
The assertion now matches "subagent-driven-development", "Subagent-Driven
Development", and "Subagent Driven" since Claude's responses may use
different casing and formatting styles.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 14:34:38 -08:00
Daniel E.
8904b7d9dc codex: clarify subagent tool mapping in bootstrap 2026-01-25 18:42:22 -05:00
Jesse Vincent
469a6d81eb Merge pull request #349 from obra/fix/opencode-issues
fix(opencode): standardize on plugins/ directory, fix symlink docs
2026-01-23 12:09:13 -08:00
Jesse Vincent
4b6cef98ac chore: bump version to 4.1.1
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 20:08:47 +00:00
Jesse Vincent
03087b13b8 fix(opencode): standardize on plugins/ directory per official docs
OpenCode officially documents ~/.config/opencode/plugins/ (plural) as the
plugin directory. Our docs previously used plugin/ (singular), which also
works but caused confusion.

Changes:
- Renamed .opencode/plugin/ to .opencode/plugins/ in repo structure
- Updated INSTALL.md to use plugins/ everywhere
- Updated README.opencode.md (all platforms: Linux, macOS, Windows CMD,
  PowerShell, Git Bash) to use plugins/
- Updated test scripts to match

Tested: Both singular and plural forms work, but we now match official docs.

Fixes #343

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 18:31:45 +00:00
Jesse Vincent
493ac18dfe fix(opencode): update docs for native skills, fix symlink instructions
Issues addressed:
- #342: INSTALL.md still referenced removed find_skills/use_skill tools
- #339: Symlink instructions could fail if target already exists

Changes:
- INSTALL.md: Added missing skills symlink step, updated to native skill tool
- INSTALL.md: Removed Node.js prerequisite (no longer needed)
- README.opencode.md: Added explicit rm before ln -s (ln -sf doesn't remove dirs)
- Both files: Use ln -s instead of ln -sf for clarity

Note: #343 (plugin vs plugins folder name) not addressed in this commit

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 17:33:23 +00:00
Jesse Vincent
35d4fbcd0b chore: bump plugin version to 4.1.0
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 04:10:23 +00:00
Jesse Vincent
19c70afc99 chore: release v4.1.0
Breaking changes:
- OpenCode: Switched to native skills system (migration required)

Fixes:
- OpenCode: Fixed agent reset on session start (#226)
- OpenCode: Fixed Windows installation (#232)
- Claude Code: Fixed Windows hook execution for 2.1.x

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 04:07:35 +00:00
Jesse Vincent
405a025eea Merge pull request #335 from obra/fixes-for-main
fix: OpenCode native skills + Windows hook execution
2026-01-22 20:06:45 -08:00
Jesse Vincent
36fcd57626 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-01-23 03:56:52 +00:00
Jesse Vincent
3964d18670 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-01-23 03:56:12 +00:00
oribi
a01a135fe1 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.
2026-01-19 13:54:50 -08:00
Vinicius da Motta
ac471e69c2 fix use_skill agent context (#290) 2026-01-18 17:02:48 -08:00
Joshua Shanks
a08f088968 docs: fix documentation accuracy issues in skills (#157)
- Fix broken commit message HEREDOC syntax in sharing-skills/SKILL.md
  - Move entire message inside command substitution for valid bash

- Fix contradictory test requirements in systematic-debugging/SKILL.md
  - Clarify automated tests are "strongly preferred"
  - One-off scripts should be documented for regression testing
  - Requirement is for "reproducible test" not escape clause

- Fix typo in testing-skills-with-subagents/SKILL.md
  - "ith" -> "with" in checklist item
2026-01-14 14:21:22 -08:00
Jesse Vincent
b9e16498b9 Release v4.0.3: Strengthen using-superpowers for explicit skill requests 2025-12-26 22:55:32 -06:00
Jesse Vincent
f6d50c74b2 Bump version to 4.0.3 2025-12-26 22:53:58 -06:00
Jesse Vincent
3dac35e0b3 Strengthen using-superpowers for explicit skill requests
Addresses failure mode where Claude skips skill invocation even when
user explicitly requests it by name (e.g., "subagent-driven-development,
please").

Skill changes:
- "Check for skills" → "Invoke relevant or requested skills"
- "BEFORE ANY RESPONSE" → "BEFORE any response or action"
- Added reassurance that wrong skill invocations are okay
- New red flag: "I know what that means"

Tests:
- New test suite for explicit skill requests
- Single-turn and multi-turn scenarios with --continue
- Tests with haiku model and user CLAUDE.md
2025-12-26 22:41:22 -06:00
Jesse Vincent
131c1f189f Release v4.0.2: Make slash commands user-only
- Added disable-model-invocation to /brainstorm, /execute-plan, /write-plan
- Commands now restricted to manual user invocation only
- Underlying skills remain available for autonomous invocation
2025-12-23 23:03:31 -08:00
Jesse Vincent
9baedaa117 Make slash commands user-only with disable-model-invocation
Added disable-model-invocation: true to /brainstorm, /execute-plan, and
/write-plan commands. Claude can still invoke the underlying skills
directly, but the slash commands are now restricted to manual user
invocation only.
2025-12-23 23:03:19 -08:00
Jesse Vincent
66a2dbd80a Add automation-over-documentation guidance to writing-skills
Mechanical constraints should be automated, not documented—save skills
for judgment calls.

Based on insight from @EthanJStark in PR #146.
2025-12-23 23:03:19 -08:00
Jesse Vincent
1455ac0631 Add GitHub thread reply guidance to receiving-code-review
When replying to inline review comments, use the thread API rather than
posting top-level PR comments.

Based on feedback from @ralphbean in PR #79.
2025-12-23 23:03:19 -08:00
egornomic
e64ad670df fix: inherit agent model (#144) 2025-12-23 21:46:15 -08:00
Mike Harrison
c037dcbf4b fix: use git check-ignore for worktree gitignore verification (#160)
* fix: use git check-ignore for worktree gitignore verification

The using-git-worktrees skill previously used grep to check only the
local .gitignore file, missing patterns in global gitignore configurations
(core.excludesfile). This caused unnecessary modifications to local
.gitignore when the directory was already globally ignored.

Changed verification from grep to git check-ignore, which respects Git's
full ignore hierarchy (local, global, and system gitignore files).

Fixes obra/superpowers#101

Tested with: Subagent pressure scenarios verifying correct behavior with
global gitignore configuration. Baseline test confirmed the bug, post-fix
test confirmed correct behavior.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

* style: convert bold emphasis to headings in Common Mistakes section

Convert **Title** patterns to ### Title headings for markdown lint
compliance (MD036 - no emphasis as heading).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 11:26:33 -08:00
Jesse Vincent
a7a8c08c02 Clarify that Skill tool loads skill content directly
Fixes pattern where Claude would invoke a skill then try to Read the
file separately. The Skill tool already provides the content.

- Add "How to Access Skills" section to using-superpowers
- Change "read the skill" → "invoke the skill"
- Commands now use fully qualified names (superpowers:brainstorming etc)
2025-12-22 14:27:35 -08:00
Jesse Vincent
80643c2604 Update README for v4.0.0 skill consolidations and two-stage review 2025-12-17 18:07:40 -08:00
Jesse Vincent
95c6e16336 Prepare v4.0.0 release
- Rewrite release notes centering new features (two-stage review,
  debugging tools, test infrastructure)
- Bump version to 4.0.0 in plugin.json and marketplace.json
- Remove .claude/settings.local.json from tracking
- Add .claude/ to .gitignore
2025-12-17 16:45:35 -08:00
Jesse Vincent
612fbcdd01 Tweak the brainstorming skill to try to improve triggering 2025-12-17 16:44:52 -08:00
Jesse Vincent
70bf3a9e7f Bump version to v4.0.0 2025-12-17 16:44:52 -08:00
Jesse Vincent
c2125b41e3 Update v3.7.0 release notes with all changes since v3.6.2 2025-12-17 16:44:52 -08:00
Jesse Vincent
ae0ef56b44 Add skill triggering test framework
Creates tests/skill-triggering/ to validate skills trigger correctly from
naive prompts (without explicitly naming the skill). Tests 6 skills:
- systematic-debugging
- test-driven-development
- writing-plans
- dispatching-parallel-agents
- executing-plans
- requesting-code-review

All 6 tests pass - skills trigger correctly based on their descriptions.
2025-12-17 16:44:52 -08:00
Jesse Vincent
030a222af1 Fix skill descriptions: remove workflow summaries that override flowcharts
Testing revealed that descriptions summarizing workflow cause Claude to
follow the description instead of reading the skill body. Changed all
descriptions to "when to use" triggers only:

- dispatching-parallel-agents: 2+ independent tasks without shared state
- executing-plans: have a written plan to execute with review checkpoints
- requesting-code-review: completing tasks, features, or before merging
- systematic-debugging: encountering bugs before proposing fixes
- test-driven-development: implementing features before writing code
- writing-plans: have spec/requirements for multi-step task before coding
- writing-skills: updated with "description trap" documentation

The description trap: workflow summaries in descriptions create shortcuts
Claude takes, skipping the skill body entirely.
2025-12-17 16:44:52 -08:00
Jesse Vincent
2a19be0b78 Document skill description trap: descriptions override flowcharts
Testing revealed that skill descriptions summarizing workflow cause
Claude to follow the description instead of reading the skill body.

- A description saying "code review between tasks" caused ONE review
- The flowchart clearly showed TWO reviews (spec compliance + quality)
- Minimal description ("Use when...") correctly deferred to flowchart

Updated writing-skills with:
- "Description = When to Use, NOT What the Skill Does" section
- Cautionary tale about this actual failure
- Examples of good (triggers only) vs bad (workflow summary) descriptions

Updated subagent-driven-development:
- Removed workflow summary from description
- Now just: "Use when executing implementation plans..."

Updated test runner:
- Added --dangerously-skip-permissions for automated testing
2025-12-17 16:44:52 -08:00
Jesse Vincent
cd83439bb2 Add .claude settings to scaffolds for auto-approved permissions 2025-12-17 16:44:52 -08:00
Jesse Vincent
ed06dcbe27 Fix skill description to match flowchart: two-stage review (spec then quality) 2025-12-17 16:44:52 -08:00
Jesse Vincent
baef5241aa Add test suite for subagent-driven-development skill
Two test projects for validating the skill with full end-to-end runs:
- go-fractals: 10 tasks, CLI tool with Sierpinski and Mandelbrot
- svelte-todo: 12 tasks, CRUD app with localStorage and Playwright

Each test has design.md, plan.md, and scaffold.sh. Run with:
  ./tests/subagent-driven-dev/run-test.sh go-fractals
2025-12-17 16:44:51 -08:00
Jesse Vincent
28ba020000 Add render-graphs.js tool for visualizing skill flowcharts 2025-12-17 16:44:51 -08:00
Jesse Vincent
a9b94ae5d7 Rewrite subagent-driven-development with executable flowcharts
- Add graphviz/dot flowcharts as primary executable instructions
- Extract prompt templates to separate collateral files:
  - ./implementer-prompt.md
  - ./spec-reviewer-prompt.md
  - ./code-quality-reviewer-prompt.md
- Use qualified skill names (superpowers:skill-name)
- Make flowchart labels explicit and action-oriented
- Add "When to Use" decision flowchart
- Keep detailed prose as supporting content
2025-12-17 16:44:51 -08:00
Jesse Vincent
5845b52747 Consolidate debugging techniques into systematic-debugging skill
Move condition-based-waiting, defense-in-depth, and root-cause-tracing
into systematic-debugging as progressive disclosure supporting files.

These techniques are now available as reference material within the
systematic-debugging skill directory, reducing skill count while keeping
content accessible when needed.

Note: Claude Code's SLASH_COMMAND_TOOL_CHAR_BUDGET env variable silently
limits skill discovery, which drove this consolidation to ensure core
skills remain visible.
2025-12-17 16:44:51 -08:00
Jesse Vincent
3f725ff0d4 Strengthen brainstorming skill trigger and add skill priority guidance
- Update brainstorming description to use imperative "You MUST use this"
- Clarify trigger: "before any creative work - creating features, building
  components, adding functionality, or modifying behavior"
- Add Skill Priority section to using-superpowers to ensure process skills
  (brainstorming, debugging) are invoked before implementation skills
2025-12-17 16:44:51 -08:00
Jesse Vincent
b57c27d815 Integrate testing-skills-with-subagents into writing-skills
- Moved testing-skills-with-subagents to writing-skills/testing-skills-with-subagents.md
- Moved examples/ directory to writing-skills/examples/
- Updated writing-skills to reference via @testing-skills-with-subagents.md
- Updated README to reflect consolidation
- Removed standalone skill (now a supporting reference)
2025-12-17 16:44:51 -08:00
Jesse Vincent
718ec45d33 Integrate testing-anti-patterns into test-driven-development
- Moved testing-anti-patterns to test-driven-development/testing-anti-patterns.md
- Added reference in TDD skill for progressive disclosure
- Updated README to reflect consolidation
- Removed standalone skill (now a supporting reference)
2025-12-17 16:44:51 -08:00
Jesse Vincent
c7caee5647 Remove obsolete sharing-skills skill
The contribution workflow is now via standard GitHub PR process,
not a dedicated skill. The skill was documenting an old workflow
that no longer applies.
2025-12-17 16:44:51 -08:00
Jesse Vincent
1f611f5c0c Add v3.7.0 release notes for dev branch changes 2025-12-17 16:44:51 -08:00
Jesse Vincent
2d7408d0c6 Improve using-superpowers skill to prevent rationalization failures
Tested against claude -p with multiple scenarios. Key fixes:
- Clarify skill check comes BEFORE ANY response including clarifications
- Add rationalizations: "I need more context first", "Let me explore first", "This feels productive"
- Flowchart entry point now "User message received" → clearer blocking gate
- Shorter, more scannable format (flowchart + table)

Verified: "Fix login bug" now triggers systematic-debugging first
2025-12-17 16:44:51 -08:00
Jesse Vincent
9464a51779 Add comprehensive testing documentation
Documents:
- How to run integration tests
- subagent-driven-development test details
- Token analysis tool usage
- Troubleshooting common issues
- Writing new integration tests
- Session transcript format
2025-12-17 16:44:51 -08:00
Jesse Vincent
faa65e7163 Add token usage analysis to subagent-driven-development test
- Rewrote analyze-token-usage.py to parse main session file correctly
- Extracts usage from toolUseResult fields for each subagent
- Shows breakdown by agent with descriptions
- Integrated into test-subagent-driven-development-integration.sh
- Displays token usage automatically after each test run
2025-12-17 16:44:50 -08:00
Jesse Vincent
24ca8cd9d5 fix: verify skill usage via session transcript not text output
The skill instructions are internal and don't appear in user-facing
output. Updated verification to parse the session JSONL transcript
and check for actual tool usage:
- Skill tool invocation
- Task tool (subagents)
- TodoWrite (tracking)
- Implementation results
2025-12-17 16:44:50 -08:00
Jesse Vincent
8fbeca830a test: use bypassPermissions mode for unrestricted testing
dontAsk mode was auto-denying Write tool. Use bypassPermissions
instead to allow full tool access in this controlled test environment.
2025-12-17 16:44:50 -08:00
Jesse Vincent
67de772d7f test: auto-approve permissions with --permission-mode dontAsk
Headless tests need automatic permission approval to write files.
Using dontAsk mode to auto-approve permissions for test directory.
2025-12-17 16:44:50 -08:00
Jesse Vincent
cf72863792 test: add --add-dir flag for temp directory access
Claude needs explicit permission to access the temp test directory.
Added --add-dir flag to grant access to the test project.
2025-12-17 16:44:50 -08:00
Jesse Vincent
baa23b16bb test: show Claude output in real-time during integration test
Use tee instead of redirection so test output is visible during
execution while still being saved to file for analysis.
2025-12-17 16:44:50 -08:00
Jesse Vincent
0aba33be1c fix: run integration test from superpowers dir to access local dev skills
The superpowers-dev marketplace makes skills available only when running
from the plugin directory. Updated test to run claude from superpowers
directory while working on the test project.
2025-12-17 16:44:50 -08:00
Jesse Vincent
06310d6f5f Fix tests to use --allowed-tools flag
Claude Code headless mode requires --allowed-tools flag to actually
execute tool calls. Without it, Claude only responds as if it's doing
things but doesn't actually use tools.

Changes:
- Updated run_claude helper to accept allowed_tools parameter
- Updated integration test to use --allowed-tools=all
- This enables actual tool execution (Write, Task, Bash, etc.)

Now the integration test should actually execute the workflow instead
of just talking about it.
2025-12-17 16:44:50 -08:00
Jesse Vincent
dc11a093c3 Fix syntax error in integration test
Simplified command substitution to avoid shell parsing issues.
Instead of nested heredoc in command substitution, write prompt
to file first then read it.
2025-12-17 16:44:50 -08:00
Jesse Vincent
fa946ae465 Add integration test for subagent-driven-development
Created full end-to-end integration test that executes a real plan
and verifies the new workflow improvements actually work.

New test: test-subagent-driven-development-integration.sh
- Creates real Node.js test project
- Generates implementation plan (2 tasks)
- Executes using subagent-driven-development skill
- Verifies 8 key behaviors:
  1. Plan read once at beginning (not per task)
  2. Full task text provided to subagents (not file reading)
  3. Subagents perform self-review
  4. Spec compliance review before code quality
  5. Spec reviewer reads code independently
  6. Working implementation produced
  7. Tests pass
  8. No extra features added (spec compliance)

Integration tests are opt-in (--integration flag) due to 10-30 min runtime.

Updated run-skill-tests.sh:
- Added --integration flag
- Separates fast tests from integration tests
- Shows note when integration tests skipped

Updated README with integration test documentation.

Run with:
  ./run-skill-tests.sh                # Fast tests only
  ./run-skill-tests.sh --integration  # Include integration tests
2025-12-17 16:44:50 -08:00
Jesse Vincent
51a171cd14 Add Claude Code skills test framework
Created automated test suite for testing superpowers skills using
Claude Code CLI in headless mode.

New files:
- tests/claude-code/run-skill-tests.sh - Main test runner
- tests/claude-code/test-helpers.sh - Helper functions for testing
- tests/claude-code/test-subagent-driven-development.sh - First test
- tests/claude-code/README.md - Documentation

Test framework features:
- Run Claude Code with prompts and capture output
- Assertion helpers (contains, not_contains, count, order)
- Test project creation helpers
- Timeout support (default 5 minutes)
- Verbose mode for debugging
- Specific test selection

First test verifies subagent-driven-development skill:
- Skill loading
- Workflow ordering (spec compliance before code quality)
- Self-review requirements
- Plan reading efficiency (read once)
- Spec compliance reviewer skepticism
- Review loops
- Task context provision

Run with: cd tests/claude-code && ./run-skill-tests.sh
2025-12-17 16:44:50 -08:00
Jesse Vincent
466332f698 Emphasize spec compliance review must complete before code quality
Made sequencing explicit:
- Spec compliance review loop must fully complete () before code quality
- Added "Do NOT proceed to code quality review until spec compliance is "
- Code Quality Review section starts with "Only run after spec compliance review is complete"
- Red Flags: Added "Start code quality review before spec compliance is  (wrong order)"

This ensures we don't waste time reviewing code quality of the wrong
implementation. Verify they built the right thing first, then verify
they built it well.
2025-12-17 16:44:49 -08:00
Jesse Vincent
87afde2390 Make spec compliance reviewer skeptical and verification-focused
The spec compliance reviewer now:
- Does NOT trust implementer's report
- Is warned implementer finished suspiciously quickly
- MUST verify everything by reading actual code
- Compares implementation to requirements line by line
- Reports issues with file:line references

Key additions:
- "Do Not Trust the Report" section
- Explicit DO NOT / DO lists
- "Verify by reading code, not by trusting report"
- Changed "What Was Implemented" to "What Implementer Claims They Built"

This prevents rubber-stamping and ensures independent verification
of spec compliance against actual codebase.
2025-12-17 16:44:49 -08:00
Jesse Vincent
2a6a40fe10 Improve subagent-driven-development workflow
Key improvements based on feedback:

1. Read plan once, not per task
   - Extract all tasks in Step 1
   - Reference extracted tasks in Step 2
   - Eliminates redundant file reading

2. Enable questions during work
   - Not just before, but also while working
   - "It's always OK to ask questions"
   - Don't guess or make assumptions

3. Add self-review before reporting
   - Completeness: implemented everything?
   - Quality: best work, clear names?
   - Discipline: avoided overbuilding?
   - Testing: comprehensive, real behavior?
   - Catches issues before handoff

4. Add spec compliance review
   - Separate reviewer checks: built the right thing?
   - Flags missing requirements
   - Flags extra/unneeded work
   - Flags misunderstandings
   - Runs BEFORE code quality review

5. Make reviews loops, not one-shot
   - Reviewer finds issues
   - Implementer fixes
   - Reviewer reviews again
   - Repeat until approved
   - Applies to both spec and code quality

Two-stage review process:
- Stage 1: Spec compliance (right thing?)
- Stage 2: Code quality (built well?)

This enables subagents to do their best work with clear requirements,
opportunities to clarify, self-critique, and thorough review loops.
2025-12-17 16:44:49 -08:00
Jesse Vincent
97ce1f8fe0 Update subagent-driven-development: controller provides full task text
Changed workflow so controller provides complete task context directly
rather than making subagent read plan file.

Key changes:
- Controller reads plan and extracts full task text
- Controller provides scene-setting context (dependencies, architecture)
- Subagent receives complete information in prompt (no file reading)
- Subagent can ask clarifying questions before beginning work
- Controller handles questions/concerns before subagent proceeds

Benefits:
- No file reading overhead for subagent
- Controller curates exactly what context is needed
- Questions surfaced before work begins (not after)
- Subagent has complete information to do best work

This enables subagents to start with clarity rather than ambiguity.
2025-12-17 16:44:49 -08:00
Jesse Vincent
e7e50ac947 Add skills improvement plan from user feedback
Analyzed feedback from two Claude instances using superpowers in real
development scenarios. Identified 8 core problems and proposed improvements
organized by impact and risk.

Key problems:
- Configuration change verification gap (verify success not intent)
- Background process accumulation across subagents
- Context bloat in subagent prompts
- Missing self-reflection before handoff
- Mock-interface drift
- Code reviewer file access issues
- Skills not being read/enforced
- Fix workflow latency

Proposed improvements organized in 3 phases:
- Phase 1: High-impact, low-risk (do first)
- Phase 2: Moderate changes (test carefully)
- Phase 3: Optimization (validate first)

See plan for detailed analysis and open questions.
2025-12-17 16:44:49 -08:00
Joshua Shanks
5faddc4087 fix codex path in release notes (#155)
Signed-off-by: Joshua Shanks <jjshanks@gmail.com>
2025-12-09 22:44:45 -08:00
Joshua Shanks
d2900eae0c fix: correct context window documentation link (#156)
Update relative link to absolute URL for external Anthropic docs.
2025-12-09 22:44:14 -08:00
Shaan Majid
4ac67830d9 chore: gitignore .claude/settings.local.json (#153)
This file contains machine-specific paths and permissions that cause
warnings when cloning the repo fresh.
2025-12-09 12:02:49 -08:00
Jesse Vincent
154d664373 Release v3.6.2: Fix Linux compatibility in polyglot hook wrapper
Fixed POSIX compatibility issue in hooks/run-hook.cmd that caused
"Bad substitution" errors on Ubuntu/Debian systems where /bin/sh is dash.

Changes:
- Replaced bash-specific ${BASH_SOURCE[0]:-$0} with POSIX-compliant $0
- Tested with both bash and sh (POSIX mode) on macOS
- Updated version to 3.6.2 in all required files

Fixes #141
2025-12-03 10:14:19 -08:00
Jesse Vincent
8462c20cce Release v3.6.1: Fix Windows arg forwarding in polyglot wrapper
- Add validation for missing script name
- Forward up to 8 additional arguments to bash on Windows
- Fixes CodeRabbit review feedback from #134
2025-12-01 16:18:56 -08:00
Jesse Vincent
a0c1e73a1d Release v3.6.0: Add Windows support for plugin hooks
New features:
- Cross-platform polyglot wrapper (run-hook.cmd) for Windows/Unix
- Pure bash JSON escaping for Windows compatibility
- Documentation for polyglot hooks setup
2025-12-01 15:52:36 -08:00
Jesse Vincent
94e9e2596c Add Windows support for plugin hooks (#134)
* feat: Add Windows support for session-start hook

- Create polyglot session-start.cmd that works in both CMD and bash
- Update hooks.json to use the .cmd polyglot launcher
- Replace sed/awk with pure bash for JSON escaping (Windows compatibility)

The polyglot script uses a heredoc trick:
- CMD sees the @echo off block and runs bash.exe with cygpath conversion
- Bash sees a heredoc and skips to the Unix section

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

* fix: Add execute permission to session-start.cmd for Unix

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

* docs: Add comprehensive polyglot hooks documentation

- Add docs/windows/polyglot-hooks.md explaining the cross-platform technique
- Add reusable run-hook.cmd wrapper for parameterized hook execution
- Document how the polyglot works in CMD vs bash
- Include troubleshooting section and related GitHub issues

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

* test: Add polyglot hook test script for macOS/Linux

Run ./test-polyglot.sh from repo root to verify:
- Required files exist with execute permissions
- Simple wrapper (session-start.cmd) produces valid JSON
- Parameterized wrapper (run-hook.cmd) works
- Heredoc correctly skips CMD block on Unix

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

* fix: Use direct pipe to jq in test to avoid variable escaping issues

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

* refactor: Use single reusable run-hook.cmd for all hooks

- Remove session-start.cmd in favor of run-hook.cmd
- Update hooks.json to use: run-hook.cmd session-start.sh
- Simplify test script to only test run-hook.cmd

This makes it easy to add more hooks - just create the .sh file
and add a line to hooks.json pointing to run-hook.cmd with the script name.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

* fix: Simplify run-hook.cmd CMD block

Pass path directly to bash instead of using cygpath in a subshell.
The complex quoting was causing issues on Windows.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

* chore: Remove test-polyglot.sh

Testing complete - polyglot hooks work on Windows and macOS.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-01 15:42:12 -08:00
avleen
1b878e4fa1 Remove model name from core-reviewer (#120) 2025-11-30 13:22:56 -08:00
Jesse Vincent
515c86fd07 tweak: clarify skill tool path 2025-11-29 09:29:31 -08:00
Jesse Vincent
e416a0e105 Revert "feat: echo skill base directory in use-skill"
This reverts commit a08f7de64b.
2025-11-28 22:48:40 -08:00
Jesse Vincent
a08f7de64b feat: echo skill base directory in use-skill 2025-11-28 22:43:02 -08:00
Josh Thomas
207a23e4d5 fix(opencode): Use synthetic: true for invisible content injection (#122)
The OpenCode plugin injects the bootstrap and skill content as visible
user messages. While `noReply: true` prevents an AI response, the
injected content still appears in the chat UI which makes it just a bit
noisy.

OpenCode's `TextPartInput` supports a `synthetic` Boolean property that
hides parts from the UI while keeping them visible to the AI -- it's
been available in the v2 message format since around the v1.0.0 version
bump.
2025-11-26 09:38:35 -08:00
Jesse Vincent
c35c5f637e Update README to be a little more human-written (and mention github sponsors) 2025-11-24 13:13:01 -08:00
Jesse Vincent
9a01a0dcc1 chore: bump version to 3.5.1 2025-11-24 12:29:02 -08:00
Jesse Vincent
8c7826c34d fix(opencode): use session.created event for bootstrap injection
Switch from chat.message hook to session.created event for injecting
the using-superpowers skill content. The new approach:

- Injects at session creation via session.prompt() with noReply: true
- Explicitly tells model the skill is already loaded to prevent
  redundant use_skill calls
- Consolidates bootstrap generation into getBootstrapContent() helper
- Removes fallback pattern in favor of single implementation

Tested with 10 consecutive test runs and manual skill trigger validation.
2025-11-24 12:28:11 -08:00
Stefan Otte
4ae8fc8713 Use more generic "#!/usr/bin/env bash" instead of "#!/bin/bash" (#80)
"#!/bin/bash" does not work with nixos.
2025-11-24 09:45:58 -08:00
Jesse Vincent
94089bdce5 chore: bump version to 3.5.0 2025-11-23 20:04:24 -08:00
Jesse Vincent
9297fd24d5 docs: update release notes with test suite and documentation improvements 2025-11-23 19:52:46 -08:00
Claude
d0806ba5af fix: cleanup remaining code review issues
- Remove unused destructured parameters (project, $, worktree) from plugin
- Add test coverage for checkForUpdates function (error handling cases)
2025-11-24 00:25:26 +00:00
Claude
6ecd72c5bf fix: address code review issues in opencode support branch
- Fix test runner exiting early due to ((var++)) returning 1 with set -e
- Remove duplicate frontmatter stripping in superpowers-codex, use shared skillsCore.stripFrontmatter()
- Remove unused promptsDir/promptFile variables from opencode plugin
- Derive superpowers skills path from __dirname for better install flexibility
- Simplify test-skills-core.sh by removing failing ESM import attempt
2025-11-23 23:37:53 +00:00
Jesse Vincent
f600f969f5 docs: remove duplicate sections and fix conflicting information 2025-11-23 14:51:44 -08:00
Jesse Vincent
4ef2f9185d docs: add using-git-worktrees and subagent-driven-development to workflow 2025-11-23 14:05:59 -08:00
Jesse Vincent
8a626e75f3 docs: rewrite workflow in terms of skills, not commands 2025-11-23 14:01:32 -08:00
Jesse Vincent
014b11cf57 docs: emphasize automatic skill activation over manual commands 2025-11-23 13:57:36 -08:00
Jesse Vincent
3f73365155 docs: add workflow section showing brainstorm→plan→execute→finish flow 2025-11-23 13:55:23 -08:00
Jesse Vincent
9f33fc95bf docs: rewrite README to explain problem, solution, and philosophy clearly 2025-11-23 13:53:53 -08:00
Jesse Vincent
9220bb62af docs: simplify opencode readme instructions to match codex style 2025-11-23 13:50:37 -08:00
Jesse Vincent
f5a4002daf docs: reorganize platform installation docs with inline quick-start and detailed guides 2025-11-23 13:49:12 -08:00
Jesse Vincent
9dcf5eaabe fix: add OPENCODE_CONFIG_DIR for proper test isolation 2025-11-23 13:36:26 -08:00
Jesse Vincent
f3d6c331a1 test: add automated test suite for opencode plugin
Create comprehensive tests in tests/opencode/ that verify the plugin
works correctly in an isolated test environment:

- setup.sh: Creates temp HOME and installs plugin with proper symlinks
- test-plugin-loading.sh: Verifies plugin structure and JavaScript syntax
- test-skills-core.sh: Unit tests for skills-core.js library functions
- test-tools.sh: Integration tests for use_skill/find_skills (requires OpenCode)
- test-priority.sh: Tests project > personal > superpowers priority
- run-tests.sh: Main test runner with options for integration tests

Run basic tests: ./tests/opencode/run-tests.sh
Run all tests: ./tests/opencode/run-tests.sh --integration
2025-11-23 12:28:58 -08:00
Jesse Vincent
b0ba2cf15a docs: update documentation with message insertion and project skills features 2025-11-23 12:14:48 -08:00
Jesse Vincent
cbbd8d2edf docs: add project-local skills documentation 2025-11-23 12:13:19 -08:00
Jesse Vincent
9cd6c52acc feat: use message insertion pattern for persistence and add project skills support
- Add project-local skills directory (.opencode/skills/) with highest priority
- Use client.session.prompt() with noReply for skill loading to persist across compaction
- Add session.compacted event handler to re-inject bootstrap after context compaction
- Update find_skills to list skills from project > personal > superpowers directories
- Support project: prefix for explicit project skill loading
- Keep chat.message hook as fallback for initial context injection
2025-11-23 12:10:41 -08:00
Jesse Vincent
107859a748 refactor: remove prompt file, use automatic chat.message injection
- Delete .opencode/prompts/superpowers.txt (no longer needed)
- Simplify INSTALL.md to remove prompt file copying and agent configuration steps
- Installation now relies on plugin's chat.message hook for automatic context injection
- Cleaner, simpler setup process with fewer manual configuration steps
2025-11-23 10:57:48 -08:00
Jesse Vincent
5f5b789e3e feat: add chat.message hook to inject superpowers context automatically 2025-11-23 10:51:26 -08:00
Jesse Vincent
7db10cf540 docs: add implementation plan 2025-11-22 21:09:07 -08:00
Jesse Vincent
67ce04077b fix: use tool() helper function for proper OpenCode tool definitions 2025-11-22 21:07:57 -08:00
Jesse Vincent
d749c620b5 fix: use tool object instead of tools array per opencode api 2025-11-22 21:04:00 -08:00
Jesse Vincent
aa1fe045c6 refactor: use static prompt file instead of dynamic config hook 2025-11-22 20:59:53 -08:00
Jesse Vincent
368674419a fix: use agent prompts instead of event hooks for context injection
OpenCode doesn't support injecting context through event hooks. Instead,
the plugin now generates a prompt file that agents can reference via
{file:./prompts/superpowers.txt} in their configuration.
2025-11-22 16:13:05 -08:00
Jesse Vincent
c940d84f3d fix: use correct event subscription format for opencode 2025-11-22 15:47:38 -08:00
Jesse Vincent
8e7f90a954 fix: use session.created hook instead of session.started 2025-11-22 15:45:58 -08:00
Jesse Vincent
d92de28150 refactor: convert skills-core and plugin to pure ESM for module compatibility 2025-11-22 13:23:05 -08:00
Jesse Vincent
fa53c8f925 fix: use require inside plugin function to load commonjs module 2025-11-22 13:22:17 -08:00
Jesse Vincent
d3e89e8719 fix: convert opencode plugin to ES module syntax
- Replace CommonJS require() with ES import statements
- Use createRequire() for loading CommonJS skills-core module
- Export plugin as 'SuperpowersPlugin' named export
- Maintains compatibility with existing skills-core.js CommonJS module
2025-11-22 12:53:26 -08:00
Jesse Vincent
b746f7587b docs: fix plugin installation instructions for opencode 2025-11-22 12:50:43 -08:00
Jesse Vincent
4eab16380b refactor: extract frontmatter stripping to shared helper function 2025-11-22 12:41:58 -08:00
Jesse Vincent
7ffff61965 docs: add opencode support to release notes 2025-11-22 12:34:35 -08:00
Jesse Vincent
fbd419e394 docs: add opencode support to readme 2025-11-22 12:34:21 -08:00
Jesse Vincent
a131267d7c docs: add opencode installation guide 2025-11-22 12:34:06 -08:00
Jesse Vincent
26c152b37e feat: implement session.started hook for opencode 2025-11-22 12:31:23 -08:00
Jesse Vincent
6ae8ef4733 feat: implement find_skills tool for opencode 2025-11-22 12:30:48 -08:00
Jesse Vincent
1aa29ad52b feat: implement use_skill tool for opencode 2025-11-22 12:30:20 -08:00
Jesse Vincent
6847cf4cfc feat: create opencode plugin scaffold 2025-11-22 12:29:50 -08:00
Jesse Vincent
425b40359c refactor: remove unused whenToUse references from codex 2025-11-22 12:27:31 -08:00
Jesse Vincent
9e5ba91be6 refactor: use shared checkForUpdates in codex 2025-11-22 12:15:14 -08:00
Jesse Vincent
4abd4df171 refactor: use shared findSkillsInDir in codex 2025-11-22 12:12:59 -08:00
Jesse Vincent
5dd31b90ee refactor: use shared extractFrontmatter in codex 2025-11-22 12:12:01 -08:00
Jesse Vincent
0fbdfa3c4a refactor: import shared skills core in codex 2025-11-22 12:08:53 -08:00
Jesse Vincent
a23eead918 feat: add git update checking to core module 2025-11-22 12:06:53 -08:00
Jesse Vincent
4594596e38 feat: add skill path resolution with shadowing support 2025-11-22 12:04:42 -08:00
Jesse Vincent
536fd24603 feat: add skill discovery function to core module 2025-11-22 12:02:15 -08:00
Jesse Vincent
85effaaedb feat: create shared skills core module with frontmatter parser
Extract frontmatter parsing logic into lib/skills-core.js to enable
code reuse between Codex and OpenCode implementations.
2025-11-22 12:01:15 -08:00
Jesse Vincent
6cec629cf3 Remove unused initialize-skills.sh script
- Deleted lib/initialize-skills.sh (no longer called)
- Removed permission entry from .claude/settings.local.json
2025-11-22 11:36:28 -08:00
Jesse Vincent
5dd8871a1b Add OpenCode support design document
- Native OpenCode plugin approach using their JavaScript plugin system
- Shared core module (lib/skills-core.js) for code reuse with Codex
- Custom tools: use_skill and find_skills
- Session startup hook for automatic bootstrap
- Three-phase implementation plan
2025-11-22 11:36:28 -08:00
Jesse Vincent
84283dfc05 Update GitHub funding configuration 2025-11-21 16:46:32 -08:00
Jesse Vincent
d90334e030 Remove duplicate mis-placed "commands" - Fixes #112 2025-11-20 12:08:17 -06:00
Dave Seleno
9a9618489d fix: yaml error in code-reviewer agent (#115) 2025-11-20 10:03:56 -08:00
Roland Huß
02c87670de Update installation instructions for Claude Code (#90)
Refactor installation instructions for installing the plugin so that it can be easy copied & pasted to the CLI, as Claude code expects each command separately.
2025-11-06 12:44:59 -08:00
Jesse Vincent
b187e75a1e Bump version to 3.4.1 2025-10-31 11:16:48 -07:00
Jesse Vincent
8674dc0868 Optimize superpowers bootstrap to eliminate redundant skill execution
- Update session-start hook to clarify that using-superpowers content is provided directly
- Add explicit guidance to use Skill tool only for other skills
- Prevents confusing loop where agents execute using-superpowers manually
- Reduces overhead and improves user experience

Fixes redundant skill execution in bootstrap workflow.
2025-10-31 10:49:39 -07:00
Jesse Vincent
42d44ceaf9 Fix plugin manifest version to match 3.4.0 release
Update .claude-plugin/plugin.json version from 3.2.3 to 3.4.0 to match
the version already set in marketplace.json. This ensures consistency
across all plugin manifest files.
2025-10-31 09:58:07 -07:00
Jesse Vincent
d46dddd32c Bump plugin version to 3.4.0 2025-10-30 20:28:51 -07:00
Jesse Vincent
b1fa6a1a46 Update release notes for v3.4.0 brainstorming simplification 2025-10-30 20:25:45 -07:00
Jesse Vincent
8e38ab86dc Simplify brainstorming skill to match original vision
Remove heavyweight 6-phase process with formal checklists and return to
conversational approach:
- Natural dialogue instead of structured phases
- One question at a time without rigid progression
- 200-300 word design sections with validation
- Keep documentation and implementation handoff
- Remove AskUserQuestion tool requirements and complex flowcharts

This aligns with the original spec: help turn ideas into designs through
collaborative questioning, then present design in small sections.
2025-10-30 20:21:28 -07:00
Jesse Vincent
31fd764285 Update release notes for v3.3.1 writing improvements 2025-10-28 11:10:15 -07:00
Jesse Vincent
e3208f1d93 Apply writing clarity improvements to brainstorming skill
Applied Strunk's "Elements of Style" principles:
- Rule 13: Omitted needless words (removed "already", "genuinely", etc.)
- Rule 11: Converted negative to positive form ("don't ask" → "ask only when")
- Rule 10: Used active voice where appropriate
- Rule 15: Improved parallel construction in lists
- General: Made language more direct and concrete

Changes maintain the skill's functionality while improving readability.
2025-10-28 11:07:55 -07:00
Jesse Vincent
1d21ee842d Refine brainstorming skill for proactive research 2025-10-28 10:59:47 -07:00
Jesse Vincent
aa8c6b4fd0 Clarify personal skill directories for Codex 2025-10-28 10:46:05 -07:00
Jesse Vincent
22f57e7cb0 Improve README and add update checking to bootstrap
- Make README more egalitarian: 'AI coding assistants' vs 'Claude Code'
- Reorganize installation: 'Claude Code (via Plugin Marketplace)' and 'Codex (Experimental)'
- Add update checking to bootstrap with 3-second timeout protection
- Bootstrap now checks if local installation is behind GitHub and suggests 'git pull'
- Network failures or timeouts don't block bootstrap (graceful fallback)
2025-10-28 02:27:32 +00:00
Jesse Vincent
da9f4f1edd Release v3.3.0: Add experimental Codex support
- Restructured Codex files to .codex/ directory
- Updated README with simplified GitHub URL installation
- Added comprehensive release notes for v3.3.0
- Moved superpowers-codex script to .codex/superpowers-codex
- Updated all path references for new structure
- Installation now uses GitHub raw URL for streamlined setup

Codex support includes:
- Unified superpowers-codex script with bootstrap/use-skill/find-skills
- Cross-platform Node.js implementation
- Namespaced skills (superpowers:skill-name)
- Tool mapping (TodoWrite→update_plan, etc.)
- Clean skill display without frontmatter
- Personal skill override system
2025-10-28 02:15:53 +00:00
Jesse Vincent
5831c4dfea Fix AGENTS.md to be minimal one-liner + explanatory text
- AGENTS.md (in user's ~/.codex/) now just tells Codex to run bootstrap
- Bootstrap contains all the critical rules and skill locations
- Updated INSTALL.md to show the simplified AGENTS.md example
- Added explanatory text: 'Superpowers teach you new skills and capabilities'
2025-10-28 01:36:10 +00:00
Jesse Vincent
26487902f8 Add Codex superpowers integration
- Single unified script: superpowers-codex with bootstrap/use-skill/find-skills commands
- Cross-platform Node.js implementation (works on Windows, macOS, Linux)
- Namespaced skills: superpowers:skill-name for superpowers, skill-name for personal
- Personal skills override superpowers skills when names match
- Clean skill display: shows name/description without raw frontmatter
- Helpful context: shows supporting files directory for each skill
- Tool mapping for Codex: TodoWrite→update_plan, subagents→manual fallback, etc.
- Updated terminology: "Superpowers skills" instead of "Core skills"
- Bootstrap integration with AGENTS.md for automatic startup
- Installation guide and bootstrap instructions specific to Codex
2025-10-28 01:19:17 +00:00
Jesse Vincent
19e2997334 Release v3.2.3: Update using-superpowers to use Skill tool 2025-10-23 16:34:55 -07:00
Jesse Vincent
c88b0d674f Update using-superpowers skill to use Skill tool instead of Read tool
The Skill tool is the proper mechanism for invoking skills, not the Read tool.
Updated the bootstrap instructions and anti-rationalization guidance to reflect this.
2025-10-23 16:34:05 -07:00
Jesse Vincent
17bbc2b130 Release v3.2.2: Strengthen using-superpowers against agent rationalization 2025-10-21 20:12:56 -07:00
Jesse Vincent
f6ee98a41a Strengthen using-superpowers skill against agent rationalization
Add three layers of enforcement to prevent agents from skipping skill usage:

1. EXTREMELY-IMPORTANT block with absolute language
   - "If even 1% chance a skill applies, you MUST read it"
   - "You do not have a choice. You cannot rationalize your way out."

2. MANDATORY FIRST RESPONSE PROTOCOL checklist
   - 5-step process agents must complete before any response
   - Explicit "responding without this = failure" consequence

3. Common Rationalizations section with 8 specific patterns
   - "This is just a simple question" → WRONG
   - "I can check files quickly" → WRONG
   - "Let me gather information first" → WRONG
   - Plus 5 more common evasion patterns

These changes address observed agent behavior where they rationalize
around skill usage despite clear instructions. The forceful language
and pre-emptive counter-arguments aim to make rationalization harder.
2025-10-21 20:01:06 -07:00
Jesse Vincent
e3d881b7b6 Release v3.2.1: Add code-reviewer agent to plugin
Fixes #55

Added superpowers:code-reviewer agent to plugin's agents/ directory.
Previously, skills referenced a code-reviewer agent that users needed
to configure personally, causing failures for new users.

Changes:
- New: agents/code-reviewer.md - Agent definition with systematic review checklist
- Updated: skills/requesting-code-review/SKILL.md - Use superpowers:code-reviewer
- Updated: skills/subagent-driven-development/SKILL.md - Use superpowers:code-reviewer
- Version bump: 3.2.0 -> 3.2.1
- Added: .claude-plugin/marketplace.json for local development testing
2025-10-20 10:19:24 -07:00
Jesse Vincent
184a4c464e bump to 3.2.0 2025-10-20 08:42:32 -07:00
Jesse Vincent
7fc125e5e9 Update RELEASE-NOTES.md for v3.2.0 release 2025-10-18 10:41:29 -07:00
Jesse Vincent
79436abffa Update all superpowers skill references to use namespace prefix
Skills are now namespaced as superpowers:<name> when referenced.
Updated all REQUIRED SUB-SKILL, RECOMMENDED SUB-SKILL, and
REQUIRED BACKGROUND references to use the superpowers: prefix.

Also added -design suffix to brainstorming skill's design document
filename to distinguish from implementation plan documents.

Files updated:
- brainstorming: Added -design suffix, updated skill references
- executing-plans: Updated finishing-a-development-branch reference
- subagent-driven-development: Updated finishing-a-development-branch reference
- systematic-debugging: Updated root-cause-tracing and test-driven-development references
- testing-skills-with-subagents: Updated test-driven-development reference
- writing-plans: Updated executing-plans and subagent-driven-development references
- writing-skills: Updated test-driven-development, systematic-debugging, and testing-skills-with-subagents references
2025-10-18 10:38:54 -07:00
Jesse Vincent
9597f088c4 Add design documentation phase to brainstorming skill
The old brainstorming command included writing the design document
before handing off to implementation planning. This was lost when
the command was converted to a skill.

Added Phase 4: Design Documentation to write the validated design
to docs/plans/YYYY-MM-DD-<topic>.md before proceeding to worktree
setup and planning.

Tested with subagent to verify design document is written and
committed even under time pressure.
2025-10-18 10:19:14 -07:00
Jesse Vincent
7ce751294e Remove test design document 2025-10-18 10:18:57 -07:00
Jesse Vincent
1ef5758621 Add design document for format-on-save feature 2025-10-18 10:18:38 -07:00
Jesse Vincent
accb1231fc Fix command syntax in README to use namespaced format (#44)
Plugin-provided commands are automatically namespaced by Claude Code
to avoid conflicts. Updated all documentation to show correct syntax.

Changes:
- README.md: Updated all command examples to use /superpowers:* format
- plugin.json: Bump version to 3.1.1
- RELEASE-NOTES.md: Added v3.1.1 release entry

Fixes #44
2025-10-17 22:06:12 -07:00
Jesse Vincent
22ec50318e Update README for v3.0+ integrated skills architecture
Removed all references to the separate obra/superpowers-skills repository
and updated documentation to reflect that skills are now included directly
in the plugin using Claude Code's first-party skills system.

Changes:
- Removed outdated architecture section about repository separation
- Removed find-skills tool and SUPERPOWERS_SKILLS_ROOT references
- Removed git-based update and forking workflows
- Updated contributing section for direct repository contributions
- Updated skills list to match current plugin structure
- Simplified installation and update instructions
2025-10-17 18:50:12 -07:00
Jesse Vincent
0bc5a5989d Update RELEASE-NOTES.md for v3.1.0 release 2025-10-17 14:38:56 -07:00
Jesse Vincent
e59cf658c5 Add command redirects for brainstorm and write-plan
- commands/brainstorm.md: Redirect to brainstorming skill
- commands/write-plan.md: Redirect to writing-plans skill

These command files provide Claude Code slash commands that invoke the
corresponding skills with proper descriptions for discoverability.
2025-10-17 14:37:21 -07:00
Jesse Vincent
4d8db812ae Add AskUserQuestion tool guidance to brainstorming skill
- Add explicit guidance to use AskUserQuestion in Phase 1 (Understanding)
- Add explicit guidance to use AskUserQuestion in Phase 2 (Exploration)
- Add concrete examples showing how to structure questions with options
- Add "Question Patterns" section explaining when to use AskUserQuestion vs open-ended
- Update Quick Reference table to include Tool Usage column
- Update Key Principles to mention structured choices with AskUserQuestion

Benefits:
- Makes it clear when to use structured vs open-ended questions
- Provides concrete examples for effective use of AskUserQuestion
- Helps present options with clear trade-offs
- 156 lines (well under 500-line Anthropic recommendation)
2025-10-17 10:48:50 -07:00
Jesse Vincent
141953a4be Improve skill cross-references for clarity and compliance
Update all skill references to use explicit requirement markers:
- REQUIRED BACKGROUND: For prerequisite understanding
- REQUIRED SUB-SKILL: For mandatory workflow dependencies
- Complementary skills: For optional but helpful related skills

Changes:
- Remove old path format (skills/collaboration/X → X)
- Add explicit "REQUIRED" markers to make dependencies clear
- Update Integration sections with categorized skill relationships
- Fix non-existent skill references
- Update cross-reference documentation in writing-skills

This makes it immediately clear which skills MUST be used vs optional references,
helping Claude understand and comply with skill dependencies.
2025-10-17 10:18:50 -07:00
Jesse Vincent
9e82a51f34 Align brainstorming skill with Anthropic best practices
- Fix description: correct grammar and use third-person voice
- Add Quick Reference table for easy scanning
- Add copyable checklist for tracking progress through phases
- Add decision flowchart for when to revisit earlier phases
- Convert "Remember" section to structured Key Principles table
- Remove references to non-existent related skills

Follows Anthropic patterns:
- Workflow with checklist format
- Quick reference table at top
- Appropriate use of flowchart for decision points
- Scannable table format for principles
- 108 lines (well under 500-line recommendation)
2025-10-17 10:13:14 -07:00
Jesse Vincent
a681cfb024 Add Anthropic's official skill authoring best practices
- Add anthropic-best-practices.md as ancillary reference document
- Reference it in writing-skills SKILL.md overview
- Provides official guidance on skill structure, progressive disclosure, workflows,
  and evaluation patterns that complement the TDD-focused approach
2025-10-17 10:00:12 -07:00
Jesse Vincent
48410c7f19 Standardize skill frontmatter names to lowercase and kebab-case
- Update all 20 skill frontmatter names to match their directory names in lowercase
- Fix defense-in-depth name (was Defense-in-Depth-Validation)
- Fix receiving-code-review name (was Code-Review-Reception)
- Update all skill announcements and cross-references to use lowercase names
- Update commands redirects to reference lowercase skill names

Ensures consistent naming: skill directory names, frontmatter names, and documentation
references all use lowercase kebab-case format (e.g., brainstorming, test-driven-development)
2025-10-17 09:40:36 -07:00
Jesse Vincent
2076e49d18 Strengthen the migration message 2025-10-16 14:26:48 -07:00
Jesse Vincent
d6ca4d6213 oops 2025-10-16 13:21:16 -07:00
Jesse Vincent
10afd4eacc Now that the "Skill" tool is public, use that 2025-10-16 11:38:38 -07:00
Jesse Vincent
451db491b8 Update our bootstrap for first-party claude skills 2025-10-16 08:12:18 -07:00
Jesse Vincent
deb45f5cad Adding back our old getting-started skill since the claude code bootstrap does not seem to trigger our skills quite as effectively yet 2025-10-16 07:35:57 -07:00
Jesse Vincent
32659fe0f3 some skill-writing update for the brave new world 2025-10-16 07:30:06 -07:00
Jesse Vincent
9c9547cc04 Now that skills are a first-class thing in Claude Code, restore them to the primary plugin 2025-10-16 07:19:00 -07:00
Jesse Vincent
84123b8450 Revert "Reapply "Move superpowers plugin into plugins/superpowers-bootstrap subdirectory""
This reverts commit 0fdea80a7d.
2025-10-15 22:56:12 -07:00
Jesse Vincent
9db0a61515 Revert "2.0.5"
This reverts commit e548c5d628.
2025-10-15 22:56:11 -07:00
Jesse Vincent
e548c5d628 2.0.5 2025-10-15 22:43:17 -07:00
Jesse Vincent
0fdea80a7d Reapply "Move superpowers plugin into plugins/superpowers-bootstrap subdirectory"
This reverts commit d6ac9a8b5d.

turns out this worked. it's just that anthropic changed claude's startup hook output
2025-10-15 22:42:20 -07:00
Jesse Vincent
d6ac9a8b5d Revert "Move superpowers plugin into plugins/superpowers-bootstrap subdirectory"
This reverts commit 809956f3bf.
2025-10-15 22:34:56 -07:00
Jesse Vincent
809956f3bf Move superpowers plugin into plugins/superpowers-bootstrap subdirectory
This restructures the repo to support multiple plugins by moving the current
plugin into a subdirectory. The plugin continues to be published as "superpowers"
in the marketplace.
2025-10-15 22:27:45 -07:00
Jesse Vincent
02429d7e26 2.0.4 to force a refresh 2025-10-14 13:43:54 -07:00
Jesse Vincent
51e14692c9 That's what I get for hand-editing json 2025-10-14 13:42:57 -07:00
Jesse Vincent
b331a79267 Bump the version to try to get claude to pick up the update 2025-10-14 13:32:21 -07:00
Jesse Vincent
2d89035187 remove now-obsolete category field 2025-10-14 13:30:33 -07:00
Jesse Vincent
a3bbf5f009 Bump version to 2.0.2
Bug fix release:
- Fixed false warning when local skills repo is ahead of upstream
- Added release notes for 2.0.1 and 2.0.2
2025-10-12 21:36:19 -07:00
Jesse Vincent
927512f1ab Fix false warning when local skills repo is ahead of upstream
The initialization script was incorrectly warning about upstream updates
when the local repository was ahead of upstream. This happened because
the logic didn't distinguish between three states:
- Local behind: LOCAL=BASE, REMOTE≠BASE → should update or warn
- Local ahead: LOCAL≠BASE, REMOTE=BASE → no warning needed
- Diverged: LOCAL≠BASE, REMOTE≠BASE → should warn

Changed the else clause to only set SKILLS_BEHIND when REMOTE≠BASE,
which correctly handles all three scenarios.

Fixes the issue reported in #8 where users with local commits ahead
of upstream were seeing spurious "new skills available" warnings.
2025-10-12 21:16:54 -07:00
Jesse Vincent
998a3d545f Bump version to 2.0.1
Bug fix release: Fix session-start hook execution when local repo is ahead of upstream
2025-10-12 21:05:17 -07:00
Ryan Nelson
b6f6ce12a6 Fix session-start hook execution in plugin context
Fixes #8

- Use /bin/zsh fallback when BASH_SOURCE is unbound
- Add || true to handle empty grep results gracefully

Co-authored-by: ryancnelson <ryancnelson@users.noreply.github.com>
2025-10-12 21:01:36 -07:00
Jesse Vincent
bde691cedf Merge pull request #6 from obra/feature/skills-repo-separation
Skills Repository Separation v2.0.0
2025-10-11 14:19:43 -07:00
Jesse Vincent
9eefffc541 Fix skills auto-update to fetch from tracking branch
Determine and fetch from the current branch's tracking remote instead of
hardcoding upstream/origin. This ensures the correct remote is updated
regardless of fork/upstream setup.

Fixes issue where auto-update wasn't fetching on session start.
2025-10-11 14:17:47 -07:00
Jesse Vincent
488139d6d1 Apply Strunk's style principles to prose
Following The Elements of Style:
- Use active voice (Rule 10): "We rewrote" not "has been rewritten"
- Omit needless words (Rule 13): removed "automatically", "optionally", etc.
- Break up long sentences: split run-on second sentence into short, direct statements
- Put statements in positive form (Rule 11): direct assertions rather than negatives
- Keep it concise: "Claude notifies" not "Claude will notify"

Overview section now more direct and forceful while maintaining all information.
2025-10-11 14:07:56 -07:00
Jesse Vincent
0f30fd2989 Add high-level overview section to release notes
Provides prose description of v2.0 changes before diving into details:
- Skills repository separation (what it means, why it matters)
- Nine new skills (problem-solving, research, architecture)
- using-skills rewrite (imperative tone, clearer structure)
- Improved tools (find-skills outputs usable paths)
- Community focus (easier to contribute and improve skills)
2025-10-11 14:07:56 -07:00
Jesse Vincent
5c19a391d9 Rename release notes to avoid file proliferation 2025-10-11 14:07:56 -07:00
Jesse Vincent
a39561bd41 Add comprehensive v2.0.0 release notes
Documents all changes since v1.0.0:
- Skills repository separation (breaking change)
- New problem-solving and research skills (PR #1)
- Personal superpowers system (PR #2, later replaced)
- Auto-update functionality
- Skills improvements (using-skills v4.0.0, sharing-skills v2.0.0)
- Tools improvements (find-skills, skill-run)
- Plugin infrastructure changes
- Migration guide for existing users
2025-10-11 14:07:56 -07:00
Jesse Vincent
f6327a0051 Update README for skills repository architecture
- Fix auto-update description (now auto-fetches and fast-forwards)
- Update skill name: updating-skills → pulling-updates-from-skills-repository
- Remove obsolete setting-up-personal-superpowers reference
- Add pulling-updates-from-skills-repository to Meta skills list
- Add prominent skills repository link
- Update sharing-skills description (branch and PR workflow)
2025-10-11 14:07:56 -07:00
Jesse Vincent
b063888520 Add testing documentation and local marketplace config 2025-10-11 14:07:33 -07:00
Jesse Vincent
d5e2fe7876 Make skills auto-update verbose for debugging 2025-10-11 12:07:08 -07:00
Jesse Vincent
d1f42e5462 Move 'skills behind' warning to end of session start output 2025-10-11 12:05:08 -07:00
Jesse Vincent
60cb0cd0ca Auto-update skills repo with fast-forward merge on session start 2025-10-11 12:02:15 -07:00
Jesse Vincent
661e6292c6 Add skills location info to session-start output 2025-10-11 11:59:44 -07:00
Jesse Vincent
562428563d Remove obsolete setup-personal-superpowers call and github recommendation logic 2025-10-11 11:53:56 -07:00
Jesse Vincent
e39929b541 Remove obsolete setup-personal-superpowers hook (replaced by initialize-skills.sh) 2025-10-11 11:50:51 -07:00
Jesse Vincent
a1a1c3119d Update README to reflect new skills repository architecture 2025-10-11 11:19:46 -07:00
Jesse Vincent
5b0b086829 Update hooks to use skills repository from ~/.config/superpowers/skills
Changes:
- Set SUPERPOWERS_SKILLS_ROOT environment variable
- Call lib/initialize-skills.sh to handle clone/fetch/notification
- Update find-skills path to ${SUPERPOWERS_SKILLS_ROOT}/skills/using-skills/find-skills
- Update using-skills path (renamed from getting-started)
- Include initialization output in session start message
- Update slash command paths to use SUPERPOWERS_SKILLS_ROOT

Implements Task 7 from skills-repo-separation plan.
2025-10-11 11:14:44 -07:00
Jesse Vincent
400ac0f436 Fix duplicate upstream remote addition when forking 2025-10-11 11:09:18 -07:00
Jesse Vincent
eea083623e Add skills repository initialization script 2025-10-11 11:05:30 -07:00
Jesse Vincent
87f04224ef Remove bundled skills and scripts (now in obra/superpowers-skills) 2025-10-11 10:58:19 -07:00
Jesse Vincent
015a07f7d7 Show skills list and getting-started at session start
Session start hook now:
- Inlines full getting-started/SKILL.md content (no @ links in hooks)
- Runs find-skills and shows complete skills list
- Shows tool paths after the guide

Getting-started improvements:
- Removed "Just Read This Guide?" section (redundant with hook)
- Removed "Last thing" announcement requirement
- Tightened intro from ~80 to ~35 words
- Simplified "How to Load Skills" section
- Updated Workflow 2 to reference skills list shown at session start
- Removed redundant find-skills path examples

This eliminates friction - agents see all available skills immediately without
needing to search first. No excuse for "I didn't want to spend time searching."
2025-10-10 22:59:26 -07:00
Jesse Vincent
33622d710e Bump getting-started skill version to 3.1.0 2025-10-10 22:35:16 -07:00
Jesse Vincent
2227e3151e Add cross-referencing guidance to writing-skills
Added section "5. Cross-Referencing Other Skills" under CSO, explaining:
- Proper format: skills/path/name (no @ prefix or /SKILL.md suffix)
- Why: @ syntax force-loads files, burning context unnecessarily
- How to read: Use Read tool on ${CLAUDE_PLUGIN_ROOT}/skills/path/SKILL.md

This completes the move of cross-referencing guidance from getting-started
to writing-skills, improving separation of concerns.
2025-10-10 22:20:28 -07:00
Jesse Vincent
cd83c0aac8 Move cross-referencing guidance from getting-started to writing-skills
Improved separation of concerns:
- getting-started: focused on USING skills (workflows, finding, reading)
- writing-skills: focused on WRITING skills (including cross-references)

The "Referencing Skills in Documentation" section belongs in writing-skills
because it's authoring guidance, not usage guidance. Added as subsection 5
under Claude Search Optimization (CSO).

Tested with subagents to verify improved clarity in both skills.
2025-10-10 22:19:22 -07:00
Jesse Vincent
7f3a1e7428 Refactor getting-started skill for clarity
Fixed three key issues identified through TDD testing:

1. Removed writing-skills content duplication
   - Moved detailed RED-GREEN-REFACTOR process to skills/meta/writing-skills
   - Added concise pointer to writing-skills for those who need it

2. Clarified conversation search workflow
   - Changed "Mandatory Workflow 3" → "Workflow 3: Historical Context Search (Conditional)"
   - Updated Workflow 2 step 2 to explicitly reference Workflow 3's conditions
   - Eliminated contradiction between mandatory and conditional framing

3. Fixed typo: "juming" → "jumping"

Tested with subagents before and after changes to verify improvements.
2025-10-10 21:58:01 -07:00
Jesse Vincent
7421ddfc2f Merge pull request #1 from obra/amplifier-skills
Add problem-solving skills from amplifier patterns
2025-10-10 21:17:33 -07:00
Jesse Vincent
35cec21e96 Merge pull request #2 from obra/personal-superpowers
Add personal superpowers overlay system
2025-10-10 21:16:29 -07:00
Jesse Vincent
f801cd616d docs: add attribution for skills derived from amplifier
Credit amplifier repo (github.com/microsoft/amplifier @ 2adb63f)
for agent patterns that inspired these skills.
2025-10-10 17:39:38 -07:00
Jesse Vincent
32eb6ed221 revert: restore phase-based workflows with flexibility
Mode-switching was overcomplicated. Back to phases with explicit permission
to revisit earlier phases when constraints emerge or validation fails.

Simpler, clearer, preserves what worked.
2025-10-10 17:26:14 -07:00
Jesse Vincent
e8c960641e revert: remove Workflow 4 - pressure testing showed it won't be used
Agents don't search for skills when stuck, even with explicit workflow.
Trust organic discovery via symptom-based when_to_use instead.
2025-10-10 17:16:48 -07:00
Jesse Vincent
3c26a7f875 feat: strengthen stuck-handling discovery and improve trigger clarity
**Discovery enhancement:**
- Add Mandatory Workflow 4 to getting-started: "When Stuck"
- Creates path: getting-started → when-stuck dispatch → specific technique
- Prevents spinning wheels without seeking help

**Trigger clarity:**
- Replace phrase examples with pattern descriptions
- "Partner reveals constraint you didn't consider" (pattern) not "Oh, I forgot..." (phrase)
- Emphasizes NEW information that invalidates current context
- Prevents ambiguity between new constraints vs clarifications

Tested: All skills verified with subagents, triggers work correctly.
2025-10-10 16:58:30 -07:00
Jesse Vincent
ec15b59c89 refactor: split emergent-patterns into focused problem-solving skills
**Restructure:**
- Split detecting-emergent-patterns (216 lines) into 5 focused skills (~60 lines each)
- Move tracing-lineages to skills/research/ (better category fit)
- Create skills/problem-solving/ category

**New problem-solving skills:**
- simplification-cascades: Find one insight that eliminates multiple components
- collision-zone-thinking: Force unrelated concepts together for breakthroughs
- meta-pattern-recognition: Spot patterns in 3+ domains
- inversion-exercise: Flip assumptions to reveal alternatives
- scale-game: Test at extremes to find fundamental limits
- when-stuck: Dispatch skill that maps stuck-symptoms to techniques

**Improvements:**
- Symptom-based when_to_use (what you'd actually think/feel)
- Quick reference tables for rapid scanning
- Pattern-based triggers (not exact phrase matching)
- Cross-references from brainstorming for discoverability

Each skill now: scannable in 30 seconds, applicable immediately, focused on one technique.
2025-10-10 14:34:51 -07:00
Jesse Vincent
e901534e9e fix: make decision record paths project-agnostic
Use common locations instead of project-specific paths
2025-10-10 14:04:27 -07:00
Jesse Vincent
d3dd95027e fix: remove amplifier-specific paths from tracing-knowledge-lineages
Replace 'ai_working/decisions/' with generic decision record locations
2025-10-10 14:02:47 -07:00
Jesse Vincent
958527f07e feat: add skill cross-references for discoverability
- Reference preserving-productive-tensions from brainstorming EXPLORING mode
- Reference detecting-emergent-patterns from brainstorming when stuck
- Reference tracing-knowledge-lineages from brainstorming before changes
- Reference tracing-knowledge-lineages from executing-plans REVIEWING mode

Makes new architecture skills discoverable through commonly-used workflows.
2025-10-10 13:46:15 -07:00
Jesse Vincent
dedae3a786 feat: add mode-switching and amplifier-inspired skills
**Mode-switching enhancements:**
- Update brainstorming skill with flexible UNDERSTANDING/EXPLORING/DESIGNING modes
- Update executing-plans skill with REVIEWING/EXECUTING/BLOCKED/REPORTING modes
- Add inline dot diagrams with full contextual labels for all valid transitions
- Enforce explicit mode switch announcements

**New architecture skills from amplifier patterns:**
- preserving-productive-tensions: Recognize when to preserve multiple valid approaches vs force resolution
- tracing-knowledge-lineages: Understand idea evolution to avoid repeating failures
- detecting-emergent-patterns: Cross-domain synthesis, collision-zone thinking, simplification cascades

All skills pressure-tested with subagents using RED-GREEN-REFACTOR methodology.
2025-10-10 11:58:54 -07:00
167 changed files with 14368 additions and 8841 deletions

View File

@@ -0,0 +1,20 @@
{
"name": "superpowers-dev",
"description": "Development marketplace for Superpowers core skills library",
"owner": {
"name": "Jesse Vincent",
"email": "jesse@fsck.com"
},
"plugins": [
{
"name": "superpowers",
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
"version": "4.2.0",
"source": "./",
"author": {
"name": "Jesse Vincent",
"email": "jesse@fsck.com"
}
}
]
}

View File

@@ -1,7 +1,7 @@
{
"name": "superpowers",
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
"version": "1.0.0",
"version": "4.2.0",
"author": {
"name": "Jesse Vincent",
"email": "jesse@fsck.com"
@@ -9,6 +9,5 @@
"homepage": "https://github.com/obra/superpowers",
"repository": "https://github.com/obra/superpowers",
"license": "MIT",
"keywords": ["skills", "tdd", "debugging", "collaboration", "best-practices", "workflows"],
"category": "productivity"
"keywords": ["skills", "tdd", "debugging", "collaboration", "best-practices", "workflows"]
}

67
.codex/INSTALL.md Normal file
View File

@@ -0,0 +1,67 @@
# Installing Superpowers for Codex
Enable superpowers skills in Codex via native skill discovery. Just clone and symlink.
## Prerequisites
- Git
## Installation
1. **Clone the superpowers repository:**
```bash
git clone https://github.com/obra/superpowers.git ~/.codex/superpowers
```
2. **Create the skills symlink:**
```bash
mkdir -p ~/.agents/skills
ln -s ~/.codex/superpowers/skills ~/.agents/skills/superpowers
```
**Windows (PowerShell):**
```powershell
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.agents\skills"
cmd /c mklink /J "$env:USERPROFILE\.agents\skills\superpowers" "$env:USERPROFILE\.codex\superpowers\skills"
```
3. **Restart Codex** (quit and relaunch the CLI) to discover the skills.
## Migrating from old bootstrap
If you installed superpowers before native skill discovery, you need to:
1. **Update the repo:**
```bash
cd ~/.codex/superpowers && git pull
```
2. **Create the skills symlink** (step 2 above) — this is the new discovery mechanism.
3. **Remove the old bootstrap block** from `~/.codex/AGENTS.md` — any block referencing `superpowers-codex bootstrap` is no longer needed.
4. **Restart Codex.**
## Verify
```bash
ls -la ~/.agents/skills/superpowers
```
You should see a symlink (or junction on Windows) pointing to your superpowers skills directory.
## Updating
```bash
cd ~/.codex/superpowers && git pull
```
Skills update instantly through the symlink.
## Uninstalling
```bash
rm ~/.agents/skills/superpowers
```
Optionally delete the clone: `rm -rf ~/.codex/superpowers`.

17
.gitattributes vendored Normal file
View File

@@ -0,0 +1,17 @@
# Ensure shell scripts always have LF line endings
*.sh text eol=lf
# Ensure the polyglot wrapper keeps LF (it's parsed by both cmd and bash)
*.cmd text eol=lf
# Common text files
*.md text eol=lf
*.json text eol=lf
*.js text eol=lf
*.mjs text eol=lf
*.ts text eol=lf
# Explicitly mark binary files
*.png binary
*.jpg binary
*.gif binary

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
# These are supported funding model platforms
github: [obra]

4
.gitignore vendored
View File

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

119
.opencode/INSTALL.md Normal file
View File

@@ -0,0 +1,119 @@
# Installing Superpowers for OpenCode
## Prerequisites
- [OpenCode.ai](https://opencode.ai) installed
- Git installed
## Installation Steps
### 1. Clone Superpowers
```bash
git clone https://github.com/obra/superpowers.git ~/.config/opencode/superpowers
```
### 2. Register the Plugin
Create a symlink so OpenCode discovers the plugin:
```bash
mkdir -p ~/.config/opencode/plugins
rm -f ~/.config/opencode/plugins/superpowers.js
ln -s ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js ~/.config/opencode/plugins/superpowers.js
```
### 3. Symlink Skills
Create a symlink so OpenCode's native skill tool discovers superpowers skills:
```bash
mkdir -p ~/.config/opencode/skills
rm -rf ~/.config/opencode/skills/superpowers
ln -s ~/.config/opencode/superpowers/skills ~/.config/opencode/skills/superpowers
```
### 4. Restart OpenCode
Restart OpenCode. The plugin will automatically inject superpowers context.
Verify by asking: "do you have superpowers?"
## Usage
### Finding Skills
Use OpenCode's native `skill` tool to list available skills:
```
use skill tool to list skills
```
### Loading a Skill
Use OpenCode's native `skill` tool to load a specific skill:
```
use skill tool to load superpowers/brainstorming
```
### Personal Skills
Create your own skills in `~/.config/opencode/skills/`:
```bash
mkdir -p ~/.config/opencode/skills/my-skill
```
Create `~/.config/opencode/skills/my-skill/SKILL.md`:
```markdown
---
name: my-skill
description: Use when [condition] - [what it does]
---
# My Skill
[Your skill content here]
```
### Project Skills
Create project-specific skills in `.opencode/skills/` within your project.
**Skill Priority:** Project skills > Personal skills > Superpowers skills
## Updating
```bash
cd ~/.config/opencode/superpowers
git pull
```
## Troubleshooting
### Plugin not loading
1. Check plugin symlink: `ls -l ~/.config/opencode/plugins/superpowers.js`
2. Check source exists: `ls ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js`
3. Check OpenCode logs for errors
### Skills not found
1. Check skills symlink: `ls -l ~/.config/opencode/skills/superpowers`
2. Verify it points to: `~/.config/opencode/superpowers/skills`
3. Use `skill` tool to list what's discovered
### Tool mapping
When skills reference Claude Code tools:
- `TodoWrite``update_plan`
- `Task` with subagents → `@mention` syntax
- `Skill` tool → OpenCode's native `skill` tool
- File operations → your native tools
## Getting Help
- Report issues: https://github.com/obra/superpowers/issues
- Full documentation: https://github.com/obra/superpowers/blob/main/docs/README.opencode.md

View File

@@ -0,0 +1,95 @@
/**
* Superpowers plugin for OpenCode.ai
*
* Injects superpowers bootstrap context via system prompt transform.
* Skills are discovered via OpenCode's native skill tool from symlinked directory.
*/
import path from 'path';
import fs from 'fs';
import os from 'os';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
// Simple frontmatter extraction (avoid dependency on skills-core for bootstrap)
const extractAndStripFrontmatter = (content) => {
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
if (!match) return { frontmatter: {}, content };
const frontmatterStr = match[1];
const body = match[2];
const frontmatter = {};
for (const line of frontmatterStr.split('\n')) {
const colonIdx = line.indexOf(':');
if (colonIdx > 0) {
const key = line.slice(0, colonIdx).trim();
const value = line.slice(colonIdx + 1).trim().replace(/^["']|["']$/g, '');
frontmatter[key] = value;
}
}
return { frontmatter, content: body };
};
// Normalize a path: trim whitespace, expand ~, resolve to absolute
const normalizePath = (p, homeDir) => {
if (!p || typeof p !== 'string') return null;
let normalized = p.trim();
if (!normalized) return null;
if (normalized.startsWith('~/')) {
normalized = path.join(homeDir, normalized.slice(2));
} else if (normalized === '~') {
normalized = homeDir;
}
return path.resolve(normalized);
};
export const SuperpowersPlugin = async ({ client, directory }) => {
const homeDir = os.homedir();
const superpowersSkillsDir = path.resolve(__dirname, '../../skills');
const envConfigDir = normalizePath(process.env.OPENCODE_CONFIG_DIR, homeDir);
const configDir = envConfigDir || path.join(homeDir, '.config/opencode');
// Helper to generate bootstrap content
const getBootstrapContent = () => {
// Try to load using-superpowers skill
const skillPath = path.join(superpowersSkillsDir, 'using-superpowers', 'SKILL.md');
if (!fs.existsSync(skillPath)) return null;
const fullContent = fs.readFileSync(skillPath, 'utf8');
const { content } = extractAndStripFrontmatter(fullContent);
const toolMapping = `**Tool Mapping for OpenCode:**
When skills reference tools you don't have, substitute OpenCode equivalents:
- \`TodoWrite\`\`update_plan\`
- \`Task\` tool with subagents → Use OpenCode's subagent system (@mention)
- \`Skill\` tool → OpenCode's native \`skill\` tool
- \`Read\`, \`Write\`, \`Edit\`, \`Bash\` → Your native tools
**Skills location:**
Superpowers skills are in \`${configDir}/skills/superpowers/\`
Use OpenCode's native \`skill\` tool to list and load skills.`;
return `<EXTREMELY_IMPORTANT>
You have superpowers.
**IMPORTANT: The using-superpowers skill content is included below. It is ALREADY LOADED - you are currently following it. Do NOT use the skill tool to load "using-superpowers" again - that would be redundant.**
${content}
${toolMapping}
</EXTREMELY_IMPORTANT>`;
};
return {
// Use system prompt transform to inject bootstrap (fixes #226 agent reset bug)
'experimental.chat.system.transform': async (_input, output) => {
const bootstrap = getBootstrapContent();
if (bootstrap) {
(output.system ||= []).push(bootstrap);
}
}
};
};

242
README.md
View File

@@ -1,154 +1,114 @@
# Superpowers
Give Claude Code superpowers with a comprehensive skills library of proven techniques, patterns, and tools.
Superpowers is a complete software development workflow for your coding agents, built on top of a set of composable "skills" and some initial instructions that make sure your agent uses them.
## What You Get
## How it works
- **Testing Skills** - TDD, async testing, anti-patterns
- **Debugging Skills** - Systematic debugging, root cause tracing, verification
- **Collaboration Skills** - Brainstorming, planning, code review, parallel agents
- **Meta Skills** - Creating, testing, and contributing skills
It starts from the moment you fire up your coding agent. As soon as it sees that you're building something, it *doesn't* just jump into trying to write code. Instead, it steps back and asks you what you're really trying to do.
Plus:
- **Slash Commands** - `/brainstorm`, `/write-plan`, `/execute-plan`
- **Skills Search** - Grep-powered discovery of relevant skills
- **Gap Tracking** - Failed searches logged for skill creation
Once it's teased a spec out of the conversation, it shows it to you in chunks short enough to actually read and digest.
## Learn More
After you've signed off on the design, your agent puts together an implementation plan that's clear enough for an enthusiastic junior engineer with poor taste, no judgement, no project context, and an aversion to testing to follow. It emphasizes true red/green TDD, YAGNI (You Aren't Gonna Need It), and DRY.
Next up, once you say "go", it launches a *subagent-driven-development* process, having agents work through each engineering task, inspecting and reviewing their work, and continuing forward. It's not uncommon for Claude to be able to work autonomously for a couple hours at a time without deviating from the plan you put together.
There's a bunch more to it, but that's the core of the system. And because the skills trigger automatically, you don't need to do anything special. Your coding agent just has Superpowers.
## Sponsorship
If Superpowers has helped you do stuff that makes money and you are so inclined, I'd greatly appreciate it if you'd consider [sponsoring my opensource work](https://github.com/sponsors/obra).
Thanks!
- Jesse
Read the introduction: [Superpowers for Claude Code](https://blog.fsck.com/2025/10/09/superpowers/)
## Installation
### Via Plugin Marketplace (Recommended)
**Note:** Installation differs by platform. Claude Code has a built-in plugin system. Codex and OpenCode require manual setup.
### Claude Code (via Plugin Marketplace)
In Claude Code, register the marketplace first:
```bash
# In Claude Code
/plugin marketplace add obra/superpowers-marketplace
```
Then install the plugin from this marketplace:
```bash
/plugin install superpowers@superpowers-marketplace
```
That's it! On first session, the plugin automatically:
- Sets up `~/.config/superpowers/` as your personal skills repository
- Initializes git repo for version control
- Makes core skills searchable alongside your personal skills
- Adds `/brainstorm`, `/write-plan`, and `/execute-plan` commands
- Offers to create public GitHub repo for sharing your skills
### Verify Installation
```bash
# Check that commands appear
/help
Start a new session and ask Claude to help with something that would trigger a skill (e.g., "help me plan this feature" or "let's debug this issue"). Claude should automatically invoke the relevant superpowers skill.
# Should see:
# /brainstorm - Interactive design refinement
# /write-plan - Create implementation plan
# /execute-plan - Execute plan in batches
### Codex
Tell Codex:
```
Fetch and follow instructions from https://raw.githubusercontent.com/obra/superpowers/refs/heads/main/.codex/INSTALL.md
```
## Quick Start
**Detailed docs:** [docs/README.codex.md](docs/README.codex.md)
### Your Personal Skills
### OpenCode
Write your own skills to `~/.config/superpowers/skills/`:
- All personal skills automatically discovered by search tools
- Personal skills shadow core skills when names match
- Version controlled with git
- Optional: Share on GitHub and contribute back to core
Tell OpenCode:
See `skills/meta/writing-skills` for how to create new skills.
See `skills/meta/sharing-skills` for how to contribute to core.
### Finding Skills
Find both personal and core skills before starting any task:
```bash
${CLAUDE_PLUGIN_ROOT}/scripts/find-skills # All skills with descriptions
${CLAUDE_PLUGIN_ROOT}/scripts/find-skills test # Filter by pattern
${CLAUDE_PLUGIN_ROOT}/scripts/find-skills 'TDD|debug' # Regex pattern
```
Fetch and follow instructions from https://raw.githubusercontent.com/obra/superpowers/refs/heads/main/.opencode/INSTALL.md
```
### Using Slash Commands
**Detailed docs:** [docs/README.opencode.md](docs/README.opencode.md)
**Brainstorm a design:**
```
/brainstorm
```
## The Basic Workflow
**Create an implementation plan:**
```
/write-plan
```
1. **brainstorming** - Activates before writing code. Refines rough ideas through questions, explores alternatives, presents design in sections for validation. Saves design document.
**Execute the plan:**
```
/execute-plan
```
2. **using-git-worktrees** - Activates after design approval. Creates isolated workspace on new branch, runs project setup, verifies clean test baseline.
3. **writing-plans** - Activates with approved design. Breaks work into bite-sized tasks (2-5 minutes each). Every task has exact file paths, complete code, verification steps.
4. **subagent-driven-development** or **executing-plans** - Activates with plan. Dispatches fresh subagent per task with two-stage review (spec compliance, then code quality), or executes in batches with human checkpoints.
5. **test-driven-development** - Activates during implementation. Enforces RED-GREEN-REFACTOR: write failing test, watch it fail, write minimal code, watch it pass, commit. Deletes code written before tests.
6. **requesting-code-review** - Activates between tasks. Reviews against plan, reports issues by severity. Critical issues block progress.
7. **finishing-a-development-branch** - Activates when tasks complete. Verifies tests, presents options (merge/PR/keep/discard), cleans up worktree.
**The agent checks for relevant skills before any task.** Mandatory workflows, not suggestions.
## What's Inside
### Skills Library
**Testing** (`skills/testing/`)
- test-driven-development - RED-GREEN-REFACTOR cycle
- condition-based-waiting - Async test patterns
- testing-anti-patterns - Common pitfalls to avoid
**Testing**
- **test-driven-development** - RED-GREEN-REFACTOR cycle (includes testing anti-patterns reference)
**Debugging** (`skills/debugging/`)
- systematic-debugging - 4-phase root cause process
- root-cause-tracing - Find the real problem
- verification-before-completion - Ensure it's actually fixed
- defense-in-depth - Multiple validation layers
**Debugging**
- **systematic-debugging** - 4-phase root cause process (includes root-cause-tracing, defense-in-depth, condition-based-waiting techniques)
- **verification-before-completion** - Ensure it's actually fixed
**Collaboration** (`skills/collaboration/`)
- brainstorming - Socratic design refinement
- writing-plans - Detailed implementation plans
- executing-plans - Batch execution with checkpoints
- dispatching-parallel-agents - Concurrent subagent workflows
- remembering-conversations - Search past work
- using-git-worktrees - Parallel development branches
- requesting-code-review - Pre-review checklist
- receiving-code-review - Responding to feedback
**Collaboration**
- **brainstorming** - Socratic design refinement
- **writing-plans** - Detailed implementation plans
- **executing-plans** - Batch execution with checkpoints
- **dispatching-parallel-agents** - Concurrent subagent workflows
- **requesting-code-review** - Pre-review checklist
- **receiving-code-review** - Responding to feedback
- **using-git-worktrees** - Parallel development branches
- **finishing-a-development-branch** - Merge/PR decision workflow
- **subagent-driven-development** - Fast iteration with two-stage review (spec compliance, then code quality)
**Meta** (`skills/meta/`)
- setting-up-personal-superpowers - Personal skills repository setup
- writing-skills - TDD for documentation, create new skills
- sharing-skills - Contribute skills back to core
- testing-skills-with-subagents - Validate skill quality
- gardening-skills-wiki - Maintain and improve skills
### Commands
- **brainstorm.md** - Interactive design refinement using Socratic method
- **write-plan.md** - Create detailed implementation plans
- **execute-plan.md** - Execute plans in batches with review checkpoints
### Tools
**In `scripts/` directory:**
- **find-skills** - Unified skill discovery with descriptions (replaces list-skills + skills-search)
- **skill-run** - Generic runner for any skill script (searches personal then core)
**Skill-specific tools:**
- **search-conversations** - Semantic search of past Claude sessions (in remembering-conversations skill)
**Using scripts:**
```bash
${CLAUDE_PLUGIN_ROOT}/scripts/find-skills # Show all skills
${CLAUDE_PLUGIN_ROOT}/scripts/find-skills pattern # Search skills
${CLAUDE_PLUGIN_ROOT}/scripts/skill-run <path> [args] # Run any skill script
```
## How It Works
1. **SessionStart Hook** - Auto-setup personal skills repo, inject core skills context
2. **Two-Tier Skills** - Personal skills (`~/.config/superpowers/skills/`) + Core skills (plugin)
3. **Skills Discovery** - `find-skills` searches both locations with descriptions
4. **Shadowing** - Personal skills override core skills when paths match
5. **Mandatory Workflow** - Skills become required when they exist for your task
6. **Gap Tracking** - Failed searches logged to `~/.config/superpowers/search-log.jsonl`
**Meta**
- **writing-skills** - Create new skills following best practices (includes testing methodology)
- **using-superpowers** - Introduction to the skills system
## Philosophy
@@ -156,51 +116,27 @@ ${CLAUDE_PLUGIN_ROOT}/scripts/skill-run <path> [args] # Run any skill script
- **Systematic over ad-hoc** - Process over guessing
- **Complexity reduction** - Simplicity as primary goal
- **Evidence over claims** - Verify before declaring success
- **Domain over implementation** - Work at problem level, not solution level
## Personal Superpowers Directory
The plugin auto-creates your personal superpowers directory on first session.
**Default location:** `~/.config/superpowers/`
**Customize via environment variables:**
```bash
# Option 1: Set exact location
export PERSONAL_SUPERPOWERS_DIR="$HOME/my-superpowers"
# Option 2: Use XDG standard
export XDG_CONFIG_HOME="$HOME/.local/config" # Uses $HOME/.local/config/superpowers
```
**Structure:**
```
~/.config/superpowers/ # (or your custom location)
├── .git/ # Git repository
├── .gitignore # Ignores logs and indexes
├── README.md # About your personal superpowers
├── skills/ # Your personal skills
│ └── your-skill/
│ └── SKILL.md
├── search-log.jsonl # Failed skill searches (not tracked)
└── conversation-index/ # Indexed conversations (not tracked)
```
**Why git?** Track your skills evolution, share with others, contribute back to core.
Read more: [Superpowers for Claude Code](https://blog.fsck.com/2025/10/09/superpowers/)
## Contributing
**Write personal skills:**
1. Create in `~/.config/superpowers/skills/your-skill/`
2. Follow TDD process in `skills/meta/writing-skills`
3. Commit to your personal repo
Skills live directly in this repository. To contribute:
**Share with everyone:**
1. Follow workflow in `skills/meta/sharing-skills`
2. Fork → Branch → Copy → PR to core
3. Keep personal version or delete after merge
1. Fork the repository
2. Create a branch for your skill
3. Follow the `writing-skills` skill for creating and testing new skills
4. Submit a PR
**Missing a skill?** Edit `skills/REQUESTS.md` or open an issue
See `skills/writing-skills/SKILL.md` for the complete guide.
## Updating
Skills update automatically when you update the plugin:
```bash
/plugin update superpowers
```
## License

843
RELEASE-NOTES.md Normal file
View File

@@ -0,0 +1,843 @@
# Superpowers Release Notes
## Unreleased
### Breaking Changes
**Specs and plans directory restructured**
- 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
- Migration: move existing files from `docs/plans/` to new locations if desired
**Brainstorming → writing-plans transition enforced**
- 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
**Subagent-driven development now mandatory on capable harnesses**
- 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
**OpenCode: Switched to native skills system**
Superpowers for OpenCode now uses OpenCode's native `skill` tool instead of custom `use_skill`/`find_skills` tools. This is a cleaner integration that works with OpenCode's built-in skill discovery.
**Migration required:** Skills must be symlinked to `~/.config/opencode/skills/superpowers/` (see updated installation docs).
### Fixes
**OpenCode: Fixed agent reset on session start (#226)**
The previous bootstrap injection method using `session.prompt({ noReply: true })` caused OpenCode to reset the selected agent to "build" on first message. Now uses `experimental.chat.system.transform` hook which modifies the system prompt directly without side effects.
**OpenCode: Fixed Windows installation (#232)**
- Removed dependency on `skills-core.js` (eliminates broken relative imports when file is copied instead of symlinked)
- Added comprehensive Windows installation docs for cmd.exe, PowerShell, and Git Bash
- Documented proper symlink vs junction usage for each platform
### New Features
**Visual companion for brainstorming skill**
Added optional browser-based visual companion for brainstorming sessions. When users have a browser available, brainstorming can display interactive screens showing current phase, questions, and design decisions in a more readable format than terminal output.
Components:
- `lib/brainstorm-server/` - WebSocket server for real-time updates
- `skills/brainstorming/visual-companion.md` - Integration guide
- Helper scripts for session management with proper isolation
- Browser helper library for event capture
The visual companion is opt-in and falls back gracefully to terminal-only operation.
### Bug Fixes
**Fixed Windows hook execution for Claude Code 2.1.x**
Claude Code 2.1.x changed how hooks execute on Windows: it now auto-detects `.sh` files in commands and prepends `bash `. This broke the polyglot wrapper pattern because `bash "run-hook.cmd" session-start.sh` tries to execute the .cmd file as a bash script.
Fix: hooks.json now calls session-start.sh directly. Claude Code 2.1.x handles the bash invocation automatically. Also added .gitattributes to enforce LF line endings for shell scripts (fixes CRLF issues on Windows checkout).
**Brainstorming visual companion: reduced token cost and improved persistence**
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.
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 clarified in using-superpowers**
Added explicit instruction priority hierarchy to prevent conflicts with user preferences:
1. User's explicit instructions (CLAUDE.md, direct requests) — highest priority
2. Superpowers skills — override default system behavior where they conflict
3. Default system prompt — lowest priority
This ensures users remain in control. If CLAUDE.md says "don't use TDD" and a skill says "always use TDD," CLAUDE.md wins.
## v4.2.0 (2026-02-05)
### Breaking Changes
**Codex: Replaced bootstrap CLI with native skill discovery**
The `superpowers-codex` bootstrap CLI, Windows `.cmd` wrapper, and related bootstrap content file have been removed. Codex now uses native skill discovery via `~/.agents/skills/superpowers/` symlink, so the old `use_skill`/`find_skills` CLI tools are no longer needed.
Installation is now just clone + symlink (documented in INSTALL.md). No Node.js dependency required. The old `~/.codex/skills/` path is deprecated.
### Fixes
**Windows: Fixed Claude Code 2.1.x hook execution (#331)**
Claude Code 2.1.x changed how hooks execute on Windows: it now auto-detects `.sh` files in commands and prepends `bash`. This broke the polyglot wrapper pattern because `bash "run-hook.cmd" session-start.sh` tries to execute the `.cmd` file as a bash script.
Fix: hooks.json now calls session-start.sh directly. Claude Code 2.1.x handles the bash invocation automatically. Also added .gitattributes to enforce LF line endings for shell scripts (fixes CRLF issues on Windows checkout).
**Windows: SessionStart hook runs async to prevent terminal freeze (#404, #413, #414, #419)**
The synchronous SessionStart hook blocked the TUI from entering raw mode on Windows, freezing all keyboard input. Running the hook async prevents the freeze while still injecting superpowers context.
**Windows: Fixed O(n^2) `escape_for_json` performance**
The character-by-character loop using `${input:$i:1}` was O(n^2) in bash due to substring copy overhead. On Windows Git Bash this took 60+ seconds. Replaced with bash parameter substitution (`${s//old/new}`) which runs each pattern as a single C-level pass — 7x faster on macOS, dramatically faster on Windows.
**Codex: Fixed Windows/PowerShell invocation (#285, #243)**
- Windows doesn't respect shebangs, so directly invoking the extensionless `superpowers-codex` script triggered an "Open with" dialog. All invocations now prefixed with `node`.
- Fixed `~/` path expansion on Windows — PowerShell doesn't expand `~` when passed as an argument to `node`. Changed to `$HOME` which expands correctly in both bash and PowerShell.
**Codex: Fixed path resolution in installer**
Used `fileURLToPath()` instead of manual URL pathname parsing to correctly handle paths with spaces and special characters on all platforms.
**Codex: Fixed stale skills path in writing-skills**
Updated `~/.codex/skills/` reference (deprecated) to `~/.agents/skills/` for native discovery.
### Improvements
**Worktree isolation now required before implementation**
Added `using-git-worktrees` as a required skill for both `subagent-driven-development` and `executing-plans`. Implementation workflows now explicitly require setting up an isolated worktree before starting work, preventing accidental work directly on main.
**Main branch protection softened to require explicit consent**
Instead of prohibiting main branch work entirely, the skills now allow it with explicit user consent. More flexible while still ensuring users are aware of the implications.
**Simplified installation verification**
Removed `/help` command check and specific slash command list from verification steps. Skills are primarily invoked by describing what you want to do, not by running specific commands.
**Codex: Clarified subagent tool mapping in bootstrap**
Improved documentation of how Codex tools map to Claude Code equivalents for subagent workflows.
### Tests
- Added worktree requirement test for subagent-driven-development
- Added main branch red flag warning test
- Fixed case sensitivity in skill recognition test assertions
---
## v4.1.1 (2026-01-23)
### Fixes
**OpenCode: Standardized on `plugins/` directory per official docs (#343)**
OpenCode's official documentation uses `~/.config/opencode/plugins/` (plural). Our docs previously used `plugin/` (singular). While OpenCode accepts both forms, we've standardized on the official convention to avoid confusion.
Changes:
- Renamed `.opencode/plugin/` to `.opencode/plugins/` in repo structure
- Updated all installation docs (INSTALL.md, README.opencode.md) across all platforms
- Updated test scripts to match
**OpenCode: Fixed symlink instructions (#339, #342)**
- Added explicit `rm` before `ln -s` (fixes "file already exists" errors on reinstall)
- Added missing skills symlink step that was absent from INSTALL.md
- Updated from deprecated `use_skill`/`find_skills` to native `skill` tool references
---
## v4.1.0 (2026-01-23)
### Breaking Changes
**OpenCode: Switched to native skills system**
Superpowers for OpenCode now uses OpenCode's native `skill` tool instead of custom `use_skill`/`find_skills` tools. This is a cleaner integration that works with OpenCode's built-in skill discovery.
**Migration required:** Skills must be symlinked to `~/.config/opencode/skills/superpowers/` (see updated installation docs).
### Fixes
**OpenCode: Fixed agent reset on session start (#226)**
The previous bootstrap injection method using `session.prompt({ noReply: true })` caused OpenCode to reset the selected agent to "build" on first message. Now uses `experimental.chat.system.transform` hook which modifies the system prompt directly without side effects.
**OpenCode: Fixed Windows installation (#232)**
- Removed dependency on `skills-core.js` (eliminates broken relative imports when file is copied instead of symlinked)
- Added comprehensive Windows installation docs for cmd.exe, PowerShell, and Git Bash
- Documented proper symlink vs junction usage for each platform
**Claude Code: Fixed Windows hook execution for Claude Code 2.1.x**
Claude Code 2.1.x changed how hooks execute on Windows: it now auto-detects `.sh` files in commands and prepends `bash `. This broke the polyglot wrapper pattern because `bash "run-hook.cmd" session-start.sh` tries to execute the .cmd file as a bash script.
Fix: hooks.json now calls session-start.sh directly. Claude Code 2.1.x handles the bash invocation automatically. Also added .gitattributes to enforce LF line endings for shell scripts (fixes CRLF issues on Windows checkout).
---
## v4.0.3 (2025-12-26)
### Improvements
**Strengthened using-superpowers skill for explicit skill requests**
Addressed a failure mode where Claude would skip invoking a skill even when the user explicitly requested it by name (e.g., "subagent-driven-development, please"). Claude would think "I know what that means" and start working directly instead of loading the skill.
Changes:
- Updated "The Rule" to say "Invoke relevant or requested skills" instead of "Check for skills" - emphasizing active invocation over passive checking
- Added "BEFORE any response or action" - the original wording only mentioned "response" but Claude would sometimes take action without responding first
- Added reassurance that invoking a wrong skill is okay - reduces hesitation
- Added new red flag: "I know what that means" → Knowing the concept ≠ using the skill
**Added explicit skill request tests**
New test suite in `tests/explicit-skill-requests/` that verifies Claude correctly invokes skills when users request them by name. Includes single-turn and multi-turn test scenarios.
## v4.0.2 (2025-12-23)
### Fixes
**Slash commands now user-only**
Added `disable-model-invocation: true` to all three slash commands (`/brainstorm`, `/execute-plan`, `/write-plan`). Claude can no longer invoke these commands via the Skill tool—they're restricted to manual user invocation only.
The underlying skills (`superpowers:brainstorming`, `superpowers:executing-plans`, `superpowers:writing-plans`) remain available for Claude to invoke autonomously. This change prevents confusion when Claude would invoke a command that just redirects to a skill anyway.
## v4.0.1 (2025-12-23)
### Fixes
**Clarified how to access skills in Claude Code**
Fixed a confusing pattern where Claude would invoke a skill via the Skill tool, then try to Read the skill file separately. The `using-superpowers` skill now explicitly states that the Skill tool loads skill content directly—no need to read files.
- Added "How to Access Skills" section to `using-superpowers`
- Changed "read the skill" → "invoke the skill" in instructions
- Updated slash commands to use fully qualified skill names (e.g., `superpowers:brainstorming`)
**Added GitHub thread reply guidance to receiving-code-review** (h/t @ralphbean)
Added a note about replying to inline review comments in the original thread rather than as top-level PR comments.
**Added automation-over-documentation guidance to writing-skills** (h/t @EthanJStark)
Added guidance that mechanical constraints should be automated, not documented—save skills for judgment calls.
## v4.0.0 (2025-12-17)
### New Features
**Two-stage code review in subagent-driven-development**
Subagent workflows now use two separate review stages after each task:
1. **Spec compliance review** - Skeptical reviewer verifies implementation matches spec exactly. Catches missing requirements AND over-building. Won't trust implementer's report—reads actual code.
2. **Code quality review** - Only runs after spec compliance passes. Reviews for clean code, test coverage, maintainability.
This catches the common failure mode where code is well-written but doesn't match what was requested. Reviews are loops, not one-shot: if reviewer finds issues, implementer fixes them, then reviewer checks again.
Other subagent workflow improvements:
- Controller provides full task text to workers (not file references)
- Workers can ask clarifying questions before AND during work
- Self-review checklist before reporting completion
- Plan read once at start, extracted to TodoWrite
New prompt templates in `skills/subagent-driven-development/`:
- `implementer-prompt.md` - Includes self-review checklist, encourages questions
- `spec-reviewer-prompt.md` - Skeptical verification against requirements
- `code-quality-reviewer-prompt.md` - Standard code review
**Debugging techniques consolidated with tools**
`systematic-debugging` now bundles supporting techniques and tools:
- `root-cause-tracing.md` - Trace bugs backward through call stack
- `defense-in-depth.md` - Add validation at multiple layers
- `condition-based-waiting.md` - Replace arbitrary timeouts with condition polling
- `find-polluter.sh` - Bisection script to find which test creates pollution
- `condition-based-waiting-example.ts` - Complete implementation from real debugging session
**Testing anti-patterns reference**
`test-driven-development` now includes `testing-anti-patterns.md` covering:
- Testing mock behavior instead of real behavior
- Adding test-only methods to production classes
- Mocking without understanding dependencies
- Incomplete mocks that hide structural assumptions
**Skill test infrastructure**
Three new test frameworks for validating skill behavior:
`tests/skill-triggering/` - Validates skills trigger from naive prompts without explicit naming. Tests 6 skills to ensure descriptions alone are sufficient.
`tests/claude-code/` - Integration tests using `claude -p` for headless testing. Verifies skill usage via session transcript (JSONL) analysis. Includes `analyze-token-usage.py` for cost tracking.
`tests/subagent-driven-dev/` - End-to-end workflow validation with two complete test projects:
- `go-fractals/` - CLI tool with Sierpinski/Mandelbrot (10 tasks)
- `svelte-todo/` - CRUD app with localStorage and Playwright (12 tasks)
### Major Changes
**DOT flowcharts as executable specifications**
Rewrote key skills using DOT/GraphViz flowcharts as the authoritative process definition. Prose becomes supporting content.
**The Description Trap** (documented in `writing-skills`): Discovered that skill descriptions override flowchart content when descriptions contain workflow summaries. Claude follows the short description instead of reading the detailed flowchart. Fix: descriptions must be trigger-only ("Use when X") with no process details.
**Skill priority in using-superpowers**
When multiple skills apply, process skills (brainstorming, debugging) now explicitly come before implementation skills. "Build X" triggers brainstorming first, then domain skills.
**brainstorming trigger strengthened**
Description changed to imperative: "You MUST use this before any creative work—creating features, building components, adding functionality, or modifying behavior."
### Breaking Changes
**Skill consolidation** - Six standalone skills merged:
- `root-cause-tracing`, `defense-in-depth`, `condition-based-waiting` → bundled in `systematic-debugging/`
- `testing-skills-with-subagents` → bundled in `writing-skills/`
- `testing-anti-patterns` → bundled in `test-driven-development/`
- `sharing-skills` removed (obsolete)
### Other Improvements
- **render-graphs.js** - Tool to extract DOT diagrams from skills and render to SVG
- **Rationalizations table** in using-superpowers - Scannable format including new entries: "I need more context first", "Let me explore first", "This feels productive"
- **docs/testing.md** - Guide to testing skills with Claude Code integration tests
---
## v3.6.2 (2025-12-03)
### Fixed
- **Linux Compatibility**: Fixed polyglot hook wrapper (`run-hook.cmd`) to use POSIX-compliant syntax
- Replaced bash-specific `${BASH_SOURCE[0]:-$0}` with standard `$0` on line 16
- Resolves "Bad substitution" error on Ubuntu/Debian systems where `/bin/sh` is dash
- Fixes #141
---
## 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
- **OpenCode Support**: Native JavaScript plugin for OpenCode.ai
- Custom tools: `use_skill` and `find_skills`
- Message insertion pattern for skill persistence across context compaction
- Automatic context injection via chat.message hook
- Auto re-injection on session.compacted events
- 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
- Automated test suite with proper isolation (`tests/opencode/`)
- Platform-specific documentation (`docs/README.opencode.md`, `docs/README.codex.md`)
### Changed
- **Refactored Codex Implementation**: Now uses shared `lib/skills-core.js` ES module
- Eliminates code duplication between Codex and OpenCode
- 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)
### Improvements
- Optimized superpowers bootstrap to eliminate redundant skill execution. The `using-superpowers` skill content is now provided directly in session context, with clear guidance to use the Skill tool only for other skills. This reduces overhead and prevents the confusing loop where agents would execute `using-superpowers` manually despite already having the content from session start.
## v3.4.0 (2025-10-30)
### Improvements
- Simplified `brainstorming` skill to return to original conversational vision. Removed heavyweight 6-phase process with formal checklists in favor of natural dialogue: ask questions one at a time, then present design in 200-300 word sections with validation. Keeps documentation and implementation handoff features.
## v3.3.1 (2025-10-28)
### Improvements
- Updated `brainstorming` skill to require autonomous recon before questioning, encourage recommendation-driven decisions, and prevent agents from delegating prioritization back to humans.
- Applied writing clarity improvements to `brainstorming` skill following Strunk's "Elements of Style" principles (omitted needless words, converted negative to positive form, improved parallel construction).
### Bug Fixes
- Clarified `writing-skills` guidance so it points to the correct agent-specific personal skill directories (`~/.claude/skills` for Claude Code, `~/.codex/skills` for Codex).
## v3.3.0 (2025-10-28)
### New Features
**Experimental Codex Support**
- Added unified `superpowers-codex` script with bootstrap/use-skill/find-skills commands
- Cross-platform Node.js implementation (works on Windows, macOS, Linux)
- Namespaced skills: `superpowers:skill-name` for superpowers skills, `skill-name` for personal
- Personal skills override superpowers skills when names match
- Clean skill display: shows name/description without raw frontmatter
- Helpful context: shows supporting files directory for each skill
- Tool mapping for Codex: TodoWrite→update_plan, subagents→manual fallback, etc.
- Bootstrap integration with minimal AGENTS.md for automatic startup
- Complete installation guide and bootstrap instructions specific to Codex
**Key differences from Claude Code integration:**
- Single unified script instead of separate tools
- Tool substitution system for Codex-specific equivalents
- Simplified subagent handling (manual work instead of delegation)
- Updated terminology: "Superpowers skills" instead of "Core skills"
### Files Added
- `.codex/INSTALL.md` - Installation guide for Codex users
- `.codex/superpowers-bootstrap.md` - Bootstrap instructions with Codex adaptations
- `.codex/superpowers-codex` - Unified Node.js executable with all functionality
**Note:** Codex support is experimental. The integration provides core superpowers functionality but may require refinement based on user feedback.
## v3.2.3 (2025-10-23)
### Improvements
**Updated using-superpowers skill to use Skill tool instead of Read tool**
- Changed skill invocation instructions from Read tool to Skill tool
- Updated description: "using Read tool" → "using Skill tool"
- Updated step 3: "Use the Read tool" → "Use the Skill tool to read and run"
- Updated rationalization list: "Read the current version" → "Run the current version"
The Skill tool is the proper mechanism for invoking skills in Claude Code. This update corrects the bootstrap instructions to guide agents toward the correct tool.
### Files Changed
- Updated: `skills/using-superpowers/SKILL.md` - Changed tool references from Read to Skill
## v3.2.2 (2025-10-21)
### Improvements
**Strengthened using-superpowers skill against agent rationalization**
- Added EXTREMELY-IMPORTANT block with absolute language about mandatory skill checking
- "If even 1% chance a skill applies, you MUST read it"
- "You do not have a choice. You cannot rationalize your way out."
- Added MANDATORY FIRST RESPONSE PROTOCOL checklist
- 5-step process agents must complete before any response
- Explicit "responding without this = failure" consequence
- Added Common Rationalizations section with 8 specific evasion patterns
- "This is just a simple question" → WRONG
- "I can check files quickly" → WRONG
- "Let me gather information first" → WRONG
- Plus 5 more common patterns observed in agent behavior
These changes address observed agent behavior where they rationalize around skill usage despite clear instructions. The forceful language and pre-emptive counter-arguments aim to make non-compliance harder.
### Files Changed
- Updated: `skills/using-superpowers/SKILL.md` - Added three layers of enforcement to prevent skill-skipping rationalization
## v3.2.1 (2025-10-20)
### New Features
**Code reviewer agent now included in plugin**
- Added `superpowers:code-reviewer` agent to plugin's `agents/` directory
- Agent provides systematic code review against plans and coding standards
- Previously required users to have personal agent configuration
- All skill references updated to use namespaced `superpowers:code-reviewer`
- Fixes #55
### Files Changed
- New: `agents/code-reviewer.md` - Agent definition with review checklist and output format
- Updated: `skills/requesting-code-review/SKILL.md` - References to `superpowers:code-reviewer`
- Updated: `skills/subagent-driven-development/SKILL.md` - References to `superpowers:code-reviewer`
## v3.2.0 (2025-10-18)
### New Features
**Design documentation in brainstorming workflow**
- Added Phase 4: Design Documentation to brainstorming skill
- Design documents now written to `docs/plans/YYYY-MM-DD-<topic>-design.md` before implementation
- Restores functionality from original brainstorming command that was lost during skill conversion
- Documents written before worktree setup and implementation planning
- Tested with subagent to verify compliance under time pressure
### Breaking Changes
**Skill reference namespace standardization**
- All internal skill references now use `superpowers:` namespace prefix
- Updated format: `superpowers:test-driven-development` (previously just `test-driven-development`)
- Affects all REQUIRED SUB-SKILL, RECOMMENDED SUB-SKILL, and REQUIRED BACKGROUND references
- Aligns with how skills are invoked using the Skill tool
- Files updated: brainstorming, executing-plans, subagent-driven-development, systematic-debugging, testing-skills-with-subagents, writing-plans, writing-skills
### Improvements
**Design vs implementation plan naming**
- Design documents use `-design.md` suffix to prevent filename collisions
- Implementation plans continue using existing `YYYY-MM-DD-<feature-name>.md` format
- Both stored in `docs/plans/` directory with clear naming distinction
## v3.1.1 (2025-10-17)
### Bug Fixes
- **Fixed command syntax in README** (#44) - Updated all command references to use correct namespaced syntax (`/superpowers:brainstorm` instead of `/brainstorm`). Plugin-provided commands are automatically namespaced by Claude Code to avoid conflicts between plugins.
## v3.1.0 (2025-10-17)
### Breaking Changes
**Skill names standardized to lowercase**
- All skill frontmatter `name:` fields now use lowercase kebab-case matching directory names
- Examples: `brainstorming`, `test-driven-development`, `using-git-worktrees`
- All skill announcements and cross-references updated to lowercase format
- This ensures consistent naming across directory names, frontmatter, and documentation
### New Features
**Enhanced brainstorming skill**
- Added Quick Reference table showing phases, activities, and tool usage
- Added copyable workflow checklist for tracking progress
- Added decision flowchart for when to revisit earlier phases
- Added comprehensive AskUserQuestion tool guidance with concrete examples
- Added "Question Patterns" section explaining when to use structured vs open-ended questions
- Restructured Key Principles as scannable table
**Anthropic best practices integration**
- Added `skills/writing-skills/anthropic-best-practices.md` - Official Anthropic skill authoring guide
- Referenced in writing-skills SKILL.md for comprehensive guidance
- Provides patterns for progressive disclosure, workflows, and evaluation
### Improvements
**Skill cross-reference clarity**
- All skill references now use explicit requirement markers:
- `**REQUIRED BACKGROUND:**` - Prerequisites you must understand
- `**REQUIRED SUB-SKILL:**` - Skills that must be used in workflow
- `**Complementary skills:**` - Optional but helpful related skills
- Removed old path format (`skills/collaboration/X` → just `X`)
- Updated Integration sections with categorized relationships (Required vs Complementary)
- Updated cross-reference documentation with best practices
**Alignment with Anthropic best practices**
- Fixed description grammar and voice (fully third-person)
- Added Quick Reference tables for scanning
- Added workflow checklists Claude can copy and track
- Appropriate use of flowcharts for non-obvious decision points
- Improved scannable table formats
- All skills well under 500-line recommendation
### Bug Fixes
- **Re-added missing command redirects** - Restored `commands/brainstorm.md` and `commands/write-plan.md` that were accidentally removed in v3.0 migration
- Fixed `defense-in-depth` name mismatch (was `Defense-in-Depth-Validation`)
- Fixed `receiving-code-review` name mismatch (was `Code-Review-Reception`)
- Fixed `commands/brainstorm.md` reference to correct skill name
- Removed references to non-existent related skills
### Documentation
**writing-skills improvements**
- Updated cross-referencing guidance with explicit requirement markers
- Added reference to Anthropic's official best practices
- Improved examples showing proper skill reference format
## v3.0.1 (2025-10-16)
### Changes
We now use Anthropic's first-party skills system!
## v2.0.2 (2025-10-12)
### Bug Fixes
- **Fixed false warning when local skills repo is ahead of upstream** - The initialization script was incorrectly warning "New skills available from upstream" when the local repository had commits ahead of upstream. The logic now correctly distinguishes between three git states: local behind (should update), local ahead (no warning), and diverged (should warn).
## v2.0.1 (2025-10-12)
### Bug Fixes
- **Fixed session-start hook execution in plugin context** (#8, PR #9) - The hook was failing silently with "Plugin hook error" preventing skills context from loading. Fixed by:
- Using `${BASH_SOURCE[0]:-$0}` fallback when BASH_SOURCE is unbound in Claude Code's execution context
- Adding `|| true` to handle empty grep results gracefully when filtering status flags
---
# Superpowers v2.0.0 Release Notes
## Overview
Superpowers v2.0 makes skills more accessible, maintainable, and community-driven through a major architectural shift.
The headline change is **skills repository separation**: all skills, scripts, and documentation have moved from the plugin into a dedicated repository ([obra/superpowers-skills](https://github.com/obra/superpowers-skills)). This transforms superpowers from a monolithic plugin into a lightweight shim that manages a local clone of the skills repository. Skills auto-update on session start. Users fork and contribute improvements via standard git workflows. The skills library versions independently from the plugin.
Beyond infrastructure, this release adds nine new skills focused on problem-solving, research, and architecture. We rewrote the core **using-skills** documentation with imperative tone and clearer structure, making it easier for Claude to understand when and how to use skills. **find-skills** now outputs paths you can paste directly into the Read tool, eliminating friction in the skills discovery workflow.
Users experience seamless operation: the plugin handles cloning, forking, and updating automatically. Contributors find the new architecture makes improving and sharing skills trivial. This release lays the foundation for skills to evolve rapidly as a community resource.
## Breaking Changes
### Skills Repository Separation
**The biggest change:** Skills no longer live in the plugin. They've been moved to a separate repository at [obra/superpowers-skills](https://github.com/obra/superpowers-skills).
**What this means for you:**
- **First install:** Plugin automatically clones skills to `~/.config/superpowers/skills/`
- **Forking:** During setup, you'll be offered the option to fork the skills repo (if `gh` is installed)
- **Updates:** Skills auto-update on session start (fast-forward when possible)
- **Contributing:** Work on branches, commit locally, submit PRs to upstream
- **No more shadowing:** Old two-tier system (personal/core) replaced with single-repo branch workflow
**Migration:**
If you have an existing installation:
1. Your old `~/.config/superpowers/.git` will be backed up to `~/.config/superpowers/.git.bak`
2. Old skills will be backed up to `~/.config/superpowers/skills.bak`
3. Fresh clone of obra/superpowers-skills will be created at `~/.config/superpowers/skills/`
### Removed Features
- **Personal superpowers overlay system** - Replaced with git branch workflow
- **setup-personal-superpowers hook** - Replaced by initialize-skills.sh
## New Features
### Skills Repository Infrastructure
**Automatic Clone & Setup** (`lib/initialize-skills.sh`)
- Clones obra/superpowers-skills on first run
- Offers fork creation if GitHub CLI is installed
- Sets up upstream/origin remotes correctly
- Handles migration from old installation
**Auto-Update**
- Fetches from tracking remote on every session start
- Auto-merges with fast-forward when possible
- Notifies when manual sync needed (branch diverged)
- Uses pulling-updates-from-skills-repository skill for manual sync
### New Skills
**Problem-Solving Skills** (`skills/problem-solving/`)
- **collision-zone-thinking** - Force unrelated concepts together for emergent insights
- **inversion-exercise** - Flip assumptions to reveal hidden constraints
- **meta-pattern-recognition** - Spot universal principles across domains
- **scale-game** - Test at extremes to expose fundamental truths
- **simplification-cascades** - Find insights that eliminate multiple components
- **when-stuck** - Dispatch to right problem-solving technique
**Research Skills** (`skills/research/`)
- **tracing-knowledge-lineages** - Understand how ideas evolved over time
**Architecture Skills** (`skills/architecture/`)
- **preserving-productive-tensions** - Keep multiple valid approaches instead of forcing premature resolution
### Skills Improvements
**using-skills (formerly getting-started)**
- Renamed from getting-started to using-skills
- Complete rewrite with imperative tone (v4.0.0)
- Front-loaded critical rules
- Added "Why" explanations for all workflows
- Always includes /SKILL.md suffix in references
- Clearer distinction between rigid rules and flexible patterns
**writing-skills**
- Cross-referencing guidance moved from using-skills
- Added token efficiency section (word count targets)
- Improved CSO (Claude Search Optimization) guidance
**sharing-skills**
- Updated for new branch-and-PR workflow (v2.0.0)
- Removed personal/core split references
**pulling-updates-from-skills-repository** (new)
- Complete workflow for syncing with upstream
- Replaces old "updating-skills" skill
### Tools Improvements
**find-skills**
- Now outputs full paths with /SKILL.md suffix
- Makes paths directly usable with Read tool
- Updated help text
**skill-run**
- Moved from scripts/ to skills/using-skills/
- Improved documentation
### Plugin Infrastructure
**Session Start Hook**
- Now loads from skills repository location
- Shows full skills list at session start
- Prints skills location info
- Shows update status (updated successfully / behind upstream)
- Moved "skills behind" warning to end of output
**Environment Variables**
- `SUPERPOWERS_SKILLS_ROOT` set to `~/.config/superpowers/skills`
- Used consistently throughout all paths
## Bug Fixes
- Fixed duplicate upstream remote addition when forking
- Fixed find-skills double "skills/" prefix in output
- Removed obsolete setup-personal-superpowers call from session-start
- Fixed path references throughout hooks and commands
## Documentation
### README
- Updated for new skills repository architecture
- Prominent link to superpowers-skills repo
- Updated auto-update description
- Fixed skill names and references
- Updated Meta skills list
### Testing Documentation
- Added comprehensive testing checklist (`docs/TESTING-CHECKLIST.md`)
- Created local marketplace config for testing
- Documented manual testing scenarios
## Technical Details
### File Changes
**Added:**
- `lib/initialize-skills.sh` - Skills repo initialization and auto-update
- `docs/TESTING-CHECKLIST.md` - Manual testing scenarios
- `.claude-plugin/marketplace.json` - Local testing config
**Removed:**
- `skills/` directory (82 files) - Now in obra/superpowers-skills
- `scripts/` directory - Now in obra/superpowers-skills/skills/using-skills/
- `hooks/setup-personal-superpowers.sh` - Obsolete
**Modified:**
- `hooks/session-start.sh` - Use skills from ~/.config/superpowers/skills
- `commands/brainstorm.md` - Updated paths to SUPERPOWERS_SKILLS_ROOT
- `commands/write-plan.md` - Updated paths to SUPERPOWERS_SKILLS_ROOT
- `commands/execute-plan.md` - Updated paths to SUPERPOWERS_SKILLS_ROOT
- `README.md` - Complete rewrite for new architecture
### Commit History
This release includes:
- 20+ commits for skills repository separation
- PR #1: Amplifier-inspired problem-solving and research skills
- PR #2: Personal superpowers overlay system (later replaced)
- Multiple skill refinements and documentation improvements
## Upgrade Instructions
### Fresh Install
```bash
# In Claude Code
/plugin marketplace add obra/superpowers-marketplace
/plugin install superpowers@superpowers-marketplace
```
The plugin handles everything automatically.
### Upgrading from v1.x
1. **Backup your personal skills** (if you have any):
```bash
cp -r ~/.config/superpowers/skills ~/superpowers-skills-backup
```
2. **Update the plugin:**
```bash
/plugin update superpowers
```
3. **On next session start:**
- Old installation will be backed up automatically
- Fresh skills repo will be cloned
- If you have GitHub CLI, you'll be offered the option to fork
4. **Migrate personal skills** (if you had any):
- Create a branch in your local skills repo
- Copy your personal skills from backup
- Commit and push to your fork
- Consider contributing back via PR
## What's Next
### For Users
- Explore the new problem-solving skills
- Try the branch-based workflow for skill improvements
- Contribute skills back to the community
### For Contributors
- Skills repository is now at https://github.com/obra/superpowers-skills
- Fork → Branch → PR workflow
- See skills/meta/writing-skills/SKILL.md for TDD approach to documentation
## Known Issues
None at this time.
## Credits
- Problem-solving skills inspired by Amplifier patterns
- Community contributions and feedback
- Extensive testing and iteration on skill effectiveness
---
**Full Changelog:** https://github.com/obra/superpowers/compare/dd013f6...main
**Skills Repository:** https://github.com/obra/superpowers-skills
**Issues:** https://github.com/obra/superpowers/issues

48
agents/code-reviewer.md Normal file
View File

@@ -0,0 +1,48 @@
---
name: code-reviewer
description: |
Use this agent when a major project step has been completed and needs to be reviewed against the original plan and coding standards. Examples: <example>Context: The user is creating a code-review agent that should be called after a logical chunk of code is written. user: "I've finished implementing the user authentication system as outlined in step 3 of our plan" assistant: "Great work! Now let me use the code-reviewer agent to review the implementation against our plan and coding standards" <commentary>Since a major project step has been completed, use the code-reviewer agent to validate the work against the plan and identify any issues.</commentary></example> <example>Context: User has completed a significant feature implementation. user: "The API endpoints for the task management system are now complete - that covers step 2 from our architecture document" assistant: "Excellent! Let me have the code-reviewer agent examine this implementation to ensure it aligns with our plan and follows best practices" <commentary>A numbered step from the planning document has been completed, so the code-reviewer agent should review the work.</commentary></example>
model: inherit
---
You are a Senior Code Reviewer with expertise in software architecture, design patterns, and best practices. Your role is to review completed project steps against original plans and ensure code quality standards are met.
When reviewing completed work, you will:
1. **Plan Alignment Analysis**:
- Compare the implementation against the original planning document or step description
- Identify any deviations from the planned approach, architecture, or requirements
- Assess whether deviations are justified improvements or problematic departures
- Verify that all planned functionality has been implemented
2. **Code Quality Assessment**:
- Review code for adherence to established patterns and conventions
- Check for proper error handling, type safety, and defensive programming
- Evaluate code organization, naming conventions, and maintainability
- Assess test coverage and quality of test implementations
- Look for potential security vulnerabilities or performance issues
3. **Architecture and Design Review**:
- Ensure the implementation follows SOLID principles and established architectural patterns
- Check for proper separation of concerns and loose coupling
- Verify that the code integrates well with existing systems
- Assess scalability and extensibility considerations
4. **Documentation and Standards**:
- Verify that code includes appropriate comments and documentation
- Check that file headers, function documentation, and inline comments are present and accurate
- Ensure adherence to project-specific coding standards and conventions
5. **Issue Identification and Recommendations**:
- Clearly categorize issues as: Critical (must fix), Important (should fix), or Suggestions (nice to have)
- For each issue, provide specific examples and actionable recommendations
- When you identify plan deviations, explain whether they're problematic or beneficial
- Suggest specific improvements with code examples when helpful
6. **Communication Protocol**:
- If you find significant deviations from the plan, ask the coding agent to review and confirm the changes
- If you identify issues with the original plan itself, recommend plan updates
- For implementation problems, provide clear guidance on fixes needed
- Always acknowledge what was done well before highlighting issues
Your output should be structured, actionable, and focused on helping maintain high code quality while ensuring project goals are met. Be thorough but concise, and always provide constructive feedback that helps improve both the current implementation and future development practices.

View File

@@ -1,36 +0,0 @@
# Claude Commands
Slash commands for Claude that reference skills.
## Available Commands
- `/brainstorm` - Interactive idea refinement using Socratic method (→ `@skills/collaboration/brainstorming/SKILL.md`)
- `/write-plan` - Create detailed implementation plan (→ `@skills/collaboration/writing-plans/SKILL.md`)
- `/execute-plan` - Execute plan in batches with review (→ `@skills/collaboration/executing-plans/SKILL.md`)
## Format
Each command is a simple markdown file containing a single `@` reference to a skill:
```markdown
@skills/collaboration/brainstorming/SKILL.md
```
When you run the command (e.g., `/brainstorm`), Claude loads and follows that skill.
## Creating Custom Commands
To add your own commands:
1. Create `your-command.md` in this directory
2. Add a single line referencing a skill:
```markdown
@skills/your-category/your-skill/SKILL.md
```
3. The command `/your-command` is now available
## Installation
These commands are automatically symlinked to `~/.claude/commands/` by the clank installer.
See `@skills/meta/installing-skills/SKILL.md` for installation details.

View File

@@ -1,5 +1,6 @@
---
description: Interactive design refinement using Socratic method
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
---
Read and follow: ${CLAUDE_PLUGIN_ROOT}/skills/collaboration/brainstorming/SKILL.md
Invoke the superpowers:brainstorming skill and follow it exactly as presented to you

View File

@@ -1,5 +1,6 @@
---
description: Execute plan in batches with review checkpoints
disable-model-invocation: true
---
Read and follow: ${CLAUDE_PLUGIN_ROOT}/skills/collaboration/executing-plans/SKILL.md
Invoke the superpowers:executing-plans skill and follow it exactly as presented to you

View File

@@ -1,5 +1,6 @@
---
description: Create detailed implementation plan with bite-sized tasks
disable-model-invocation: true
---
Read and follow: ${CLAUDE_PLUGIN_ROOT}/skills/collaboration/writing-plans/SKILL.md
Invoke the superpowers:writing-plans skill and follow it exactly as presented to you

120
docs/README.codex.md Normal file
View File

@@ -0,0 +1,120 @@
# Superpowers for Codex
Guide for using Superpowers with OpenAI Codex via native skill discovery.
## Quick Install
Tell Codex:
```
Fetch and follow instructions from https://raw.githubusercontent.com/obra/superpowers/refs/heads/main/.codex/INSTALL.md
```
## Manual Installation
### Prerequisites
- OpenAI Codex CLI
- Git
### Steps
1. Clone the repo:
```bash
git clone https://github.com/obra/superpowers.git ~/.codex/superpowers
```
2. Create the skills symlink:
```bash
mkdir -p ~/.agents/skills
ln -s ~/.codex/superpowers/skills ~/.agents/skills/superpowers
```
3. Restart Codex.
### Windows
Use a junction instead of a symlink (works without Developer Mode):
```powershell
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.agents\skills"
cmd /c mklink /J "$env:USERPROFILE\.agents\skills\superpowers" "$env:USERPROFILE\.codex\superpowers\skills"
```
## How It Works
Codex has native skill discovery — it scans `~/.agents/skills/` at startup, parses SKILL.md frontmatter, and loads skills on demand. Superpowers skills are made visible through a single symlink:
```
~/.agents/skills/superpowers/ → ~/.codex/superpowers/skills/
```
The `using-superpowers` skill is discovered automatically and enforces skill usage discipline — no additional configuration needed.
## Usage
Skills are discovered automatically. Codex activates them when:
- You mention a skill by name (e.g., "use brainstorming")
- The task matches a skill's description
- The `using-superpowers` skill directs Codex to use one
### Personal Skills
Create your own skills in `~/.agents/skills/`:
```bash
mkdir -p ~/.agents/skills/my-skill
```
Create `~/.agents/skills/my-skill/SKILL.md`:
```markdown
---
name: my-skill
description: Use when [condition] - [what it does]
---
# My Skill
[Your skill content here]
```
The `description` field is how Codex decides when to activate a skill automatically — write it as a clear trigger condition.
## Updating
```bash
cd ~/.codex/superpowers && git pull
```
Skills update instantly through the symlink.
## Uninstalling
```bash
rm ~/.agents/skills/superpowers
```
**Windows (PowerShell):**
```powershell
Remove-Item "$env:USERPROFILE\.agents\skills\superpowers"
```
Optionally delete the clone: `rm -rf ~/.codex/superpowers` (Windows: `Remove-Item -Recurse -Force "$env:USERPROFILE\.codex\superpowers"`).
## Troubleshooting
### Skills not showing up
1. Verify the symlink: `ls -la ~/.agents/skills/superpowers`
2. Check skills exist: `ls ~/.codex/superpowers/skills`
3. Restart Codex — skills are discovered at startup
### Windows junction issues
Junctions normally work without special permissions. If creation fails, try running PowerShell as administrator.
## Getting Help
- Report issues: https://github.com/obra/superpowers/issues
- Main documentation: https://github.com/obra/superpowers

330
docs/README.opencode.md Normal file
View File

@@ -0,0 +1,330 @@
# Superpowers for OpenCode
Complete guide for using Superpowers with [OpenCode.ai](https://opencode.ai).
## Quick Install
Tell OpenCode:
```
Clone https://github.com/obra/superpowers to ~/.config/opencode/superpowers, then create directory ~/.config/opencode/plugins, then symlink ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js to ~/.config/opencode/plugins/superpowers.js, then symlink ~/.config/opencode/superpowers/skills to ~/.config/opencode/skills/superpowers, then restart opencode.
```
## Manual Installation
### Prerequisites
- [OpenCode.ai](https://opencode.ai) installed
- Git installed
### macOS / Linux
```bash
# 1. Install Superpowers (or update existing)
if [ -d ~/.config/opencode/superpowers ]; then
cd ~/.config/opencode/superpowers && git pull
else
git clone https://github.com/obra/superpowers.git ~/.config/opencode/superpowers
fi
# 2. Create directories
mkdir -p ~/.config/opencode/plugins ~/.config/opencode/skills
# 3. Remove old symlinks/directories if they exist
rm -f ~/.config/opencode/plugins/superpowers.js
rm -rf ~/.config/opencode/skills/superpowers
# 4. Create symlinks
ln -s ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js ~/.config/opencode/plugins/superpowers.js
ln -s ~/.config/opencode/superpowers/skills ~/.config/opencode/skills/superpowers
# 5. Restart OpenCode
```
#### Verify Installation
```bash
ls -l ~/.config/opencode/plugins/superpowers.js
ls -l ~/.config/opencode/skills/superpowers
```
Both should show symlinks pointing to the superpowers directory.
### Windows
**Prerequisites:**
- Git installed
- Either **Developer Mode** enabled OR **Administrator privileges**
- Windows 10: Settings → Update & Security → For developers
- Windows 11: Settings → System → For developers
Pick your shell below: [Command Prompt](#command-prompt) | [PowerShell](#powershell) | [Git Bash](#git-bash)
#### Command Prompt
Run as Administrator, or with Developer Mode enabled:
```cmd
:: 1. Install Superpowers
git clone https://github.com/obra/superpowers.git "%USERPROFILE%\.config\opencode\superpowers"
:: 2. Create directories
mkdir "%USERPROFILE%\.config\opencode\plugins" 2>nul
mkdir "%USERPROFILE%\.config\opencode\skills" 2>nul
:: 3. Remove existing links (safe for reinstalls)
del "%USERPROFILE%\.config\opencode\plugins\superpowers.js" 2>nul
rmdir "%USERPROFILE%\.config\opencode\skills\superpowers" 2>nul
:: 4. Create plugin symlink (requires Developer Mode or Admin)
mklink "%USERPROFILE%\.config\opencode\plugins\superpowers.js" "%USERPROFILE%\.config\opencode\superpowers\.opencode\plugins\superpowers.js"
:: 5. Create skills junction (works without special privileges)
mklink /J "%USERPROFILE%\.config\opencode\skills\superpowers" "%USERPROFILE%\.config\opencode\superpowers\skills"
:: 6. Restart OpenCode
```
#### PowerShell
Run as Administrator, or with Developer Mode enabled:
```powershell
# 1. Install Superpowers
git clone https://github.com/obra/superpowers.git "$env:USERPROFILE\.config\opencode\superpowers"
# 2. Create directories
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.config\opencode\plugins"
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.config\opencode\skills"
# 3. Remove existing links (safe for reinstalls)
Remove-Item "$env:USERPROFILE\.config\opencode\plugins\superpowers.js" -Force -ErrorAction SilentlyContinue
Remove-Item "$env:USERPROFILE\.config\opencode\skills\superpowers" -Force -ErrorAction SilentlyContinue
# 4. Create plugin symlink (requires Developer Mode or Admin)
New-Item -ItemType SymbolicLink -Path "$env:USERPROFILE\.config\opencode\plugins\superpowers.js" -Target "$env:USERPROFILE\.config\opencode\superpowers\.opencode\plugins\superpowers.js"
# 5. Create skills junction (works without special privileges)
New-Item -ItemType Junction -Path "$env:USERPROFILE\.config\opencode\skills\superpowers" -Target "$env:USERPROFILE\.config\opencode\superpowers\skills"
# 6. Restart OpenCode
```
#### Git Bash
Note: Git Bash's native `ln` command copies files instead of creating symlinks. Use `cmd //c mklink` instead (the `//c` is Git Bash syntax for `/c`).
```bash
# 1. Install Superpowers
git clone https://github.com/obra/superpowers.git ~/.config/opencode/superpowers
# 2. Create directories
mkdir -p ~/.config/opencode/plugins ~/.config/opencode/skills
# 3. Remove existing links (safe for reinstalls)
rm -f ~/.config/opencode/plugins/superpowers.js 2>/dev/null
rm -rf ~/.config/opencode/skills/superpowers 2>/dev/null
# 4. Create plugin symlink (requires Developer Mode or Admin)
cmd //c "mklink \"$(cygpath -w ~/.config/opencode/plugins/superpowers.js)\" \"$(cygpath -w ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js)\""
# 5. Create skills junction (works without special privileges)
cmd //c "mklink /J \"$(cygpath -w ~/.config/opencode/skills/superpowers)\" \"$(cygpath -w ~/.config/opencode/superpowers/skills)\""
# 6. Restart OpenCode
```
#### WSL Users
If running OpenCode inside WSL, use the [macOS / Linux](#macos--linux) instructions instead.
#### Verify Installation
**Command Prompt:**
```cmd
dir /AL "%USERPROFILE%\.config\opencode\plugins"
dir /AL "%USERPROFILE%\.config\opencode\skills"
```
**PowerShell:**
```powershell
Get-ChildItem "$env:USERPROFILE\.config\opencode\plugins" | Where-Object { $_.LinkType }
Get-ChildItem "$env:USERPROFILE\.config\opencode\skills" | Where-Object { $_.LinkType }
```
Look for `<SYMLINK>` or `<JUNCTION>` in the output.
#### Troubleshooting Windows
**"You do not have sufficient privilege" error:**
- Enable Developer Mode in Windows Settings, OR
- Right-click your terminal → "Run as Administrator"
**"Cannot create a file when that file already exists":**
- Run the removal commands (step 3) first, then retry
**Symlinks not working after git clone:**
- Run `git config --global core.symlinks true` and re-clone
## Usage
### Finding Skills
Use OpenCode's native `skill` tool to list all available skills:
```
use skill tool to list skills
```
### Loading a Skill
Use OpenCode's native `skill` tool to load a specific skill:
```
use skill tool to load superpowers/brainstorming
```
### Personal Skills
Create your own skills in `~/.config/opencode/skills/`:
```bash
mkdir -p ~/.config/opencode/skills/my-skill
```
Create `~/.config/opencode/skills/my-skill/SKILL.md`:
```markdown
---
name: my-skill
description: Use when [condition] - [what it does]
---
# My Skill
[Your skill content here]
```
### Project Skills
Create project-specific skills in your OpenCode project:
```bash
# In your OpenCode project
mkdir -p .opencode/skills/my-project-skill
```
Create `.opencode/skills/my-project-skill/SKILL.md`:
```markdown
---
name: my-project-skill
description: Use when [condition] - [what it does]
---
# My Project Skill
[Your skill content here]
```
## Skill Locations
OpenCode discovers skills from these locations:
1. **Project skills** (`.opencode/skills/`) - Highest priority
2. **Personal skills** (`~/.config/opencode/skills/`)
3. **Superpowers skills** (`~/.config/opencode/skills/superpowers/`) - via symlink
## Features
### Automatic Context Injection
The plugin automatically injects superpowers context via the `experimental.chat.system.transform` hook. This adds the "using-superpowers" skill content to the system prompt on every request.
### Native Skills Integration
Superpowers uses OpenCode's native `skill` tool for skill discovery and loading. Skills are symlinked into `~/.config/opencode/skills/superpowers/` so they appear alongside your personal and project skills.
### Tool Mapping
Skills written for Claude Code are automatically adapted for OpenCode. The bootstrap provides mapping instructions:
- `TodoWrite``update_plan`
- `Task` with subagents → OpenCode's `@mention` system
- `Skill` tool → OpenCode's native `skill` tool
- File operations → Native OpenCode tools
## Architecture
### Plugin Structure
**Location:** `~/.config/opencode/superpowers/.opencode/plugins/superpowers.js`
**Components:**
- `experimental.chat.system.transform` hook for bootstrap injection
- Reads and injects the "using-superpowers" skill content
### Skills
**Location:** `~/.config/opencode/skills/superpowers/` (symlink to `~/.config/opencode/superpowers/skills/`)
Skills are discovered by OpenCode's native skill system. Each skill has a `SKILL.md` file with YAML frontmatter.
## Updating
```bash
cd ~/.config/opencode/superpowers
git pull
```
Restart OpenCode to load the updates.
## Troubleshooting
### Plugin not loading
1. Check plugin exists: `ls ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js`
2. Check symlink/junction: `ls -l ~/.config/opencode/plugins/` (macOS/Linux) or `dir /AL %USERPROFILE%\.config\opencode\plugins` (Windows)
3. Check OpenCode logs: `opencode run "test" --print-logs --log-level DEBUG`
4. Look for plugin loading message in logs
### Skills not found
1. Verify skills symlink: `ls -l ~/.config/opencode/skills/superpowers` (should point to superpowers/skills/)
2. Use OpenCode's `skill` tool to list available skills
3. Check skill structure: each skill needs a `SKILL.md` file with valid frontmatter
### Windows: Module not found error
If you see `Cannot find module` errors on Windows:
- **Cause:** Git Bash `ln -sf` copies files instead of creating symlinks
- **Fix:** Use `mklink /J` directory junctions instead (see Windows installation steps)
### Bootstrap not appearing
1. Verify using-superpowers skill exists: `ls ~/.config/opencode/superpowers/skills/using-superpowers/SKILL.md`
2. Check OpenCode version supports `experimental.chat.system.transform` hook
3. Restart OpenCode after plugin changes
## Getting Help
- Report issues: https://github.com/obra/superpowers/issues
- Main documentation: https://github.com/obra/superpowers
- OpenCode docs: https://opencode.ai/docs/
## Testing
Verify your installation:
```bash
# Check plugin loads
opencode run --print-logs "hello" 2>&1 | grep -i superpowers
# Check skills are discoverable
opencode run "use skill tool to list all skills" 2>&1 | grep -i superpowers
# Check bootstrap injection
opencode run "what superpowers do you have?"
```
The agent should mention having superpowers and be able to list skills from `superpowers/`.

View File

@@ -0,0 +1,294 @@
# OpenCode Support Design
**Date:** 2025-11-22
**Author:** Bot & Jesse
**Status:** Design Complete, Awaiting Implementation
## Overview
Add full superpowers support for OpenCode.ai using a native OpenCode plugin architecture that shares core functionality with the existing Codex implementation.
## Background
OpenCode.ai is a coding agent similar to Claude Code and Codex. Previous attempts to port superpowers to OpenCode (PR #93, PR #116) used file-copying approaches. This design takes a different approach: building a native OpenCode plugin using their JavaScript/TypeScript plugin system while sharing code with the Codex implementation.
### Key Differences Between Platforms
- **Claude Code**: Native Anthropic plugin system + file-based skills
- **Codex**: No plugin system → bootstrap markdown + CLI script
- **OpenCode**: JavaScript/TypeScript plugins with event hooks and custom tools API
### OpenCode's Agent System
- **Primary agents**: Build (default, full access) and Plan (restricted, read-only)
- **Subagents**: General (research, searching, multi-step tasks)
- **Invocation**: Automatic dispatch by primary agents OR manual `@mention` syntax
- **Configuration**: Custom agents in `opencode.json` or `~/.config/opencode/agent/`
## Architecture
### High-Level Structure
1. **Shared Core Module** (`lib/skills-core.js`)
- Common skill discovery and parsing logic
- Used by both Codex and OpenCode implementations
2. **Platform-Specific Wrappers**
- Codex: CLI script (`.codex/superpowers-codex`)
- OpenCode: Plugin module (`.opencode/plugin/superpowers.js`)
3. **Skill Directories**
- Core: `~/.config/opencode/superpowers/skills/` (or installed location)
- Personal: `~/.config/opencode/skills/` (shadows core skills)
### Code Reuse Strategy
Extract common functionality from `.codex/superpowers-codex` into shared module:
```javascript
// lib/skills-core.js
module.exports = {
extractFrontmatter(filePath), // Parse name + description from YAML
findSkillsInDir(dir, maxDepth), // Recursive SKILL.md discovery
findAllSkills(dirs), // Scan multiple directories
resolveSkillPath(skillName, dirs), // Handle shadowing (personal > core)
checkForUpdates(repoDir) // Git fetch/status check
};
```
### Skill Frontmatter Format
Current format (no `when_to_use` field):
```yaml
---
name: skill-name
description: Use when [condition] - [what it does]; [additional context]
---
```
## OpenCode Plugin Implementation
### Custom Tools
**Tool 1: `use_skill`**
Loads a specific skill's content into the conversation (equivalent to Claude's Skill tool).
```javascript
{
name: 'use_skill',
description: 'Load and read a specific skill to guide your work',
schema: z.object({
skill_name: z.string().describe('Name of skill (e.g., "superpowers:brainstorming")')
}),
execute: async ({ skill_name }) => {
const { skillPath, content, frontmatter } = resolveAndReadSkill(skill_name);
const skillDir = path.dirname(skillPath);
return `# ${frontmatter.name}
# ${frontmatter.description}
# Supporting tools and docs are in ${skillDir}
# ============================================
${content}`;
}
}
```
**Tool 2: `find_skills`**
Lists all available skills with metadata.
```javascript
{
name: 'find_skills',
description: 'List all available skills',
schema: z.object({}),
execute: async () => {
const skills = discoverAllSkills();
return skills.map(s =>
`${s.namespace}:${s.name}
${s.description}
Directory: ${s.directory}
`).join('\n');
}
}
```
### Session Startup Hook
When a new session starts (`session.started` event):
1. **Inject using-superpowers content**
- Full content of the using-superpowers skill
- Establishes mandatory workflows
2. **Run find_skills automatically**
- Display full list of available skills upfront
- Include skill directories for each
3. **Inject tool mapping instructions**
```markdown
**Tool Mapping for OpenCode:**
When skills reference tools you don't have, substitute:
- `TodoWrite` → `update_plan`
- `Task` with subagents → Use OpenCode subagent system (@mention)
- `Skill` tool → `use_skill` custom tool
- Read, Write, Edit, Bash → Your native equivalents
**Skill directories contain:**
- Supporting scripts (run with bash)
- Additional documentation (read with read tool)
- Utilities specific to that skill
```
4. **Check for updates** (non-blocking)
- Quick git fetch with timeout
- Notify if updates available
### Plugin Structure
```javascript
// .opencode/plugin/superpowers.js
const skillsCore = require('../../lib/skills-core');
const path = require('path');
const fs = require('fs');
const { z } = require('zod');
export const SuperpowersPlugin = async ({ client, directory, $ }) => {
const superpowersDir = path.join(process.env.HOME, '.config/opencode/superpowers');
const personalDir = path.join(process.env.HOME, '.config/opencode/skills');
return {
'session.started': async () => {
const usingSuperpowers = await readSkill('using-superpowers');
const skillsList = await findAllSkills();
const toolMapping = getToolMappingInstructions();
return {
context: `${usingSuperpowers}\n\n${skillsList}\n\n${toolMapping}`
};
},
tools: [
{
name: 'use_skill',
description: 'Load and read a specific skill',
schema: z.object({
skill_name: z.string()
}),
execute: async ({ skill_name }) => {
// Implementation using skillsCore
}
},
{
name: 'find_skills',
description: 'List all available skills',
schema: z.object({}),
execute: async () => {
// Implementation using skillsCore
}
}
]
};
};
```
## File Structure
```
superpowers/
├── lib/
│ └── skills-core.js # NEW: Shared skill logic
├── .codex/
│ ├── superpowers-codex # UPDATED: Use skills-core
│ ├── superpowers-bootstrap.md
│ └── INSTALL.md
├── .opencode/
│ ├── plugin/
│ │ └── superpowers.js # NEW: OpenCode plugin
│ └── INSTALL.md # NEW: Installation guide
└── skills/ # Unchanged
```
## Implementation Plan
### Phase 1: Refactor Shared Core
1. Create `lib/skills-core.js`
- Extract frontmatter parsing from `.codex/superpowers-codex`
- Extract skill discovery logic
- Extract path resolution (with shadowing)
- Update to use only `name` and `description` (no `when_to_use`)
2. Update `.codex/superpowers-codex` to use shared core
- Import from `../lib/skills-core.js`
- Remove duplicated code
- Keep CLI wrapper logic
3. Test Codex implementation still works
- Verify bootstrap command
- Verify use-skill command
- Verify find-skills command
### Phase 2: Build OpenCode Plugin
1. Create `.opencode/plugin/superpowers.js`
- Import shared core from `../../lib/skills-core.js`
- Implement plugin function
- Define custom tools (use_skill, find_skills)
- Implement session.started hook
2. Create `.opencode/INSTALL.md`
- Installation instructions
- Directory setup
- Configuration guidance
3. Test OpenCode implementation
- Verify session startup bootstrap
- Verify use_skill tool works
- Verify find_skills tool works
- Verify skill directories are accessible
### Phase 3: Documentation & Polish
1. Update README with OpenCode support
2. Add OpenCode installation to main docs
3. Update RELEASE-NOTES
4. Test both Codex and OpenCode work correctly
## Next Steps
1. **Create isolated workspace** (using git worktrees)
- Branch: `feature/opencode-support`
2. **Follow TDD where applicable**
- Test shared core functions
- Test skill discovery and parsing
- Integration tests for both platforms
3. **Incremental implementation**
- Phase 1: Refactor shared core + update Codex
- Verify Codex still works before moving on
- Phase 2: Build OpenCode plugin
- Phase 3: Documentation and polish
4. **Testing strategy**
- Manual testing with real OpenCode installation
- Verify skill loading, directories, scripts work
- Test both Codex and OpenCode side-by-side
- Verify tool mappings work correctly
5. **PR and merge**
- Create PR with complete implementation
- Test in clean environment
- Merge to main
## Benefits
- **Code reuse**: Single source of truth for skill discovery/parsing
- **Maintainability**: Bug fixes apply to both platforms
- **Extensibility**: Easy to add future platforms (Cursor, Windsurf, etc.)
- **Native integration**: Uses OpenCode's plugin system properly
- **Consistency**: Same skill experience across all platforms

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,711 @@
# Skills Improvements from User Feedback
**Date:** 2025-11-28
**Status:** Draft
**Source:** Two Claude instances using superpowers in real development scenarios
---
## Executive Summary
Two Claude instances provided detailed feedback from actual development sessions. Their feedback reveals **systematic gaps** in current skills that allowed preventable bugs to ship despite following the skills.
**Critical insight:** These are problem reports, not just solution proposals. The problems are real; the solutions need careful evaluation.
**Key themes:**
1. **Verification gaps** - We verify operations succeed but not that they achieve intended outcomes
2. **Process hygiene** - Background processes accumulate and interfere across subagents
3. **Context optimization** - Subagents get too much irrelevant information
4. **Self-reflection missing** - No prompt to critique own work before handoff
5. **Mock safety** - Mocks can drift from interfaces without detection
6. **Skill activation** - Skills exist but aren't being read/used
---
## Problems Identified
### Problem 1: Configuration Change Verification Gap
**What happened:**
- Subagent tested "OpenAI integration"
- Set `OPENAI_API_KEY` env var
- Got status 200 responses
- Reported "OpenAI integration working"
- **BUT** response contained `"model": "claude-sonnet-4-20250514"` - was actually using Anthropic
**Root cause:**
`verification-before-completion` checks operations succeed but not that outcomes reflect intended configuration changes.
**Impact:** High - False confidence in integration tests, bugs ship to production
**Example failure pattern:**
- Switch LLM provider → verify status 200 but don't check model name
- Enable feature flag → verify no errors but don't check feature is active
- Change environment → verify deployment succeeds but don't check environment vars
---
### Problem 2: Background Process Accumulation
**What happened:**
- Multiple subagents dispatched during session
- Each started background server processes
- Processes accumulated (4+ servers running)
- Stale processes still bound to ports
- Later E2E test hit stale server with wrong config
- Confusing/incorrect test results
**Root cause:**
Subagents are stateless - don't know about previous subagents' processes. No cleanup protocol.
**Impact:** Medium-High - Tests hit wrong server, false passes/failures, debugging confusion
---
### Problem 3: Context Bloat in Subagent Prompts
**What happened:**
- Standard approach: give subagent full plan file to read
- Experiment: give only task + pattern + file + verify command
- Result: Faster, more focused, single-attempt completion more common
**Root cause:**
Subagents waste tokens and attention on irrelevant plan sections.
**Impact:** Medium - Slower execution, more failed attempts
**What worked:**
```
You are adding a single E2E test to packnplay's test suite.
**Your task:** Add `TestE2E_FeaturePrivilegedMode` to `pkg/runner/e2e_test.go`
**What to test:** A local devcontainer feature that requests `"privileged": true`
in its metadata should result in the container running with `--privileged` flag.
**Follow the exact pattern of TestE2E_FeatureOptionValidation** (at the end of the file)
**After writing, run:** `go test -v ./pkg/runner -run TestE2E_FeaturePrivilegedMode -timeout 5m`
```
---
### Problem 4: No Self-Reflection Before Handoff
**What happened:**
- Added self-reflection prompt: "Look at your work with fresh eyes - what could be better?"
- Implementer for Task 5 identified failing test was due to implementation bug, not test bug
- Traced to line 99: `strings.Join(metadata.Entrypoint, " ")` creating invalid Docker syntax
- Without self-reflection, would have just reported "test fails" without root cause
**Root cause:**
Implementers don't naturally step back and critique their own work before reporting completion.
**Impact:** Medium - Bugs handed off to reviewer that implementer could have caught
---
### Problem 5: Mock-Interface Drift
**What happened:**
```typescript
// Interface defines close()
interface PlatformAdapter {
close(): Promise<void>;
}
// Code (BUGGY) calls cleanup()
await adapter.cleanup();
// Mock (MATCHES BUG) defines cleanup()
vi.mock('web-adapter', () => ({
WebAdapter: vi.fn().mockImplementation(() => ({
cleanup: vi.fn().mockResolvedValue(undefined), // Wrong!
})),
}));
```
- Tests passed
- Runtime crashed: "adapter.cleanup is not a function"
**Root cause:**
Mock derived from what buggy code calls, not from interface definition. TypeScript can't catch inline mocks with wrong method names.
**Impact:** High - Tests give false confidence, runtime crashes
**Why testing-anti-patterns didn't prevent this:**
The skill covers testing mock behavior and mocking without understanding, but not the specific pattern of "derive mock from interface, not implementation."
---
### Problem 6: Code Reviewer File Access
**What happened:**
- Code reviewer subagent dispatched
- Couldn't find test file: "The file doesn't appear to exist in the repository"
- File actually exists
- Reviewer didn't know to explicitly read it first
**Root cause:**
Reviewer prompts don't include explicit file reading instructions.
**Impact:** Low-Medium - Reviews fail or incomplete
---
### Problem 7: Fix Workflow Latency
**What happened:**
- Implementer identifies bug during self-reflection
- Implementer knows the fix
- Current workflow: report → I dispatch fixer → fixer fixes → I verify
- Extra round-trip adds latency without adding value
**Root cause:**
Rigid separation between implementer and fixer roles when implementer has already diagnosed.
**Impact:** Low - Latency, but no correctness issue
---
### Problem 8: Skills Not Being Read
**What happened:**
- `testing-anti-patterns` skill exists
- Neither human nor subagents read it before writing tests
- Would have prevented some issues (though not all - see Problem 5)
**Root cause:**
No enforcement that subagents read relevant skills. No prompt includes skill reading.
**Impact:** Medium - Skill investment wasted if not used
---
## Proposed Improvements
### 1. verification-before-completion: Add Configuration Change Verification
**Add new section:**
```markdown
## Verifying Configuration Changes
When testing changes to configuration, providers, feature flags, or environment:
**Don't just verify the operation succeeded. Verify the output reflects the intended change.**
### Common Failure Pattern
Operation succeeds because *some* valid config exists, but it's not the config you intended to test.
### Examples
| Change | Insufficient | Required |
|--------|-------------|----------|
| Switch LLM provider | Status 200 | Response contains expected model name |
| Enable feature flag | No errors | Feature behavior actually active |
| Change environment | Deploy succeeds | Logs/vars reference new environment |
| Set credentials | Auth succeeds | Authenticated user/context is correct |
### Gate Function
```
BEFORE claiming configuration change works:
1. IDENTIFY: What should be DIFFERENT after this change?
2. LOCATE: Where is that difference observable?
- Response field (model name, user ID)
- Log line (environment, provider)
- Behavior (feature active/inactive)
3. RUN: Command that shows the observable difference
4. VERIFY: Output contains expected difference
5. ONLY THEN: Claim configuration change works
Red flags:
- "Request succeeded" without checking content
- Checking status code but not response body
- Verifying no errors but not positive confirmation
```
**Why this works:**
Forces verification of INTENT, not just operation success.
---
### 2. subagent-driven-development: Add Process Hygiene for E2E Tests
**Add new section:**
```markdown
## Process Hygiene for E2E Tests
When dispatching subagents that start services (servers, databases, message queues):
### Problem
Subagents are stateless - they don't know about processes started by previous subagents. Background processes persist and can interfere with later tests.
### Solution
**Before dispatching E2E test subagent, include cleanup in prompt:**
```
BEFORE starting any services:
1. Kill existing processes: pkill -f "<service-pattern>" 2>/dev/null || true
2. Wait for cleanup: sleep 1
3. Verify port free: lsof -i :<port> && echo "ERROR: Port still in use" || echo "Port free"
AFTER tests complete:
1. Kill the process you started
2. Verify cleanup: pgrep -f "<service-pattern>" || echo "Cleanup successful"
```
### Example
```
Task: Run E2E test of API server
Prompt includes:
"Before starting the server:
- Kill any existing servers: pkill -f 'node.*server.js' 2>/dev/null || true
- Verify port 3001 is free: lsof -i :3001 && exit 1 || echo 'Port available'
After tests:
- Kill the server you started
- Verify: pgrep -f 'node.*server.js' || echo 'Cleanup verified'"
```
### Why This Matters
- Stale processes serve requests with wrong config
- Port conflicts cause silent failures
- Process accumulation slows system
- Confusing test results (hitting wrong server)
```
**Trade-off analysis:**
- Adds boilerplate to prompts
- But prevents very confusing debugging
- Worth it for E2E test subagents
---
### 3. subagent-driven-development: Add Lean Context Option
**Modify Step 2: Execute Task with Subagent**
**Before:**
```
Read that task carefully from [plan-file].
```
**After:**
```
## Context Approaches
**Full Plan (default):**
Use when tasks are complex or have dependencies:
```
Read Task N from [plan-file] carefully.
```
**Lean Context (for independent tasks):**
Use when task is standalone and pattern-based:
```
You are implementing: [1-2 sentence task description]
File to modify: [exact path]
Pattern to follow: [reference to existing function/test]
What to implement: [specific requirement]
Verification: [exact command to run]
[Do NOT include full plan file]
```
**Use lean context when:**
- Task follows existing pattern (add similar test, implement similar feature)
- Task is self-contained (doesn't need context from other tasks)
- Pattern reference is sufficient (e.g., "follow TestE2E_FeatureOptionValidation")
**Use full plan when:**
- Task has dependencies on other tasks
- Requires understanding of overall architecture
- Complex logic that needs context
```
**Example:**
```
Lean context prompt:
"You are adding a test for privileged mode in devcontainer features.
File: pkg/runner/e2e_test.go
Pattern: Follow TestE2E_FeatureOptionValidation (at end of file)
Test: Feature with `"privileged": true` in metadata results in `--privileged` flag
Verify: go test -v ./pkg/runner -run TestE2E_FeaturePrivilegedMode -timeout 5m
Report: Implementation, test results, any issues."
```
**Why this works:**
Reduces token usage, increases focus, faster completion when appropriate.
---
### 4. subagent-driven-development: Add Self-Reflection Step
**Modify Step 2: Execute Task with Subagent**
**Add to prompt template:**
```
When done, BEFORE reporting back:
Take a step back and review your work with fresh eyes.
Ask yourself:
- Does this actually solve the task as specified?
- Are there edge cases I didn't consider?
- Did I follow the pattern correctly?
- If tests are failing, what's the ROOT CAUSE (implementation bug vs test bug)?
- What could be better about this implementation?
If you identify issues during this reflection, fix them now.
Then report:
- What you implemented
- Self-reflection findings (if any)
- Test results
- Files changed
```
**Why this works:**
Catches bugs implementer can find themselves before handoff. Documented case: identified entrypoint bug through self-reflection.
**Trade-off:**
Adds ~30 seconds per task, but catches issues before review.
---
### 5. requesting-code-review: Add Explicit File Reading
**Modify the code-reviewer template:**
**Add at the beginning:**
```markdown
## Files to Review
BEFORE analyzing, read these files:
1. [List specific files that changed in the diff]
2. [Files referenced by changes but not modified]
Use Read tool to load each file.
If you cannot find a file:
- Check exact path from diff
- Try alternate locations
- Report: "Cannot locate [path] - please verify file exists"
DO NOT proceed with review until you've read the actual code.
```
**Why this works:**
Explicit instruction prevents "file not found" issues.
---
### 6. testing-anti-patterns: Add Mock-Interface Drift Anti-Pattern
**Add new Anti-Pattern 6:**
```markdown
## Anti-Pattern 6: Mocks Derived from Implementation
**The violation:**
```typescript
// Code (BUGGY) calls cleanup()
await adapter.cleanup();
// Mock (MATCHES BUG) has cleanup()
const mock = {
cleanup: vi.fn().mockResolvedValue(undefined)
};
// Interface (CORRECT) defines close()
interface PlatformAdapter {
close(): Promise<void>;
}
```
**Why this is wrong:**
- Mock encodes the bug into the test
- TypeScript can't catch inline mocks with wrong method names
- Test passes because both code and mock are wrong
- Runtime crashes when real object is used
**The fix:**
```typescript
// ✅ GOOD: Derive mock from interface
// Step 1: Open interface definition (PlatformAdapter)
// Step 2: List methods defined there (close, initialize, etc.)
// Step 3: Mock EXACTLY those methods
const mock = {
initialize: vi.fn().mockResolvedValue(undefined),
close: vi.fn().mockResolvedValue(undefined), // From interface!
};
// Now test FAILS because code calls cleanup() which doesn't exist
// That failure reveals the bug BEFORE runtime
```
### Gate Function
```
BEFORE writing any mock:
1. STOP - Do NOT look at the code under test yet
2. FIND: The interface/type definition for the dependency
3. READ: The interface file
4. LIST: Methods defined in the interface
5. MOCK: ONLY those methods with EXACTLY those names
6. DO NOT: Look at what your code calls
IF your test fails because code calls something not in mock:
✅ GOOD - The test found a bug in your code
Fix the code to call the correct interface method
NOT the mock
Red flags:
- "I'll mock what the code calls"
- Copying method names from implementation
- Mock written without reading interface
- "The test is failing so I'll add this method to the mock"
```
**Detection:**
When you see runtime error "X is not a function" and tests pass:
1. Check if X is mocked
2. Compare mock methods to interface methods
3. Look for method name mismatches
```
**Why this works:**
Directly addresses the failure pattern from feedback.
---
### 7. subagent-driven-development: Require Skills Reading for Test Subagents
**Add to prompt template when task involves testing:**
```markdown
BEFORE writing any tests:
1. Read testing-anti-patterns skill:
Use Skill tool: superpowers:testing-anti-patterns
2. Apply gate functions from that skill when:
- Writing mocks
- Adding methods to production classes
- Mocking dependencies
This is NOT optional. Tests that violate anti-patterns will be rejected in review.
```
**Why this works:**
Ensures skills are actually used, not just exist.
**Trade-off:**
Adds time to each task, but prevents entire classes of bugs.
---
### 8. subagent-driven-development: Allow Implementer to Fix Self-Identified Issues
**Modify Step 2:**
**Current:**
```
Subagent reports back with summary of work.
```
**Proposed:**
```
Subagent performs self-reflection, then:
IF self-reflection identifies fixable issues:
1. Fix the issues
2. Re-run verification
3. Report: "Initial implementation + self-reflection fix"
ELSE:
Report: "Implementation complete"
Include in report:
- Self-reflection findings
- Whether fixes were applied
- Final verification results
```
**Why this works:**
Reduces latency when implementer already knows the fix. Documented case: would have saved one round-trip for entrypoint bug.
**Trade-off:**
Slightly more complex prompt, but faster end-to-end.
---
## Implementation Plan
### Phase 1: High-Impact, Low-Risk (Do First)
1. **verification-before-completion: Configuration change verification**
- Clear addition, doesn't change existing content
- Addresses high-impact problem (false confidence in tests)
- File: `skills/verification-before-completion/SKILL.md`
2. **testing-anti-patterns: Mock-interface drift**
- Adds new anti-pattern, doesn't modify existing
- Addresses high-impact problem (runtime crashes)
- File: `skills/testing-anti-patterns/SKILL.md`
3. **requesting-code-review: Explicit file reading**
- Simple addition to template
- Fixes concrete problem (reviewers can't find files)
- File: `skills/requesting-code-review/SKILL.md`
### Phase 2: Moderate Changes (Test Carefully)
4. **subagent-driven-development: Process hygiene**
- Adds new section, doesn't change workflow
- Addresses medium-high impact (test reliability)
- File: `skills/subagent-driven-development/SKILL.md`
5. **subagent-driven-development: Self-reflection**
- Changes prompt template (higher risk)
- But documented to catch bugs
- File: `skills/subagent-driven-development/SKILL.md`
6. **subagent-driven-development: Skills reading requirement**
- Adds prompt overhead
- But ensures skills are actually used
- File: `skills/subagent-driven-development/SKILL.md`
### Phase 3: Optimization (Validate First)
7. **subagent-driven-development: Lean context option**
- Adds complexity (two approaches)
- Needs validation that it doesn't cause confusion
- File: `skills/subagent-driven-development/SKILL.md`
8. **subagent-driven-development: Allow implementer to fix**
- Changes workflow (higher risk)
- Optimization, not bug fix
- File: `skills/subagent-driven-development/SKILL.md`
---
## Open Questions
1. **Lean context approach:**
- Should we make it the default for pattern-based tasks?
- How do we decide which approach to use?
- Risk of being too lean and missing important context?
2. **Self-reflection:**
- Will this slow down simple tasks significantly?
- Should it only apply to complex tasks?
- How do we prevent "reflection fatigue" where it becomes rote?
3. **Process hygiene:**
- Should this be in subagent-driven-development or a separate skill?
- Does it apply to other workflows beyond E2E tests?
- How do we handle cases where process SHOULD persist (dev servers)?
4. **Skills reading enforcement:**
- Should we require ALL subagents to read relevant skills?
- How do we keep prompts from becoming too long?
- Risk of over-documenting and losing focus?
---
## Success Metrics
How do we know these improvements work?
1. **Configuration verification:**
- Zero instances of "test passed but wrong config was used"
- Jesse doesn't say "that's not actually testing what you think"
2. **Process hygiene:**
- Zero instances of "test hit wrong server"
- No port conflict errors during E2E test runs
3. **Mock-interface drift:**
- Zero instances of "tests pass but runtime crashes on missing method"
- No method name mismatches between mocks and interfaces
4. **Self-reflection:**
- Measurable: Do implementer reports include self-reflection findings?
- Qualitative: Do fewer bugs make it to code review?
5. **Skills reading:**
- Subagent reports reference skill gate functions
- Fewer anti-pattern violations in code review
---
## Risks and Mitigations
### Risk: Prompt Bloat
**Problem:** Adding all these requirements makes prompts overwhelming
**Mitigation:**
- Phase implementation (don't add everything at once)
- Make some additions conditional (E2E hygiene only for E2E tests)
- Consider templates for different task types
### Risk: Analysis Paralysis
**Problem:** Too much reflection/verification slows execution
**Mitigation:**
- Keep gate functions quick (seconds, not minutes)
- Make lean context opt-in initially
- Monitor task completion times
### Risk: False Sense of Security
**Problem:** Following checklist doesn't guarantee correctness
**Mitigation:**
- Emphasize gate functions are minimums, not maximums
- Keep "use judgment" language in skills
- Document that skills catch common failures, not all failures
### Risk: Skill Divergence
**Problem:** Different skills give conflicting advice
**Mitigation:**
- Review changes across all skills for consistency
- Document how skills interact (Integration sections)
- Test with real scenarios before deployment
---
## Recommendation
**Proceed with Phase 1 immediately:**
- verification-before-completion: Configuration change verification
- testing-anti-patterns: Mock-interface drift
- requesting-code-review: Explicit file reading
**Test Phase 2 with Jesse before finalizing:**
- Get feedback on self-reflection impact
- Validate process hygiene approach
- Confirm skills reading requirement is worth overhead
**Hold Phase 3 pending validation:**
- Lean context needs real-world testing
- Implementer-fix workflow change needs careful evaluation
These changes address real problems documented by users while minimizing risk of making skills worse.

View File

@@ -0,0 +1,571 @@
# Visual Brainstorming Companion Implementation Plan
> **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.
**Architecture:** Claude writes HTML to a temp file. A local Node.js server watches that file and serves it with an auto-injected helper library. User interactions flow via WebSocket to server stdout, which Claude sees in background task output.
**Tech Stack:** Node.js, Express, ws (WebSocket), chokidar (file watching)
---
## Task 1: Create the Server Foundation
**Files:**
- Create: `lib/brainstorm-server/index.js`
- Create: `lib/brainstorm-server/package.json`
**Step 1: Create package.json**
```json
{
"name": "brainstorm-server",
"version": "1.0.0",
"description": "Visual brainstorming companion server for Claude Code",
"main": "index.js",
"dependencies": {
"chokidar": "^3.5.3",
"express": "^4.18.2",
"ws": "^8.14.2"
}
}
```
**Step 2: Create minimal server that starts**
```javascript
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const chokidar = require('chokidar');
const fs = require('fs');
const path = require('path');
const PORT = process.env.BRAINSTORM_PORT || 3333;
const SCREEN_FILE = process.env.BRAINSTORM_SCREEN || '/tmp/brainstorm/screen.html';
const SCREEN_DIR = path.dirname(SCREEN_FILE);
// Ensure screen directory exists
if (!fs.existsSync(SCREEN_DIR)) {
fs.mkdirSync(SCREEN_DIR, { recursive: true });
}
// Create default screen if none exists
if (!fs.existsSync(SCREEN_FILE)) {
fs.writeFileSync(SCREEN_FILE, `<!DOCTYPE html>
<html>
<head>
<title>Brainstorm Companion</title>
<style>
body { font-family: system-ui, sans-serif; padding: 2rem; max-width: 800px; margin: 0 auto; }
h1 { color: #333; }
p { color: #666; }
</style>
</head>
<body>
<h1>Brainstorm Companion</h1>
<p>Waiting for Claude to push a screen...</p>
</body>
</html>`);
}
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
// Track connected browsers for reload notifications
const clients = new Set();
wss.on('connection', (ws) => {
clients.add(ws);
ws.on('close', () => clients.delete(ws));
ws.on('message', (data) => {
// User interaction event - write to stdout for Claude
const event = JSON.parse(data.toString());
console.log(JSON.stringify({ type: 'user-event', ...event }));
});
});
// Serve current screen with helper.js injected
app.get('/', (req, res) => {
let html = fs.readFileSync(SCREEN_FILE, 'utf-8');
// Inject helper script before </body>
const helperScript = fs.readFileSync(path.join(__dirname, 'helper.js'), 'utf-8');
const injection = `<script>\n${helperScript}\n</script>`;
if (html.includes('</body>')) {
html = html.replace('</body>', `${injection}\n</body>`);
} else {
html += injection;
}
res.type('html').send(html);
});
// Watch for screen file changes
chokidar.watch(SCREEN_FILE).on('change', () => {
console.log(JSON.stringify({ type: 'screen-updated', file: SCREEN_FILE }));
// Notify all browsers to reload
clients.forEach(ws => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: 'reload' }));
}
});
});
server.listen(PORT, '127.0.0.1', () => {
console.log(JSON.stringify({ type: 'server-started', port: PORT, url: `http://localhost:${PORT}` }));
});
```
**Step 3: Run npm install**
Run: `cd lib/brainstorm-server && npm install`
Expected: Dependencies installed
**Step 4: Test server starts**
Run: `cd lib/brainstorm-server && timeout 3 node index.js || true`
Expected: See JSON with `server-started` and port info
**Step 5: Commit**
```bash
git add lib/brainstorm-server/
git commit -m "feat: add brainstorm server foundation"
```
---
## Task 2: Create the Helper Library
**Files:**
- Create: `lib/brainstorm-server/helper.js`
**Step 1: Create helper.js with event auto-capture**
```javascript
(function() {
const WS_URL = 'ws://' + window.location.host;
let ws = null;
let eventQueue = [];
function connect() {
ws = new WebSocket(WS_URL);
ws.onopen = () => {
// Send any queued events
eventQueue.forEach(e => ws.send(JSON.stringify(e)));
eventQueue = [];
};
ws.onmessage = (msg) => {
const data = JSON.parse(msg.data);
if (data.type === 'reload') {
window.location.reload();
}
};
ws.onclose = () => {
// Reconnect after 1 second
setTimeout(connect, 1000);
};
}
function send(event) {
event.timestamp = Date.now();
if (ws && ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify(event));
} else {
eventQueue.push(event);
}
}
// Auto-capture clicks on interactive elements
document.addEventListener('click', (e) => {
const target = e.target.closest('button, a, [data-choice], [role="button"], input[type="submit"]');
if (!target) return;
// Don't capture regular link navigation
if (target.tagName === 'A' && !target.dataset.choice) return;
e.preventDefault();
send({
type: 'click',
text: target.textContent.trim(),
choice: target.dataset.choice || null,
id: target.id || null,
className: target.className || null
});
});
// Auto-capture form submissions
document.addEventListener('submit', (e) => {
e.preventDefault();
const form = e.target;
const formData = new FormData(form);
const data = {};
formData.forEach((value, key) => { data[key] = value; });
send({
type: 'submit',
formId: form.id || null,
formName: form.name || null,
data: data
});
});
// Auto-capture input changes (debounced)
let inputTimeout = null;
document.addEventListener('input', (e) => {
const target = e.target;
if (!target.matches('input, textarea, select')) return;
clearTimeout(inputTimeout);
inputTimeout = setTimeout(() => {
send({
type: 'input',
name: target.name || null,
id: target.id || null,
value: target.value,
inputType: target.type || target.tagName.toLowerCase()
});
}, 500); // 500ms debounce
});
// Expose for explicit use if needed
window.brainstorm = {
send: send,
choice: (value, metadata = {}) => send({ type: 'choice', value, ...metadata })
};
connect();
})();
```
**Step 2: Verify helper.js is syntactically valid**
Run: `node -c lib/brainstorm-server/helper.js`
Expected: No syntax errors
**Step 3: Commit**
```bash
git add lib/brainstorm-server/helper.js
git commit -m "feat: add browser helper library for event capture"
```
---
## Task 3: Write Tests for the Server
**Files:**
- Create: `tests/brainstorm-server/server.test.js`
- Create: `tests/brainstorm-server/package.json`
**Step 1: Create test package.json**
```json
{
"name": "brainstorm-server-tests",
"version": "1.0.0",
"scripts": {
"test": "node server.test.js"
}
}
```
**Step 2: Write server tests**
```javascript
const { spawn } = require('child_process');
const http = require('http');
const WebSocket = require('ws');
const fs = require('fs');
const path = require('path');
const assert = require('assert');
const SERVER_PATH = path.join(__dirname, '../../lib/brainstorm-server/index.js');
const TEST_PORT = 3334;
const TEST_SCREEN = '/tmp/brainstorm-test/screen.html';
// Clean up test directory
function cleanup() {
if (fs.existsSync(path.dirname(TEST_SCREEN))) {
fs.rmSync(path.dirname(TEST_SCREEN), { recursive: true });
}
}
async function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function fetch(url) {
return new Promise((resolve, reject) => {
http.get(url, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => resolve({ status: res.statusCode, body: data }));
}).on('error', reject);
});
}
async function runTests() {
cleanup();
// Start server
const server = spawn('node', [SERVER_PATH], {
env: { ...process.env, BRAINSTORM_PORT: TEST_PORT, BRAINSTORM_SCREEN: TEST_SCREEN }
});
let stdout = '';
server.stdout.on('data', (data) => { stdout += data.toString(); });
server.stderr.on('data', (data) => { console.error('Server stderr:', data.toString()); });
await sleep(1000); // Wait for server to start
try {
// Test 1: Server starts and outputs JSON
console.log('Test 1: Server startup message');
assert(stdout.includes('server-started'), 'Should output server-started');
assert(stdout.includes(TEST_PORT.toString()), 'Should include port');
console.log(' PASS');
// Test 2: GET / returns HTML with helper injected
console.log('Test 2: Serves HTML with helper injected');
const res = await fetch(`http://localhost:${TEST_PORT}/`);
assert.strictEqual(res.status, 200);
assert(res.body.includes('brainstorm'), 'Should include brainstorm content');
assert(res.body.includes('WebSocket'), 'Should have helper.js injected');
console.log(' PASS');
// Test 3: WebSocket connection and event relay
console.log('Test 3: WebSocket relays events to stdout');
stdout = ''; // Reset stdout capture
const ws = new WebSocket(`ws://localhost:${TEST_PORT}`);
await new Promise(resolve => ws.on('open', resolve));
ws.send(JSON.stringify({ type: 'click', text: 'Test Button' }));
await sleep(100);
assert(stdout.includes('user-event'), 'Should relay user events');
assert(stdout.includes('Test Button'), 'Should include event data');
ws.close();
console.log(' PASS');
// Test 4: File change triggers reload notification
console.log('Test 4: File change notifies browsers');
const ws2 = new WebSocket(`ws://localhost:${TEST_PORT}`);
await new Promise(resolve => ws2.on('open', resolve));
let gotReload = false;
ws2.on('message', (data) => {
const msg = JSON.parse(data.toString());
if (msg.type === 'reload') gotReload = true;
});
// Modify the screen file
fs.writeFileSync(TEST_SCREEN, '<html><body>Updated</body></html>');
await sleep(500);
assert(gotReload, 'Should send reload message on file change');
ws2.close();
console.log(' PASS');
console.log('\nAll tests passed!');
} finally {
server.kill();
cleanup();
}
}
runTests().catch(err => {
console.error('Test failed:', err);
process.exit(1);
});
```
**Step 3: Run tests**
Run: `cd tests/brainstorm-server && npm install ws && node server.test.js`
Expected: All tests pass
**Step 4: Commit**
```bash
git add tests/brainstorm-server/
git commit -m "test: add brainstorm server integration tests"
```
---
## Task 4: Add Visual Companion to Brainstorming Skill
**Files:**
- Modify: `skills/brainstorming/SKILL.md`
- Create: `skills/brainstorming/visual-companion.md` (supporting doc)
**Step 1: Create the supporting documentation**
Create `skills/brainstorming/visual-companion.md`:
```markdown
# Visual Companion Reference
## Starting the Server
Run as a background job:
```bash
node ${PLUGIN_ROOT}/lib/brainstorm-server/index.js
```
Tell the user: "I've started a visual companion at http://localhost:3333 - open it in a browser."
## Pushing Screens
Write HTML to `/tmp/brainstorm/screen.html`. The server watches this file and auto-refreshes the browser.
## Reading User Responses
Check the background task output for JSON events:
```json
{"type":"user-event","type":"click","text":"Option A","choice":"optionA","timestamp":1234567890}
{"type":"user-event","type":"submit","data":{"notes":"My feedback"},"timestamp":1234567891}
```
Event types:
- **click**: User clicked button or `data-choice` element
- **submit**: User submitted form (includes all form data)
- **input**: User typed in field (debounced 500ms)
## HTML Patterns
### Choice Cards
```html
<div class="options">
<button data-choice="optionA">
<h3>Option A</h3>
<p>Description</p>
</button>
<button data-choice="optionB">
<h3>Option B</h3>
<p>Description</p>
</button>
</div>
```
### Interactive Mockup
```html
<div class="mockup">
<header data-choice="header">App Header</header>
<nav data-choice="nav">Navigation</nav>
<main data-choice="main">Content</main>
</div>
```
### Form with Notes
```html
<form>
<label>Priority: <input type="range" name="priority" min="1" max="5"></label>
<textarea name="notes" placeholder="Additional thoughts..."></textarea>
<button type="submit">Submit</button>
</form>
```
### Explicit JavaScript
```html
<button onclick="brainstorm.choice('custom', {extra: 'data'})">Custom</button>
```
```
**Step 2: Add visual companion section to brainstorming skill**
Add after "Key Principles" in `skills/brainstorming/SKILL.md`:
```markdown
## Visual Companion (Optional)
When brainstorming involves visual elements - UI mockups, wireframes, interactive prototypes - use the browser-based visual companion.
**When to use:**
- Presenting UI/UX options that benefit from visual comparison
- Showing wireframes or layout options
- Gathering structured feedback (ratings, forms)
- Prototyping click interactions
**How it works:**
1. Start the server as a background job
2. Tell user to open http://localhost:3333
3. Write HTML to `/tmp/brainstorm/screen.html` (auto-refreshes)
4. Check background task output for user interactions
The terminal remains the primary conversation interface. The browser is a visual aid.
**Reference:** See `visual-companion.md` in this skill directory for HTML patterns and API details.
```
**Step 3: Verify the edits**
Run: `grep -A5 "Visual Companion" skills/brainstorming/SKILL.md`
Expected: Shows the new section
**Step 4: Commit**
```bash
git add skills/brainstorming/
git commit -m "feat: add visual companion to brainstorming skill"
```
---
## Task 5: Add Server to Plugin Ignore (Optional Cleanup)
**Files:**
- Check if `.gitignore` needs node_modules exclusion for lib/brainstorm-server
**Step 1: Check current gitignore**
Run: `cat .gitignore 2>/dev/null || echo "No .gitignore"`
**Step 2: Add node_modules if needed**
If not already present, add:
```
lib/brainstorm-server/node_modules/
```
**Step 3: Commit if changed**
```bash
git add .gitignore
git commit -m "chore: ignore brainstorm-server node_modules"
```
---
## Summary
After completing all tasks:
1. **Server** at `lib/brainstorm-server/` - Node.js server that watches HTML file and relays events
2. **Helper library** auto-injected - captures clicks, forms, inputs
3. **Tests** at `tests/brainstorm-server/` - verifies server behavior
4. **Brainstorming skill** updated with visual companion section and `visual-companion.md` reference doc
**To use:**
1. Start server as background job: `node lib/brainstorm-server/index.js &`
2. Tell user to open `http://localhost:3333`
3. Write HTML to `/tmp/brainstorm/screen.html`
4. Check task output for user events

View File

@@ -0,0 +1,301 @@
# Document Review System Implementation 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.
**Architecture:** Create reviewer prompt templates in each skill directory. Modify skill files to add review loops after document creation. Use Task tool with general-purpose subagent for reviewer dispatch.
**Tech Stack:** Markdown skill files, subagent dispatch via Task tool
**Spec:** docs/superpowers/specs/2026-01-22-document-review-system-design.md
---
## Chunk 1: Spec Document Reviewer
This chunk adds the spec document reviewer to the brainstorming skill.
### Task 1: Create Spec Document Reviewer Prompt Template
**Files:**
- Create: `skills/brainstorming/spec-document-reviewer-prompt.md`
- [ ] **Step 1:** Create the reviewer prompt template file
```markdown
# Spec Document Reviewer Prompt Template
Use this template when dispatching a spec document reviewer subagent.
**Purpose:** Verify the spec is complete, consistent, and ready for implementation planning.
**Dispatch after:** Spec document is written to docs/superpowers/specs/
```
Task tool (general-purpose):
description: "Review spec document"
prompt: |
You are a spec document reviewer. Verify this spec is complete and ready for planning.
**Spec to review:** [SPEC_FILE_PATH]
## What to Check
| Category | What to Look For |
|----------|------------------|
| Completeness | TODOs, placeholders, "TBD", incomplete sections |
| Coverage | Missing error handling, edge cases, integration points |
| Consistency | Internal contradictions, conflicting requirements |
| Clarity | Ambiguous requirements |
| YAGNI | Unrequested features, over-engineering |
## CRITICAL
Look especially hard for:
- Any TODO markers or placeholder text
- Sections saying "to be defined later" or "will spec when X is done"
- Sections noticeably less detailed than others
## Output Format
## Spec Review
**Status:** ✅ Approved | ❌ Issues Found
**Issues (if any):**
- [Section X]: [specific issue] - [why it matters]
**Recommendations (advisory):**
- [suggestions that don't block approval]
```
**Reviewer returns:** Status, Issues (if any), Recommendations
```
- [ ] **Step 2:** Verify the file was created correctly
Run: `cat skills/brainstorming/spec-document-reviewer-prompt.md | head -20`
Expected: Shows the header and purpose section
- [ ] **Step 3:** Commit
```bash
git add skills/brainstorming/spec-document-reviewer-prompt.md
git commit -m "feat: add spec document reviewer prompt template"
```
---
### Task 2: Add Review Loop to Brainstorming Skill
**Files:**
- Modify: `skills/brainstorming/SKILL.md`
- [ ] **Step 1:** Read the current brainstorming skill
Run: `cat skills/brainstorming/SKILL.md`
- [ ] **Step 2:** Add the review loop section after "After the Design"
Find the "After the Design" section and add a new "Spec Review Loop" section after documentation but before implementation:
```markdown
**Spec Review Loop:**
After writing the spec document:
1. Dispatch spec-document-reviewer subagent (see spec-document-reviewer-prompt.md)
2. If ❌ Issues Found:
- Fix the issues in the spec document
- Re-dispatch reviewer
- Repeat until ✅ Approved
3. If ✅ Approved: proceed to implementation setup
**Review loop guidance:**
- Same agent that wrote the spec fixes it (preserves context)
- If loop exceeds 5 iterations, surface to human for guidance
- Reviewers are advisory - explain disagreements if you believe feedback is incorrect
```
- [ ] **Step 3:** Verify the changes
Run: `grep -A 15 "Spec Review Loop" skills/brainstorming/SKILL.md`
Expected: Shows the new review loop section
- [ ] **Step 4:** Commit
```bash
git add skills/brainstorming/SKILL.md
git commit -m "feat: add spec review loop to brainstorming skill"
```
---
## Chunk 2: Plan Document Reviewer
This chunk adds the plan document reviewer to the writing-plans skill.
### Task 3: Create Plan Document Reviewer Prompt Template
**Files:**
- Create: `skills/writing-plans/plan-document-reviewer-prompt.md`
- [ ] **Step 1:** Create the reviewer prompt template file
```markdown
# Plan Document Reviewer Prompt Template
Use this template when dispatching a plan document reviewer subagent.
**Purpose:** Verify the plan chunk is complete, matches the spec, and has proper task decomposition.
**Dispatch after:** Each plan chunk is written
```
Task tool (general-purpose):
description: "Review plan chunk N"
prompt: |
You are a plan document reviewer. Verify this plan chunk is complete and ready for implementation.
**Plan chunk to review:** [PLAN_FILE_PATH] - Chunk N only
**Spec for reference:** [SPEC_FILE_PATH]
## What to Check
| Category | What to Look For |
|----------|------------------|
| Completeness | TODOs, placeholders, incomplete tasks, missing steps |
| Spec Alignment | Chunk covers relevant spec requirements, no scope creep |
| Task Decomposition | Tasks atomic, clear boundaries, steps actionable |
| Task Syntax | Checkbox syntax (`- [ ]`) on tasks and steps |
| Chunk Size | Each chunk under 1000 lines |
## CRITICAL
Look especially hard for:
- Any TODO markers or placeholder text
- Steps that say "similar to X" without actual content
- Incomplete task definitions
- Missing verification steps or expected outputs
## Output Format
## Plan Review - Chunk N
**Status:** ✅ Approved | ❌ Issues Found
**Issues (if any):**
- [Task X, Step Y]: [specific issue] - [why it matters]
**Recommendations (advisory):**
- [suggestions that don't block approval]
```
**Reviewer returns:** Status, Issues (if any), Recommendations
```
- [ ] **Step 2:** Verify the file was created
Run: `cat skills/writing-plans/plan-document-reviewer-prompt.md | head -20`
Expected: Shows the header and purpose section
- [ ] **Step 3:** Commit
```bash
git add skills/writing-plans/plan-document-reviewer-prompt.md
git commit -m "feat: add plan document reviewer prompt template"
```
---
### Task 4: Add Review Loop to Writing-Plans Skill
**Files:**
- Modify: `skills/writing-plans/SKILL.md`
- [ ] **Step 1:** Read current skill file
Run: `cat skills/writing-plans/SKILL.md`
- [ ] **Step 2:** Add chunk-by-chunk review section
Add before the "Execution Handoff" section:
```markdown
## Plan Review Loop
After completing each chunk of the plan:
1. Dispatch plan-document-reviewer subagent for the current chunk
- Provide: chunk content, path to spec document
2. If ❌ Issues Found:
- Fix the issues in the chunk
- Re-dispatch reviewer for that chunk
- Repeat until ✅ Approved
3. If ✅ Approved: proceed to next chunk (or execution handoff if last chunk)
**Chunk boundaries:** Use `## Chunk N: <name>` headings to delimit chunks. Each chunk should be ≤1000 lines and logically self-contained.
```
- [ ] **Step 3:** Update task syntax examples to use checkboxes
Change the Task Structure section to show checkbox syntax:
```markdown
### Task N: [Component Name]
- [ ] **Step 1:** Write the failing test
- File: `tests/path/test.py`
...
```
- [ ] **Step 4:** Verify the review loop section was added
Run: `grep -A 15 "Plan Review Loop" skills/writing-plans/SKILL.md`
Expected: Shows the new review loop section
- [ ] **Step 5:** Verify the task syntax examples were updated
Run: `grep -A 5 "Task N:" skills/writing-plans/SKILL.md`
Expected: Shows checkbox syntax `### Task N:`
- [ ] **Step 6:** Commit
```bash
git add skills/writing-plans/SKILL.md
git commit -m "feat: add plan review loop and checkbox syntax to writing-plans skill"
```
---
## Chunk 3: Update Plan Document Header
This chunk updates the plan document header template to reference the new checkbox syntax requirements.
### Task 5: Update Plan Header Template in Writing-Plans Skill
**Files:**
- Modify: `skills/writing-plans/SKILL.md`
- [ ] **Step 1:** Read current plan header template
Run: `grep -A 20 "Plan Document Header" skills/writing-plans/SKILL.md`
- [ ] **Step 2:** Update the header template to reference checkbox syntax
The plan header should note that tasks and steps use checkbox syntax. Update the header comment:
```markdown
> **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 Claude:" skills/writing-plans/SKILL.md`
Expected: Shows updated header with checkbox syntax mention
- [ ] **Step 4:** Commit
```bash
git add skills/writing-plans/SKILL.md
git commit -m "docs: update plan header to reference checkbox syntax"
```

View File

@@ -0,0 +1,136 @@
# Document Review System Design
## Overview
Add two new review stages to the superpowers workflow:
1. **Spec Document Review** - After brainstorming, before writing-plans
2. **Plan Document Review** - After writing-plans, before implementation
Both follow the iterative loop pattern used by implementation reviews.
## Spec Document Reviewer
**Purpose:** Verify the spec is complete, consistent, and ready for implementation planning.
**Location:** `skills/brainstorming/spec-document-reviewer-prompt.md`
**What it checks for:**
| Category | What to Look For |
|----------|------------------|
| Completeness | TODOs, placeholders, "TBD", incomplete sections |
| Coverage | Missing error handling, edge cases, integration points |
| Consistency | Internal contradictions, conflicting requirements |
| Clarity | Ambiguous requirements |
| YAGNI | Unrequested features, over-engineering |
**Output format:**
```
## Spec Review
**Status:** Approved | Issues Found
**Issues (if any):**
- [Section X]: [issue] - [why it matters]
**Recommendations (advisory):**
- [suggestions that don't block approval]
```
**Review loop:** Issues found -> brainstorming agent fixes -> re-review -> repeat until approved.
**Dispatch mechanism:** Use the Task tool with `subagent_type: general-purpose`. The reviewer prompt template provides the full prompt. The brainstorming skill's controller dispatches the reviewer.
## Plan Document Reviewer
**Purpose:** Verify the plan is complete, matches the spec, and has proper task decomposition.
**Location:** `skills/writing-plans/plan-document-reviewer-prompt.md`
**What it checks for:**
| Category | What to Look For |
|----------|------------------|
| Completeness | TODOs, placeholders, incomplete tasks |
| Spec Alignment | Plan covers spec requirements, no scope creep |
| Task Decomposition | Tasks atomic, clear boundaries |
| Task Syntax | Checkbox syntax on tasks and steps |
| Chunk Size | Each chunk under 1000 lines |
**Chunk definition:** A chunk is a logical grouping of tasks within the plan document, delimited by `## Chunk N: <name>` headings. The writing-plans skill creates these boundaries based on logical phases (e.g., "Foundation", "Core Features", "Integration"). Each chunk should be self-contained enough to review independently.
**Spec alignment verification:** The reviewer receives both:
1. The plan document (or current chunk)
2. The path to the spec document for reference
The reviewer reads both and compares requirements coverage.
**Output format:** Same as spec reviewer, but scoped to the current chunk.
**Review process (chunk-by-chunk):**
1. Writing-plans creates chunk N
2. Controller dispatches plan-document-reviewer with chunk N content and spec path
3. Reviewer reads chunk and spec, returns verdict
4. If issues: writing-plans agent fixes chunk N, goto step 2
5. If approved: proceed to chunk N+1
6. Repeat until all chunks approved
**Dispatch mechanism:** Same as spec reviewer - Task tool with `subagent_type: general-purpose`.
## Updated Workflow
```
brainstorming -> spec -> SPEC REVIEW LOOP -> writing-plans -> plan -> PLAN REVIEW LOOP -> implementation
```
**Spec Review Loop:**
1. Spec complete
2. Dispatch reviewer
3. If issues: fix -> goto 2
4. If approved: proceed
**Plan Review Loop:**
1. Chunk N complete
2. Dispatch reviewer for chunk N
3. If issues: fix -> goto 2
4. If approved: next chunk or implementation
## Markdown Task Syntax
Tasks and steps use checkbox syntax:
```markdown
- [ ] ### Task 1: Name
- [ ] **Step 1:** Description
- File: path
- Command: cmd
```
## Error Handling
**Review loop termination:**
- No hard iteration limit - loops continue until reviewer approves
- If loop exceeds 5 iterations, the controller should surface this to the human for guidance
- The human can choose to: continue iterating, approve with known issues, or abort
**Disagreement handling:**
- Reviewers are advisory - they flag issues but don't block
- If the agent believes reviewer feedback is incorrect, it should explain why in its fix
- If disagreement persists after 3 iterations on the same issue, surface to human
**Malformed reviewer output:**
- Controller should validate reviewer output has required fields (Status, Issues if applicable)
- If malformed, re-dispatch reviewer with a note about expected format
- After 2 malformed responses, surface to human
## Files to Change
**New files:**
- `skills/brainstorming/spec-document-reviewer-prompt.md`
- `skills/writing-plans/plan-document-reviewer-prompt.md`
**Modified files:**
- `skills/brainstorming/SKILL.md` - add review loop after spec written
- `skills/writing-plans/SKILL.md` - add chunk-by-chunk review loop, update task syntax examples

303
docs/testing.md Normal file
View File

@@ -0,0 +1,303 @@
# Testing Superpowers Skills
This document describes how to test Superpowers skills, particularly the integration tests for complex skills like `subagent-driven-development`.
## Overview
Testing skills that involve subagents, workflows, and complex interactions requires running actual Claude Code sessions in headless mode and verifying their behavior through session transcripts.
## Test Structure
```
tests/
├── claude-code/
│ ├── test-helpers.sh # Shared test utilities
│ ├── test-subagent-driven-development-integration.sh
│ ├── analyze-token-usage.py # Token analysis tool
│ └── run-skill-tests.sh # Test runner (if exists)
```
## Running Tests
### Integration Tests
Integration tests execute real Claude Code sessions with actual skills:
```bash
# Run the subagent-driven-development integration test
cd tests/claude-code
./test-subagent-driven-development-integration.sh
```
**Note:** Integration tests can take 10-30 minutes as they execute real implementation plans with multiple subagents.
### Requirements
- Must run from the **superpowers plugin directory** (not from temp directories)
- Claude Code must be installed and available as `claude` command
- Local dev marketplace must be enabled: `"superpowers@superpowers-dev": true` in `~/.claude/settings.json`
## Integration Test: subagent-driven-development
### What It Tests
The integration test verifies the `subagent-driven-development` skill correctly:
1. **Plan Loading**: Reads the plan once at the beginning
2. **Full Task Text**: Provides complete task descriptions to subagents (doesn't make them read files)
3. **Self-Review**: Ensures subagents perform self-review before reporting
4. **Review Order**: Runs spec compliance review before code quality review
5. **Review Loops**: Uses review loops when issues are found
6. **Independent Verification**: Spec reviewer reads code independently, doesn't trust implementer reports
### How It Works
1. **Setup**: Creates a temporary Node.js project with a minimal implementation plan
2. **Execution**: Runs Claude Code in headless mode with the skill
3. **Verification**: Parses the session transcript (`.jsonl` file) to verify:
- Skill tool was invoked
- Subagents were dispatched (Task tool)
- TodoWrite was used for tracking
- Implementation files were created
- Tests pass
- Git commits show proper workflow
4. **Token Analysis**: Shows token usage breakdown by subagent
### Test Output
```
========================================
Integration Test: subagent-driven-development
========================================
Test project: /tmp/tmp.xyz123
=== Verification Tests ===
Test 1: Skill tool invoked...
[PASS] subagent-driven-development skill was invoked
Test 2: Subagents dispatched...
[PASS] 7 subagents dispatched
Test 3: Task tracking...
[PASS] TodoWrite used 5 time(s)
Test 6: Implementation verification...
[PASS] src/math.js created
[PASS] add function exists
[PASS] multiply function exists
[PASS] test/math.test.js created
[PASS] Tests pass
Test 7: Git commit history...
[PASS] Multiple commits created (3 total)
Test 8: No extra features added...
[PASS] No extra features added
=========================================
Token Usage Analysis
=========================================
Usage Breakdown:
----------------------------------------------------------------------------------------------------
Agent Description Msgs Input Output Cache Cost
----------------------------------------------------------------------------------------------------
main Main session (coordinator) 34 27 3,996 1,213,703 $ 4.09
3380c209 implementing Task 1: Create Add Function 1 2 787 24,989 $ 0.09
34b00fde implementing Task 2: Create Multiply Function 1 4 644 25,114 $ 0.09
3801a732 reviewing whether an implementation matches... 1 5 703 25,742 $ 0.09
4c142934 doing a final code review... 1 6 854 25,319 $ 0.09
5f017a42 a code reviewer. Review Task 2... 1 6 504 22,949 $ 0.08
a6b7fbe4 a code reviewer. Review Task 1... 1 6 515 22,534 $ 0.08
f15837c0 reviewing whether an implementation matches... 1 6 416 22,485 $ 0.07
----------------------------------------------------------------------------------------------------
TOTALS:
Total messages: 41
Input tokens: 62
Output tokens: 8,419
Cache creation tokens: 132,742
Cache read tokens: 1,382,835
Total input (incl cache): 1,515,639
Total tokens: 1,524,058
Estimated cost: $4.67
(at $3/$15 per M tokens for input/output)
========================================
Test Summary
========================================
STATUS: PASSED
```
## Token Analysis Tool
### Usage
Analyze token usage from any Claude Code session:
```bash
python3 tests/claude-code/analyze-token-usage.py ~/.claude/projects/<project-dir>/<session-id>.jsonl
```
### Finding Session Files
Session transcripts are stored in `~/.claude/projects/` with the working directory path encoded:
```bash
# Example for /Users/jesse/Documents/GitHub/superpowers/superpowers
SESSION_DIR="$HOME/.claude/projects/-Users-jesse-Documents-GitHub-superpowers-superpowers"
# Find recent sessions
ls -lt "$SESSION_DIR"/*.jsonl | head -5
```
### What It Shows
- **Main session usage**: Token usage by the coordinator (you or main Claude instance)
- **Per-subagent breakdown**: Each Task invocation with:
- Agent ID
- Description (extracted from prompt)
- Message count
- Input/output tokens
- Cache usage
- Estimated cost
- **Totals**: Overall token usage and cost estimate
### Understanding the Output
- **High cache reads**: Good - means prompt caching is working
- **High input tokens on main**: Expected - coordinator has full context
- **Similar costs per subagent**: Expected - each gets similar task complexity
- **Cost per task**: Typical range is $0.05-$0.15 per subagent depending on task
## Troubleshooting
### Skills Not Loading
**Problem**: Skill not found when running headless tests
**Solutions**:
1. Ensure you're running FROM the superpowers directory: `cd /path/to/superpowers && tests/...`
2. Check `~/.claude/settings.json` has `"superpowers@superpowers-dev": true` in `enabledPlugins`
3. Verify skill exists in `skills/` directory
### Permission Errors
**Problem**: Claude blocked from writing files or accessing directories
**Solutions**:
1. Use `--permission-mode bypassPermissions` flag
2. Use `--add-dir /path/to/temp/dir` to grant access to test directories
3. Check file permissions on test directories
### Test Timeouts
**Problem**: Test takes too long and times out
**Solutions**:
1. Increase timeout: `timeout 1800 claude ...` (30 minutes)
2. Check for infinite loops in skill logic
3. Review subagent task complexity
### Session File Not Found
**Problem**: Can't find session transcript after test run
**Solutions**:
1. Check the correct project directory in `~/.claude/projects/`
2. Use `find ~/.claude/projects -name "*.jsonl" -mmin -60` to find recent sessions
3. Verify test actually ran (check for errors in test output)
## Writing New Integration Tests
### Template
```bash
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "$SCRIPT_DIR/test-helpers.sh"
# Create test project
TEST_PROJECT=$(create_test_project)
trap "cleanup_test_project $TEST_PROJECT" EXIT
# Set up test files...
cd "$TEST_PROJECT"
# Run Claude with skill
PROMPT="Your test prompt here"
cd "$SCRIPT_DIR/../.." && timeout 1800 claude -p "$PROMPT" \
--allowed-tools=all \
--add-dir "$TEST_PROJECT" \
--permission-mode bypassPermissions \
2>&1 | tee output.txt
# Find and analyze session
WORKING_DIR_ESCAPED=$(echo "$SCRIPT_DIR/../.." | sed 's/\\//-/g' | sed 's/^-//')
SESSION_DIR="$HOME/.claude/projects/$WORKING_DIR_ESCAPED"
SESSION_FILE=$(find "$SESSION_DIR" -name "*.jsonl" -type f -mmin -60 | sort -r | head -1)
# Verify behavior by parsing session transcript
if grep -q '"name":"Skill".*"skill":"your-skill-name"' "$SESSION_FILE"; then
echo "[PASS] Skill was invoked"
fi
# Show token analysis
python3 "$SCRIPT_DIR/analyze-token-usage.py" "$SESSION_FILE"
```
### Best Practices
1. **Always cleanup**: Use trap to cleanup temp directories
2. **Parse transcripts**: Don't grep user-facing output - parse the `.jsonl` session file
3. **Grant permissions**: Use `--permission-mode bypassPermissions` and `--add-dir`
4. **Run from plugin dir**: Skills only load when running from the superpowers directory
5. **Show token usage**: Always include token analysis for cost visibility
6. **Test real behavior**: Verify actual files created, tests passing, commits made
## Session Transcript Format
Session transcripts are JSONL (JSON Lines) files where each line is a JSON object representing a message or tool result.
### Key Fields
```json
{
"type": "assistant",
"message": {
"content": [...],
"usage": {
"input_tokens": 27,
"output_tokens": 3996,
"cache_read_input_tokens": 1213703
}
}
}
```
### Tool Results
```json
{
"type": "user",
"toolUseResult": {
"agentId": "3380c209",
"usage": {
"input_tokens": 2,
"output_tokens": 787,
"cache_read_input_tokens": 24989
},
"prompt": "You are implementing Task 1...",
"content": [{"type": "text", "text": "..."}]
}
}
```
The `agentId` field links to subagent sessions, and the `usage` field contains token usage for that specific subagent invocation.

View File

@@ -0,0 +1,212 @@
# Cross-Platform Polyglot Hooks for Claude Code
Claude Code plugins need hooks that work on Windows, macOS, and Linux. This document explains the polyglot wrapper technique that makes this possible.
## The Problem
Claude Code runs hook commands through the system's default shell:
- **Windows**: CMD.exe
- **macOS/Linux**: bash or sh
This creates several challenges:
1. **Script execution**: Windows CMD can't execute `.sh` files directly - it tries to open them in a text editor
2. **Path format**: Windows uses backslashes (`C:\path`), Unix uses forward slashes (`/path`)
3. **Environment variables**: `$VAR` syntax doesn't work in CMD
4. **No `bash` in PATH**: Even with Git Bash installed, `bash` isn't in the PATH when CMD runs
## The Solution: Polyglot `.cmd` Wrapper
A polyglot script is valid syntax in multiple languages simultaneously. Our wrapper is valid in both CMD and bash:
```cmd
: << 'CMDBLOCK'
@echo off
"C:\Program Files\Git\bin\bash.exe" -l -c "\"$(cygpath -u \"$CLAUDE_PLUGIN_ROOT\")/hooks/session-start.sh\""
exit /b
CMDBLOCK
# Unix shell runs from here
"${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh"
```
### How It Works
#### On Windows (CMD.exe)
1. `: << 'CMDBLOCK'` - CMD sees `:` as a label (like `:label`) and ignores `<< 'CMDBLOCK'`
2. `@echo off` - Suppresses command echoing
3. The bash.exe command runs with:
- `-l` (login shell) to get proper PATH with Unix utilities
- `cygpath -u` converts Windows path to Unix format (`C:\foo``/c/foo`)
4. `exit /b` - Exits the batch script, stopping CMD here
5. Everything after `CMDBLOCK` is never reached by CMD
#### On Unix (bash/sh)
1. `: << 'CMDBLOCK'` - `:` is a no-op, `<< 'CMDBLOCK'` starts a heredoc
2. Everything until `CMDBLOCK` is consumed by the heredoc (ignored)
3. `# Unix shell runs from here` - Comment
4. The script runs directly with the Unix path
## File Structure
```
hooks/
├── hooks.json # Points to the .cmd wrapper
├── session-start.cmd # Polyglot wrapper (cross-platform entry point)
└── session-start.sh # Actual hook logic (bash script)
```
### hooks.json
```json
{
"hooks": {
"SessionStart": [
{
"matcher": "startup|resume|clear|compact",
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/session-start.cmd\""
}
]
}
]
}
}
```
Note: The path must be quoted because `${CLAUDE_PLUGIN_ROOT}` may contain spaces on Windows (e.g., `C:\Program Files\...`).
## Requirements
### Windows
- **Git for Windows** must be installed (provides `bash.exe` and `cygpath`)
- Default installation path: `C:\Program Files\Git\bin\bash.exe`
- If Git is installed elsewhere, the wrapper needs modification
### Unix (macOS/Linux)
- Standard bash or sh shell
- The `.cmd` file must have execute permission (`chmod +x`)
## Writing Cross-Platform Hook Scripts
Your actual hook logic goes in the `.sh` file. To ensure it works on Windows (via Git Bash):
### Do:
- Use pure bash builtins when possible
- Use `$(command)` instead of backticks
- Quote all variable expansions: `"$VAR"`
- Use `printf` or here-docs for output
### Avoid:
- External commands that may not be in PATH (sed, awk, grep)
- If you must use them, they're available in Git Bash but ensure PATH is set up (use `bash -l`)
### Example: JSON Escaping Without sed/awk
Instead of:
```bash
escaped=$(echo "$content" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | awk '{printf "%s\\n", $0}')
```
Use pure bash:
```bash
escape_for_json() {
local input="$1"
local output=""
local i char
for (( i=0; i<${#input}; i++ )); do
char="${input:$i:1}"
case "$char" in
$'\\') output+='\\' ;;
'"') output+='\"' ;;
$'\n') output+='\n' ;;
$'\r') output+='\r' ;;
$'\t') output+='\t' ;;
*) output+="$char" ;;
esac
done
printf '%s' "$output"
}
```
## Reusable Wrapper Pattern
For plugins with multiple hooks, you can create a generic wrapper that takes the script name as an argument:
### run-hook.cmd
```cmd
: << 'CMDBLOCK'
@echo off
set "SCRIPT_DIR=%~dp0"
set "SCRIPT_NAME=%~1"
"C:\Program Files\Git\bin\bash.exe" -l -c "cd \"$(cygpath -u \"%SCRIPT_DIR%\")\" && \"./%SCRIPT_NAME%\""
exit /b
CMDBLOCK
# Unix shell runs from here
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
SCRIPT_NAME="$1"
shift
"${SCRIPT_DIR}/${SCRIPT_NAME}" "$@"
```
### hooks.json using the reusable wrapper
```json
{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" session-start.sh"
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" validate-bash.sh"
}
]
}
]
}
}
```
## Troubleshooting
### "bash is not recognized"
CMD can't find bash. The wrapper uses the full path `C:\Program Files\Git\bin\bash.exe`. If Git is installed elsewhere, update the path.
### "cygpath: command not found" or "dirname: command not found"
Bash isn't running as a login shell. Ensure `-l` flag is used.
### Path has weird `\/` in it
`${CLAUDE_PLUGIN_ROOT}` expanded to a Windows path ending with backslash, then `/hooks/...` was appended. Use `cygpath` to convert the entire path.
### Script opens in text editor instead of running
The hooks.json is pointing directly to the `.sh` file. Point to the `.cmd` wrapper instead.
### Works in terminal but not as hook
Claude Code may run hooks differently. Test by simulating the hook environment:
```powershell
$env:CLAUDE_PLUGIN_ROOT = "C:\path\to\plugin"
cmd /c "C:\path\to\plugin\hooks\session-start.cmd"
```
## Related Issues
- [anthropics/claude-code#9758](https://github.com/anthropics/claude-code/issues/9758) - .sh scripts open in editor on Windows
- [anthropics/claude-code#3417](https://github.com/anthropics/claude-code/issues/3417) - Hooks don't work on Windows
- [anthropics/claude-code#6023](https://github.com/anthropics/claude-code/issues/6023) - CLAUDE_PROJECT_DIR not found

View File

@@ -6,7 +6,8 @@
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh"
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh",
"async": true
}
]
}

43
hooks/run-hook.cmd Executable file
View File

@@ -0,0 +1,43 @@
: << 'CMDBLOCK'
@echo off
REM ============================================================================
REM DEPRECATED: This polyglot wrapper is no longer used as of Claude Code 2.1.x
REM ============================================================================
REM
REM Claude Code 2.1.x changed the Windows execution model for hooks:
REM
REM Before (2.0.x): Hooks ran with shell:true, using the system default shell.
REM This wrapper provided cross-platform compatibility by
REM being both a valid .cmd file (Windows) and bash script.
REM
REM After (2.1.x): Claude Code now auto-detects .sh files in hook commands
REM and prepends "bash " on Windows. This broke the wrapper
REM because the command:
REM "run-hook.cmd" session-start.sh
REM became:
REM bash "run-hook.cmd" session-start.sh
REM ...and bash cannot execute a .cmd file.
REM
REM The fix: hooks.json now calls session-start.sh directly. Claude Code 2.1.x
REM handles the bash invocation automatically on Windows.
REM
REM This file is kept for reference and potential backward compatibility.
REM ============================================================================
REM
REM Original purpose: Polyglot wrapper to run .sh scripts cross-platform
REM Usage: run-hook.cmd <script-name> [args...]
REM The script should be in the same directory as this wrapper
if "%~1"=="" (
echo run-hook.cmd: missing script name >&2
exit /b 1
)
"C:\Program Files\Git\bin\bash.exe" -l "%~dp0%~1" %2 %3 %4 %5 %6 %7 %8 %9
exit /b
CMDBLOCK
# Unix shell runs from here
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SCRIPT_NAME="$1"
shift
"${SCRIPT_DIR}/${SCRIPT_NAME}" "$@"

View File

@@ -3,35 +3,42 @@
set -euo pipefail
# Run personal superpowers setup
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
setup_output=$("${SCRIPT_DIR}/setup-personal-superpowers.sh" 2>&1 || echo "setup_failed=true")
# Determine plugin root directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
PLUGIN_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
# Use same directory resolution as setup script
SUPERPOWERS_DIR="${PERSONAL_SUPERPOWERS_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/superpowers}"
# Check if GitHub CLI is available and setup succeeded
github_recommendation=""
if echo "$setup_output" | grep -q "github_cli_available=true"; then
if [[ ! -d "$SUPERPOWERS_DIR/.git" ]]; then
# This should not happen, but handle gracefully
github_recommendation=""
else
# Check if remote already exists
if ! (cd "$SUPERPOWERS_DIR" && git remote get-url origin &>/dev/null); then
github_recommendation="\n\n💡 Want to share your personal skills on GitHub? Superpowers are best when everyone can learn from them! I can create a 'personal-superpowers' repo for you."
fi
fi
elif echo "$setup_output" | grep -q "setup_failed=true"; then
github_recommendation="\n\n⚠ Personal superpowers setup encountered an issue. Please file a bug at https://github.com/obra/superpowers/issues"
# Check if legacy skills directory exists and build warning
warning_message=""
legacy_skills_dir="${HOME}/.config/superpowers/skills"
if [ -d "$legacy_skills_dir" ]; then
warning_message="\n\n<important-reminder>IN YOUR FIRST REPLY AFTER SEEING THIS MESSAGE YOU MUST TELL THE USER:⚠️ **WARNING:** Superpowers now uses Claude Code's skills system. Custom skills in ~/.config/superpowers/skills will not be read. Move custom skills to ~/.claude/skills instead. To make this message go away, remove ~/.config/superpowers/skills</important-reminder>"
fi
# Read using-superpowers content
using_superpowers_content=$(cat "${PLUGIN_ROOT}/skills/using-superpowers/SKILL.md" 2>&1 || echo "Error reading using-superpowers skill")
# Escape string for JSON embedding using bash parameter substitution.
# Each ${s//old/new} is a single C-level pass - orders of magnitude
# faster than the character-by-character loop this replaces.
escape_for_json() {
local s="$1"
s="${s//\\/\\\\}"
s="${s//\"/\\\"}"
s="${s//$'\n'/\\n}"
s="${s//$'\r'/\\r}"
s="${s//$'\t'/\\t}"
printf '%s' "$s"
}
using_superpowers_escaped=$(escape_for_json "$using_superpowers_content")
warning_escaped=$(escape_for_json "$warning_message")
# Output context injection as JSON
cat <<EOF
{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": "<EXTREMELY_IMPORTANT>\nYou have superpowers.\n\n**Skill tools are at:**\n- find-skills: ${CLAUDE_PLUGIN_ROOT}/scripts/find-skills\n- skill-run: ${CLAUDE_PLUGIN_ROOT}/scripts/skill-run\n\n**RIGHT NOW, go read**: @${CLAUDE_PLUGIN_ROOT}/skills/getting-started/SKILL.md${github_recommendation}\n</EXTREMELY_IMPORTANT>"
"additionalContext": "<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>"
}
}
EOF

View File

@@ -1,52 +0,0 @@
#!/usr/bin/env bash
# Setup script for personal superpowers directory
# Creates personal superpowers directory with git repo for personal skills
set -euo pipefail
# Use PERSONAL_SUPERPOWERS_DIR if set, otherwise XDG_CONFIG_HOME/superpowers, otherwise ~/.config/superpowers
SUPERPOWERS_DIR="${PERSONAL_SUPERPOWERS_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/superpowers}"
SKILLS_DIR="${SUPERPOWERS_DIR}/skills"
# Check if already set up
if [[ -d "${SUPERPOWERS_DIR}/.git" ]] && [[ -d "${SKILLS_DIR}" ]]; then
# Already set up, nothing to do
exit 0
fi
# Create directory structure
mkdir -p "${SKILLS_DIR}"
# Create .gitignore
cat > "${SUPERPOWERS_DIR}/.gitignore" <<'EOF'
# Superpowers local data
search-log.jsonl
conversation-index/
conversation-archive/
EOF
# Create README
cat > "${SUPERPOWERS_DIR}/README.md" <<'EOF'
# My Personal Superpowers
Personal skills and techniques for Claude Code.
Learn more about Superpowers: https://github.com/obra/superpowers
EOF
# Initialize git repo if not already initialized
if [[ ! -d "${SUPERPOWERS_DIR}/.git" ]]; then
cd "${SUPERPOWERS_DIR}"
git init -q
git add .gitignore README.md
git commit -q -m "Initial commit: Personal superpowers setup"
fi
# Check for gh and recommend GitHub setup
if command -v gh &> /dev/null; then
echo "github_cli_available=true"
else
echo "github_cli_available=false"
fi
exit 0

View File

@@ -0,0 +1,236 @@
<!DOCTYPE html>
<html>
<head>
<title>Brainstorm Companion</title>
<style>
/*
* BRAINSTORM COMPANION FRAME TEMPLATE
*
* This template provides a consistent frame with:
* - OS-aware light/dark theming
* - Fixed header and feedback footer
* - Scrollable main content area
* - CSS helpers for common UI patterns
*
* CLAUDE: Replace the contents of #claude-content with your content.
* Keep the header, main wrapper, and feedback-footer intact.
*/
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; overflow: hidden; }
/* ===== THEME VARIABLES ===== */
:root {
--bg-primary: #f5f5f7;
--bg-secondary: #ffffff;
--bg-tertiary: #e5e5e7;
--border: #d1d1d6;
--text-primary: #1d1d1f;
--text-secondary: #86868b;
--text-tertiary: #aeaeb2;
--accent: #0071e3;
--accent-hover: #0077ed;
--success: #34c759;
--warning: #ff9f0a;
--error: #ff3b30;
--selected-bg: #e8f4fd;
--selected-border: #0071e3;
}
@media (prefers-color-scheme: dark) {
:root {
--bg-primary: #1d1d1f;
--bg-secondary: #2d2d2f;
--bg-tertiary: #3d3d3f;
--border: #424245;
--text-primary: #f5f5f7;
--text-secondary: #86868b;
--text-tertiary: #636366;
--accent: #0a84ff;
--accent-hover: #409cff;
--selected-bg: rgba(10, 132, 255, 0.15);
--selected-border: #0a84ff;
}
}
body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
display: flex;
flex-direction: column;
line-height: 1.5;
}
/* ===== FRAME STRUCTURE ===== */
.header {
background: var(--bg-secondary);
padding: 0.5rem 1.5rem;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid var(--border);
flex-shrink: 0;
}
.header h1 { font-size: 0.85rem; font-weight: 500; color: var(--text-secondary); }
.header .status { font-size: 0.7rem; color: var(--success); display: flex; align-items: center; gap: 0.4rem; }
.header .status::before { content: ''; width: 6px; height: 6px; background: var(--success); border-radius: 50%; }
.main { flex: 1; overflow-y: auto; }
#claude-content { padding: 2rem; min-height: 100%; }
.feedback-footer {
background: var(--bg-secondary);
border-top: 1px solid var(--border);
padding: 0.75rem 1.5rem;
flex-shrink: 0;
}
.feedback-footer label { display: block; font-size: 0.65rem; color: var(--text-secondary); margin-bottom: 0.4rem; text-transform: uppercase; letter-spacing: 0.05em; }
.feedback-row { display: flex; gap: 0.5rem; }
.feedback-footer textarea {
flex: 1;
background: var(--bg-primary);
border: 1px solid var(--border);
border-radius: 6px;
padding: 0.5rem 0.75rem;
color: var(--text-primary);
font-family: inherit;
font-size: 0.85rem;
resize: none;
height: 36px;
}
.feedback-footer textarea:focus { outline: none; border-color: var(--accent); }
.feedback-footer button {
background: var(--accent);
color: white;
border: none;
padding: 0 1rem;
border-radius: 6px;
font-size: 0.8rem;
cursor: pointer;
}
.feedback-footer button:hover { background: var(--accent-hover); }
/* ===== TYPOGRAPHY ===== */
h2 { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.5rem; }
h3 { font-size: 1.1rem; font-weight: 600; margin-bottom: 0.25rem; }
.subtitle { color: var(--text-secondary); margin-bottom: 1.5rem; }
.section { margin-bottom: 2rem; }
.label { font-size: 0.7rem; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.5rem; }
/* ===== OPTIONS (for A/B/C choices) ===== */
.options { display: flex; flex-direction: column; gap: 0.75rem; }
.option {
background: var(--bg-secondary);
border: 2px solid var(--border);
border-radius: 12px;
padding: 1rem 1.25rem;
cursor: pointer;
transition: all 0.15s ease;
display: flex;
align-items: flex-start;
gap: 1rem;
}
.option:hover { border-color: var(--accent); }
.option.selected { background: var(--selected-bg); border-color: var(--selected-border); }
.option .letter {
background: var(--bg-tertiary);
color: var(--text-secondary);
width: 1.75rem; height: 1.75rem;
border-radius: 6px;
display: flex; align-items: center; justify-content: center;
font-weight: 600; font-size: 0.85rem; flex-shrink: 0;
}
.option.selected .letter { background: var(--accent); color: white; }
.option .content { flex: 1; }
.option .content h3 { font-size: 0.95rem; margin-bottom: 0.15rem; }
.option .content p { color: var(--text-secondary); font-size: 0.85rem; margin: 0; }
/* ===== CARDS (for showing designs/mockups) ===== */
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1rem; }
.card {
background: var(--bg-secondary);
border: 1px solid var(--border);
border-radius: 12px;
overflow: hidden;
cursor: pointer;
transition: all 0.15s ease;
}
.card:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
.card.selected { border-color: var(--selected-border); border-width: 2px; }
.card-image { background: var(--bg-tertiary); aspect-ratio: 16/10; display: flex; align-items: center; justify-content: center; }
.card-body { padding: 1rem; }
.card-body h3 { margin-bottom: 0.25rem; }
.card-body p { color: var(--text-secondary); font-size: 0.85rem; }
/* ===== MOCKUP CONTAINER ===== */
.mockup {
background: var(--bg-secondary);
border: 1px solid var(--border);
border-radius: 12px;
overflow: hidden;
margin-bottom: 1.5rem;
}
.mockup-header {
background: var(--bg-tertiary);
padding: 0.5rem 1rem;
font-size: 0.75rem;
color: var(--text-secondary);
border-bottom: 1px solid var(--border);
}
.mockup-body { padding: 1.5rem; }
/* ===== SPLIT VIEW (side-by-side comparison) ===== */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; }
@media (max-width: 700px) { .split { grid-template-columns: 1fr; } }
/* ===== PROS/CONS ===== */
.pros-cons { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin: 1rem 0; }
.pros, .cons { background: var(--bg-secondary); border-radius: 8px; padding: 1rem; }
.pros h4 { color: var(--success); font-size: 0.85rem; margin-bottom: 0.5rem; }
.cons h4 { color: var(--error); font-size: 0.85rem; margin-bottom: 0.5rem; }
.pros ul, .cons ul { margin-left: 1.25rem; font-size: 0.85rem; color: var(--text-secondary); }
.pros li, .cons li { margin-bottom: 0.25rem; }
/* ===== PLACEHOLDER (for mockup areas) ===== */
.placeholder {
background: var(--bg-tertiary);
border: 2px dashed var(--border);
border-radius: 8px;
padding: 2rem;
text-align: center;
color: var(--text-tertiary);
}
/* ===== INLINE MOCKUP ELEMENTS ===== */
.mock-nav { background: var(--accent); color: white; padding: 0.75rem 1rem; display: flex; gap: 1.5rem; font-size: 0.9rem; }
.mock-sidebar { background: var(--bg-tertiary); padding: 1rem; min-width: 180px; }
.mock-content { padding: 1.5rem; flex: 1; }
.mock-button { background: var(--accent); color: white; border: none; padding: 0.5rem 1rem; border-radius: 6px; font-size: 0.85rem; }
.mock-input { background: var(--bg-primary); border: 1px solid var(--border); border-radius: 6px; padding: 0.5rem; width: 100%; }
</style>
</head>
<body>
<div class="header">
<h1>Brainstorm Companion</h1>
<div class="status">Connected</div>
</div>
<div class="main">
<div id="claude-content">
<!-- CLAUDE: Replace this content -->
<h2>Visual Brainstorming</h2>
<p class="subtitle">Claude will show mockups and options here.</p>
</div>
</div>
<div class="feedback-footer">
<label>Feedback for Claude</label>
<div class="feedback-row">
<textarea id="feedback" placeholder="Add notes (optional)..." onkeydown="if(event.key==='Enter'&&!event.shiftKey){event.preventDefault();send()}"></textarea>
<button onclick="send()">Send</button>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,139 @@
(function() {
const WS_URL = 'ws://' + window.location.host;
let ws = null;
let eventQueue = [];
function connect() {
ws = new WebSocket(WS_URL);
ws.onopen = () => {
eventQueue.forEach(e => ws.send(JSON.stringify(e)));
eventQueue = [];
};
ws.onmessage = (msg) => {
const data = JSON.parse(msg.data);
if (data.type === 'reload') {
window.location.reload();
}
};
ws.onclose = () => {
setTimeout(connect, 1000);
};
}
function sendEvent(event) {
event.timestamp = Date.now();
if (ws && ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify(event));
} else {
eventQueue.push(event);
}
}
// Auto-capture clicks on interactive elements
document.addEventListener('click', (e) => {
const target = e.target.closest('button, a, [data-choice], [role="button"], input[type="submit"]');
if (!target) return;
// Don't capture regular link navigation
if (target.tagName === 'A' && !target.dataset.choice) return;
// Don't capture the Send feedback button (handled by send())
if (target.id === 'send-feedback') return;
e.preventDefault();
sendEvent({
type: 'click',
text: target.textContent.trim(),
choice: target.dataset.choice || null,
id: target.id || null,
className: target.className || null
});
});
// Auto-capture form submissions
document.addEventListener('submit', (e) => {
e.preventDefault();
const form = e.target;
const formData = new FormData(form);
const data = {};
formData.forEach((value, key) => { data[key] = value; });
sendEvent({
type: 'submit',
formId: form.id || null,
formName: form.name || null,
data: data
});
});
// Auto-capture input changes (debounced)
let inputTimeout = null;
document.addEventListener('input', (e) => {
const target = e.target;
if (!target.matches('input, textarea, select')) return;
clearTimeout(inputTimeout);
inputTimeout = setTimeout(() => {
sendEvent({
type: 'input',
name: target.name || null,
id: target.id || null,
value: target.value,
inputType: target.type || target.tagName.toLowerCase()
});
}, 500);
});
// Send to Claude - triggers feedback delivery
function sendToClaude(feedback) {
sendEvent({
type: 'send-to-claude',
feedback: feedback || null
});
// Show themed confirmation page
document.body.innerHTML = `
<div style="display: flex; align-items: center; justify-content: center; height: 100vh; font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif; background: var(--bg-primary, #f5f5f7);">
<div style="text-align: center; color: var(--text-secondary, #86868b);">
<h2 style="color: var(--text-primary, #1d1d1f); margin-bottom: 0.5rem;">Sent to Claude</h2>
<p>Return to the terminal to see Claude's response.</p>
</div>
</div>
`;
}
// Frame UI: selection tracking and feedback send
window.selectedChoice = null;
window.toggleSelect = function(el) {
const container = el.closest('.options') || el.closest('.cards');
if (container) {
container.querySelectorAll('.option, .card').forEach(o => o.classList.remove('selected'));
}
el.classList.add('selected');
window.selectedChoice = el.dataset.choice;
};
window.send = function() {
const feedbackEl = document.getElementById('feedback');
const feedback = feedbackEl ? feedbackEl.value.trim() : '';
const payload = {};
if (window.selectedChoice) payload.choice = window.selectedChoice;
if (feedback) payload.feedback = feedback;
if (Object.keys(payload).length === 0) return;
sendToClaude(payload);
if (feedbackEl) feedbackEl.value = '';
};
// Expose API for explicit use
window.brainstorm = {
send: sendEvent,
choice: (value, metadata = {}) => sendEvent({ type: 'choice', value, ...metadata }),
sendToClaude: sendToClaude
};
connect();
})();

View File

@@ -0,0 +1,132 @@
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const chokidar = require('chokidar');
const fs = require('fs');
const path = require('path');
const PORT = process.env.BRAINSTORM_PORT || (49152 + Math.floor(Math.random() * 16383));
const SCREEN_DIR = process.env.BRAINSTORM_DIR || '/tmp/brainstorm';
if (!fs.existsSync(SCREEN_DIR)) {
fs.mkdirSync(SCREEN_DIR, { recursive: true });
}
// Load frame template and helper script once at startup
const frameTemplate = fs.readFileSync(path.join(__dirname, 'frame-template.html'), 'utf-8');
const helperScript = fs.readFileSync(path.join(__dirname, 'helper.js'), 'utf-8');
const helperInjection = `<script>\n${helperScript}\n</script>`;
// Detect whether content is a full HTML document or a bare fragment
function isFullDocument(html) {
const trimmed = html.trimStart().toLowerCase();
return trimmed.startsWith('<!doctype') || trimmed.startsWith('<html');
}
// Wrap a content fragment in the frame template
function wrapInFrame(content) {
return frameTemplate.replace(
/(<div id="claude-content">)[\s\S]*?(<\/div>\s*<\/div>\s*<div class="feedback-footer">)/,
`$1\n ${content}\n $2`
);
}
// Find the newest .html file in the directory by mtime
function getNewestScreen() {
const files = fs.readdirSync(SCREEN_DIR)
.filter(f => f.endsWith('.html'))
.map(f => ({
name: f,
path: path.join(SCREEN_DIR, f),
mtime: fs.statSync(path.join(SCREEN_DIR, f)).mtime.getTime()
}))
.sort((a, b) => b.mtime - a.mtime);
return files.length > 0 ? files[0].path : null;
}
const WAITING_PAGE = `<!DOCTYPE html>
<html>
<head>
<title>Brainstorm Companion</title>
<style>
body { font-family: system-ui, sans-serif; padding: 2rem; max-width: 800px; margin: 0 auto; }
h1 { color: #333; }
p { color: #666; }
</style>
</head>
<body>
<h1>Brainstorm Companion</h1>
<p>Waiting for Claude to push a screen...</p>
</body>
</html>`;
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
const clients = new Set();
wss.on('connection', (ws) => {
clients.add(ws);
ws.on('close', () => clients.delete(ws));
ws.on('message', (data) => {
const event = JSON.parse(data.toString());
console.log(JSON.stringify({ source: 'user-event', ...event }));
});
});
// Serve newest screen with helper.js injected
app.get('/', (req, res) => {
const screenFile = getNewestScreen();
let html;
if (!screenFile) {
html = WAITING_PAGE;
} else {
const raw = fs.readFileSync(screenFile, 'utf-8');
html = isFullDocument(raw) ? raw : wrapInFrame(raw);
}
// Inject helper script
if (html.includes('</body>')) {
html = html.replace('</body>', `${helperInjection}\n</body>`);
} else {
html += helperInjection;
}
res.type('html').send(html);
});
// Watch for new or changed .html files
chokidar.watch(SCREEN_DIR, { ignoreInitial: true })
.on('add', (filePath) => {
if (filePath.endsWith('.html')) {
console.log(JSON.stringify({ type: 'screen-added', file: filePath }));
clients.forEach(ws => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: 'reload' }));
}
});
}
})
.on('change', (filePath) => {
if (filePath.endsWith('.html')) {
console.log(JSON.stringify({ type: 'screen-updated', file: filePath }));
clients.forEach(ws => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: 'reload' }));
}
});
}
});
server.listen(PORT, '127.0.0.1', () => {
console.log(JSON.stringify({
type: 'server-started',
port: PORT,
url: `http://localhost:${PORT}`,
screen_dir: SCREEN_DIR
}));
});

1036
lib/brainstorm-server/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
{
"name": "brainstorm-server",
"version": "1.0.0",
"description": "Visual brainstorming companion server for Claude Code",
"main": "index.js",
"dependencies": {
"chokidar": "^3.5.3",
"express": "^4.18.2",
"ws": "^8.14.2"
}
}

View File

@@ -0,0 +1,68 @@
#!/bin/bash
# Start the brainstorm server and output connection info
# Usage: start-server.sh [--project-dir <path>]
#
# Starts server on a random high port, outputs JSON with URL.
# Each session gets its own directory to avoid conflicts.
#
# Options:
# --project-dir <path> Store session files under <path>/.superpowers/brainstorm/
# instead of /tmp. Files persist after server stops.
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# Parse arguments
PROJECT_DIR=""
while [[ $# -gt 0 ]]; do
case "$1" in
--project-dir)
PROJECT_DIR="$2"
shift 2
;;
*)
echo "{\"error\": \"Unknown argument: $1\"}"
exit 1
;;
esac
done
# Generate unique session directory
SESSION_ID="$$-$(date +%s)"
if [[ -n "$PROJECT_DIR" ]]; then
SCREEN_DIR="${PROJECT_DIR}/.superpowers/brainstorm/${SESSION_ID}"
else
SCREEN_DIR="/tmp/brainstorm-${SESSION_ID}"
fi
PID_FILE="${SCREEN_DIR}/.server.pid"
LOG_FILE="${SCREEN_DIR}/.server.log"
# Create fresh session directory
mkdir -p "$SCREEN_DIR"
# Kill any existing server
if [[ -f "$PID_FILE" ]]; then
old_pid=$(cat "$PID_FILE")
kill "$old_pid" 2>/dev/null
rm -f "$PID_FILE"
fi
# Start server, capturing output to log file
cd "$SCRIPT_DIR"
BRAINSTORM_DIR="$SCREEN_DIR" node index.js > "$LOG_FILE" 2>&1 &
SERVER_PID=$!
echo "$SERVER_PID" > "$PID_FILE"
# Wait for server-started message (check log file)
for i in {1..50}; do
if grep -q "server-started" "$LOG_FILE" 2>/dev/null; then
grep "server-started" "$LOG_FILE" | head -1
exit 0
fi
sleep 0.1
done
# Timeout - server didn't start
echo '{"error": "Server failed to start within 5 seconds"}'
exit 1

View File

@@ -0,0 +1,31 @@
#!/bin/bash
# Stop the brainstorm server and clean up
# Usage: stop-server.sh <screen_dir>
#
# Kills the server process. Only deletes session directory if it's
# under /tmp (ephemeral). Persistent directories (.superpowers/) are
# kept so mockups can be reviewed later.
SCREEN_DIR="$1"
if [[ -z "$SCREEN_DIR" ]]; then
echo '{"error": "Usage: stop-server.sh <screen_dir>"}'
exit 1
fi
PID_FILE="${SCREEN_DIR}/.server.pid"
if [[ -f "$PID_FILE" ]]; then
pid=$(cat "$PID_FILE")
kill "$pid" 2>/dev/null
rm -f "$PID_FILE" "${SCREEN_DIR}/.server.log"
# Only delete ephemeral /tmp directories
if [[ "$SCREEN_DIR" == /tmp/* ]]; then
rm -rf "$SCREEN_DIR"
fi
echo '{"status": "stopped"}'
else
echo '{"status": "not_running"}'
fi

View File

@@ -0,0 +1,27 @@
#!/bin/bash
# Wait for user feedback from the brainstorm browser
# Usage: wait-for-feedback.sh <screen_dir>
#
# Blocks until user sends feedback, then outputs the JSON.
# Write HTML to screen_file BEFORE calling this.
SCREEN_DIR="${1:?Usage: wait-for-feedback.sh <screen_dir>}"
LOG_FILE="${SCREEN_DIR}/.server.log"
if [[ ! -d "$SCREEN_DIR" ]]; then
echo '{"error": "Screen directory not found"}' >&2
exit 1
fi
# Record current position in log file
LOG_POS=$(wc -l < "$LOG_FILE" 2>/dev/null || echo 0)
# Poll for new lines containing the event
while true; do
RESULT=$(tail -n +$((LOG_POS + 1)) "$LOG_FILE" 2>/dev/null | grep -m 1 "send-to-claude")
if [[ -n "$RESULT" ]]; then
echo "$RESULT"
exit 0
fi
sleep 0.2
done

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

@@ -1,142 +0,0 @@
#!/usr/bin/env bash
# find-skills - Find and list skills with descriptions
# Shows all skills by default, filters by pattern if provided
# Searches personal superpowers first, then core (personal shadows core)
set -euo pipefail
# Determine directories
PERSONAL_SUPERPOWERS_DIR="${PERSONAL_SUPERPOWERS_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/superpowers}"
PERSONAL_SKILLS_DIR="${PERSONAL_SUPERPOWERS_DIR}/skills"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PLUGIN_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
CORE_SKILLS_DIR="${PLUGIN_ROOT}/skills"
LOG_FILE="${PERSONAL_SUPERPOWERS_DIR}/search-log.jsonl"
# Show help
if [[ "${1:-}" == "--help" ]] || [[ "${1:-}" == "-h" ]]; then
cat <<'EOF'
find-skills - Find and list skills with descriptions
USAGE:
find-skills Show all skills with descriptions
find-skills PATTERN Filter skills by grep pattern
find-skills --help Show this help
EXAMPLES:
find-skills # All skills
find-skills test # Skills matching "test"
find-skills 'test.*driven|TDD' # Regex pattern
OUTPUT:
Each line shows: skill-path - description
Personal skills listed first, then core skills
Personal skills shadow core skills when paths match
SEARCH:
Searches both skill content AND path names.
Personal skills at: ~/.config/superpowers/skills/
Core skills at: plugin installation directory
EOF
exit 0
fi
# Get pattern (optional)
PATTERN="${1:-}"
# Function to extract description from SKILL.md
get_description() {
local file="$1"
grep "^description:" "$file" 2>/dev/null | sed 's/description: *//' || echo ""
}
# Function to get relative skill path
get_skill_path() {
local file="$1"
local base_dir="$2"
local rel_path="${file#$base_dir/}"
echo "${rel_path%/SKILL.md}"
}
# Collect all matching skills (use simple list for bash 3.2 compatibility)
seen_skills_list=""
results=()
# If pattern provided, log the search
if [[ -n "$PATTERN" ]]; then
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
echo "{\"timestamp\":\"$timestamp\",\"query\":\"$PATTERN\"}" >> "$LOG_FILE" 2>/dev/null || true
fi
# Search personal skills first
if [[ -d "$PERSONAL_SKILLS_DIR" ]]; then
while IFS= read -r file; do
[[ -z "$file" ]] && continue
skill_path=$(get_skill_path "$file" "$PERSONAL_SKILLS_DIR")
description=$(get_description "$file")
seen_skills_list="${seen_skills_list}${skill_path}"$'\n'
results+=("$skill_path|$description")
done < <(
if [[ -n "$PATTERN" ]]; then
# Pattern mode: search content and paths
{
grep -E -r "$PATTERN" "$PERSONAL_SKILLS_DIR/" --include="SKILL.md" -l 2>/dev/null || true
find "$PERSONAL_SKILLS_DIR/" -name "SKILL.md" -type f 2>/dev/null | grep -E "$PATTERN" 2>/dev/null || true
} | sort -u
else
# Show all
find "$PERSONAL_SKILLS_DIR/" -name "SKILL.md" -type f 2>/dev/null || true
fi
)
fi
# Search core skills (only if not shadowed)
while IFS= read -r file; do
[[ -z "$file" ]] && continue
skill_path=$(get_skill_path "$file" "$CORE_SKILLS_DIR")
# Skip if shadowed by personal skill
echo "$seen_skills_list" | grep -q "^${skill_path}$" && continue
description=$(get_description "$file")
results+=("$skill_path|$description")
done < <(
if [[ -n "$PATTERN" ]]; then
# Pattern mode: search content and paths
{
grep -E -r "$PATTERN" "$CORE_SKILLS_DIR/" --include="SKILL.md" -l 2>/dev/null || true
find "$CORE_SKILLS_DIR/" -name "SKILL.md" -type f 2>/dev/null | grep -E "$PATTERN" 2>/dev/null || true
} | sort -u
else
# Show all
find "$CORE_SKILLS_DIR/" -name "SKILL.md" -type f 2>/dev/null || true
fi
)
# Check if we found anything
if [[ ${#results[@]} -eq 0 ]]; then
if [[ -n "$PATTERN" ]]; then
echo "❌ No skills found matching: $PATTERN"
echo ""
echo "Search logged. If a skill should exist, consider writing it!"
else
echo "❌ No skills found"
fi
exit 0
fi
# Sort and display results
printf "%s\n" "${results[@]}" | sort | while IFS='|' read -r skill_path description; do
if [[ -n "$description" ]]; then
echo "skills/$skill_path - $description"
else
echo "skills/$skill_path"
fi
done
exit 0

View File

@@ -1,54 +0,0 @@
#!/usr/bin/env bash
# Generic runner for skill scripts
# Searches personal superpowers first, then core plugin
#
# Usage: scripts/skill-run <skill-relative-path> [args...]
# Example: scripts/skill-run skills/collaboration/remembering-conversations/tool/search-conversations "query"
set -euo pipefail
if [[ $# -eq 0 ]]; then
cat <<'EOF'
Usage: scripts/skill-run <skill-relative-path> [args...]
Runs scripts from skills, checking personal superpowers first, then core.
Examples:
scripts/skill-run skills/collaboration/remembering-conversations/tool/search-conversations "query"
scripts/skill-run skills/collaboration/remembering-conversations/tool/index-conversations --cleanup
The script will be found at:
1. ~/.config/superpowers/<skill-relative-path> (personal, if exists)
2. ${CLAUDE_PLUGIN_ROOT}/<skill-relative-path> (core plugin)
EOF
exit 1
fi
# Get the script path to run
SCRIPT_PATH="$1"
shift # Remove script path from args, leaving remaining args
# Determine directories
PERSONAL_SUPERPOWERS_DIR="${PERSONAL_SUPERPOWERS_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/superpowers}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PLUGIN_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
# Try personal superpowers first
PERSONAL_SCRIPT="${PERSONAL_SUPERPOWERS_DIR}/${SCRIPT_PATH}"
if [[ -x "$PERSONAL_SCRIPT" ]]; then
exec "$PERSONAL_SCRIPT" "$@"
fi
# Fall back to core plugin
CORE_SCRIPT="${PLUGIN_ROOT}/${SCRIPT_PATH}"
if [[ -x "$CORE_SCRIPT" ]]; then
exec "$CORE_SCRIPT" "$@"
fi
# Not found
echo "Error: Script not found: $SCRIPT_PATH" >&2
echo "" >&2
echo "Searched:" >&2
echo " $PERSONAL_SCRIPT (personal)" >&2
echo " $CORE_SCRIPT (core)" >&2
exit 1

View File

@@ -1,36 +0,0 @@
# Skill Requests
Use this page to document skills you wish existed. Add requests here when you encounter situations where a skill would have helped.
## Format
```markdown
## [Short Descriptive Name]
**What I need:** One-line description
**When I'd use it:** Specific situations/symptoms
**Why I need this:** What makes this non-obvious or worth capturing
**Added:** YYYY-MM-DD
```
---
## Current Requests
(None yet - add requests below as you discover needs)
---
## Completed Requests
Skills that have been created from this list will move here with links.
---
## Guidelines
- **Be specific** - "Flaky test debugging" not "testing help"
- **Include symptoms** - Error messages, behavior patterns
- **Explain non-obvious** - Why can't you just figure this out?
- **One skill per request** - Keep them focused
your human partner reviews this periodically and we create skills together.

View File

@@ -0,0 +1,82 @@
---
name: brainstorming
description: "You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation."
---
# Brainstorming Ideas Into Designs
Help turn ideas into fully formed designs and specs through natural collaborative dialogue.
Start by understanding the current project context, then ask questions one at a time to refine the idea. Once you understand what you're building, present the design in small sections (200-300 words), checking after each section whether it looks right so far.
## The Process
**Understanding the idea:**
- Check out the current project state first (files, docs, recent commits)
- Ask questions one at a time to refine the idea
- Prefer multiple choice questions when possible, but open-ended is fine too
- Only one question per message - if a topic needs more exploration, break it into multiple questions
- Focus on understanding: purpose, constraints, success criteria
**Exploring approaches:**
- Propose 2-3 different approaches with trade-offs
- Present options conversationally with your recommendation and reasoning
- Lead with your recommended option and explain why
**Presenting the design:**
- Once you believe you understand what you're building, present the design
- Break it into sections of 200-300 words
- Ask after each section whether it looks right so far
- Cover: architecture, components, data flow, error handling, testing
- Be ready to go back and clarify if something doesn't make sense
**Design for isolation and clarity:**
- Break the system into smaller units that each have one clear purpose, communicate through well-defined interfaces, and can be understood and tested independently
- For each unit, you should be able to answer: what does it do, how do you use it, and what does it depend on?
- Can someone understand what a unit does without reading its internals? Can you change the internals without breaking consumers? If not, the boundaries need work.
- Smaller, well-bounded units are also easier for you to work with - you reason better about code you can hold in context at once, and your edits are more reliable when files are focused. When a file grows large, that's often a signal that it's doing too much.
**Working in existing codebases:**
- Explore the current structure before proposing changes. Follow existing patterns.
- Where existing code has problems that affect the work (e.g., a file that's grown too large, unclear boundaries, tangled responsibilities), include targeted improvements as part of the design - the way a good developer improves code they're working in.
- Don't propose unrelated refactoring. Stay focused on what serves the current goal.
## After the Design
**Documentation:**
- Write the validated design (spec) to `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md`
- (User preferences for spec location override this default)
- Use elements-of-style:writing-clearly-and-concisely skill if available
- Commit the design document to git
**Spec Review Loop:**
After writing the spec document:
1. Dispatch spec-document-reviewer subagent (see spec-document-reviewer-prompt.md)
2. If Issues Found: fix, re-dispatch, repeat until Approved
3. If loop exceeds 5 iterations, surface to human for guidance
**Implementation (if continuing):**
- Ask: "Ready to set up for implementation?"
- Use superpowers:using-git-worktrees to create isolated workspace
- **REQUIRED:** Use superpowers:writing-plans to create detailed implementation plan
- Do NOT use platform planning features (e.g., EnterPlanMode, plan mode)
- Do NOT start implementing directly - the writing-plans skill comes first
## Key Principles
- **One question at a time** - Don't overwhelm with multiple questions
- **Multiple choice preferred** - Easier to answer than open-ended when possible
- **YAGNI ruthlessly** - Remove unnecessary features from all designs
- **Explore alternatives** - Always propose 2-3 approaches before settling
- **Incremental validation** - Present design in sections, validate each
- **Be flexible** - Go back and clarify when something doesn't make sense
## Visual Companion (Claude Code Only)
A browser-based visual companion for showing mockups, diagrams, and options during brainstorming. Use it whenever visual representation would make feedback easier than text descriptions alone.
**When the topic involves visual decisions, ask:**
> "This involves some visual decisions. I can show mockups in a browser window so you can see options and give feedback visually. This feature is still new — it can be token-intensive and a bit slow, but it works well for layout, design, and architecture questions. Want to try it? (Requires opening a local URL)"
If they agree, read the detailed guide before proceeding:
`${CLAUDE_PLUGIN_ROOT}/skills/brainstorming/visual-companion.md`

View File

@@ -0,0 +1,49 @@
# Spec Document Reviewer Prompt Template
Use this template when dispatching a spec document reviewer subagent.
**Purpose:** Verify the spec is complete, consistent, and ready for implementation planning.
**Dispatch after:** Spec document is written to docs/superpowers/specs/
```
Task tool (general-purpose):
description: "Review spec document"
prompt: |
You are a spec document reviewer. Verify this spec is complete and ready for planning.
**Spec to review:** [SPEC_FILE_PATH]
## What to Check
| Category | What to Look For |
|----------|------------------|
| Completeness | TODOs, placeholders, "TBD", incomplete sections |
| Coverage | Missing error handling, edge cases, integration points |
| Consistency | Internal contradictions, conflicting requirements |
| Clarity | Ambiguous requirements |
| YAGNI | Unrequested features, over-engineering |
| Architecture | Units with clear boundaries, well-defined interfaces, independently understandable and testable |
## CRITICAL
Look especially hard for:
- Any TODO markers or placeholder text
- Sections saying "to be defined later" or "will spec when X is done"
- Sections noticeably less detailed than others
- Units that lack clear boundaries or interfaces — can you understand what each unit does without reading its internals?
## Output Format
## Spec Review
**Status:** ✅ Approved | ❌ Issues Found
**Issues (if any):**
- [Section X]: [specific issue] - [why it matters]
**Recommendations (advisory):**
- [suggestions that don't block approval]
```
**Reviewer returns:** Status, Issues (if any), Recommendations

View File

@@ -0,0 +1,203 @@
# Visual Companion Guide
Browser-based visual brainstorming companion for showing mockups, diagrams, and options.
## When to Use
Use the visual companion when seeing beats describing:
- **UI mockups** — layouts, navigation, component designs
- **Architecture diagrams** — system components, data flow, relationships
- **Complex choices** — multi-option decisions with visual trade-offs
- **Design polish** — when the question is about look and feel
- **Spatial relationships** — file structures, database schemas, state machines
Don't use it for simple text questions, code review, or when the user prefers terminal-only interaction.
## How It Works
The server watches a directory for HTML files and serves the newest one to the browser. You write HTML content, the user sees it in their browser, clicks options or types feedback, and you receive their response as JSON.
**Content fragments vs full documents:** If your HTML file starts with `<!DOCTYPE` or `<html`, the server serves it as-is (just injects the helper script). Otherwise, the server automatically wraps your content in the frame template — adding the header, CSS theme, feedback footer, and all interactive infrastructure. **Write content fragments by default.** Only write full documents when you need complete control over the page.
## Starting a Session
```bash
# Start server with persistence (mockups saved to project)
${CLAUDE_PLUGIN_ROOT}/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"}
```
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.
## The Loop
1. **Start watcher first** (background bash) — avoids race condition:
```bash
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/wait-for-feedback.sh $SCREEN_DIR
```
2. **Write HTML** to a new file in `screen_dir`:
- Use semantic filenames: `platform.html`, `visual-style.html`, `layout.html`
- **Never reuse filenames** — each screen gets a fresh file
- Use Write tool — **never use cat/heredoc** (dumps noise into terminal)
- Server automatically serves the newest file
3. **Tell user what to expect:**
- Remind them of the URL (every step, not just first)
- Give a brief text summary of what's on screen (e.g., "Showing 3 layout options for the homepage")
4. **Wait for feedback** — call `TaskOutput(task_id, block=true, timeout=600000)`
- If timeout, call TaskOutput again (watcher still running)
- After 3 timeouts (30 min), say "Let me know when you want to continue"
5. **Process feedback** — returns JSON like `{"choice": "a", "feedback": "make header smaller"}`
6. **Iterate or advance** — if feedback changes current screen, write a new file (e.g., `layout-v2.html`). Only move to the next question when the current step is validated.
7. Repeat until done.
## Writing Content Fragments
Write just the content that goes inside the page. The server wraps it in the frame template automatically (header, theme CSS, feedback footer, interactive JS).
**Minimal example:**
```html
<h2>Which layout works better?</h2>
<p class="subtitle">Consider readability and visual hierarchy</p>
<div class="options">
<div class="option" data-choice="a" onclick="toggleSelect(this)">
<div class="letter">A</div>
<div class="content">
<h3>Single Column</h3>
<p>Clean, focused reading experience</p>
</div>
</div>
<div class="option" data-choice="b" onclick="toggleSelect(this)">
<div class="letter">B</div>
<div class="content">
<h3>Two Column</h3>
<p>Sidebar navigation with main content</p>
</div>
</div>
</div>
```
That's it. No `<html>`, no CSS, no `<script>` tags needed. The server provides all of that.
## CSS Classes Available
The frame template provides these CSS classes for your content:
### Options (A/B/C choices)
```html
<div class="options">
<div class="option" data-choice="a" onclick="toggleSelect(this)">
<div class="letter">A</div>
<div class="content">
<h3>Title</h3>
<p>Description</p>
</div>
</div>
</div>
```
### Cards (visual designs)
```html
<div class="cards">
<div class="card" data-choice="design1" onclick="toggleSelect(this)">
<div class="card-image"><!-- mockup content --></div>
<div class="card-body">
<h3>Name</h3>
<p>Description</p>
</div>
</div>
</div>
```
### Mockup container
```html
<div class="mockup">
<div class="mockup-header">Preview: Dashboard Layout</div>
<div class="mockup-body"><!-- your mockup HTML --></div>
</div>
```
### Split view (side-by-side)
```html
<div class="split">
<div class="mockup"><!-- left --></div>
<div class="mockup"><!-- right --></div>
</div>
```
### Pros/Cons
```html
<div class="pros-cons">
<div class="pros"><h4>Pros</h4><ul><li>Benefit</li></ul></div>
<div class="cons"><h4>Cons</h4><ul><li>Drawback</li></ul></div>
</div>
```
### Mock elements (wireframe building blocks)
```html
<div class="mock-nav">Logo | Home | About | Contact</div>
<div style="display: flex;">
<div class="mock-sidebar">Navigation</div>
<div class="mock-content">Main content area</div>
</div>
<button class="mock-button">Action Button</button>
<input class="mock-input" placeholder="Input field">
<div class="placeholder">Placeholder area</div>
```
### Typography and sections
- `h2` — page title
- `h3` — section heading
- `.subtitle` — secondary text below title
- `.section` — content block with bottom margin
- `.label` — small uppercase label text
## User Feedback Format
```json
{
"choice": "option-id",
"feedback": "user notes"
}
```
Both fields are optional — user may select without notes, or send notes without a selection.
## Design Tips
- **Scale fidelity to the question** — wireframes for layout, polish for polish questions
- **Explain the question on each page** — "Which layout feels more professional?" not just "Pick one"
- **Iterate before advancing** — if feedback changes current screen, write a new version
- **2-4 options max** per screen
- **Use real content when it matters** — for a photography portfolio, use actual images (Unsplash). Placeholder content obscures design issues.
- **Keep mockups simple** — focus on layout and structure, not pixel-perfect design
## File Naming
- Use semantic names: `platform.html`, `visual-style.html`, `layout.html`
- Never reuse filenames — each screen must be a new file
- For iterations: append version suffix like `layout-v2.html`, `layout-v3.html`
- Server serves newest file by modification time
## Cleaning Up
```bash
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/stop-server.sh $SCREEN_DIR
```
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 (JS API): `${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/helper.js`

View File

@@ -1,56 +0,0 @@
---
name: Brainstorming Ideas Into Designs
description: Interactive idea refinement using Socratic method to develop fully-formed designs
when_to_use: When your human partner says "I've got an idea", "Let's make/build/create", "I want to implement/add", "What if we". When starting design for complex feature. Before writing implementation plans. When idea needs refinement and exploration. ACTIVATE THIS AUTOMATICALLY when your human partner describes a feature or project idea - don't wait for /brainstorm command.
version: 2.0.0
---
# Brainstorming Ideas Into Designs
## Overview
Transform rough ideas into fully-formed designs through structured questioning and alternative exploration.
**Core principle:** Ask questions to understand, explore alternatives, present design incrementally for validation.
**Announce at start:** "I'm using the Brainstorming skill to refine your idea into a design."
## The Process
### Phase 1: Understanding
- Check current project state in working directory
- Ask ONE question at a time to refine the idea
- Prefer multiple choice when possible
- Gather: Purpose, constraints, success criteria
### Phase 2: Exploration
- Propose 2-3 different approaches (reference skills/coding/exploring-alternatives)
- For each: Core architecture, trade-offs, complexity assessment
- Ask your human partner which approach resonates
### Phase 3: Design Presentation
- Present in 200-300 word sections
- Cover: Architecture, components, data flow, error handling, testing
- Ask after each section: "Does this look right so far?"
### Phase 4: Worktree Setup (for implementation)
When design is approved and implementation will follow:
- Announce: "I'm using the Using Git Worktrees skill to set up an isolated workspace."
- Switch to skills/collaboration/using-git-worktrees
- Follow that skill's process for directory selection, safety verification, and setup
- Return here when worktree ready
### Phase 5: Planning Handoff
Ask: "Ready to create the implementation plan?"
When your human partner confirms (any affirmative response):
- Announce: "I'm using the Writing Plans skill to create the implementation plan."
- Switch to skills/collaboration/writing-plans skill
- Create detailed plan in the worktree
## Remember
- One question per message during Phase 1
- Apply YAGNI ruthlessly (reference skills/architecture/reducing-complexity)
- Explore 2-3 alternatives before settling
- Present incrementally, validate as you go
- Announce skill usage at start

View File

@@ -1,59 +0,0 @@
---
name: Executing Plans
description: Execute detailed plans in batches with review checkpoints
when_to_use: When have a complete implementation plan to execute. When implementing in separate session from planning. When your human partner points you to a plan file to implement.
version: 2.0.0
---
# Executing Plans
## Overview
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."
## The Process
### Step 1: Load and Review Plan
1. Read plan file
2. Review critically - identify any questions or concerns about the plan
3. If concerns: Raise them with your human partner before starting
4. If no concerns: Create TodoWrite and proceed
### Step 2: Execute Batch
**Default: First 3 tasks**
For each task:
1. Mark as in_progress
2. Follow each step exactly (plan has bite-sized steps)
3. Run verifications as specified
4. Mark as completed
### 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."
- Switch to skills/collaboration/finishing-a-development-branch
- Follow that skill to verify tests, present options, execute choice
## Remember
- Review plan critically first
- Follow plan steps exactly
- Don't skip verifications
- Reference skills when plan says to
- Between batches: just report and wait

View File

@@ -1,329 +0,0 @@
# Conversation Search Deployment Guide
Quick reference for deploying and maintaining the conversation indexing system.
## Initial Deployment
```bash
cd ~/.claude/skills/collaboration/remembering-conversations/tool
# 1. Install hook
./install-hook
# 2. Index existing conversations (with parallel summarization)
./index-conversations --cleanup --concurrency 8
# 3. Verify index health
./index-conversations --verify
# 4. Test search
./search-conversations "test query"
```
**Expected results:**
- Hook installed at `~/.claude/hooks/sessionEnd`
- Summaries created for all conversations (50-120 words each)
- Search returns relevant results in <1 second
- No verification errors
**Performance tip:** Use `--concurrency 8` or `--concurrency 16` for 8-16x faster summarization on initial indexing. Hook uses concurrency=1 (safe for background).
## Ongoing Maintenance
### Automatic (No Action Required)
- Hook runs after every session ends
- New conversations indexed in background (<30 sec per conversation)
- Summaries generated automatically
### Weekly Health Check
```bash
cd ~/.claude/skills/collaboration/remembering-conversations/tool
./index-conversations --verify
```
If issues found:
```bash
./index-conversations --repair
```
### After System Changes
| Change | Action |
|--------|--------|
| Moved conversation archive | Update paths in code, run `--rebuild` |
| Updated CLAUDE.md | Run `--verify` to check for issues |
| Changed database schema | Backup DB, run `--rebuild` |
| Hook not running | Check executable: `chmod +x ~/.claude/hooks/sessionEnd` |
## Recovery Scenarios
| Issue | Diagnosis | Fix |
|-------|-----------|-----|
| **Missing summaries** | `--verify` shows "Missing summaries: N" | `--repair` regenerates missing summaries |
| **Orphaned DB entries** | `--verify` shows "Orphaned entries: N" | `--repair` removes orphaned entries |
| **Outdated indexes** | `--verify` shows "Outdated files: N" | `--repair` re-indexes modified files |
| **Corrupted database** | Errors during search/verify | `--rebuild` (re-indexes everything, requires confirmation) |
| **Hook not running** | No summaries for new conversations | See Troubleshooting below |
| **Slow indexing** | Takes >30 sec per conversation | Check API key, network, Haiku fallback in logs |
## Monitoring
### Health Checks
```bash
# Check hook installed and executable
ls -l ~/.claude/hooks/sessionEnd
# Check recent conversations
ls -lt ~/.config/superpowers/conversation-archive/*/*.jsonl | head -5
# Check database size
ls -lh ~/.config/superpowers/conversation-index/db.sqlite
# Full verification
./index-conversations --verify
```
### Expected Behavior Metrics
- **Hook execution:** Within seconds of session end
- **Indexing speed:** <30 seconds per conversation
- **Summary length:** 50-120 words
- **Search latency:** <1 second
- **Verification:** 0 errors when healthy
### Log Output
Normal indexing:
```
Initializing database...
Loading embedding model...
Processing project: my-project (3 conversations)
Summary: 87 words
Indexed conversation.jsonl: 5 exchanges
✅ Indexing complete! Conversations: 3, Exchanges: 15
```
Verification with issues:
```
Verifying conversation index...
Verified 100 conversations.
=== Verification Results ===
Missing summaries: 2
Orphaned entries: 0
Outdated files: 1
Corrupted files: 0
Run with --repair to fix these issues.
```
## Troubleshooting
### Hook Not Running
**Symptoms:** New conversations not indexed automatically
**Diagnosis:**
```bash
# 1. Check hook exists and is executable
ls -l ~/.claude/hooks/sessionEnd
# Should show: -rwxr-xr-x ... sessionEnd
# 2. Check $SESSION_ID is set during sessions
echo $SESSION_ID
# Should show: session ID when in active session
# 3. Check indexer exists
ls -l ~/.claude/skills/collaboration/remembering-conversations/tool/index-conversations
# Should show: -rwxr-xr-x ... index-conversations
# 4. Test hook manually
SESSION_ID=test-$(date +%s) ~/.claude/hooks/sessionEnd
```
**Fix:**
```bash
# Make hook executable
chmod +x ~/.claude/hooks/sessionEnd
# Reinstall if needed
./install-hook
```
### Summaries Failing
**Symptoms:** Verify shows missing summaries, repair fails
**Diagnosis:**
```bash
# Check API key
echo $ANTHROPIC_API_KEY
# Should show: sk-ant-...
# Try manual indexing with logging
./index-conversations 2>&1 | tee index.log
grep -i error index.log
```
**Fix:**
```bash
# Set API key if missing
export ANTHROPIC_API_KEY="your-key-here"
# Check for rate limits (wait and retry)
sleep 60 && ./index-conversations --repair
# Fallback uses claude-3-haiku-20240307 (cheaper)
# Check logs for: "Summary: N words" to confirm success
```
### Search Not Finding Results
**Symptoms:** `./search-conversations "query"` returns no results
**Diagnosis:**
```bash
# 1. Verify conversations indexed
./index-conversations --verify
# 2. Check database exists and has data
ls -lh ~/.config/superpowers/conversation-index/db.sqlite
# Should be > 100KB if conversations indexed
# 3. Try text search (exact match)
./search-conversations --text "exact phrase from conversation"
# 4. Check for corruption
sqlite3 ~/.config/superpowers/conversation-index/db.sqlite "SELECT COUNT(*) FROM exchanges;"
# Should show number > 0
```
**Fix:**
```bash
# If database missing or corrupt
./index-conversations --rebuild
# If specific conversations missing
./index-conversations --repair
# If still failing, check embedding model
rm -rf ~/.cache/transformers # Force re-download
./index-conversations
```
### Database Corruption
**Symptoms:** Errors like "database disk image is malformed"
**Fix:**
```bash
# 1. Backup current database
cp ~/.config/superpowers/conversation-index/db.sqlite ~/.config/superpowers/conversation-index/db.sqlite.backup
# 2. Rebuild from scratch
./index-conversations --rebuild
# Confirms with: "Are you sure? [yes/NO]:"
# Type: yes
# 3. Verify rebuild
./index-conversations --verify
```
## Commands Reference
```bash
# Index all conversations
./index-conversations
# Index specific session (called by hook)
./index-conversations --session <session-id>
# Index only unprocessed conversations
./index-conversations --cleanup
# Verify index health
./index-conversations --verify
# Repair issues found by verify
./index-conversations --repair
# Rebuild everything (with confirmation)
./index-conversations --rebuild
# Search conversations (semantic)
./search-conversations "query"
# Search conversations (text match)
./search-conversations --text "exact phrase"
# Install/reinstall hook
./install-hook
```
## Subagent Workflow
**For searching conversations from within Claude Code sessions**, use the subagent pattern (see `skills/getting-started` for complete workflow).
**Template:** `tool/prompts/search-agent.md`
**Key requirements:**
- Synthesis must be 200-1000 words (Summary section)
- All sources must include: project, date, file path, status
- No raw conversation excerpts (synthesize instead)
- Follow-up via subagent (not direct file reads)
**Manual test checklist:**
1. ✓ Dispatch subagent with search template
2. ✓ Verify synthesis 200-1000 words
3. ✓ Verify all sources have metadata (project, date, path, status)
4. ✓ Ask follow-up → dispatch second subagent to dig deeper
5. ✓ Confirm no raw conversations in main context
## Files and Directories
```
~/.claude/
├── hooks/
│ └── sessionEnd # Hook that triggers indexing
└── skills/collaboration/remembering-conversations/
├── SKILL.md # Main documentation
├── DEPLOYMENT.md # This file
└── tool/
├── index-conversations # Main indexer
├── search-conversations # Search interface
├── install-hook # Hook installer
├── test-deployment.sh # End-to-end tests
├── src/ # TypeScript source
└── prompts/
└── search-agent.md # Subagent template
~/.config/superpowers/
├── conversation-archive/ # Archived conversations
│ └── <project>/
│ ├── <uuid>.jsonl # Conversation file
│ └── <uuid>-summary.txt # AI summary (50-120 words)
└── conversation-index/
└── db.sqlite # SQLite database with embeddings
```
## Deployment Checklist
### Initial Setup
- [ ] Hook installed: `./install-hook`
- [ ] Existing conversations indexed: `./index-conversations`
- [ ] Verification clean: `./index-conversations --verify`
- [ ] Search working: `./search-conversations "test"`
- [ ] Subagent template exists: `ls tool/prompts/search-agent.md`
### Ongoing
- [ ] Weekly: Run `--verify` and `--repair` if needed
- [ ] After system changes: Re-verify
- [ ] Monitor: Check hook runs (summaries appear for new conversations)
### Testing
- [ ] Run end-to-end tests: `./test-deployment.sh`
- [ ] All 5 scenarios pass
- [ ] Manual subagent test (see scenario 5 in test output)

View File

@@ -1,133 +0,0 @@
# Managing Conversation Index
Index, archive, and maintain conversations for search.
## Quick Start
**Install auto-indexing hook:**
```bash
~/.claude/skills/collaboration/remembering-conversations/tool/install-hook
```
**Index all conversations:**
```bash
~/.claude/skills/collaboration/remembering-conversations/tool/index-conversations
```
**Process unindexed only:**
```bash
~/.claude/skills/collaboration/remembering-conversations/tool/index-conversations --cleanup
```
## Features
- **Automatic indexing** via sessionEnd hook (install once, forget)
- **Semantic search** across all past conversations
- **AI summaries** (Claude Haiku with Sonnet fallback)
- **Recovery modes** (verify, repair, rebuild)
- **Permanent archive** at `~/.config/superpowers/conversation-archive/`
## Setup
### 1. Install Hook (One-Time)
```bash
cd ~/.claude/skills/collaboration/remembering-conversations/tool
./install-hook
```
Handles existing hooks gracefully (merge or replace). Runs in background after each session.
### 2. Index Existing Conversations
```bash
# Index everything
./index-conversations
# Or just unindexed (faster, cheaper)
./index-conversations --cleanup
```
## Index Modes
```bash
# Index all (first run or full rebuild)
./index-conversations
# Index specific session (used by hook)
./index-conversations --session <uuid>
# Process only unindexed (missing summaries)
./index-conversations --cleanup
# Check index health
./index-conversations --verify
# Fix detected issues
./index-conversations --repair
# Nuclear option (deletes DB, re-indexes everything)
./index-conversations --rebuild
```
## Recovery Scenarios
| Situation | Command |
|-----------|---------|
| Missed conversations | `--cleanup` |
| Hook didn't run | `--cleanup` |
| Updated conversation | `--verify` then `--repair` |
| Corrupted database | `--rebuild` |
| Index health check | `--verify` |
## Troubleshooting
**Hook not running:**
- Check: `ls -l ~/.claude/hooks/sessionEnd` (should be executable)
- Test: `SESSION_ID=test-$(date +%s) ~/.claude/hooks/sessionEnd`
- Re-install: `./install-hook`
**Summaries failing:**
- Check API key: `echo $ANTHROPIC_API_KEY`
- Check logs in ~/.config/superpowers/conversation-index/
- Try manual: `./index-conversations --session <uuid>`
**Search not finding results:**
- Verify indexed: `./index-conversations --verify`
- Try text search: `./search-conversations --text "exact phrase"`
- Rebuild if needed: `./index-conversations --rebuild`
## Excluding Projects
To exclude specific projects from indexing (e.g., meta-conversations), create:
`~/.config/superpowers/conversation-index/exclude.txt`
```
# One project name per line
# Lines starting with # are comments
-Users-yourname-Documents-some-project
```
Or set env variable:
```bash
export CONVERSATION_SEARCH_EXCLUDE_PROJECTS="project1,project2"
```
## Storage
- **Archive:** `~/.config/superpowers/conversation-archive/<project>/<uuid>.jsonl`
- **Summaries:** `~/.config/superpowers/conversation-archive/<project>/<uuid>-summary.txt`
- **Database:** `~/.config/superpowers/conversation-index/db.sqlite`
- **Exclusions:** `~/.config/superpowers/conversation-index/exclude.txt` (optional)
## Technical Details
- **Embeddings:** @xenova/transformers (all-MiniLM-L6-v2, 384 dimensions, local/free)
- **Vector search:** sqlite-vec (local/free)
- **Summaries:** Claude Haiku with Sonnet fallback (~$0.01-0.02/conversation)
- **Parser:** Handles multi-message exchanges and sidechains
## See Also
- **Searching:** See SKILL.md for search modes (vector, text, time filtering)
- **Deployment:** See DEPLOYMENT.md for production runbook

View File

@@ -1,69 +0,0 @@
---
name: Remembering Conversations
description: Search previous Claude Code conversations for facts, patterns, decisions, and context using semantic or text search
when_to_use: When your human partner mentions "we discussed this before". When debugging similar issues. When looking for architectural decisions or code patterns from past work. Before reinventing solutions. When you need to find a specific git SHA or error message.
version: 1.0.0
---
# Remembering Conversations
Search archived conversations using semantic similarity or exact text matching.
**Core principle:** Search before reinventing.
**Announce:** "I'm searching previous conversations for [topic]."
**Setup:** See INDEXING.md
## When to Use
**Search when:**
- Your human partner mentions "we discussed this before"
- Debugging similar issues
- Looking for architectural decisions or patterns
- Before implementing something familiar
**Don't search when:**
- Info in current conversation
- Question about current codebase (use Grep/Read)
## In-Session Use
**Always use subagents** (50-100x context savings). See skills/getting-started for workflow.
**Manual/CLI use:** Direct search (below) for humans outside Claude Code sessions.
## Direct Search (Manual/CLI)
**Tool:** `${CLAUDE_PLUGIN_ROOT}/skills/collaboration/remembering-conversations/tool/search-conversations`
**Modes:**
```bash
search-conversations "query" # Vector similarity (default)
search-conversations --text "exact" # Exact string match
search-conversations --both "query" # Both modes
```
**Flags:**
```bash
--after YYYY-MM-DD # Filter by date
--before YYYY-MM-DD # Filter by date
--limit N # Max results (default: 10)
--help # Full usage
```
**Examples:**
```bash
# Semantic search
search-conversations "React Router authentication errors"
# Find git SHA
search-conversations --text "a1b2c3d4"
# Time range
search-conversations --after 2025-09-01 "refactoring"
```
Returns: project, date, conversation summary, matched exchange, similarity %, file path.
**For details:** Run `search-conversations --help`

View File

@@ -1,8 +0,0 @@
node_modules/
dist/
*.log
.DS_Store
# Local data (database and archives are at ~/.clank/, not in repo)
*.sqlite*
.cache/

View File

@@ -1,10 +0,0 @@
#!/bin/bash
# Auto-index conversation after session ends
# Copy to ~/.claude/hooks/sessionEnd to enable
INDEXER="$HOME/.claude/skills/collaboration/remembering-conversations/tool/index-conversations"
if [ -n "$SESSION_ID" ] && [ -x "$INDEXER" ]; then
# Run in background, suppress output
"$INDEXER" --session "$SESSION_ID" > /dev/null 2>&1 &
fi

View File

@@ -1,83 +0,0 @@
#!/bin/bash
cd "$(dirname "$0")"
SCRIPT_DIR="$(pwd)"
case "$1" in
--help|-h)
cat <<'EOF'
index-conversations - Index and manage conversation archives
USAGE:
index-conversations [COMMAND] [OPTIONS]
COMMANDS:
(default) Index all conversations
--cleanup Process only unindexed conversations (fast, cheap)
--session ID Index specific session (used by hook)
--verify Check index health
--repair Fix detected issues
--rebuild Delete DB and re-index everything (requires confirmation)
OPTIONS:
--concurrency N Parallel summarization (1-16, default: 1)
-c N Short form of --concurrency
--no-summaries Skip AI summary generation (free, but no summaries in results)
--help, -h Show this help
EXAMPLES:
# Index all unprocessed (recommended for backfill)
index-conversations --cleanup
# Index with 8 parallel summarizations (8x faster)
index-conversations --cleanup --concurrency 8
# Index without AI summaries (free, fast)
index-conversations --cleanup --no-summaries
# Check index health
index-conversations --verify
# Fix any issues found
index-conversations --repair
# Nuclear option (deletes everything, re-indexes)
index-conversations --rebuild
WORKFLOW:
1. Initial setup: index-conversations --cleanup
2. Ongoing: Auto-indexed by sessionEnd hook
3. Health check: index-conversations --verify (weekly)
4. Recovery: index-conversations --repair (if issues found)
SEE ALSO:
INDEXING.md - Setup and maintenance guide
DEPLOYMENT.md - Production runbook
EOF
exit 0
;;
--session)
npx tsx "$SCRIPT_DIR/src/index-cli.ts" index-session "$@"
;;
--cleanup)
npx tsx "$SCRIPT_DIR/src/index-cli.ts" index-cleanup "$@"
;;
--verify)
npx tsx "$SCRIPT_DIR/src/index-cli.ts" verify "$@"
;;
--repair)
npx tsx "$SCRIPT_DIR/src/index-cli.ts" repair "$@"
;;
--rebuild)
echo "⚠️ This will DELETE the entire database and re-index everything."
read -p "Are you sure? [yes/NO]: " confirm
if [ "$confirm" = "yes" ]; then
npx tsx "$SCRIPT_DIR/src/index-cli.ts" rebuild "$@"
else
echo "Cancelled"
fi
;;
*)
npx tsx "$SCRIPT_DIR/src/index-cli.ts" index-all "$@"
;;
esac

View File

@@ -1,82 +0,0 @@
#!/bin/bash
# Install sessionEnd hook with merge support
HOOK_DIR="$HOME/.claude/hooks"
HOOK_FILE="$HOOK_DIR/sessionEnd"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SOURCE_HOOK="$SCRIPT_DIR/hooks/sessionEnd"
echo "Installing conversation indexing hook..."
# Create hooks directory
mkdir -p "$HOOK_DIR"
# Handle existing hook
if [ -f "$HOOK_FILE" ]; then
echo "⚠️ Existing sessionEnd hook found"
# Check if our indexer is already installed
if grep -q "remembering-conversations.*index-conversations" "$HOOK_FILE"; then
echo "✓ Indexer already installed in existing hook"
exit 0
fi
# Create backup
BACKUP="$HOOK_FILE.backup.$(date +%s)"
cp "$HOOK_FILE" "$BACKUP"
echo "Created backup: $BACKUP"
# Offer merge or replace
echo ""
echo "Options:"
echo " (m) Merge - Add indexer to existing hook"
echo " (r) Replace - Overwrite with our hook"
echo " (c) Cancel - Exit without changes"
echo ""
read -p "Choose [m/r/c]: " choice
case "$choice" in
m|M)
# Append our indexer
cat >> "$HOOK_FILE" <<'EOF'
# Auto-index conversations (remembering-conversations skill)
INDEXER="$HOME/.claude/skills/collaboration/remembering-conversations/tool/index-conversations"
if [ -n "$SESSION_ID" ] && [ -x "$INDEXER" ]; then
"$INDEXER" --session "$SESSION_ID" > /dev/null 2>&1 &
fi
EOF
echo "✓ Merged indexer into existing hook"
;;
r|R)
cp "$SOURCE_HOOK" "$HOOK_FILE"
chmod +x "$HOOK_FILE"
echo "✓ Replaced hook with our version"
;;
c|C)
echo "Installation cancelled"
exit 1
;;
*)
echo "Invalid choice. Exiting."
exit 1
;;
esac
else
# No existing hook, install fresh
cp "$SOURCE_HOOK" "$HOOK_FILE"
chmod +x "$HOOK_FILE"
echo "✓ Installed sessionEnd hook"
fi
# Verify executable
if [ ! -x "$HOOK_FILE" ]; then
chmod +x "$HOOK_FILE"
fi
echo ""
echo "Hook installed successfully!"
echo "Location: $HOOK_FILE"
echo ""
echo "Test it:"
echo " SESSION_ID=test-\$(date +%s) $HOOK_FILE"

View File

@@ -1,124 +0,0 @@
#!/usr/bin/env bash
# Migrate conversation archive and index from ~/.clank to ~/.config/superpowers
#
# IMPORTANT: This preserves all data. The old ~/.clank directory is not deleted,
# allowing you to verify the migration before removing it manually.
set -euo pipefail
# Determine target directory
SUPERPOWERS_DIR="${PERSONAL_SUPERPOWERS_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/superpowers}"
OLD_ARCHIVE="$HOME/.clank/conversation-archive"
OLD_INDEX="$HOME/.clank/conversation-index"
NEW_ARCHIVE="${SUPERPOWERS_DIR}/conversation-archive"
NEW_INDEX="${SUPERPOWERS_DIR}/conversation-index"
echo "Migration: ~/.clank → ${SUPERPOWERS_DIR}"
echo ""
# Check if source exists
if [[ ! -d "$HOME/.clank" ]]; then
echo "✅ No ~/.clank directory found. Nothing to migrate."
exit 0
fi
# Check if already migrated
if [[ -d "$NEW_ARCHIVE" ]] || [[ -d "$NEW_INDEX" ]]; then
echo "⚠️ Destination already exists:"
[[ -d "$NEW_ARCHIVE" ]] && echo " - ${NEW_ARCHIVE}"
[[ -d "$NEW_INDEX" ]] && echo " - ${NEW_INDEX}"
echo ""
echo "Migration appears to have already run."
echo "To re-run migration, manually remove destination directories first."
exit 1
fi
# Show what will be migrated
echo "Source directories:"
if [[ -d "$OLD_ARCHIVE" ]]; then
archive_size=$(du -sh "$OLD_ARCHIVE" | cut -f1)
archive_count=$(find "$OLD_ARCHIVE" -name "*.jsonl" | wc -l | tr -d ' ')
echo " Archive: ${OLD_ARCHIVE} (${archive_count} conversations, ${archive_size})"
else
echo " Archive: Not found"
fi
if [[ -d "$OLD_INDEX" ]]; then
index_size=$(du -sh "$OLD_INDEX" | cut -f1)
echo " Index: ${OLD_INDEX} (${index_size})"
else
echo " Index: Not found"
fi
echo ""
echo "Destination: ${SUPERPOWERS_DIR}"
echo ""
# Confirm
read -p "Proceed with migration? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Migration cancelled."
exit 0
fi
# Ensure destination base exists
mkdir -p "${SUPERPOWERS_DIR}"
# Migrate archive
if [[ -d "$OLD_ARCHIVE" ]]; then
echo "Copying conversation archive..."
cp -r "$OLD_ARCHIVE" "$NEW_ARCHIVE"
echo " ✓ Archive migrated"
fi
# Migrate index
if [[ -d "$OLD_INDEX" ]]; then
echo "Copying conversation index..."
cp -r "$OLD_INDEX" "$NEW_INDEX"
echo " ✓ Index migrated"
fi
# Update database paths to point to new location
if [[ -f "$NEW_INDEX/db.sqlite" ]]; then
echo "Updating database paths..."
sqlite3 "$NEW_INDEX/db.sqlite" "UPDATE exchanges SET archive_path = REPLACE(archive_path, '/.clank/', '/.config/superpowers/') WHERE archive_path LIKE '%/.clank/%';"
echo " ✓ Database paths updated"
fi
# Verify migration
echo ""
echo "Verifying migration..."
if [[ -d "$OLD_ARCHIVE" ]]; then
old_count=$(find "$OLD_ARCHIVE" -name "*.jsonl" | wc -l | tr -d ' ')
new_count=$(find "$NEW_ARCHIVE" -name "*.jsonl" | wc -l | tr -d ' ')
if [[ "$old_count" -eq "$new_count" ]]; then
echo " ✓ All $new_count conversations migrated"
else
echo " ⚠️ Conversation count mismatch: old=$old_count, new=$new_count"
exit 1
fi
fi
if [[ -f "$OLD_INDEX/db.sqlite" ]]; then
old_size=$(stat -f%z "$OLD_INDEX/db.sqlite" 2>/dev/null || stat --format=%s "$OLD_INDEX/db.sqlite" 2>/dev/null)
new_size=$(stat -f%z "$NEW_INDEX/db.sqlite" 2>/dev/null || stat --format=%s "$NEW_INDEX/db.sqlite" 2>/dev/null)
echo " ✓ Database migrated (${new_size} bytes)"
fi
echo ""
echo "✅ Migration complete!"
echo ""
echo "Next steps:"
echo " 1. Test search: ./search-conversations 'test query'"
echo " 2. Verify results look correct"
echo " 3. Once verified, manually remove old directory:"
echo " rm -rf ~/.clank"
echo ""
echo "The old ~/.clank directory is preserved for safety."
exit 0

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +0,0 @@
{
"name": "conversation-search",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"index": "./index-conversations",
"search": "./search-conversations",
"test": "vitest run",
"test:watch": "vitest"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "module",
"dependencies": {
"@anthropic-ai/claude-agent-sdk": "^0.1.9",
"@xenova/transformers": "^2.17.2",
"better-sqlite3": "^12.4.1",
"sqlite-vec": "^0.1.7-alpha.2"
},
"devDependencies": {
"@types/better-sqlite3": "^7.6.13",
"@types/node": "^24.7.0",
"tsx": "^4.20.6",
"typescript": "^5.9.3",
"vitest": "^3.2.4"
}
}

View File

@@ -1,157 +0,0 @@
# Conversation Search Agent
You are searching historical Claude Code conversations for relevant context.
**Your task:**
1. Search conversations for: {TOPIC}
2. Read the top 2-5 most relevant results
3. Synthesize key findings (max 1000 words)
4. Return synthesis + source pointers (so main agent can dig deeper)
## Search Query
{SEARCH_QUERY}
## What to Look For
{FOCUS_AREAS}
Example focus areas:
- What was the problem or question?
- What solution was chosen and why?
- What alternatives were considered and rejected?
- Any gotchas, edge cases, or lessons learned?
- Relevant code patterns, APIs, or approaches used
- Architectural decisions and rationale
## How to Search
Run:
```bash
~/.claude/skills/collaboration/remembering-conversations/tool/search-conversations "{SEARCH_QUERY}"
```
This returns:
- Project name and date
- Conversation summary (AI-generated)
- Matched exchange with similarity score
- File path and line numbers
Read the full conversations for top 2-5 results to get complete context.
## Output Format
**Required structure:**
### Summary
[Synthesize findings in 200-1000 words. Adapt structure to what you found:
- Quick answer? 1-2 paragraphs.
- Complex topic? Use sections (Context/Solution/Rationale/Lessons/Code).
- Multiple approaches? Compare and contrast.
- Historical evolution? Show progression chronologically.
Focus on actionable insights for the current task.]
### Sources
[List ALL conversations examined, in order of relevance:]
**1. [project-name, YYYY-MM-DD]** - X% match
Conversation summary: [One sentence - what was this conversation about?]
File: ~/.clank/conversation-archive/.../uuid.jsonl:start-end
Status: [Read in detail | Reviewed summary only | Skimmed]
**2. [project-name, YYYY-MM-DD]** - X% match
Conversation summary: ...
File: ...
Status: ...
[Continue for all examined sources...]
### For Follow-Up
Main agent can:
- Ask you to dig deeper into specific source (#1, #2, etc.)
- Ask you to read adjacent exchanges in a conversation
- Ask you to search with refined query
- Read sources directly (discouraged - risks context bloat)
## Critical Rules
**DO:**
- Search using the provided query
- Read full conversations for top results
- Synthesize into actionable insights (200-1000 words)
- Include ALL sources with metadata (project, date, summary, file, status)
- Focus on what will help the current task
- Include specific details (function names, error messages, line numbers)
**DO NOT:**
- Include raw conversation excerpts (synthesize instead)
- Paste full file contents
- Add meta-commentary ("I searched and found...")
- Exceed 1000 words in Summary section
- Return search results verbatim
## Example Output
```
### Summary
developer needed to handle authentication errors in React Router 7 data loaders
without crashing the app. The solution uses RR7's errorElement + useRouteError()
to catch 401s and redirect to login.
**Key implementation:**
Protected route wrapper catches loader errors, checks error.status === 401.
If 401, redirects to /login with return URL. Otherwise shows error boundary.
**Why this works:**
Loaders can't use hooks (tried useNavigate, failed). Throwing redirect()
bypasses error handling. Final approach lets errors bubble to errorElement
where component context is available.
**Critical gotchas:**
- Test with expired tokens, not just missing tokens
- Error boundaries need unique keys per route or won't reset
- Always include return URL in redirect
- Loaders execute before components, no hook access
**Code pattern:**
```typescript
// In loader
if (!response.ok) throw { status: response.status, message: 'Failed' };
// In ErrorBoundary
const error = useRouteError();
if (error.status === 401) navigate('/login?return=' + location.pathname);
```
### Sources
**1. [react-router-7-starter, 2024-09-17]** - 92% match
Conversation summary: Built authentication system with JWT, implemented protected routes
File: ~/.clank/conversation-archive/react-router-7-starter/19df92b9.jsonl:145-289
Status: Read in detail (multiple exchanges on error handling evolution)
**2. [react-router-docs-reading, 2024-09-10]** - 78% match
Conversation summary: Read RR7 docs, discussed new loader patterns and errorElement
File: ~/.clank/conversation-archive/react-router-docs-reading/a3c871f2.jsonl:56-98
Status: Reviewed summary only (confirmed errorElement usage)
**3. [auth-debugging, 2024-09-18]** - 73% match
Conversation summary: Fixed token expiration handling and error boundary reset issues
File: ~/.clank/conversation-archive/react-router-7-starter/7b2e8d91.jsonl:201-345
Status: Read in detail (discovered gotchas about keys and expired tokens)
### For Follow-Up
Main agent can ask me to:
- Dig deeper into source #1 (full error handling evolution)
- Read adjacent exchanges in #3 (more debugging context)
- Search for "React Router error boundary patterns" more broadly
```
This output:
- Synthesis: ~350 words (actionable, specific)
- Sources: Full metadata for 3 conversations
- Enables iteration without context bloat

View File

@@ -1,105 +0,0 @@
#!/bin/bash
cd "$(dirname "$0")"
# Parse arguments
MODE="vector"
AFTER=""
BEFORE=""
LIMIT="10"
QUERY=""
while [[ $# -gt 0 ]]; do
case $1 in
--help|-h)
cat <<'EOF'
search-conversations - Search previous Claude Code conversations
USAGE:
search-conversations [OPTIONS] <query>
MODES:
(default) Vector similarity search (semantic)
--text Exact string matching (for git SHAs, error codes)
--both Combine vector + text search
OPTIONS:
--after DATE Only conversations after YYYY-MM-DD
--before DATE Only conversations before YYYY-MM-DD
--limit N Max results (default: 10)
--help, -h Show this help
EXAMPLES:
# Semantic search
search-conversations "React Router authentication errors"
# Find exact string (git SHA, error message)
search-conversations --text "a1b2c3d4e5f6"
# Time filtering
search-conversations --after 2025-09-01 "refactoring"
search-conversations --before 2025-10-01 --limit 20 "bug fix"
# Combine modes
search-conversations --both "React Router data loading"
OUTPUT FORMAT:
For each result:
- Project name and date
- Conversation summary (AI-generated)
- Matched exchange with similarity % (vector mode)
- File path with line numbers
Example:
1. [react-router-7-starter, 2025-09-17]
Built authentication with JWT, implemented protected routes.
92% match: "How do I handle auth errors in loaders?"
~/.clank/conversation-archive/.../uuid.jsonl:145-167
QUERY TIPS:
- Use natural language: "How did we handle X?"
- Be specific: "React Router data loading" not "routing"
- Include context: "TypeScript type narrowing in guards"
SEE ALSO:
skills/collaboration/remembering-conversations/INDEXING.md - Manage index
skills/collaboration/remembering-conversations/SKILL.md - Usage guide
EOF
exit 0
;;
--text)
MODE="text"
shift
;;
--both)
MODE="both"
shift
;;
--after)
AFTER="$2"
shift 2
;;
--before)
BEFORE="$2"
shift 2
;;
--limit)
LIMIT="$2"
shift 2
;;
*)
QUERY="$QUERY $1"
shift
;;
esac
done
QUERY=$(echo "$QUERY" | sed 's/^ *//')
if [ -z "$QUERY" ]; then
echo "Usage: search-conversations [options] <query>"
echo "Try: search-conversations --help"
exit 1
fi
npx tsx src/search-cli.ts "$QUERY" "$MODE" "$LIMIT" "$AFTER" "$BEFORE"

View File

@@ -1,112 +0,0 @@
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { initDatabase, migrateSchema, insertExchange } from './db.js';
import { ConversationExchange } from './types.js';
import fs from 'fs';
import path from 'path';
import os from 'os';
import Database from 'better-sqlite3';
describe('database migration', () => {
const testDir = path.join(os.tmpdir(), 'db-migration-test-' + Date.now());
const dbPath = path.join(testDir, 'test.db');
beforeEach(() => {
fs.mkdirSync(testDir, { recursive: true });
process.env.TEST_DB_PATH = dbPath;
});
afterEach(() => {
delete process.env.TEST_DB_PATH;
fs.rmSync(testDir, { recursive: true, force: true });
});
it('adds last_indexed column to existing database', () => {
// Create a database with old schema (no last_indexed)
const db = new Database(dbPath);
db.exec(`
CREATE TABLE exchanges (
id TEXT PRIMARY KEY,
project TEXT NOT NULL,
timestamp TEXT NOT NULL,
user_message TEXT NOT NULL,
assistant_message TEXT NOT NULL,
archive_path TEXT NOT NULL,
line_start INTEGER NOT NULL,
line_end INTEGER NOT NULL,
embedding BLOB
)
`);
// Verify column doesn't exist
const columnsBefore = db.prepare(`PRAGMA table_info(exchanges)`).all();
const hasLastIndexedBefore = columnsBefore.some((col: any) => col.name === 'last_indexed');
expect(hasLastIndexedBefore).toBe(false);
db.close();
// Run migration
const migratedDb = initDatabase();
// Verify column now exists
const columnsAfter = migratedDb.prepare(`PRAGMA table_info(exchanges)`).all();
const hasLastIndexedAfter = columnsAfter.some((col: any) => col.name === 'last_indexed');
expect(hasLastIndexedAfter).toBe(true);
migratedDb.close();
});
it('handles existing last_indexed column gracefully', () => {
// Create database with migration already applied
const db = initDatabase();
// Run migration again - should not error
expect(() => migrateSchema(db)).not.toThrow();
db.close();
});
});
describe('insertExchange with last_indexed', () => {
const testDir = path.join(os.tmpdir(), 'insert-test-' + Date.now());
const dbPath = path.join(testDir, 'test.db');
beforeEach(() => {
fs.mkdirSync(testDir, { recursive: true });
process.env.TEST_DB_PATH = dbPath;
});
afterEach(() => {
delete process.env.TEST_DB_PATH;
fs.rmSync(testDir, { recursive: true, force: true });
});
it('sets last_indexed timestamp when inserting exchange', () => {
const db = initDatabase();
const exchange: ConversationExchange = {
id: 'test-id-1',
project: 'test-project',
timestamp: '2024-01-01T00:00:00Z',
userMessage: 'Hello',
assistantMessage: 'Hi there!',
archivePath: '/test/path.jsonl',
lineStart: 1,
lineEnd: 2
};
const beforeInsert = Date.now();
// Create proper 384-dimensional embedding
const embedding = new Array(384).fill(0.1);
insertExchange(db, exchange, embedding);
const afterInsert = Date.now();
// Query the exchange
const row = db.prepare(`SELECT last_indexed FROM exchanges WHERE id = ?`).get('test-id-1') as any;
expect(row.last_indexed).toBeDefined();
expect(row.last_indexed).toBeGreaterThanOrEqual(beforeInsert);
expect(row.last_indexed).toBeLessThanOrEqual(afterInsert);
db.close();
});
});

View File

@@ -1,130 +0,0 @@
import Database from 'better-sqlite3';
import { ConversationExchange } from './types.js';
import path from 'path';
import fs from 'fs';
import * as sqliteVec from 'sqlite-vec';
import { getDbPath } from './paths.js';
export function migrateSchema(db: Database.Database): void {
const hasColumn = db.prepare(`
SELECT COUNT(*) as count FROM pragma_table_info('exchanges')
WHERE name='last_indexed'
`).get() as { count: number };
if (hasColumn.count === 0) {
console.log('Migrating schema: adding last_indexed column...');
db.prepare('ALTER TABLE exchanges ADD COLUMN last_indexed INTEGER').run();
console.log('Migration complete.');
}
}
export function initDatabase(): Database.Database {
const dbPath = getDbPath();
// Ensure directory exists
const dbDir = path.dirname(dbPath);
if (!fs.existsSync(dbDir)) {
fs.mkdirSync(dbDir, { recursive: true });
}
const db = new Database(dbPath);
// Load sqlite-vec extension
sqliteVec.load(db);
// Enable WAL mode for better concurrency
db.pragma('journal_mode = WAL');
// Create exchanges table
db.exec(`
CREATE TABLE IF NOT EXISTS exchanges (
id TEXT PRIMARY KEY,
project TEXT NOT NULL,
timestamp TEXT NOT NULL,
user_message TEXT NOT NULL,
assistant_message TEXT NOT NULL,
archive_path TEXT NOT NULL,
line_start INTEGER NOT NULL,
line_end INTEGER NOT NULL,
embedding BLOB
)
`);
// Create vector search index
db.exec(`
CREATE VIRTUAL TABLE IF NOT EXISTS vec_exchanges USING vec0(
id TEXT PRIMARY KEY,
embedding FLOAT[384]
)
`);
// Create index on timestamp for sorting
db.exec(`
CREATE INDEX IF NOT EXISTS idx_timestamp ON exchanges(timestamp DESC)
`);
// Run migrations
migrateSchema(db);
return db;
}
export function insertExchange(
db: Database.Database,
exchange: ConversationExchange,
embedding: number[]
): void {
const now = Date.now();
const stmt = db.prepare(`
INSERT OR REPLACE INTO exchanges
(id, project, timestamp, user_message, assistant_message, archive_path, line_start, line_end, last_indexed)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
stmt.run(
exchange.id,
exchange.project,
exchange.timestamp,
exchange.userMessage,
exchange.assistantMessage,
exchange.archivePath,
exchange.lineStart,
exchange.lineEnd,
now
);
// Insert into vector table (delete first since virtual tables don't support REPLACE)
const delStmt = db.prepare(`DELETE FROM vec_exchanges WHERE id = ?`);
delStmt.run(exchange.id);
const vecStmt = db.prepare(`
INSERT INTO vec_exchanges (id, embedding)
VALUES (?, ?)
`);
vecStmt.run(exchange.id, Buffer.from(new Float32Array(embedding).buffer));
}
export function getAllExchanges(db: Database.Database): Array<{ id: string; archivePath: string }> {
const stmt = db.prepare(`SELECT id, archive_path as archivePath FROM exchanges`);
return stmt.all() as Array<{ id: string; archivePath: string }>;
}
export function getFileLastIndexed(db: Database.Database, archivePath: string): number | null {
const stmt = db.prepare(`
SELECT MAX(last_indexed) as lastIndexed
FROM exchanges
WHERE archive_path = ?
`);
const row = stmt.get(archivePath) as { lastIndexed: number | null };
return row.lastIndexed;
}
export function deleteExchange(db: Database.Database, id: string): void {
// Delete from vector table
db.prepare(`DELETE FROM vec_exchanges WHERE id = ?`).run(id);
// Delete from main table
db.prepare(`DELETE FROM exchanges WHERE id = ?`).run(id);
}

View File

@@ -1,39 +0,0 @@
import { pipeline, Pipeline } from '@xenova/transformers';
let embeddingPipeline: Pipeline | null = null;
export async function initEmbeddings(): Promise<void> {
if (!embeddingPipeline) {
console.log('Loading embedding model (first run may take time)...');
embeddingPipeline = await pipeline(
'feature-extraction',
'Xenova/all-MiniLM-L6-v2'
);
console.log('Embedding model loaded');
}
}
export async function generateEmbedding(text: string): Promise<number[]> {
if (!embeddingPipeline) {
await initEmbeddings();
}
// Truncate text to avoid token limits (512 tokens max for this model)
const truncated = text.substring(0, 2000);
const output = await embeddingPipeline!(truncated, {
pooling: 'mean',
normalize: true
});
return Array.from(output.data);
}
export async function generateExchangeEmbedding(
userMessage: string,
assistantMessage: string
): Promise<number[]> {
// Combine user question and assistant answer for better searchability
const combined = `User: ${userMessage}\n\nAssistant: ${assistantMessage}`;
return generateEmbedding(combined);
}

View File

@@ -1,121 +0,0 @@
#!/usr/bin/env node
import { verifyIndex, repairIndex } from './verify.js';
import { indexSession, indexUnprocessed, indexConversations } from './indexer.js';
import { initDatabase } from './db.js';
import { getDbPath, getArchiveDir } from './paths.js';
import fs from 'fs';
import path from 'path';
const command = process.argv[2];
// Parse --concurrency flag from remaining args
function getConcurrency(): number {
const concurrencyIndex = process.argv.findIndex(arg => arg === '--concurrency' || arg === '-c');
if (concurrencyIndex !== -1 && process.argv[concurrencyIndex + 1]) {
const value = parseInt(process.argv[concurrencyIndex + 1], 10);
if (value >= 1 && value <= 16) return value;
}
return 1; // default
}
// Parse --no-summaries flag
function getNoSummaries(): boolean {
return process.argv.includes('--no-summaries');
}
const concurrency = getConcurrency();
const noSummaries = getNoSummaries();
async function main() {
try {
switch (command) {
case 'index-session':
const sessionId = process.argv[3];
if (!sessionId) {
console.error('Usage: index-cli index-session <session-id>');
process.exit(1);
}
await indexSession(sessionId, concurrency, noSummaries);
break;
case 'index-cleanup':
await indexUnprocessed(concurrency, noSummaries);
break;
case 'verify':
console.log('Verifying conversation index...');
const issues = await verifyIndex();
console.log('\n=== Verification Results ===');
console.log(`Missing summaries: ${issues.missing.length}`);
console.log(`Orphaned entries: ${issues.orphaned.length}`);
console.log(`Outdated files: ${issues.outdated.length}`);
console.log(`Corrupted files: ${issues.corrupted.length}`);
if (issues.missing.length > 0) {
console.log('\nMissing summaries:');
issues.missing.forEach(m => console.log(` ${m.path}`));
}
if (issues.missing.length + issues.orphaned.length + issues.outdated.length + issues.corrupted.length > 0) {
console.log('\nRun with --repair to fix these issues.');
process.exit(1);
} else {
console.log('\n✅ Index is healthy!');
}
break;
case 'repair':
console.log('Verifying conversation index...');
const repairIssues = await verifyIndex();
if (repairIssues.missing.length + repairIssues.orphaned.length + repairIssues.outdated.length > 0) {
await repairIndex(repairIssues);
} else {
console.log('✅ No issues to repair!');
}
break;
case 'rebuild':
console.log('Rebuilding entire index...');
// Delete database
const dbPath = getDbPath();
if (fs.existsSync(dbPath)) {
fs.unlinkSync(dbPath);
console.log('Deleted existing database');
}
// Delete all summary files
const archiveDir = getArchiveDir();
if (fs.existsSync(archiveDir)) {
const projects = fs.readdirSync(archiveDir);
for (const project of projects) {
const projectPath = path.join(archiveDir, project);
if (!fs.statSync(projectPath).isDirectory()) continue;
const summaries = fs.readdirSync(projectPath).filter(f => f.endsWith('-summary.txt'));
for (const summary of summaries) {
fs.unlinkSync(path.join(projectPath, summary));
}
}
console.log('Deleted all summary files');
}
// Re-index everything
console.log('Re-indexing all conversations...');
await indexConversations(undefined, undefined, concurrency, noSummaries);
break;
case 'index-all':
default:
await indexConversations(undefined, undefined, concurrency, noSummaries);
break;
}
} catch (error) {
console.error('Error:', error);
process.exit(1);
}
}
main();

View File

@@ -1,374 +0,0 @@
import fs from 'fs';
import path from 'path';
import os from 'os';
import { initDatabase, insertExchange } from './db.js';
import { parseConversation } from './parser.js';
import { initEmbeddings, generateExchangeEmbedding } from './embeddings.js';
import { summarizeConversation } from './summarizer.js';
import { ConversationExchange } from './types.js';
import { getArchiveDir, getExcludeConfigPath } from './paths.js';
// Set max output tokens for Claude SDK (used by summarizer)
process.env.CLAUDE_CODE_MAX_OUTPUT_TOKENS = '20000';
// Increase max listeners for concurrent API calls
import { EventEmitter } from 'events';
EventEmitter.defaultMaxListeners = 20;
// Allow overriding paths for testing
function getProjectsDir(): string {
return process.env.TEST_PROJECTS_DIR || path.join(os.homedir(), '.claude', 'projects');
}
// Projects to exclude from indexing (configurable via env or config file)
function getExcludedProjects(): string[] {
// Check env variable first
if (process.env.CONVERSATION_SEARCH_EXCLUDE_PROJECTS) {
return process.env.CONVERSATION_SEARCH_EXCLUDE_PROJECTS.split(',').map(p => p.trim());
}
// Check for config file
const configPath = getExcludeConfigPath();
if (fs.existsSync(configPath)) {
const content = fs.readFileSync(configPath, 'utf-8');
return content.split('\n').map(line => line.trim()).filter(line => line && !line.startsWith('#'));
}
// Default: no exclusions
return [];
}
// Process items in batches with limited concurrency
async function processBatch<T, R>(
items: T[],
processor: (item: T) => Promise<R>,
concurrency: number
): Promise<R[]> {
const results: R[] = [];
for (let i = 0; i < items.length; i += concurrency) {
const batch = items.slice(i, i + concurrency);
const batchResults = await Promise.all(batch.map(processor));
results.push(...batchResults);
}
return results;
}
export async function indexConversations(
limitToProject?: string,
maxConversations?: number,
concurrency: number = 1,
noSummaries: boolean = false
): Promise<void> {
console.log('Initializing database...');
const db = initDatabase();
console.log('Loading embedding model...');
await initEmbeddings();
if (noSummaries) {
console.log('⚠️ Running in no-summaries mode (skipping AI summaries)');
}
console.log('Scanning for conversation files...');
const PROJECTS_DIR = getProjectsDir();
const ARCHIVE_DIR = getArchiveDir(); // Now uses paths.ts
const projects = fs.readdirSync(PROJECTS_DIR);
let totalExchanges = 0;
let conversationsProcessed = 0;
const excludedProjects = getExcludedProjects();
for (const project of projects) {
// Skip excluded projects
if (excludedProjects.includes(project)) {
console.log(`\nSkipping excluded project: ${project}`);
continue;
}
// Skip if limiting to specific project
if (limitToProject && project !== limitToProject) continue;
const projectPath = path.join(PROJECTS_DIR, project);
const stat = fs.statSync(projectPath);
if (!stat.isDirectory()) continue;
const files = fs.readdirSync(projectPath).filter(f => f.endsWith('.jsonl'));
if (files.length === 0) continue;
console.log(`\nProcessing project: ${project} (${files.length} conversations)`);
if (concurrency > 1) console.log(` Concurrency: ${concurrency}`);
// Create archive directory for this project
const projectArchive = path.join(ARCHIVE_DIR, project);
fs.mkdirSync(projectArchive, { recursive: true });
// Prepare all conversations first
type ConvToProcess = {
file: string;
sourcePath: string;
archivePath: string;
summaryPath: string;
exchanges: ConversationExchange[];
};
const toProcess: ConvToProcess[] = [];
for (const file of files) {
const sourcePath = path.join(projectPath, file);
const archivePath = path.join(projectArchive, file);
// Copy to archive
if (!fs.existsSync(archivePath)) {
fs.copyFileSync(sourcePath, archivePath);
console.log(` Archived: ${file}`);
}
// Parse conversation
const exchanges = await parseConversation(sourcePath, project, archivePath);
if (exchanges.length === 0) {
console.log(` Skipped ${file} (no exchanges)`);
continue;
}
toProcess.push({
file,
sourcePath,
archivePath,
summaryPath: archivePath.replace('.jsonl', '-summary.txt'),
exchanges
});
}
// Batch summarize conversations in parallel (unless --no-summaries)
if (!noSummaries) {
const needsSummary = toProcess.filter(c => !fs.existsSync(c.summaryPath));
if (needsSummary.length > 0) {
console.log(` Generating ${needsSummary.length} summaries (concurrency: ${concurrency})...`);
await processBatch(needsSummary, async (conv) => {
try {
const summary = await summarizeConversation(conv.exchanges);
fs.writeFileSync(conv.summaryPath, summary, 'utf-8');
const wordCount = summary.split(/\s+/).length;
console.log(`${conv.file}: ${wordCount} words`);
return summary;
} catch (error) {
console.log(`${conv.file}: ${error}`);
return null;
}
}, concurrency);
}
} else {
console.log(` Skipping ${toProcess.length} summaries (--no-summaries mode)`);
}
// Now process embeddings and DB inserts (fast, sequential is fine)
for (const conv of toProcess) {
for (const exchange of conv.exchanges) {
const embedding = await generateExchangeEmbedding(
exchange.userMessage,
exchange.assistantMessage
);
insertExchange(db, exchange, embedding);
}
totalExchanges += conv.exchanges.length;
conversationsProcessed++;
// Check if we hit the limit
if (maxConversations && conversationsProcessed >= maxConversations) {
console.log(`\nReached limit of ${maxConversations} conversations`);
db.close();
console.log(`✅ Indexing complete! Conversations: ${conversationsProcessed}, Exchanges: ${totalExchanges}`);
return;
}
}
}
db.close();
console.log(`\n✅ Indexing complete! Conversations: ${conversationsProcessed}, Exchanges: ${totalExchanges}`);
}
export async function indexSession(sessionId: string, concurrency: number = 1, noSummaries: boolean = false): Promise<void> {
console.log(`Indexing session: ${sessionId}`);
// Find the conversation file for this session
const PROJECTS_DIR = getProjectsDir();
const ARCHIVE_DIR = getArchiveDir(); // Now uses paths.ts
const projects = fs.readdirSync(PROJECTS_DIR);
const excludedProjects = getExcludedProjects();
let found = false;
for (const project of projects) {
if (excludedProjects.includes(project)) continue;
const projectPath = path.join(PROJECTS_DIR, project);
if (!fs.statSync(projectPath).isDirectory()) continue;
const files = fs.readdirSync(projectPath).filter(f => f.includes(sessionId) && f.endsWith('.jsonl'));
if (files.length > 0) {
found = true;
const file = files[0];
const sourcePath = path.join(projectPath, file);
const db = initDatabase();
await initEmbeddings();
const projectArchive = path.join(ARCHIVE_DIR, project);
fs.mkdirSync(projectArchive, { recursive: true });
const archivePath = path.join(projectArchive, file);
// Archive
if (!fs.existsSync(archivePath)) {
fs.copyFileSync(sourcePath, archivePath);
}
// Parse and summarize
const exchanges = await parseConversation(sourcePath, project, archivePath);
if (exchanges.length > 0) {
// Generate summary (unless --no-summaries)
const summaryPath = archivePath.replace('.jsonl', '-summary.txt');
if (!noSummaries && !fs.existsSync(summaryPath)) {
const summary = await summarizeConversation(exchanges);
fs.writeFileSync(summaryPath, summary, 'utf-8');
console.log(`Summary: ${summary.split(/\s+/).length} words`);
}
// Index
for (const exchange of exchanges) {
const embedding = await generateExchangeEmbedding(
exchange.userMessage,
exchange.assistantMessage
);
insertExchange(db, exchange, embedding);
}
console.log(`✅ Indexed session ${sessionId}: ${exchanges.length} exchanges`);
}
db.close();
break;
}
}
if (!found) {
console.log(`Session ${sessionId} not found`);
}
}
export async function indexUnprocessed(concurrency: number = 1, noSummaries: boolean = false): Promise<void> {
console.log('Finding unprocessed conversations...');
if (concurrency > 1) console.log(`Concurrency: ${concurrency}`);
if (noSummaries) console.log('⚠️ Running in no-summaries mode (skipping AI summaries)');
const db = initDatabase();
await initEmbeddings();
const PROJECTS_DIR = getProjectsDir();
const ARCHIVE_DIR = getArchiveDir(); // Now uses paths.ts
const projects = fs.readdirSync(PROJECTS_DIR);
const excludedProjects = getExcludedProjects();
type UnprocessedConv = {
project: string;
file: string;
sourcePath: string;
archivePath: string;
summaryPath: string;
exchanges: ConversationExchange[];
};
const unprocessed: UnprocessedConv[] = [];
// Collect all unprocessed conversations
for (const project of projects) {
if (excludedProjects.includes(project)) continue;
const projectPath = path.join(PROJECTS_DIR, project);
if (!fs.statSync(projectPath).isDirectory()) continue;
const files = fs.readdirSync(projectPath).filter(f => f.endsWith('.jsonl'));
for (const file of files) {
const sourcePath = path.join(projectPath, file);
const projectArchive = path.join(ARCHIVE_DIR, project);
const archivePath = path.join(projectArchive, file);
const summaryPath = archivePath.replace('.jsonl', '-summary.txt');
// Check if already indexed in database
const alreadyIndexed = db.prepare('SELECT COUNT(*) as count FROM exchanges WHERE archive_path = ?')
.get(archivePath) as { count: number };
if (alreadyIndexed.count > 0) continue;
fs.mkdirSync(projectArchive, { recursive: true });
// Archive if needed
if (!fs.existsSync(archivePath)) {
fs.copyFileSync(sourcePath, archivePath);
}
// Parse and check
const exchanges = await parseConversation(sourcePath, project, archivePath);
if (exchanges.length === 0) continue;
unprocessed.push({ project, file, sourcePath, archivePath, summaryPath, exchanges });
}
}
if (unprocessed.length === 0) {
console.log('✅ All conversations are already processed!');
db.close();
return;
}
console.log(`Found ${unprocessed.length} unprocessed conversations`);
// Batch process summaries (unless --no-summaries)
if (!noSummaries) {
const needsSummary = unprocessed.filter(c => !fs.existsSync(c.summaryPath));
if (needsSummary.length > 0) {
console.log(`Generating ${needsSummary.length} summaries (concurrency: ${concurrency})...\n`);
await processBatch(needsSummary, async (conv) => {
try {
const summary = await summarizeConversation(conv.exchanges);
fs.writeFileSync(conv.summaryPath, summary, 'utf-8');
const wordCount = summary.split(/\s+/).length;
console.log(`${conv.project}/${conv.file}: ${wordCount} words`);
return summary;
} catch (error) {
console.log(`${conv.project}/${conv.file}: ${error}`);
return null;
}
}, concurrency);
}
} else {
console.log(`Skipping summaries for ${unprocessed.length} conversations (--no-summaries mode)\n`);
}
// Now index embeddings
console.log(`\nIndexing embeddings...`);
for (const conv of unprocessed) {
for (const exchange of conv.exchanges) {
const embedding = await generateExchangeEmbedding(
exchange.userMessage,
exchange.assistantMessage
);
insertExchange(db, exchange, embedding);
}
}
db.close();
console.log(`\n✅ Processed ${unprocessed.length} conversations`);
}

View File

@@ -1,118 +0,0 @@
import fs from 'fs';
import readline from 'readline';
import { ConversationExchange } from './types.js';
import crypto from 'crypto';
interface JSONLMessage {
type: string;
message?: {
role: 'user' | 'assistant';
content: string | Array<{ type: string; text?: string }>;
};
timestamp?: string;
uuid?: string;
}
export async function parseConversation(
filePath: string,
projectName: string,
archivePath: string
): Promise<ConversationExchange[]> {
const exchanges: ConversationExchange[] = [];
const fileStream = fs.createReadStream(filePath);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
let lineNumber = 0;
let currentExchange: {
userMessage: string;
userLine: number;
assistantMessages: string[];
lastAssistantLine: number;
timestamp: string;
} | null = null;
const finalizeExchange = () => {
if (currentExchange && currentExchange.assistantMessages.length > 0) {
const exchange: ConversationExchange = {
id: crypto
.createHash('md5')
.update(`${archivePath}:${currentExchange.userLine}-${currentExchange.lastAssistantLine}`)
.digest('hex'),
project: projectName,
timestamp: currentExchange.timestamp,
userMessage: currentExchange.userMessage,
assistantMessage: currentExchange.assistantMessages.join('\n\n'),
archivePath,
lineStart: currentExchange.userLine,
lineEnd: currentExchange.lastAssistantLine
};
exchanges.push(exchange);
}
};
for await (const line of rl) {
lineNumber++;
try {
const parsed: JSONLMessage = JSON.parse(line);
// Skip non-message types
if (parsed.type !== 'user' && parsed.type !== 'assistant') {
continue;
}
if (!parsed.message) {
continue;
}
// Extract text from message content
let text = '';
if (typeof parsed.message.content === 'string') {
text = parsed.message.content;
} else if (Array.isArray(parsed.message.content)) {
text = parsed.message.content
.filter(block => block.type === 'text' && block.text)
.map(block => block.text)
.join('\n');
}
// Skip empty messages
if (!text.trim()) {
continue;
}
if (parsed.message.role === 'user') {
// Finalize previous exchange before starting new one
finalizeExchange();
// Start new exchange
currentExchange = {
userMessage: text,
userLine: lineNumber,
assistantMessages: [],
lastAssistantLine: lineNumber,
timestamp: parsed.timestamp || new Date().toISOString()
};
} else if (parsed.message.role === 'assistant' && currentExchange) {
// Accumulate assistant messages
currentExchange.assistantMessages.push(text);
currentExchange.lastAssistantLine = lineNumber;
// Update timestamp to last assistant message
if (parsed.timestamp) {
currentExchange.timestamp = parsed.timestamp;
}
}
} catch (error) {
// Skip malformed JSON lines
continue;
}
}
// Finalize last exchange
finalizeExchange();
return exchanges;
}

View File

@@ -1,56 +0,0 @@
import os from 'os';
import path from 'path';
/**
* Get the personal superpowers directory
*
* Precedence:
* 1. PERSONAL_SUPERPOWERS_DIR env var (if set)
* 2. XDG_CONFIG_HOME/superpowers (if XDG_CONFIG_HOME is set)
* 3. ~/.config/superpowers (default)
*/
export function getSuperpowersDir(): string {
if (process.env.PERSONAL_SUPERPOWERS_DIR) {
return process.env.PERSONAL_SUPERPOWERS_DIR;
}
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
if (xdgConfigHome) {
return path.join(xdgConfigHome, 'superpowers');
}
return path.join(os.homedir(), '.config', 'superpowers');
}
/**
* Get conversation archive directory
*/
export function getArchiveDir(): string {
// Allow test override
if (process.env.TEST_ARCHIVE_DIR) {
return process.env.TEST_ARCHIVE_DIR;
}
return path.join(getSuperpowersDir(), 'conversation-archive');
}
/**
* Get conversation index directory
*/
export function getIndexDir(): string {
return path.join(getSuperpowersDir(), 'conversation-index');
}
/**
* Get database path
*/
export function getDbPath(): string {
return path.join(getIndexDir(), 'db.sqlite');
}
/**
* Get exclude config path
*/
export function getExcludeConfigPath(): string {
return path.join(getIndexDir(), 'exclude.txt');
}

View File

@@ -1,109 +0,0 @@
import { describe, it, expect } from 'vitest';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
describe('search-agent template', () => {
const templatePath = path.join(__dirname, '..', 'prompts', 'search-agent.md');
it('exists at expected location', () => {
expect(fs.existsSync(templatePath)).toBe(true);
});
it('contains required placeholders', () => {
const content = fs.readFileSync(templatePath, 'utf-8');
// Check for all required placeholders
expect(content).toContain('{TOPIC}');
expect(content).toContain('{SEARCH_QUERY}');
expect(content).toContain('{FOCUS_AREAS}');
});
it('contains required output sections', () => {
const content = fs.readFileSync(templatePath, 'utf-8');
// Check for required output format sections
expect(content).toContain('### Summary');
expect(content).toContain('### Sources');
expect(content).toContain('### For Follow-Up');
});
it('specifies word count requirements', () => {
const content = fs.readFileSync(templatePath, 'utf-8');
// Should specify 200-1000 words for synthesis
expect(content).toMatch(/200-1000 words/);
expect(content).toMatch(/max 1000 words/);
});
it('includes source metadata requirements', () => {
const content = fs.readFileSync(templatePath, 'utf-8');
// Check for source metadata fields
expect(content).toContain('project-name');
expect(content).toContain('YYYY-MM-DD');
expect(content).toContain('% match');
expect(content).toContain('Conversation summary:');
expect(content).toContain('File:');
expect(content).toContain('Status:');
expect(content).toContain('Read in detail');
expect(content).toContain('Reviewed summary only');
expect(content).toContain('Skimmed');
});
it('provides search command', () => {
const content = fs.readFileSync(templatePath, 'utf-8');
// Should include the search command
expect(content).toContain('~/.claude/skills/collaboration/remembering-conversations/tool/search-conversations');
});
it('includes critical rules', () => {
const content = fs.readFileSync(templatePath, 'utf-8');
// Check for DO and DO NOT sections
expect(content).toContain('## Critical Rules');
expect(content).toContain('**DO:**');
expect(content).toContain('**DO NOT:**');
});
it('includes complete example output', () => {
const content = fs.readFileSync(templatePath, 'utf-8');
// Check example has all required components
expect(content).toContain('## Example Output');
// Example should show Summary, Sources, and For Follow-Up
const exampleSection = content.substring(content.indexOf('## Example Output'));
expect(exampleSection).toContain('### Summary');
expect(exampleSection).toContain('### Sources');
expect(exampleSection).toContain('### For Follow-Up');
// Example should show specific details
expect(exampleSection).toContain('react-router-7-starter');
expect(exampleSection).toContain('92% match');
expect(exampleSection).toContain('.jsonl');
});
it('emphasizes synthesis over raw excerpts', () => {
const content = fs.readFileSync(templatePath, 'utf-8');
// Should explicitly discourage raw conversation excerpts
expect(content).toContain('synthesize');
expect(content).toContain('raw conversation excerpts');
expect(content).toContain('synthesize instead');
});
it('provides follow-up options', () => {
const content = fs.readFileSync(templatePath, 'utf-8');
// Should explain how main agent can follow up
expect(content).toContain('Main agent can:');
expect(content).toContain('dig deeper');
expect(content).toContain('refined query');
expect(content).toContain('context bloat');
});
});

View File

@@ -1,28 +0,0 @@
import { searchConversations, formatResults, SearchOptions } from './search.js';
const query = process.argv[2];
const mode = (process.argv[3] || 'vector') as 'vector' | 'text' | 'both';
const limit = parseInt(process.argv[4] || '10');
const after = process.argv[5] || undefined;
const before = process.argv[6] || undefined;
if (!query) {
console.error('Usage: search-conversations <query> [mode] [limit] [after] [before]');
process.exit(1);
}
const options: SearchOptions = {
mode,
limit,
after,
before
};
searchConversations(query, options)
.then(results => {
console.log(formatResults(results));
})
.catch(error => {
console.error('Error searching:', error);
process.exit(1);
});

View File

@@ -1,173 +0,0 @@
import Database from 'better-sqlite3';
import { initDatabase } from './db.js';
import { initEmbeddings, generateEmbedding } from './embeddings.js';
import { SearchResult, ConversationExchange } from './types.js';
import fs from 'fs';
export interface SearchOptions {
limit?: number;
mode?: 'vector' | 'text' | 'both';
after?: string; // ISO date string
before?: string; // ISO date string
}
function validateISODate(dateStr: string, paramName: string): void {
const isoDateRegex = /^\d{4}-\d{2}-\d{2}$/;
if (!isoDateRegex.test(dateStr)) {
throw new Error(`Invalid ${paramName} date: "${dateStr}". Expected YYYY-MM-DD format (e.g., 2025-10-01)`);
}
// Verify it's actually a valid date
const date = new Date(dateStr);
if (isNaN(date.getTime())) {
throw new Error(`Invalid ${paramName} date: "${dateStr}". Not a valid calendar date.`);
}
}
export async function searchConversations(
query: string,
options: SearchOptions = {}
): Promise<SearchResult[]> {
const { limit = 10, mode = 'vector', after, before } = options;
// Validate date parameters
if (after) validateISODate(after, '--after');
if (before) validateISODate(before, '--before');
const db = initDatabase();
let results: any[] = [];
// Build time filter clause
const timeFilter = [];
if (after) timeFilter.push(`e.timestamp >= '${after}'`);
if (before) timeFilter.push(`e.timestamp <= '${before}'`);
const timeClause = timeFilter.length > 0 ? `AND ${timeFilter.join(' AND ')}` : '';
if (mode === 'vector' || mode === 'both') {
// Vector similarity search
await initEmbeddings();
const queryEmbedding = await generateEmbedding(query);
const stmt = db.prepare(`
SELECT
e.id,
e.project,
e.timestamp,
e.user_message,
e.assistant_message,
e.archive_path,
e.line_start,
e.line_end,
vec.distance
FROM vec_exchanges AS vec
JOIN exchanges AS e ON vec.id = e.id
WHERE vec.embedding MATCH ?
AND k = ?
${timeClause}
ORDER BY vec.distance ASC
`);
results = stmt.all(
Buffer.from(new Float32Array(queryEmbedding).buffer),
limit
);
}
if (mode === 'text' || mode === 'both') {
// Text search
const textStmt = db.prepare(`
SELECT
e.id,
e.project,
e.timestamp,
e.user_message,
e.assistant_message,
e.archive_path,
e.line_start,
e.line_end,
0 as distance
FROM exchanges AS e
WHERE (e.user_message LIKE ? OR e.assistant_message LIKE ?)
${timeClause}
ORDER BY e.timestamp DESC
LIMIT ?
`);
const textResults = textStmt.all(`%${query}%`, `%${query}%`, limit);
if (mode === 'both') {
// Merge and deduplicate by ID
const seenIds = new Set(results.map(r => r.id));
for (const textResult of textResults) {
if (!seenIds.has(textResult.id)) {
results.push(textResult);
}
}
} else {
results = textResults;
}
}
db.close();
return results.map((row: any) => {
const exchange: ConversationExchange = {
id: row.id,
project: row.project,
timestamp: row.timestamp,
userMessage: row.user_message,
assistantMessage: row.assistant_message,
archivePath: row.archive_path,
lineStart: row.line_start,
lineEnd: row.line_end
};
// Try to load summary if available
const summaryPath = row.archive_path.replace('.jsonl', '-summary.txt');
let summary: string | undefined;
if (fs.existsSync(summaryPath)) {
summary = fs.readFileSync(summaryPath, 'utf-8').trim();
}
// Create snippet (first 200 chars)
const snippet = exchange.userMessage.substring(0, 200) +
(exchange.userMessage.length > 200 ? '...' : '');
return {
exchange,
similarity: mode === 'text' ? undefined : 1 - row.distance,
snippet,
summary
} as SearchResult & { summary?: string };
});
}
export function formatResults(results: Array<SearchResult & { summary?: string }>): string {
if (results.length === 0) {
return 'No results found.';
}
let output = `Found ${results.length} relevant conversations:\n\n`;
results.forEach((result, index) => {
const date = new Date(result.exchange.timestamp).toISOString().split('T')[0];
output += `${index + 1}. [${result.exchange.project}, ${date}]\n`;
// Show conversation summary if available
if (result.summary) {
output += ` ${result.summary}\n\n`;
}
// Show match with similarity percentage
if (result.similarity !== undefined) {
const pct = Math.round(result.similarity * 100);
output += ` ${pct}% match: "${result.snippet}"\n`;
} else {
output += ` Match: "${result.snippet}"\n`;
}
output += ` ${result.exchange.archivePath}:${result.exchange.lineStart}-${result.exchange.lineEnd}\n\n`;
});
return output;
}

View File

@@ -1,155 +0,0 @@
import { ConversationExchange } from './types.js';
import { query } from '@anthropic-ai/claude-agent-sdk';
export function formatConversationText(exchanges: ConversationExchange[]): string {
return exchanges.map(ex => {
return `User: ${ex.userMessage}\n\nAgent: ${ex.assistantMessage}`;
}).join('\n\n---\n\n');
}
function extractSummary(text: string): string {
const match = text.match(/<summary>(.*?)<\/summary>/s);
if (match) {
return match[1].trim();
}
// Fallback if no tags found
return text.trim();
}
async function callClaude(prompt: string, useSonnet = false): Promise<string> {
const model = useSonnet ? 'sonnet' : 'haiku';
for await (const message of query({
prompt,
options: {
model,
maxTokens: 4096,
maxThinkingTokens: 0, // Disable extended thinking
systemPrompt: 'Write concise, factual summaries. Output ONLY the summary - no preamble, no "Here is", no "I will". Your output will be indexed directly.'
}
})) {
if (message && typeof message === 'object' && 'type' in message && message.type === 'result') {
const result = (message as any).result;
// Check if result is an API error (SDK returns errors as result strings)
if (typeof result === 'string' && result.includes('API Error') && result.includes('thinking.budget_tokens')) {
if (!useSonnet) {
console.log(` Haiku hit thinking budget error, retrying with Sonnet`);
return await callClaude(prompt, true);
}
// If Sonnet also fails, return error message
return result;
}
return result;
}
}
return '';
}
function chunkExchanges(exchanges: ConversationExchange[], chunkSize: number): ConversationExchange[][] {
const chunks: ConversationExchange[][] = [];
for (let i = 0; i < exchanges.length; i += chunkSize) {
chunks.push(exchanges.slice(i, i + chunkSize));
}
return chunks;
}
export async function summarizeConversation(exchanges: ConversationExchange[]): Promise<string> {
// Handle trivial conversations
if (exchanges.length === 0) {
return 'Trivial conversation with no substantive content.';
}
if (exchanges.length === 1) {
const text = formatConversationText(exchanges);
if (text.length < 100 || exchanges[0].userMessage.trim() === '/exit') {
return 'Trivial conversation with no substantive content.';
}
}
// For short conversations (≤15 exchanges), summarize directly
if (exchanges.length <= 15) {
const conversationText = formatConversationText(exchanges);
const prompt = `Context: This summary will be shown in a list to help users and Claude choose which conversations are relevant to a future activity.
Summarize what happened in 2-4 sentences. Be factual and specific. Output in <summary></summary> tags.
Include:
- What was built/changed/discussed (be specific)
- Key technical decisions or approaches
- Problems solved or current state
Exclude:
- Apologies, meta-commentary, or your questions
- Raw logs or debug output
- Generic descriptions - focus on what makes THIS conversation unique
Good:
<summary>Built JWT authentication for React app with refresh tokens and protected routes. Fixed token expiration bug by implementing refresh-during-request logic.</summary>
Bad:
<summary>I apologize. The conversation discussed authentication and various approaches were considered...</summary>
${conversationText}`;
const result = await callClaude(prompt);
return extractSummary(result);
}
// For long conversations, use hierarchical summarization
console.log(` Long conversation (${exchanges.length} exchanges) - using hierarchical summarization`);
// Chunk into groups of 8 exchanges
const chunks = chunkExchanges(exchanges, 8);
console.log(` Split into ${chunks.length} chunks`);
// Summarize each chunk
const chunkSummaries: string[] = [];
for (let i = 0; i < chunks.length; i++) {
const chunkText = formatConversationText(chunks[i]);
const prompt = `Summarize this part of a conversation in 2-3 sentences. What happened, what was built/discussed. Use <summary></summary> tags.
${chunkText}
Example: <summary>Implemented HID keyboard functionality for ESP32. Hit Bluetooth controller initialization error, fixed by adjusting memory allocation.</summary>`;
try {
const summary = await callClaude(prompt);
const extracted = extractSummary(summary);
chunkSummaries.push(extracted);
console.log(` Chunk ${i + 1}/${chunks.length}: ${extracted.split(/\s+/).length} words`);
} catch (error) {
console.log(` Chunk ${i + 1} failed, skipping`);
}
}
if (chunkSummaries.length === 0) {
return 'Error: Unable to summarize conversation.';
}
// Synthesize chunks into final summary
const synthesisPrompt = `Context: This summary will be shown in a list to help users and Claude choose which past conversations are relevant to a future activity.
Synthesize these part-summaries into one cohesive paragraph. Focus on what was accomplished and any notable technical decisions or challenges. Output in <summary></summary> tags.
Part summaries:
${chunkSummaries.map((s, i) => `${i + 1}. ${s}`).join('\n')}
Good:
<summary>Built conversation search system with JavaScript, sqlite-vec, and local embeddings. Implemented hierarchical summarization for long conversations. System archives conversations permanently and provides semantic search via CLI.</summary>
Bad:
<summary>This conversation synthesizes several topics discussed across multiple parts...</summary>
Your summary (max 200 words):`;
console.log(` Synthesizing final summary...`);
try {
const result = await callClaude(synthesisPrompt);
return extractSummary(result);
} catch (error) {
console.log(` Synthesis failed, using chunk summaries`);
return chunkSummaries.join(' ');
}
}

View File

@@ -1,16 +0,0 @@
export interface ConversationExchange {
id: string;
project: string;
timestamp: string;
userMessage: string;
assistantMessage: string;
archivePath: string;
lineStart: number;
lineEnd: number;
}
export interface SearchResult {
exchange: ConversationExchange;
similarity: number;
snippet: string;
}

View File

@@ -1,278 +0,0 @@
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { verifyIndex, repairIndex, VerificationResult } from './verify.js';
import fs from 'fs';
import path from 'path';
import os from 'os';
import { initDatabase, insertExchange } from './db.js';
import { ConversationExchange } from './types.js';
describe('verifyIndex', () => {
const testDir = path.join(os.tmpdir(), 'conversation-search-test-' + Date.now());
const projectsDir = path.join(testDir, '.claude', 'projects');
const archiveDir = path.join(testDir, '.clank', 'conversation-archive');
const dbPath = path.join(testDir, '.clank', 'conversation-index', 'db.sqlite');
beforeEach(() => {
// Create test directories
fs.mkdirSync(path.join(testDir, '.clank', 'conversation-index'), { recursive: true });
fs.mkdirSync(projectsDir, { recursive: true });
fs.mkdirSync(archiveDir, { recursive: true });
// Override environment paths for testing
process.env.TEST_PROJECTS_DIR = projectsDir;
process.env.TEST_ARCHIVE_DIR = archiveDir;
process.env.TEST_DB_PATH = dbPath;
});
afterEach(() => {
// Clean up test directory
fs.rmSync(testDir, { recursive: true, force: true });
delete process.env.TEST_PROJECTS_DIR;
delete process.env.TEST_ARCHIVE_DIR;
delete process.env.TEST_DB_PATH;
});
it('detects missing summaries', async () => {
// Create a test conversation file without a summary
const projectArchive = path.join(archiveDir, 'test-project');
fs.mkdirSync(projectArchive, { recursive: true });
const conversationPath = path.join(projectArchive, 'test-conversation.jsonl');
// Create proper JSONL format (one JSON object per line)
const messages = [
JSON.stringify({ type: 'user', message: { role: 'user', content: 'Hello' }, timestamp: '2024-01-01T00:00:00Z' }),
JSON.stringify({ type: 'assistant', message: { role: 'assistant', content: 'Hi there!' }, timestamp: '2024-01-01T00:00:01Z' })
];
fs.writeFileSync(conversationPath, messages.join('\n'));
const result = await verifyIndex();
expect(result.missing.length).toBe(1);
expect(result.missing[0].path).toBe(conversationPath);
expect(result.missing[0].reason).toBe('No summary file');
});
it('detects orphaned database entries', async () => {
// Initialize database
const db = initDatabase();
// Create an exchange in the database
const exchange: ConversationExchange = {
id: 'orphan-id-1',
project: 'deleted-project',
timestamp: '2024-01-01T00:00:00Z',
userMessage: 'This conversation was deleted',
assistantMessage: 'But still in database',
archivePath: path.join(archiveDir, 'deleted-project', 'deleted.jsonl'),
lineStart: 1,
lineEnd: 2
};
const embedding = new Array(384).fill(0.1);
insertExchange(db, exchange, embedding);
db.close();
// Verify detects orphaned entry (file doesn't exist)
const result = await verifyIndex();
expect(result.orphaned.length).toBe(1);
expect(result.orphaned[0].uuid).toBe('orphan-id-1');
expect(result.orphaned[0].path).toBe(exchange.archivePath);
});
it('detects outdated files (file modified after last_indexed)', async () => {
// Create conversation file with summary
const projectArchive = path.join(archiveDir, 'test-project');
fs.mkdirSync(projectArchive, { recursive: true });
const conversationPath = path.join(projectArchive, 'updated-conversation.jsonl');
const summaryPath = conversationPath.replace('.jsonl', '-summary.txt');
// Create initial conversation
const messages = [
JSON.stringify({ type: 'user', message: { role: 'user', content: 'Hello' }, timestamp: '2024-01-01T00:00:00Z' }),
JSON.stringify({ type: 'assistant', message: { role: 'assistant', content: 'Hi there!' }, timestamp: '2024-01-01T00:00:01Z' })
];
fs.writeFileSync(conversationPath, messages.join('\n'));
fs.writeFileSync(summaryPath, 'Test summary');
// Index it
const db = initDatabase();
const exchange: ConversationExchange = {
id: 'updated-id-1',
project: 'test-project',
timestamp: '2024-01-01T00:00:00Z',
userMessage: 'Hello',
assistantMessage: 'Hi there!',
archivePath: conversationPath,
lineStart: 1,
lineEnd: 2
};
const embedding = new Array(384).fill(0.1);
insertExchange(db, exchange, embedding);
// Get the last_indexed timestamp
const row = db.prepare(`SELECT last_indexed FROM exchanges WHERE id = ?`).get('updated-id-1') as any;
const lastIndexed = row.last_indexed;
db.close();
// Wait a bit, then modify the file
await new Promise(resolve => setTimeout(resolve, 10));
// Update the conversation file
const updatedMessages = [
...messages,
JSON.stringify({ type: 'user', message: { role: 'user', content: 'New message' }, timestamp: '2024-01-01T00:00:02Z' })
];
fs.writeFileSync(conversationPath, updatedMessages.join('\n'));
// Verify detects outdated file
const result = await verifyIndex();
expect(result.outdated.length).toBe(1);
expect(result.outdated[0].path).toBe(conversationPath);
expect(result.outdated[0].dbTime).toBe(lastIndexed);
expect(result.outdated[0].fileTime).toBeGreaterThan(lastIndexed);
});
// Note: Parser is resilient to malformed JSON - it skips bad lines
// Corruption detection would require file system errors or permission issues
// which are harder to test. Skipping for now as missing summaries is the
// primary use case for verification.
});
describe('repairIndex', () => {
const testDir = path.join(os.tmpdir(), 'conversation-repair-test-' + Date.now());
const projectsDir = path.join(testDir, '.claude', 'projects');
const archiveDir = path.join(testDir, '.clank', 'conversation-archive');
const dbPath = path.join(testDir, '.clank', 'conversation-index', 'db.sqlite');
beforeEach(() => {
// Create test directories
fs.mkdirSync(path.join(testDir, '.clank', 'conversation-index'), { recursive: true });
fs.mkdirSync(projectsDir, { recursive: true });
fs.mkdirSync(archiveDir, { recursive: true });
// Override environment paths for testing
process.env.TEST_PROJECTS_DIR = projectsDir;
process.env.TEST_ARCHIVE_DIR = archiveDir;
process.env.TEST_DB_PATH = dbPath;
});
afterEach(() => {
// Clean up test directory
fs.rmSync(testDir, { recursive: true, force: true });
delete process.env.TEST_PROJECTS_DIR;
delete process.env.TEST_ARCHIVE_DIR;
delete process.env.TEST_DB_PATH;
});
it('deletes orphaned database entries during repair', async () => {
// Initialize database with orphaned entry
const db = initDatabase();
const exchange: ConversationExchange = {
id: 'orphan-repair-1',
project: 'deleted-project',
timestamp: '2024-01-01T00:00:00Z',
userMessage: 'This conversation was deleted',
assistantMessage: 'But still in database',
archivePath: path.join(archiveDir, 'deleted-project', 'deleted.jsonl'),
lineStart: 1,
lineEnd: 2
};
const embedding = new Array(384).fill(0.1);
insertExchange(db, exchange, embedding);
db.close();
// Verify it's there
const dbBefore = initDatabase();
const beforeCount = dbBefore.prepare(`SELECT COUNT(*) as count FROM exchanges WHERE id = ?`).get('orphan-repair-1') as { count: number };
expect(beforeCount.count).toBe(1);
dbBefore.close();
// Run repair
const issues = await verifyIndex();
expect(issues.orphaned.length).toBe(1);
await repairIndex(issues);
// Verify it's gone
const dbAfter = initDatabase();
const afterCount = dbAfter.prepare(`SELECT COUNT(*) as count FROM exchanges WHERE id = ?`).get('orphan-repair-1') as { count: number };
expect(afterCount.count).toBe(0);
dbAfter.close();
});
it('re-indexes outdated files during repair', { timeout: 30000 }, async () => {
// Create conversation file with summary
const projectArchive = path.join(archiveDir, 'test-project');
fs.mkdirSync(projectArchive, { recursive: true });
const conversationPath = path.join(projectArchive, 'outdated-repair.jsonl');
const summaryPath = conversationPath.replace('.jsonl', '-summary.txt');
// Create initial conversation
const messages = [
JSON.stringify({ type: 'user', message: { role: 'user', content: 'Hello' }, timestamp: '2024-01-01T00:00:00Z' }),
JSON.stringify({ type: 'assistant', message: { role: 'assistant', content: 'Hi there!' }, timestamp: '2024-01-01T00:00:01Z' })
];
fs.writeFileSync(conversationPath, messages.join('\n'));
fs.writeFileSync(summaryPath, 'Old summary');
// Index it
const db = initDatabase();
const exchange: ConversationExchange = {
id: 'outdated-repair-1',
project: 'test-project',
timestamp: '2024-01-01T00:00:00Z',
userMessage: 'Hello',
assistantMessage: 'Hi there!',
archivePath: conversationPath,
lineStart: 1,
lineEnd: 2
};
const embedding = new Array(384).fill(0.1);
insertExchange(db, exchange, embedding);
// Get the last_indexed timestamp
const beforeRow = db.prepare(`SELECT last_indexed FROM exchanges WHERE id = ?`).get('outdated-repair-1') as any;
const beforeIndexed = beforeRow.last_indexed;
db.close();
// Wait a bit, then modify the file
await new Promise(resolve => setTimeout(resolve, 10));
// Update the conversation file (add new exchange)
const updatedMessages = [
...messages,
JSON.stringify({ type: 'user', message: { role: 'user', content: 'New message' }, timestamp: '2024-01-01T00:00:02Z' }),
JSON.stringify({ type: 'assistant', message: { role: 'assistant', content: 'New response' }, timestamp: '2024-01-01T00:00:03Z' })
];
fs.writeFileSync(conversationPath, updatedMessages.join('\n'));
// Verify detects outdated
const issues = await verifyIndex();
expect(issues.outdated.length).toBe(1);
// Wait a bit to ensure different timestamp
await new Promise(resolve => setTimeout(resolve, 10));
// Run repair
await repairIndex(issues);
// Verify it was re-indexed with new timestamp
const dbAfter = initDatabase();
const afterRow = dbAfter.prepare(`SELECT MAX(last_indexed) as last_indexed FROM exchanges WHERE archive_path = ?`).get(conversationPath) as any;
expect(afterRow.last_indexed).toBeGreaterThan(beforeIndexed);
// Verify no longer outdated
const verifyAfter = await verifyIndex();
expect(verifyAfter.outdated.length).toBe(0);
dbAfter.close();
});
});

View File

@@ -1,177 +0,0 @@
import fs from 'fs';
import path from 'path';
import { parseConversation } from './parser.js';
import { initDatabase, getAllExchanges, getFileLastIndexed } from './db.js';
import { getArchiveDir } from './paths.js';
export interface VerificationResult {
missing: Array<{ path: string; reason: string }>;
orphaned: Array<{ uuid: string; path: string }>;
outdated: Array<{ path: string; fileTime: number; dbTime: number }>;
corrupted: Array<{ path: string; error: string }>;
}
export async function verifyIndex(): Promise<VerificationResult> {
const result: VerificationResult = {
missing: [],
orphaned: [],
outdated: [],
corrupted: []
};
const archiveDir = getArchiveDir();
// Track all files we find
const foundFiles = new Set<string>();
// Find all conversation files
if (!fs.existsSync(archiveDir)) {
return result;
}
// Initialize database once for all checks
const db = initDatabase();
const projects = fs.readdirSync(archiveDir);
let totalChecked = 0;
for (const project of projects) {
const projectPath = path.join(archiveDir, project);
const stat = fs.statSync(projectPath);
if (!stat.isDirectory()) continue;
const files = fs.readdirSync(projectPath).filter(f => f.endsWith('.jsonl'));
for (const file of files) {
totalChecked++;
if (totalChecked % 100 === 0) {
console.log(` Checked ${totalChecked} conversations...`);
}
const conversationPath = path.join(projectPath, file);
foundFiles.add(conversationPath);
const summaryPath = conversationPath.replace('.jsonl', '-summary.txt');
// Check for missing summary
if (!fs.existsSync(summaryPath)) {
result.missing.push({ path: conversationPath, reason: 'No summary file' });
continue;
}
// Check if file is outdated (modified after last_indexed)
const lastIndexed = getFileLastIndexed(db, conversationPath);
if (lastIndexed !== null) {
const fileStat = fs.statSync(conversationPath);
if (fileStat.mtimeMs > lastIndexed) {
result.outdated.push({
path: conversationPath,
fileTime: fileStat.mtimeMs,
dbTime: lastIndexed
});
}
}
// Try parsing to detect corruption
try {
await parseConversation(conversationPath, project, conversationPath);
} catch (error) {
result.corrupted.push({
path: conversationPath,
error: error instanceof Error ? error.message : String(error)
});
}
}
}
console.log(`Verified ${totalChecked} conversations.`);
// Check for orphaned database entries
const dbExchanges = getAllExchanges(db);
db.close();
for (const exchange of dbExchanges) {
if (!foundFiles.has(exchange.archivePath)) {
result.orphaned.push({
uuid: exchange.id,
path: exchange.archivePath
});
}
}
return result;
}
export async function repairIndex(issues: VerificationResult): Promise<void> {
console.log('Repairing index...');
// To avoid circular dependencies, we import the indexer functions dynamically
const { initDatabase, insertExchange, deleteExchange } = await import('./db.js');
const { parseConversation } = await import('./parser.js');
const { initEmbeddings, generateExchangeEmbedding } = await import('./embeddings.js');
const { summarizeConversation } = await import('./summarizer.js');
const db = initDatabase();
await initEmbeddings();
// Remove orphaned entries first
for (const orphan of issues.orphaned) {
console.log(`Removing orphaned entry: ${orphan.uuid}`);
deleteExchange(db, orphan.uuid);
}
// Re-index missing and outdated conversations
const toReindex = [
...issues.missing.map(m => m.path),
...issues.outdated.map(o => o.path)
];
for (const conversationPath of toReindex) {
console.log(`Re-indexing: ${conversationPath}`);
try {
// Extract project name from path
const archiveDir = getArchiveDir();
const relativePath = conversationPath.replace(archiveDir + path.sep, '');
const project = relativePath.split(path.sep)[0];
// Parse conversation
const exchanges = await parseConversation(conversationPath, project, conversationPath);
if (exchanges.length === 0) {
console.log(` Skipped (no exchanges)`);
continue;
}
// Generate/update summary
const summaryPath = conversationPath.replace('.jsonl', '-summary.txt');
const summary = await summarizeConversation(exchanges);
fs.writeFileSync(summaryPath, summary, 'utf-8');
console.log(` Created summary: ${summary.split(/\s+/).length} words`);
// Index exchanges
for (const exchange of exchanges) {
const embedding = await generateExchangeEmbedding(
exchange.userMessage,
exchange.assistantMessage
);
insertExchange(db, exchange, embedding);
}
console.log(` Indexed ${exchanges.length} exchanges`);
} catch (error) {
console.error(`Failed to re-index ${conversationPath}:`, error);
}
}
db.close();
// Report corrupted files (manual intervention needed)
if (issues.corrupted.length > 0) {
console.log('\n⚠ Corrupted files (manual review needed):');
issues.corrupted.forEach(c => console.log(` ${c.path}: ${c.error}`));
}
console.log('✅ Repair complete.');
}

View File

@@ -1,374 +0,0 @@
#!/bin/bash
# End-to-end deployment testing
# Tests all deployment scenarios from docs/plans/2025-10-07-deployment-plan.md
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
INSTALL_HOOK="$SCRIPT_DIR/install-hook"
INDEX_CONVERSATIONS="$SCRIPT_DIR/index-conversations"
# Test counter
TESTS_RUN=0
TESTS_PASSED=0
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Helper functions
setup_test() {
TEST_DIR=$(mktemp -d)
export HOME="$TEST_DIR"
export TEST_PROJECTS_DIR="$TEST_DIR/.claude/projects"
export TEST_ARCHIVE_DIR="$TEST_DIR/.clank/conversation-archive"
export TEST_DB_PATH="$TEST_DIR/.clank/conversation-index/db.sqlite"
mkdir -p "$HOME/.claude/hooks"
mkdir -p "$TEST_PROJECTS_DIR"
mkdir -p "$TEST_ARCHIVE_DIR"
mkdir -p "$TEST_DIR/.clank/conversation-index"
}
cleanup_test() {
if [ -n "$TEST_DIR" ] && [ -d "$TEST_DIR" ]; then
rm -rf "$TEST_DIR"
fi
unset TEST_PROJECTS_DIR
unset TEST_ARCHIVE_DIR
unset TEST_DB_PATH
}
assert_file_exists() {
if [ ! -f "$1" ]; then
echo -e "${RED}❌ FAIL: File does not exist: $1${NC}"
return 1
fi
return 0
}
assert_file_executable() {
if [ ! -x "$1" ]; then
echo -e "${RED}❌ FAIL: File is not executable: $1${NC}"
return 1
fi
return 0
}
assert_file_contains() {
if ! grep -q "$2" "$1"; then
echo -e "${RED}❌ FAIL: File $1 does not contain: $2${NC}"
return 1
fi
return 0
}
assert_summary_exists() {
local jsonl_file="$1"
# If file is in projects dir, convert to archive path
if [[ "$jsonl_file" == *"/.claude/projects/"* ]]; then
jsonl_file=$(echo "$jsonl_file" | sed "s|/.claude/projects/|/.clank/conversation-archive/|")
fi
local summary_file="${jsonl_file%.jsonl}-summary.txt"
if [ ! -f "$summary_file" ]; then
echo -e "${RED}❌ FAIL: Summary does not exist: $summary_file${NC}"
return 1
fi
return 0
}
create_test_conversation() {
local project="$1"
local uuid="${2:-test-$(date +%s)}"
mkdir -p "$TEST_PROJECTS_DIR/$project"
local conv_file="$TEST_PROJECTS_DIR/$project/${uuid}.jsonl"
cat > "$conv_file" <<'EOF'
{"type":"user","message":{"role":"user","content":"What is TDD?"},"timestamp":"2024-01-01T00:00:00Z"}
{"type":"assistant","message":{"role":"assistant","content":"TDD stands for Test-Driven Development. You write tests first."},"timestamp":"2024-01-01T00:00:01Z"}
EOF
echo "$conv_file"
}
run_test() {
local test_name="$1"
local test_func="$2"
TESTS_RUN=$((TESTS_RUN + 1))
echo -e "\n${YELLOW}Running test: $test_name${NC}"
setup_test
if $test_func; then
echo -e "${GREEN}✓ PASS: $test_name${NC}"
TESTS_PASSED=$((TESTS_PASSED + 1))
else
echo -e "${RED}❌ FAIL: $test_name${NC}"
fi
cleanup_test
}
# ============================================================================
# Scenario 1: Fresh Installation
# ============================================================================
test_scenario_1_fresh_install() {
echo " 1. Installing hook with no existing hook..."
"$INSTALL_HOOK" > /dev/null 2>&1 || true
assert_file_exists "$HOME/.claude/hooks/sessionEnd" || return 1
assert_file_executable "$HOME/.claude/hooks/sessionEnd" || return 1
echo " 2. Creating test conversation..."
local conv_file=$(create_test_conversation "test-project" "conv-1")
echo " 3. Indexing conversation..."
cd "$SCRIPT_DIR" && "$INDEX_CONVERSATIONS" > /dev/null 2>&1
echo " 4. Verifying summary was created..."
assert_summary_exists "$conv_file" || return 1
echo " 5. Testing hook triggers indexing..."
export SESSION_ID="hook-session-$(date +%s)"
# Create conversation file with SESSION_ID in name
mkdir -p "$TEST_PROJECTS_DIR/test-project"
local new_conv="$TEST_PROJECTS_DIR/test-project/${SESSION_ID}.jsonl"
cat > "$new_conv" <<'EOF'
{"type":"user","message":{"role":"user","content":"What is TDD?"},"timestamp":"2024-01-01T00:00:00Z"}
{"type":"assistant","message":{"role":"assistant","content":"TDD stands for Test-Driven Development. You write tests first."},"timestamp":"2024-01-01T00:00:01Z"}
EOF
# Verify hook runs the index command (manually call indexer with --session)
# In real environment, hook would do this automatically
cd "$SCRIPT_DIR" && "$INDEX_CONVERSATIONS" --session "$SESSION_ID" > /dev/null 2>&1
echo " 6. Verifying session was indexed..."
assert_summary_exists "$new_conv" || return 1
echo " 7. Testing search functionality..."
local search_result=$(cd "$SCRIPT_DIR" && "$SCRIPT_DIR/search-conversations" "TDD" 2>/dev/null || echo "")
if [ -z "$search_result" ]; then
echo -e "${RED}❌ Search returned no results${NC}"
return 1
fi
return 0
}
# ============================================================================
# Scenario 2: Existing Hook (merge)
# ============================================================================
test_scenario_2_existing_hook_merge() {
echo " 1. Creating existing hook..."
cat > "$HOME/.claude/hooks/sessionEnd" <<'EOF'
#!/bin/bash
# Existing hook
echo "Existing hook running"
EOF
chmod +x "$HOME/.claude/hooks/sessionEnd"
echo " 2. Installing with merge option..."
echo "m" | "$INSTALL_HOOK" > /dev/null 2>&1 || true
echo " 3. Verifying backup created..."
local backup_count=$(ls -1 "$HOME/.claude/hooks/sessionEnd.backup."* 2>/dev/null | wc -l)
if [ "$backup_count" -lt 1 ]; then
echo -e "${RED}❌ No backup created${NC}"
return 1
fi
echo " 4. Verifying merge preserved existing content..."
assert_file_contains "$HOME/.claude/hooks/sessionEnd" "Existing hook running" || return 1
echo " 5. Verifying indexer was appended..."
assert_file_contains "$HOME/.claude/hooks/sessionEnd" "remembering-conversations.*index-conversations" || return 1
echo " 6. Testing merged hook runs both parts..."
local conv_file=$(create_test_conversation "merge-project" "merge-conv")
cd "$SCRIPT_DIR" && "$INDEX_CONVERSATIONS" > /dev/null 2>&1
export SESSION_ID="merge-session-$(date +%s)"
local hook_output=$("$HOME/.claude/hooks/sessionEnd" 2>&1)
if ! echo "$hook_output" | grep -q "Existing hook running"; then
echo -e "${RED}❌ Existing hook logic not executed${NC}"
return 1
fi
return 0
}
# ============================================================================
# Scenario 3: Recovery (verify/repair)
# ============================================================================
test_scenario_3_recovery_verify_repair() {
echo " 1. Creating conversations and indexing..."
local conv1=$(create_test_conversation "recovery-project" "conv-1")
local conv2=$(create_test_conversation "recovery-project" "conv-2")
cd "$SCRIPT_DIR" && "$INDEX_CONVERSATIONS" > /dev/null 2>&1
echo " 2. Verifying summaries exist..."
assert_summary_exists "$conv1" || return 1
assert_summary_exists "$conv2" || return 1
echo " 3. Deleting summary to simulate missing file..."
# Delete from archive (where summaries are stored)
local archive_conv1=$(echo "$conv1" | sed "s|/.claude/projects/|/.clank/conversation-archive/|")
rm "${archive_conv1%.jsonl}-summary.txt"
echo " 4. Running verify (should detect missing)..."
local verify_output=$(cd "$SCRIPT_DIR" && "$INDEX_CONVERSATIONS" --verify 2>&1)
if ! echo "$verify_output" | grep -q "Missing summaries: 1"; then
echo -e "${RED}❌ Verify did not detect missing summary${NC}"
echo "Verify output: $verify_output"
return 1
fi
echo " 5. Running repair..."
cd "$SCRIPT_DIR" && "$INDEX_CONVERSATIONS" --repair > /dev/null 2>&1
echo " 6. Verifying summary was regenerated..."
assert_summary_exists "$conv1" || return 1
echo " 7. Running verify again (should be clean)..."
verify_output=$(cd "$SCRIPT_DIR" && "$INDEX_CONVERSATIONS" --verify 2>&1)
# Verify should report no missing issues
if ! echo "$verify_output" | grep -q "Missing summaries: 0"; then
echo -e "${RED}❌ Verify still reports missing issues after repair${NC}"
echo "Verify output: $verify_output"
return 1
fi
return 0
}
# ============================================================================
# Scenario 4: Change Detection
# ============================================================================
test_scenario_4_change_detection() {
echo " 1. Creating and indexing conversation..."
local conv=$(create_test_conversation "change-project" "conv-1")
cd "$SCRIPT_DIR" && "$INDEX_CONVERSATIONS" > /dev/null 2>&1
echo " 2. Verifying initial index..."
assert_summary_exists "$conv" || return 1
echo " 3. Modifying conversation (adding exchange)..."
# Wait to ensure different mtime
sleep 1
# Modify the archive file (that's what verify checks)
local archive_conv=$(echo "$conv" | sed "s|/.claude/projects/|/.clank/conversation-archive/|")
cat >> "$archive_conv" <<'EOF'
{"type":"user","message":{"role":"user","content":"Tell me more about TDD"},"timestamp":"2024-01-01T00:00:02Z"}
{"type":"assistant","message":{"role":"assistant","content":"TDD has three phases: Red, Green, Refactor."},"timestamp":"2024-01-01T00:00:03Z"}
EOF
echo " 4. Running verify (should detect outdated)..."
local verify_output=$(cd "$SCRIPT_DIR" && "$INDEX_CONVERSATIONS" --verify 2>&1)
if ! echo "$verify_output" | grep -q "Outdated files: 1"; then
echo -e "${RED}❌ Verify did not detect outdated file${NC}"
echo "Verify output: $verify_output"
return 1
fi
echo " 5. Running repair (should re-index)..."
cd "$SCRIPT_DIR" && "$INDEX_CONVERSATIONS" --repair > /dev/null 2>&1
echo " 6. Verifying conversation is up to date..."
verify_output=$(cd "$SCRIPT_DIR" && "$INDEX_CONVERSATIONS" --verify 2>&1)
if ! echo "$verify_output" | grep -q "Outdated files: 0"; then
echo -e "${RED}❌ File still outdated after repair${NC}"
echo "Verify output: $verify_output"
return 1
fi
echo " 7. Verifying new content is searchable..."
local search_result=$(cd "$SCRIPT_DIR" && "$SCRIPT_DIR/search-conversations" "Red Green Refactor" 2>/dev/null || echo "")
if [ -z "$search_result" ]; then
echo -e "${RED}❌ New content not found in search${NC}"
return 1
fi
return 0
}
# ============================================================================
# Scenario 5: Subagent Workflow (Manual Testing Required)
# ============================================================================
test_scenario_5_subagent_workflow_docs() {
echo " This scenario requires manual testing with a live subagent."
echo " Automated checks:"
echo " 1. Verifying search-agent template exists..."
local template_file="$SCRIPT_DIR/prompts/search-agent.md"
assert_file_exists "$template_file" || return 1
echo " 2. Verifying template has required sections..."
assert_file_contains "$template_file" "### Summary" || return 1
assert_file_contains "$template_file" "### Sources" || return 1
assert_file_contains "$template_file" "### For Follow-Up" || return 1
echo ""
echo -e "${YELLOW} MANUAL TESTING REQUIRED:${NC}"
echo " To complete Scenario 5 testing:"
echo " 1. Start a new Claude Code session"
echo " 2. Ask about a past conversation topic"
echo " 3. Dispatch subagent using: skills/collaboration/remembering-conversations/tool/prompts/search-agent.md"
echo " 4. Verify synthesis is 200-1000 words"
echo " 5. Verify all sources include: project, date, file path, status"
echo " 6. Ask follow-up question to test iterative refinement"
echo " 7. Verify no raw conversations loaded into main context"
echo ""
return 0
}
# ============================================================================
# Run All Tests
# ============================================================================
echo "=========================================="
echo " End-to-End Deployment Testing"
echo "=========================================="
echo ""
echo "Testing deployment scenarios from:"
echo " docs/plans/2025-10-07-deployment-plan.md"
echo ""
run_test "Scenario 1: Fresh Installation" test_scenario_1_fresh_install
run_test "Scenario 2: Existing Hook (merge)" test_scenario_2_existing_hook_merge
run_test "Scenario 3: Recovery (verify/repair)" test_scenario_3_recovery_verify_repair
run_test "Scenario 4: Change Detection" test_scenario_4_change_detection
run_test "Scenario 5: Subagent Workflow (docs check)" test_scenario_5_subagent_workflow_docs
echo ""
echo "=========================================="
echo -e " Test Results: ${GREEN}$TESTS_PASSED${NC}/${TESTS_RUN} passed"
echo "=========================================="
if [ $TESTS_PASSED -eq $TESTS_RUN ]; then
echo -e "${GREEN}✅ All tests passed!${NC}"
exit 0
else
echo -e "${RED}❌ Some tests failed${NC}"
exit 1
fi

View File

@@ -1,226 +0,0 @@
#!/bin/bash
# Test suite for install-hook script
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
INSTALL_HOOK="$SCRIPT_DIR/install-hook"
# Test counter
TESTS_RUN=0
TESTS_PASSED=0
# Helper functions
setup_test() {
TEST_DIR=$(mktemp -d)
export HOME="$TEST_DIR"
mkdir -p "$HOME/.claude/hooks"
}
cleanup_test() {
if [ -n "$TEST_DIR" ] && [ -d "$TEST_DIR" ]; then
rm -rf "$TEST_DIR"
fi
}
assert_file_exists() {
if [ ! -f "$1" ]; then
echo "❌ FAIL: File does not exist: $1"
return 1
fi
return 0
}
assert_file_not_exists() {
if [ -f "$1" ]; then
echo "❌ FAIL: File should not exist: $1"
return 1
fi
return 0
}
assert_file_executable() {
if [ ! -x "$1" ]; then
echo "❌ FAIL: File is not executable: $1"
return 1
fi
return 0
}
assert_file_contains() {
if ! grep -q "$2" "$1"; then
echo "❌ FAIL: File $1 does not contain: $2"
return 1
fi
return 0
}
run_test() {
local test_name="$1"
local test_func="$2"
TESTS_RUN=$((TESTS_RUN + 1))
echo "Running test: $test_name"
setup_test
if $test_func; then
echo "✓ PASS: $test_name"
TESTS_PASSED=$((TESTS_PASSED + 1))
else
echo "❌ FAIL: $test_name"
fi
cleanup_test
echo ""
}
# Test 1: Fresh installation with no existing hook
test_fresh_installation() {
# Run installer with no input (non-interactive fresh install)
if [ ! -x "$INSTALL_HOOK" ]; then
echo "❌ install-hook script not found or not executable"
return 1
fi
# Should fail because script doesn't exist yet
"$INSTALL_HOOK" 2>&1 || true
# Verify hook was created
assert_file_exists "$HOME/.claude/hooks/sessionEnd" || return 1
# Verify hook is executable
assert_file_executable "$HOME/.claude/hooks/sessionEnd" || return 1
# Verify hook contains indexer reference
assert_file_contains "$HOME/.claude/hooks/sessionEnd" "remembering-conversations.*index-conversations" || return 1
return 0
}
# Test 2: Merge with existing hook (user chooses merge)
test_merge_with_existing_hook() {
# Create existing hook
cat > "$HOME/.claude/hooks/sessionEnd" <<'EOF'
#!/bin/bash
# Existing hook content
echo "Existing hook running"
EOF
chmod +x "$HOME/.claude/hooks/sessionEnd"
# Run installer and choose merge
echo "m" | "$INSTALL_HOOK" 2>&1 || true
# Verify backup was created
local backup_count=$(ls -1 "$HOME/.claude/hooks/sessionEnd.backup."* 2>/dev/null | wc -l)
if [ "$backup_count" -lt 1 ]; then
echo "❌ No backup created"
return 1
fi
# Verify original content is preserved
assert_file_contains "$HOME/.claude/hooks/sessionEnd" "Existing hook running" || return 1
# Verify indexer was appended
assert_file_contains "$HOME/.claude/hooks/sessionEnd" "remembering-conversations.*index-conversations" || return 1
return 0
}
# Test 3: Replace with existing hook (user chooses replace)
test_replace_with_existing_hook() {
# Create existing hook
cat > "$HOME/.claude/hooks/sessionEnd" <<'EOF'
#!/bin/bash
# Old hook to be replaced
echo "Old hook"
EOF
chmod +x "$HOME/.claude/hooks/sessionEnd"
# Run installer and choose replace
echo "r" | "$INSTALL_HOOK" 2>&1 || true
# Verify backup was created
local backup_count=$(ls -1 "$HOME/.claude/hooks/sessionEnd.backup."* 2>/dev/null | wc -l)
if [ "$backup_count" -lt 1 ]; then
echo "❌ No backup created"
return 1
fi
# Verify old content is gone
if grep -q "Old hook" "$HOME/.claude/hooks/sessionEnd"; then
echo "❌ Old hook content still present"
return 1
fi
# Verify new hook contains indexer
assert_file_contains "$HOME/.claude/hooks/sessionEnd" "remembering-conversations.*index-conversations" || return 1
return 0
}
# Test 4: Detection of already-installed indexer (idempotent)
test_already_installed_detection() {
# Create hook with indexer already installed
cat > "$HOME/.claude/hooks/sessionEnd" <<'EOF'
#!/bin/bash
# Auto-index conversations (remembering-conversations skill)
INDEXER="$HOME/.claude/skills/collaboration/remembering-conversations/tool/index-conversations"
if [ -n "$SESSION_ID" ] && [ -x "$INDEXER" ]; then
"$INDEXER" --session "$SESSION_ID" > /dev/null 2>&1 &
fi
EOF
chmod +x "$HOME/.claude/hooks/sessionEnd"
# Run installer - should detect and exit
local output=$("$INSTALL_HOOK" 2>&1 || true)
# Verify it detected existing installation
if ! echo "$output" | grep -q "already installed"; then
echo "❌ Did not detect existing installation"
echo "Output: $output"
return 1
fi
# Verify no backup was created (since nothing changed)
local backup_count=$(ls -1 "$HOME/.claude/hooks/sessionEnd.backup."* 2>/dev/null | wc -l)
if [ "$backup_count" -gt 0 ]; then
echo "❌ Backup created when it shouldn't have been"
return 1
fi
return 0
}
# Test 5: Executable permissions are set
test_executable_permissions() {
# Run installer
"$INSTALL_HOOK" 2>&1 || true
# Verify hook is executable
assert_file_executable "$HOME/.claude/hooks/sessionEnd" || return 1
return 0
}
# Run all tests
echo "=========================================="
echo "Testing install-hook script"
echo "=========================================="
echo ""
run_test "Fresh installation with no existing hook" test_fresh_installation
run_test "Merge with existing hook" test_merge_with_existing_hook
run_test "Replace with existing hook" test_replace_with_existing_hook
run_test "Detection of already-installed indexer" test_already_installed_detection
run_test "Executable permissions are set" test_executable_permissions
echo "=========================================="
echo "Test Results: $TESTS_PASSED/$TESTS_RUN passed"
echo "=========================================="
if [ $TESTS_PASSED -eq $TESTS_RUN ]; then
exit 0
else
exit 1
fi

View File

@@ -1,14 +0,0 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}

View File

@@ -1,188 +0,0 @@
---
name: Subagent-Driven Development
description: Execute implementation plan by dispatching fresh subagent for each task, with code review between tasks
when_to_use: Alternative to executing-plans when staying in same session. When tasks are independent. When want fast iteration with review checkpoints. After writing implementation plan.
version: 1.0.0
---
# Subagent-Driven Development
Execute plan by dispatching fresh subagent per task, with code review after each.
**Core principle:** Fresh subagent per task + review between tasks = high quality, fast iteration
## Overview
**vs. Executing Plans (parallel session):**
- Same session (no context switch)
- Fresh subagent per task (no context pollution)
- Code review after each task (catch issues early)
- Faster iteration (no human-in-loop between tasks)
**When to use:**
- Staying in this session
- Tasks are mostly independent
- Want continuous progress with quality gates
**When NOT to use:**
- Need to review plan first (use executing-plans)
- Tasks are tightly coupled (manual execution better)
- Plan needs revision (brainstorm first)
## The Process
### 1. Load Plan
Read plan file, create TodoWrite with all tasks.
### 2. Execute Task with Subagent
For each task:
**Dispatch fresh subagent:**
```
Task tool (general-purpose):
description: "Implement Task N: [task name]"
prompt: |
You are implementing Task N from [plan-file].
Read that task carefully. Your job is to:
1. Implement exactly what the task specifies
2. Write tests (following TDD if task says to)
3. Verify implementation works
4. Commit your work
5. Report back
Work from: [directory]
Report: What you implemented, what you tested, test results, files changed, any issues
```
**Subagent reports back** with summary of work.
### 3. Review Subagent's Work
**Dispatch code-reviewer subagent:**
```
Task tool (code-reviewer):
Use template at skills/collaboration/requesting-code-review/code-reviewer.md
WHAT_WAS_IMPLEMENTED: [from subagent's report]
PLAN_OR_REQUIREMENTS: Task N from [plan-file]
BASE_SHA: [commit before task]
HEAD_SHA: [current commit]
DESCRIPTION: [task summary]
```
**Code reviewer returns:** Strengths, Issues (Critical/Important/Minor), Assessment
### 4. Apply Review Feedback
**If issues found:**
- Fix Critical issues immediately
- Fix Important issues before next task
- Note Minor issues
**Dispatch follow-up subagent if needed:**
```
"Fix issues from code review: [list issues]"
```
### 5. Mark Complete, Next Task
- Mark task as completed in TodoWrite
- Move to next task
- Repeat steps 2-5
### 6. Final Review
After all tasks complete, dispatch final code-reviewer:
- Reviews entire implementation
- Checks all plan requirements met
- Validates overall architecture
### 7. Complete Development
After final review passes:
- Announce: "I'm using the Finishing a Development Branch skill to complete this work."
- Switch to skills/collaboration/finishing-a-development-branch
- Follow that skill to verify tests, present options, execute choice
## Example Workflow
```
You: I'm using Subagent-Driven Development to execute this plan.
[Load plan, create TodoWrite]
Task 1: Hook installation script
[Dispatch implementation subagent]
Subagent: Implemented install-hook with tests, 5/5 passing
[Get git SHAs, dispatch code-reviewer]
Reviewer: Strengths: Good test coverage. Issues: None. Ready.
[Mark Task 1 complete]
Task 2: Recovery modes
[Dispatch implementation subagent]
Subagent: Added verify/repair, 8/8 tests passing
[Dispatch code-reviewer]
Reviewer: Strengths: Solid. Issues (Important): Missing progress reporting
[Dispatch fix subagent]
Fix subagent: Added progress every 100 conversations
[Verify fix, mark Task 2 complete]
...
[After all tasks]
[Dispatch final code-reviewer]
Final reviewer: All requirements met, ready to merge
Done!
```
## Advantages
**vs. Manual execution:**
- Subagents follow TDD naturally
- Fresh context per task (no confusion)
- Parallel-safe (subagents don't interfere)
**vs. Executing Plans:**
- Same session (no handoff)
- Continuous progress (no waiting)
- Review checkpoints automatic
**Cost:**
- More subagent invocations
- But catches issues early (cheaper than debugging later)
## Red Flags
**Never:**
- Skip code review between tasks
- Proceed with unfixed Critical issues
- Dispatch multiple implementation subagents in parallel (conflicts)
- Implement without reading plan task
**If subagent fails task:**
- Dispatch fix subagent with specific instructions
- Don't try to fix manually (context pollution)
## Integration
**Pairs with:**
- skills/collaboration/writing-plans (creates the plan)
- skills/collaboration/requesting-code-review (review template)
- skills/testing/test-driven-development (subagents follow this)
**Alternative to:**
- skills/collaboration/executing-plans (parallel session)
See code-reviewer template: skills/collaboration/requesting-code-review/code-reviewer.md

View File

@@ -1,118 +0,0 @@
---
name: Writing Plans
description: Create detailed implementation plans with bite-sized tasks for engineers with zero codebase context
when_to_use: After brainstorming/design is complete. Before implementation begins. When delegating to another developer or session. When brainstorming skill hands off to planning.
version: 2.0.0
---
# Writing Plans
## Overview
Write comprehensive implementation plans assuming the engineer has zero context for our codebase and questionable taste. Document everything they need to know: which files to touch for each task, code, testing, docs they might need to check, how to test it. Give them the whole plan as bite-sized tasks. DRY. YAGNI. TDD. Frequent commits.
Assume they are a skilled developer, but know almost nothing about our toolset or problem domain. Assume they don't know good test design very well.
**Announce at start:** "I'm using the Writing Plans skill to create the implementation plan."
**Context:** This should be run in a dedicated worktree (created by brainstorming skill).
**Save plans to:** `docs/plans/YYYY-MM-DD-<feature-name>.md`
## Bite-Sized Task Granularity
**Each step is one action (2-5 minutes):**
- "Write the failing test" - step
- "Run it to make sure it fails" - step
- "Implement the minimal code to make the test pass" - step
- "Run the tests and make sure they pass" - step
- "Commit" - step
## Plan Document Header
**Every plan MUST start with this header:**
```markdown
# [Feature Name] Implementation Plan
> **For Claude:** Use `${CLAUDE_PLUGIN_ROOT}/skills/collaboration/executing-plans/SKILL.md` to implement this plan task-by-task.
**Goal:** [One sentence describing what this builds]
**Architecture:** [2-3 sentences about approach]
**Tech Stack:** [Key technologies/libraries]
---
```
## Task Structure
```markdown
### Task N: [Component Name]
**Files:**
- Create: `exact/path/to/file.py`
- Modify: `exact/path/to/existing.py:123-145`
- Test: `tests/exact/path/to/test.py`
**Step 1: Write the failing test**
```python
def test_specific_behavior():
result = function(input)
assert result == expected
```
**Step 2: Run test to verify it fails**
Run: `pytest tests/path/test.py::test_name -v`
Expected: FAIL with "function not defined"
**Step 3: Write minimal implementation**
```python
def function(input):
return expected
```
**Step 4: Run test to verify it passes**
Run: `pytest tests/path/test.py::test_name -v`
Expected: PASS
**Step 5: Commit**
```bash
git add tests/path/test.py src/path/file.py
git commit -m "feat: add specific feature"
```
```
## Remember
- Exact file paths always
- Complete code in plan (not "add validation")
- Exact commands with expected output
- Reference relevant skills with @ syntax
- DRY, YAGNI, TDD, frequent commits
## Execution Handoff
After saving the plan, offer execution choice:
**"Plan complete and saved to `docs/plans/<filename>.md`. Two execution options:**
**1. Subagent-Driven (this session)** - I dispatch fresh subagent per task, review between tasks, fast iteration
**2. Parallel Session (separate)** - Open new session with executing-plans, batch execution with checkpoints
**Which approach?"**
**If Subagent-Driven chosen:**
- Use skills/collaboration/subagent-driven-development
- Stay in this session
- Fresh subagent per task + code review
**If Parallel Session chosen:**
- Guide them to open new session in worktree
- New session uses skills/collaboration/executing-plans

View File

@@ -1,10 +1,6 @@
---
name: Dispatching Parallel Agents
description: Use multiple Claude agents to investigate and fix independent problems concurrently
when_to_use: Multiple unrelated failures that can be investigated independently
version: 1.0.0
languages: all
context: AI-assisted development (Claude Code or similar)
name: dispatching-parallel-agents
description: Use when facing 2+ independent tasks that can be worked on without shared state or sequential dependencies
---
# Dispatching Parallel Agents

View File

@@ -0,0 +1,84 @@
---
name: executing-plans
description: Use when you have a written implementation plan to execute in a separate session with review checkpoints
---
# Executing Plans
## Overview
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."
## The Process
### Step 1: Load and Review Plan
1. Read plan file
2. Review critically - identify any questions or concerns about the plan
3. If concerns: Raise them with your human partner before starting
4. If no concerns: Create TodoWrite and proceed
### Step 2: Execute Batch
**Default: First 3 tasks**
For each task:
1. Mark as in_progress
2. Follow each step exactly (plan has bite-sized steps)
3. Run verifications as specified
4. Mark as completed
### 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."
- **REQUIRED SUB-SKILL:** Use superpowers:finishing-a-development-branch
- Follow that skill to verify tests, present options, execute choice
## When to Stop and Ask for Help
**STOP executing immediately when:**
- 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
**Ask for clarification rather than guessing.**
## When to Revisit Earlier Steps
**Return to Review (Step 1) when:**
- Partner updates the plan based on your feedback
- Fundamental approach needs rethinking
**Don't force through blockers** - stop and ask.
## Remember
- Review plan critically first
- 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
## Integration
**Required workflow skills:**
- **superpowers:using-git-worktrees** - REQUIRED: Set up isolated workspace before starting
- **superpowers:writing-plans** - Creates the plan this skill executes
- **superpowers:finishing-a-development-branch** - Complete development after all tasks

View File

@@ -1,8 +1,6 @@
---
name: Finishing a Development Branch
description: Complete feature development with structured options for merge, PR, or cleanup
when_to_use: After completing implementation. When all tests passing. At end of executing-plans or subagent-driven-development. When feature work is done.
version: 1.0.0
name: finishing-a-development-branch
description: Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup
---
# Finishing a Development Branch
@@ -13,7 +11,7 @@ Guide completion of development work by presenting clear options and handling ch
**Core principle:** Verify tests → Present options → Execute choice → Clean up.
**Announce at start:** "I'm using the Finishing a Development Branch skill to complete this work."
**Announce at start:** "I'm using the finishing-a-development-branch skill to complete this work."
## The Process
@@ -195,8 +193,8 @@ git worktree remove <worktree-path>
## Integration
**Called by:**
- skills/collaboration/subagent-driven-development (Step 7)
- skills/collaboration/executing-plans (Step 5)
- **subagent-driven-development** (Step 7) - After all tasks complete
- **executing-plans** (Step 5) - After all batches complete
**Pairs with:**
- skills/collaboration/using-git-worktrees (created the worktree)
- **using-git-worktrees** - Cleans up worktree created by that skill

View File

@@ -1,205 +0,0 @@
---
name: Getting Started with Skills
description: Skills wiki intro - mandatory workflows, search tool, brainstorming triggers, personal skills
when_to_use: Read this FIRST at start of each conversation when skills are active
version: 3.0.0
---
# Getting Started with Skills
Two skill libraries work together:
- **Core skills** at `${CLAUDE_PLUGIN_ROOT}/skills/` (from plugin)
- **Personal skills** at `~/.config/superpowers/skills/` (yours to create and share)
Personal skills shadow core skills when names match.
## Just Read This Guide?
**RIGHT NOW**: Find the plugin location and list skills:
```bash
# Find plugin location
find ~/.claude/plugins/cache -name "superpowers" -type d 2>/dev/null | grep -v ".git" | head -1
# Then run (replace PATH with the path found above):
PATH/scripts/find-skills
```
Or just use the full path directly:
```bash
~/.claude/plugins/cache/superpowers/scripts/find-skills
```
**THEN**: Follow the workflows below based on what your partner is asking for.
## How to Reference Skills
**DO NOT use @ links** - they force-load entire files, burning 200k+ context instantly.
**INSTEAD, use skill path references:**
- Format: `skills/category/skill-name` (no @ prefix, no /SKILL.md suffix)
- Example: `skills/collaboration/brainstorming` or `skills/testing/test-driven-development`
- Load with Read tool only when needed
**When you see skill references in documentation:**
- `skills/path/name` → Check personal first (`~/.config/superpowers/skills/path/name/SKILL.md`)
- If not found, check core (`${CLAUDE_PLUGIN_ROOT}/skills/path/name/SKILL.md`)
- Load supporting files only when implementing
## Mandatory Workflow 1: Brainstorming Before Coding
**When your human partner wants to start a project, no matter how big or small:**
**YOU MUST immediately read:** skills/collaboration/brainstorming
**Don't:**
- Jump straight to code
- Wait for /brainstorm command
- Skip brainstorming because you "understand the idea"
**Why:** Just writing code is almost never the right first step. We always understand requirements and plan first.
## Mandatory Workflow 2: Before ANY Task
**1. Find skills** (shows all, or filter by pattern):
Use the plugin cache path (default: `~/.claude/plugins/cache/superpowers`):
```bash
~/.claude/plugins/cache/superpowers/scripts/find-skills # Show all
~/.claude/plugins/cache/superpowers/scripts/find-skills PATTERN # Filter by pattern
```
**2. Search conversations:**
Dispatch subagent (see Workflow 3) to check for relevant past work.
**If skills found:**
1. READ the skill - check personal first (`~/.config/superpowers/skills/path/SKILL.md`), then core (`~/.claude/plugins/cache/superpowers/skills/path/SKILL.md`)
2. ANNOUNCE usage: "I'm using the [Skill Name] skill"
3. FOLLOW the skill (many are rigid requirements)
**"This doesn't count as a task" is rationalization.** Skills/conversations exist and you didn't search for them or didn't use them = failed task.
## Mandatory Workflow 3: Historical Context Search
**When:** Your human partner mentions past work, issue feels familiar, starting task in familiar domain, stuck/blocked, before reinventing
**When NOT:** Info in current convo, codebase state questions, first encounter, partner wants fresh thinking
**How (use subagent for 50-100x context savings):**
1. Dispatch subagent with template: `${CLAUDE_PLUGIN_ROOT}/skills/collaboration/remembering-conversations/tool/prompts/search-agent.md`
2. Receive synthesis (200-1000 words) + source pointers
3. Apply insights (never load raw .jsonl files)
**Example:**
```
Partner: "How did we handle auth errors in React Router?"
You: Searching past conversations...
[Dispatch subagent → 350-word synthesis]
[Apply without loading 50k tokens]
```
**Red flags:** Reading .jsonl files directly, pasting excerpts, asking "which conversation?", browsing archives
**Pattern:** Search → Subagent synthesizes → Apply. Fast, focused, context-efficient.
## Announcing Skill Usage
**Every time you start using a skill, announce it:**
"I'm using the [Skill Name] skill to [what you're doing]."
**Examples:**
- "I'm using the Brainstorming skill to refine your idea into a design."
- "I'm using the Test-Driven Development skill to implement this feature."
- "I'm using the Systematic Debugging skill to find the root cause."
- "I'm using the Refactoring Safely skill to extract these methods."
**Why:** Transparency helps your human partner understand your process and catch errors early.
## Skills with Checklists
**If a skill contains a checklist, you MUST create TodoWrite todos for EACH checklist item.**
**Don't:**
- Work through checklist mentally
- Skip creating todos "to save time"
- Batch multiple items into one todo
- Mark complete without doing them
**Why:** Checklists without TodoWrite tracking = steps get skipped. Every time.
**Examples:** TDD (write test, watch fail, implement, verify), Systematic Debugging (4 phases), Writing Skills (RED-GREEN-REFACTOR)
## How to Read a Skill
1. **Frontmatter** - `when_to_use` match your situation?
2. **Overview** - Core principle relevant?
3. **Quick Reference** - Scan for your pattern
4. **Implementation** - Full details
5. **Supporting files** - Load only when implementing
**Many skills contain rigid rules (TDD, debugging, verification).** Follow them exactly. Don't adapt away the discipline.
**Some skills are flexible patterns (architecture, naming).** Adapt core principles to your context.
The skill itself tells you which type it is.
## Referencing Skills in Documentation
**When writing documentation that references other skills:**
Use path format without `@` prefix or `/SKILL.md` suffix:
- ✅ Good: `skills/testing/test-driven-development`
- ✅ Good: `skills/debugging/systematic-debugging`
- ❌ Bad: `@skills/testing/test-driven-development/SKILL.md` (force-loads, burns context)
**Why no @ links:** `@` syntax force-loads files immediately, consuming 200k+ context before you need them.
**To read a skill reference:** Use Read tool on `${CLAUDE_PLUGIN_ROOT}/skills/category/skill-name/SKILL.md`
## Instructions ≠ Permission to Skip Workflows
Your human partner's specific instructions describe WHAT to do, not HOW.
"Add X", "Fix Y" = the goal, NOT permission to skip brainstorming, TDD, or RED-GREEN-REFACTOR.
**Red flags:** "Instruction was specific" • "Seems simple" • "Workflow is overkill"
## Writing and Sharing Skills
**All personal skills are written to `~/.config/superpowers/skills/`**
**Before writing ANY skill:**
1. **STOP** - Even if your human partner gave specific instructions
2. **Read skills/meta/writing-skills**
3. **Follow the TDD process** - No skill without failing test first
**Your human partner's specific instruction is NOT implicit permission to skip the process.**
**Red flags:**
- "Just a small addition"
- "Instruction was specific, so I can proceed"
**All of these mean: STOP and follow writing-skills process.**
**Want to share a skill with everyone?**
- See skills/meta/sharing-skills for how to contribute to core superpowers
**Want a skill that doesn't exist?**
- Write it yourself (see skills/meta/writing-skills) and share it!
- Or open an issue at https://github.com/obra/superpowers/issues
## Summary
**Starting conversation?** You just read this. Good.
**Starting any task?** Run find-skills first, announce usage, follow what you find.
**Skill has checklist?** TodoWrite for every item.
**Skills are mandatory when they exist, not optional.**
## Last thing
In the first response after reading this guide, you MUST announce to the user that you have read the getting started guide

View File

@@ -1,370 +0,0 @@
---
name: Gardening Skills Wiki
description: Maintain skills wiki health - check links, naming, cross-references, and coverage
when_to_use: When adding/removing skills. When reorganizing categories. When links feel broken. Periodically (weekly/monthly) to maintain wiki health. When INDEX files don't match directory structure. When cross-references might be stale.
version: 1.0.0
languages: bash
---
# Gardening Skills Wiki
## Overview
The skills wiki needs regular maintenance to stay healthy: links break, skills get orphaned, naming drifts, INDEX files fall out of sync.
**Core principle:** Automate health checks to maintain wiki quality without burning tokens on manual inspection.
## When to Use
**Run gardening after:**
- Adding new skills
- Removing or renaming skills
- Reorganizing categories
- Updating cross-references
- Suspicious that links are broken
**Periodic maintenance:**
- Weekly during active development
- Monthly during stable periods
## Quick Health Check
```bash
# Run all checks
~/.claude/skills/meta/gardening-skills-wiki/garden.sh
# Or run specific checks
~/.claude/skills/meta/gardening-skills-wiki/check-links.sh
~/.claude/skills/meta/gardening-skills-wiki/check-naming.sh
~/.claude/skills/meta/gardening-skills-wiki/check-index-coverage.sh
# Analyze search gaps (what skills are missing)
~/.claude/skills/meta/gardening-skills-wiki/analyze-search-gaps.sh
```
The master script runs all checks and provides a health report.
## What Gets Checked
### 1. Link Validation (`check-links.sh`)
**Checks:**
- Backtick-wrapped `@` links - backticks disable resolution
- Relative paths like skills/ or skills/gardening-skills-wiki/~/ - should use skills/ absolute paths
- All `skills/` references resolve to existing files
- Skills referenced in INDEX files exist
- Orphaned skills (not in any INDEX)
**Fixes:**
- Remove backticks from @ references
- Convert skills/ and skills/gardening-skills-wiki/~/ relative paths to skills/ absolute paths
- Update broken skills/ references to correct paths
- Add orphaned skills to their category INDEX
- Remove references to deleted skills
### 2. Naming Consistency (`check-naming.sh`)
**Checks:**
- Directory names are kebab-case
- No uppercase or underscores in directory names
- Frontmatter fields present (name, description, when_to_use, version, type)
- Skill names use active voice (not "How to...")
- Empty directories
**Fixes:**
- Rename directories to kebab-case
- Add missing frontmatter fields
- Remove empty directories
- Rephrase names to active voice
### 3. INDEX Coverage (`check-index-coverage.sh`)
**Checks:**
- All skills listed in their category INDEX
- All category INDEX files linked from main INDEX
- Skills have descriptions in INDEX entries
**Fixes:**
- Add missing skills to INDEX files
- Add category links to main INDEX
- Add descriptions for INDEX entries
## Common Issues and Fixes
### Broken Links
```
❌ BROKEN: skills/debugging/root-cause-tracing
Target: /path/to/skills/debugging/root-cause-tracing/SKILL.md
```
**Fix:** Update the reference path - skill might have moved or been renamed.
### Orphaned Skills
```
⚠️ ORPHANED: test-invariants/SKILL.md not in testing/INDEX.md
```
**Fix:** Add to the category INDEX:
```markdown
- skills/gardening-skills-wiki/test-invariants - Description of skill
```
### Backtick-Wrapped Links
```
❌ BACKTICKED: skills/testing/condition-based-waiting on line 31
File: getting-started/SKILL.md
Fix: Remove backticks - use bare @ reference
```
**Fix:** Remove backticks:
```markdown
# ❌ Bad - backticks disable link resolution
`skills/testing/condition-based-waiting`
# ✅ Good - bare @ reference
skills/testing/condition-based-waiting
```
### Relative Path Links
```
❌ RELATIVE: skills/testing in coding/SKILL.md
Fix: Use skills/ absolute path instead
```
**Fix:** Convert to absolute path:
```markdown
# ❌ Bad - relative paths are brittle
skills/testing/condition-based-waiting
# ✅ Good - absolute skills/ path
skills/testing/condition-based-waiting
```
### Naming Issues
```
⚠️ Mixed case: TestingPatterns (should be kebab-case)
```
**Fix:** Rename directory:
```bash
cd ~/.claude/skills/testing
mv TestingPatterns testing-patterns
# Update all references to old name
```
### Missing from INDEX
```
❌ NOT INDEXED: condition-based-waiting/SKILL.md
```
**Fix:** Add to `testing/INDEX.md`:
```markdown
## Available Skills
- skills/gardening-skills-wiki/condition-based-waiting - Replace timeouts with condition polling
```
### Empty Directories
```
⚠️ EMPTY: event-based-testing
```
**Fix:** Remove if no longer needed:
```bash
rm -rf ~/.claude/skills/event-based-testing
```
## Naming Conventions
### Directory Names
- **Format:** kebab-case (lowercase with hyphens)
- **Process skills:** Use gerunds when appropriate (`creating-skills`, `testing-skills`)
- **Pattern skills:** Use core concept (`flatten-with-flags`, `test-invariants`)
- **Avoid:** Mixed case, underscores, passive voice starters ("how-to-")
### Frontmatter Requirements
**Required fields:**
- `name`: Human-readable name
- `description`: One-line summary
- `when_to_use`: Symptoms and situations (CSO-critical)
- `version`: Semantic version
**Optional fields:**
- `languages`: Applicable languages
- `dependencies`: Required tools
- `context`: Special context (e.g., "AI-assisted development")
## Automation Workflow
### After Adding New Skill
```bash
# 1. Create skill
mkdir -p ~/.claude/skills/category/new-skill
vim ~/.claude/skills/category/new-skill/SKILL.md
# 2. Add to category INDEX
vim ~/.claude/skills/category/INDEX.md
# 3. Run health check
~/.claude/skills/meta/gardening-skills-wiki/garden.sh
# 4. Fix any issues reported
```
### After Reorganizing
```bash
# 1. Move/rename skills
mv ~/.claude/skills/old-category/skill ~/.claude/skills/new-category/
# 2. Update all references (grep for old paths)
grep -r "skills/gardening-skills-wiki/old-category/skill" ~/.claude/skills/
# 3. Run health check
~/.claude/skills/meta/gardening-skills-wiki/garden.sh
# 4. Fix broken links
```
### Periodic Maintenance
```bash
# Monthly: Run full health check
~/.claude/skills/meta/gardening-skills-wiki/garden.sh
# Review and fix:
# - ❌ errors (broken links, missing skills)
# - ⚠️ warnings (naming, empty dirs)
```
## The Scripts
### `garden.sh` (Master)
Runs all health checks and provides comprehensive report.
**Usage:**
```bash
~/.claude/skills/meta/gardening-skills-wiki/garden.sh [skills_dir]
```
### `check-links.sh`
Validates all `@` references and cross-links.
**Checks:**
- Backtick-wrapped `@` links (disables resolution)
- Relative paths (`skills/` or `skills/gardening-skills-wiki/~/`) - should be `skills/`
- `@` reference resolution to existing files
- Skills in INDEX files exist
- Orphaned skills detection
### `check-naming.sh`
Validates naming conventions and frontmatter.
**Checks:**
- Directory name format
- Frontmatter completeness
- Empty directories
### `check-index-coverage.sh`
Validates INDEX completeness.
**Checks:**
- Skills listed in category INDEX
- Categories linked in main INDEX
- Descriptions present
## Quick Reference
| Issue | Script | Fix |
|-------|--------|-----|
| Backtick-wrapped links | `check-links.sh` | Remove backticks from `@` refs |
| Relative paths | `check-links.sh` | Convert to `skills/` absolute |
| Broken links | `check-links.sh` | Update `@` references |
| Orphaned skills | `check-links.sh` | Add to INDEX |
| Naming issues | `check-naming.sh` | Rename directories |
| Empty dirs | `check-naming.sh` | Remove with `rm -rf` |
| Missing from INDEX | `check-index-coverage.sh` | Add to INDEX.md |
| No description | `check-index-coverage.sh` | Add to INDEX entry |
## Output Symbols
-**Pass** - Item is correct
-**Error** - Must fix (broken link, missing skill)
- ⚠️ **Warning** - Should fix (naming, empty dir)
- **Info** - Informational (no action needed)
## Integration with Workflow
**Before committing skill changes:**
```bash
~/.claude/skills/meta/gardening-skills-wiki/garden.sh
# Fix all ❌ errors
# Consider fixing ⚠️ warnings
git add .
git commit -m "Add/update skills"
```
**When links feel suspicious:**
```bash
~/.claude/skills/meta/gardening-skills-wiki/check-links.sh
```
**When INDEX seems incomplete:**
```bash
~/.claude/skills/meta/gardening-skills-wiki/check-index-coverage.sh
```
## Common Rationalizations
| Excuse | Reality |
|--------|---------|
| "Will check links manually" | Automated check is faster and more thorough |
| "INDEX probably fine" | Orphaned skills happen - always verify |
| "Naming doesn't matter" | Consistency aids discovery and maintenance |
| "Empty dir harmless" | Clutter confuses future maintainers |
| "Can skip periodic checks" | Issues compound - regular maintenance prevents big cleanups |
## Real-World Impact
**Without gardening:**
- Broken links discovered during urgent tasks
- Orphaned skills never found
- Naming drifts over time
- INDEX files fall out of sync
**With gardening:**
- 30-second health check catches issues early
- Automated validation prevents manual inspection
- Consistent structure aids discovery
- Wiki stays maintainable
## The Bottom Line
**Don't manually inspect - automate the checks.**
Run `garden.sh` after changes and periodically. Fix ❌ errors immediately, address ⚠️ warnings when convenient.
Maintained wiki = findable skills = reusable knowledge.

View File

@@ -1,35 +0,0 @@
#!/usr/bin/env bash
# Analyze failed skills-search queries to identify missing skills
set -euo pipefail
SKILLS_DIR="${HOME}/.claude/skills"
LOG_FILE="${SKILLS_DIR}/.search-log.jsonl"
if [[ ! -f "$LOG_FILE" ]]; then
echo "No search log found at $LOG_FILE"
exit 0
fi
echo "Skills Search Gap Analysis"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Count total searches
total=$(wc -l < "$LOG_FILE")
echo "Total searches: $total"
echo ""
# Extract and count unique queries
echo "Most common searches:"
jq -r '.query' "$LOG_FILE" 2>/dev/null | sort | uniq -c | sort -rn | head -20
echo ""
echo "Recent searches (last 10):"
tail -10 "$LOG_FILE" | jq -r '"\(.timestamp) - \(.query)"' 2>/dev/null
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "High-frequency searches indicate missing skills."
echo "Review patterns and create skills as needed."

View File

@@ -1,70 +0,0 @@
#!/bin/bash
# Check that all skills are properly listed in INDEX files
SKILLS_DIR="${1:-$HOME/Documents/GitHub/dotfiles/.claude/skills}"
echo "## INDEX Coverage"
# For each category with an INDEX
for category_dir in "$SKILLS_DIR"/*/; do
category=$(basename "$category_dir")
# Skip if not a directory
[[ ! -d "$category_dir" ]] && continue
index_file="$category_dir/INDEX.md"
# Skip if no INDEX (meta directories might not have one)
[[ ! -f "$index_file" ]] && continue
# Find all SKILL.md files in this category
skill_count=0
indexed_count=0
missing_count=0
while IFS= read -r skill_file; do
skill_count=$((skill_count + 1))
skill_name=$(basename $(dirname "$skill_file"))
# Check if skill is referenced in INDEX
if grep -q "@$skill_name/SKILL.md" "$index_file"; then
indexed_count=$((indexed_count + 1))
else
echo " ❌ NOT INDEXED: $skill_name/SKILL.md"
missing_count=$((missing_count + 1))
fi
done < <(find "$category_dir" -mindepth 2 -type f -name "SKILL.md")
if [ $skill_count -gt 0 ] && [ $missing_count -eq 0 ]; then
echo "$category: all $skill_count skills indexed"
elif [ $missing_count -gt 0 ]; then
echo " ⚠️ $category: $missing_count/$skill_count skills missing"
fi
done
echo ""
# Verify INDEX entries have descriptions
find "$SKILLS_DIR" -type f -name "INDEX.md" | while read -r index_file; do
category=$(basename $(dirname "$index_file"))
# Extract skill references
grep -o '@[a-zA-Z0-9-]*/SKILL\.md' "$index_file" | while read -r ref; do
skill_name=${ref#@}
skill_name=${skill_name%/SKILL.md}
# Get the line with the reference
line_num=$(grep -n "$ref" "$index_file" | cut -d: -f1)
# Check if there's a description on the same line or next line
description=$(sed -n "${line_num}p" "$index_file" | sed "s|.*$ref *- *||")
if [[ -z "$description" || "$description" == *"$ref"* ]]; then
# No description on same line, check next line
next_line=$((line_num + 1))
description=$(sed -n "${next_line}p" "$index_file")
if [[ -z "$description" ]]; then
echo " ⚠️ NO DESCRIPTION: $category/INDEX.md reference to $skill_name"
fi
fi
done
done

View File

@@ -1,119 +0,0 @@
#!/bin/bash
# Check for @ links (force-load context) and validate skill path references
SKILLS_DIR="${1:-$HOME/Documents/GitHub/dotfiles/.claude/skills}"
echo "## Links & References"
broken_refs=0
backticked_refs=0
relative_refs=0
at_links=0
while IFS= read -r file; do
# Extract @ references - must start line, be after space/paren/dash, or be standalone
# Exclude: emails, decorators, code examples with @staticmethod/@example
# First, check for backtick-wrapped @ links
grep -nE '`[^`]*@[a-zA-Z0-9._~/-]+\.(md|sh|ts|js|py)[^`]*`' "$file" | while IFS=: read -r line_num match; do
# Get actual line to check if in code block
actual_line=$(sed -n "${line_num}p" "$file")
# Skip if line is indented (code block) or in fenced code
if [[ "$actual_line" =~ ^[[:space:]]{4,} ]]; then
continue
fi
code_block_count=$(sed -n "1,${line_num}p" "$file" | grep -c '^```')
if [ $((code_block_count % 2)) -eq 1 ]; then
continue
fi
ref=$(echo "$match" | grep -o '@[a-zA-Z0-9._~/-]*\.[a-zA-Z0-9]*')
echo " ❌ BACKTICKED: $ref on line $line_num"
echo " File: $(basename $(dirname "$file"))/$(basename "$file")"
echo " Fix: Remove backticks - use bare @ reference"
backticked_refs=$((backticked_refs + 1))
done
# Check for ANY @ links to .md/.sh/.ts/.js/.py files (force-loads, burns context)
grep -nE '(^|[ \(>-])@[a-zA-Z0-9._/-]+\.(md|sh|ts|js|py)' "$file" | \
grep -v '@[a-zA-Z0-9._%+-]*@' | \
grep -v 'email.*@' | \
grep -v '`.*@.*`' | while IFS=: read -r line_num match; do
ref=$(echo "$match" | grep -o '@[a-zA-Z0-9._/-]+\.(md|sh|ts|js|py)')
ref_path="${ref#@}"
# Skip if in fenced code block
actual_line=$(sed -n "${line_num}p" "$file")
if [[ "$actual_line" =~ ^[[:space:]]{4,} ]]; then
continue
fi
code_block_count=$(sed -n "1,${line_num}p" "$file" | grep -c '^```')
if [ $((code_block_count % 2)) -eq 1 ]; then
continue
fi
# Any @ link is wrong - should use skills/path format
echo " ❌ @ LINK: $ref on line $line_num"
echo " File: $(basename $(dirname "$file"))/$(basename "$file")"
# Suggest correct format
if [[ "$ref_path" == skills/* ]]; then
# @skills/category/name/SKILL.md → skills/category/name
corrected="${ref_path#skills/}"
corrected="${corrected%/SKILL.md}"
echo " Fix: $ref → skills/$corrected"
elif [[ "$ref_path" == ../* ]]; then
echo " Fix: Convert to skills/category/skill-name format"
else
echo " Fix: Convert to skills/category/skill-name format"
fi
at_links=$((at_links + 1))
done
done < <(find "$SKILLS_DIR" -type f -name "*.md")
# Summary
total_issues=$((backticked_refs + at_links))
if [ $total_issues -eq 0 ]; then
echo " ✅ All skill references OK"
else
[ $backticked_refs -gt 0 ] && echo "$backticked_refs backticked references"
[ $at_links -gt 0 ] && echo "$at_links @ links (force-load context)"
fi
echo ""
echo "Correct format: skills/category/skill-name"
echo " ❌ Bad: @skills/path/SKILL.md (force-loads) or @../path (brittle)"
echo " ✅ Good: skills/category/skill-name (load with Read tool when needed)"
echo ""
# Verify all skills mentioned in INDEX files exist
find "$SKILLS_DIR" -type f -name "INDEX.md" | while read -r index_file; do
index_dir=$(dirname "$index_file")
# Extract skill references (format: @skill-name/SKILL.md)
grep -o '@[a-zA-Z0-9-]*/SKILL\.md' "$index_file" | while read -r skill_ref; do
skill_path="$index_dir/${skill_ref#@}"
if [[ ! -f "$skill_path" ]]; then
echo " ❌ BROKEN: $skill_ref in $(basename "$index_dir")/INDEX.md"
echo " Expected: $skill_path"
fi
done
done
echo ""
find "$SKILLS_DIR" -type f -path "*/*/SKILL.md" | while read -r skill_file; do
skill_dir=$(basename $(dirname "$skill_file"))
category_dir=$(dirname $(dirname "$skill_file"))
index_file="$category_dir/INDEX.md"
if [[ -f "$index_file" ]]; then
if ! grep -q "@$skill_dir/SKILL.md" "$index_file"; then
echo " ⚠️ ORPHANED: $skill_dir/SKILL.md not in $(basename "$category_dir")/INDEX.md"
fi
fi
done

View File

@@ -1,72 +0,0 @@
#!/bin/bash
# Check naming consistency in skills wiki
SKILLS_DIR="${1:-$HOME/Documents/GitHub/dotfiles/.claude/skills}"
echo "## Naming & Structure"
issues=0
find "$SKILLS_DIR" -type d -mindepth 2 -maxdepth 2 | while read -r dir; do
dir_name=$(basename "$dir")
# Skip if it's an INDEX or top-level category
if [[ "$dir_name" == "INDEX.md" ]] || [[ $(dirname "$dir") == "$SKILLS_DIR" ]]; then
continue
fi
# Check for naming issues
if [[ "$dir_name" =~ [A-Z] ]]; then
echo " ⚠️ Mixed case: $dir_name (should be kebab-case)"
issues=$((issues + 1))
fi
if [[ "$dir_name" =~ _ ]]; then
echo " ⚠️ Underscore: $dir_name (should use hyphens)"
issues=$((issues + 1))
fi
# Check if name follows gerund pattern for process skills
if [[ -f "$dir/SKILL.md" ]]; then
type=$(grep "^type:" "$dir/SKILL.md" | head -1 | cut -d: -f2 | xargs)
if [[ "$type" == "technique" ]] && [[ ! "$dir_name" =~ ing$ ]] && [[ ! "$dir_name" =~ -with- ]] && [[ ! "$dir_name" =~ ^test- ]]; then
# Techniques might want -ing but not required
:
fi
fi
done
[ $issues -eq 0 ] && echo " ✅ Directory names OK" || echo " ⚠️ $issues naming issues"
echo ""
find "$SKILLS_DIR" -type d -empty | while read -r empty_dir; do
echo " ⚠️ EMPTY: $(realpath --relative-to="$SKILLS_DIR" "$empty_dir" 2>/dev/null || echo "$empty_dir")"
done
echo ""
find "$SKILLS_DIR" -type f -name "SKILL.md" | while read -r skill_file; do
skill_name=$(basename $(dirname "$skill_file"))
# Check for required fields
if ! grep -q "^name:" "$skill_file"; then
echo " ❌ MISSING 'name': $skill_name/SKILL.md"
fi
if ! grep -q "^description:" "$skill_file"; then
echo " ❌ MISSING 'description': $skill_name/SKILL.md"
fi
if ! grep -q "^when_to_use:" "$skill_file"; then
echo " ❌ MISSING 'when_to_use': $skill_name/SKILL.md"
fi
if ! grep -q "^version:" "$skill_file"; then
echo " ⚠️ MISSING 'version': $skill_name/SKILL.md"
fi
# Check for active voice in name (should not start with "How to")
name_value=$(grep "^name:" "$skill_file" | head -1 | cut -d: -f2- | xargs)
if [[ "$name_value" =~ ^How\ to ]]; then
echo " ⚠️ Passive name: $skill_name has 'How to' prefix (prefer active voice)"
fi
done

View File

@@ -1,25 +0,0 @@
#!/bin/bash
# Master gardening script for skills wiki maintenance
SKILLS_DIR="${1:-$HOME/Documents/GitHub/dotfiles/.claude/skills}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo "=== Skills Wiki Health Check ==="
echo ""
# Make scripts executable if not already
chmod +x "$SCRIPT_DIR"/*.sh 2>/dev/null
# Run all checks
bash "$SCRIPT_DIR/check-naming.sh" "$SKILLS_DIR"
echo ""
bash "$SCRIPT_DIR/check-links.sh" "$SKILLS_DIR"
echo ""
bash "$SCRIPT_DIR/check-index-coverage.sh" "$SKILLS_DIR"
echo ""
echo "=== Health Check Complete ==="
echo ""
echo "Fix: ❌ errors (broken/missing) | Consider: ⚠️ warnings | ✅ = correct"

View File

@@ -1,162 +0,0 @@
---
name: Setting Up Personal Superpowers
description: Automatic setup of ~/.config/superpowers/ for personal skills, optional GitHub repo creation
when_to_use: Runs automatically on first session. Reference when helping users with personal skills setup.
version: 1.0.0
languages: bash
---
# Setting Up Personal Superpowers
## Overview
Personal superpowers directory is automatically set up on your first session. It provides a place to create and manage your own skills alongside the core superpowers library.
**Default location:** `~/.config/superpowers/`
**Customizable via:**
- `PERSONAL_SUPERPOWERS_DIR` environment variable (highest priority)
- `XDG_CONFIG_HOME` environment variable (if set, uses `$XDG_CONFIG_HOME/superpowers`)
- Falls back to `~/.config/superpowers`
**Structure:**
```
~/.config/superpowers/
├── .git/ # Git repository
├── .gitignore # Ignores logs and indexes
├── README.md # About your personal superpowers
├── skills/ # Your personal skills
│ └── your-skill/
│ └── SKILL.md
├── search-log.jsonl # Skill search history (not tracked)
└── conversation-index/ # Conversation search index (not tracked)
```
## How It Works
The SessionStart hook runs `hooks/setup-personal-superpowers.sh` which:
1. Checks if `~/.config/superpowers/.git/` and `~/.config/superpowers/skills/` exist
2. If not, creates directory structure
3. Initializes git repository
4. Creates `.gitignore`, `README.md`
5. Makes initial commit
6. Checks for `gh` CLI availability
If GitHub CLI is available and no remote exists, you'll see a recommendation to create a public GitHub repo.
## Creating GitHub Repository
When prompted, you can create a public `personal-superpowers` repo:
```bash
cd ~/.config/superpowers
gh repo create personal-superpowers --public --source=. --push
gh repo edit --add-topic superpowers
```
**Why public?** Superpowers are best when everyone can learn from them!
**Privacy:** If you prefer private or local-only:
- **Private:** Use `--private` instead of `--public`
- **Local-only:** Just use the local git repo without pushing to GitHub
## What Gets Tracked
**.gitignore includes:**
- `search-log.jsonl` - Your skill search history
- `conversation-index/` - Conversation search index
- `conversation-archive/` - Archived conversations
**Everything else is tracked**, including:
- Your personal skills in `skills/`
- README.md
- Any additional documentation you add
## Personal vs Core Skills
**Search order:**
1. `~/.config/superpowers/skills/` (personal)
2. `${CLAUDE_PLUGIN_ROOT}/skills/` (core)
**Personal skills shadow core skills** - if you have `~/.config/superpowers/skills/testing/test-driven-development/SKILL.md`, it will be used instead of the core version.
The `find-skills` tool automatically searches both locations with deduplication.
## Writing Skills
See skills/meta/writing-skills for how to create new skills.
All personal skills are written to `~/.config/superpowers/skills/`.
## Sharing Skills
See skills/meta/sharing-skills for how to contribute skills back to the core superpowers repository.
## Custom Location
To use a different location for your personal superpowers:
```bash
# In your shell rc file (.bashrc, .zshrc, etc)
export PERSONAL_SUPERPOWERS_DIR="$HOME/my-superpowers"
# Or use XDG_CONFIG_HOME
export XDG_CONFIG_HOME="$HOME/.local/config" # Will use $HOME/.local/config/superpowers
```
## Manual Setup
If auto-setup fails or you need to set up manually:
```bash
# Use your preferred location
SUPERPOWERS_DIR="${PERSONAL_SUPERPOWERS_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/superpowers}"
mkdir -p "$SUPERPOWERS_DIR/skills"
cd "$SUPERPOWERS_DIR"
git init
cat > .gitignore <<'EOF'
search-log.jsonl
conversation-index/
conversation-archive/
EOF
cat > README.md <<'EOF'
# My Personal Superpowers
Personal skills and techniques for Claude Code.
Learn more about Superpowers: https://github.com/obra/superpowers
EOF
git add .gitignore README.md
git commit -m "Initial commit: Personal superpowers setup"
# Optional: Create GitHub repo
gh repo create personal-superpowers --public --source=. --push
gh repo edit --add-topic superpowers
```
## Troubleshooting
**Setup failed during SessionStart:**
File a bug at https://github.com/obra/superpowers/issues
**Personal skills not being found:**
- Check `~/.config/superpowers/skills/` exists
- Verify skill has `SKILL.md` file
- Run `${CLAUDE_PLUGIN_ROOT}/scripts/find-skills` to see if it appears
**GitHub push failed:**
- Check `gh auth status`
- Verify repo was created: `gh repo view personal-superpowers`
- Try manual push: `cd ~/.config/superpowers && git push -u origin main`
## Multi-CLI Support
The personal superpowers directory is CLI-agnostic. It works with:
- Claude Code (current)
- OpenAI Codex CLI (future)
- Gemini CLI (future)
Each CLI installs its own base superpowers, but they all read from the same `~/.config/superpowers/skills/` for personal skills.

View File

@@ -1,240 +0,0 @@
---
name: Sharing Skills
description: Contribute personal skills back to core superpowers via fork, branch, and PR
when_to_use: When you have a personal skill that would benefit others and want to contribute it to the core superpowers library
version: 1.0.0
languages: bash
---
# Sharing Skills
## Overview
Contribute personal skills from `~/.config/superpowers/skills/` back to the core superpowers repository.
**Workflow:** Fork → Clone to temp → Sync → Branch → Copy skill → Commit → Push → PR
## When to Share
**Share when:**
- Skill applies broadly (not project-specific)
- Pattern/technique others would benefit from
- Well-tested and documented
- Follows skills/meta/writing-skills guidelines
**Keep personal when:**
- Project-specific or organization-specific
- Experimental or unstable
- Contains sensitive information
- Too narrow/niche for general use
## Prerequisites
- `gh` CLI installed and authenticated
- Personal skill exists in `~/.config/superpowers/skills/your-skill/`
- Skill has been tested (see skills/meta/writing-skills for TDD process)
## Sharing Workflow
### 1. Fork Core Repository
```bash
# Check if you already have a fork
gh repo view YOUR_USERNAME/superpowers 2>/dev/null || gh repo fork obra/superpowers
```
### 2. Clone to Temporary Directory
```bash
# Create temp directory for contribution
temp_dir=$(mktemp -d)
cd "$temp_dir"
git clone git@github.com:YOUR_USERNAME/superpowers.git
cd superpowers
```
### 3. Sync with Upstream
```bash
# Add upstream if not already added
git remote add upstream https://github.com/obra/superpowers 2>/dev/null || true
# Fetch and merge latest from upstream
git fetch upstream
git checkout main
git merge upstream/main
git push origin main
```
### 4. Create Feature Branch
```bash
# Branch name: add-skillname-skill
skill_name="your-skill-name"
git checkout -b "add-${skill_name}-skill"
```
### 5. Copy Skill from Personal Repo
```bash
# Copy skill directory from personal superpowers
cp -r ~/.config/superpowers/skills/your-skill-name/ superpowers/skills/
# Verify it copied correctly
ls -la superpowers/skills/your-skill-name/
```
### 6. Commit Changes
```bash
# Add and commit
git add superpowers/skills/your-skill-name/
git commit -m "Add ${skill_name} skill
$(cat <<'EOF'
Brief description of what this skill does and why it's useful.
Tested with: [describe testing approach]
EOF
)"
```
### 7. Push to Your Fork
```bash
git push -u origin "add-${skill_name}-skill"
```
### 8. Create Pull Request
```bash
# Create PR using gh CLI
gh pr create \
--repo obra/superpowers \
--title "Add ${skill_name} skill" \
--body "$(cat <<'EOF'
## Summary
Brief description of the skill and what problem it solves.
## Testing
Describe how you tested this skill (pressure scenarios, baseline tests, etc.).
## Context
Any additional context about why this skill is needed and how it should be used.
EOF
)"
```
### 9. Cleanup
```bash
# Remove temp directory after PR is created
cd ~
rm -rf "$temp_dir"
```
## Complete Example
Here's a complete example of sharing a personal skill called "async-patterns":
```bash
# 1. Fork if needed
gh repo view $(gh api user --jq .login)/superpowers 2>/dev/null || gh repo fork obra/superpowers
# 2-3. Clone and sync
temp_dir=$(mktemp -d) && cd "$temp_dir"
gh repo clone $(gh api user --jq .login)/superpowers
cd superpowers
git remote add upstream https://github.com/obra/superpowers 2>/dev/null || true
git fetch upstream
git checkout main
git merge upstream/main
git push origin main
# 4. Create branch
git checkout -b "add-async-patterns-skill"
# 5. Copy skill
cp -r ~/.config/superpowers/skills/async-patterns/ superpowers/skills/
# 6. Commit
git add superpowers/skills/async-patterns/
git commit -m "Add async-patterns skill
Patterns for handling asynchronous operations in tests and application code.
Tested with: Multiple pressure scenarios testing agent compliance."
# 7. Push
git push -u origin "add-async-patterns-skill"
# 8. Create PR
gh pr create \
--repo obra/superpowers \
--title "Add async-patterns skill" \
--body "## Summary
Patterns for handling asynchronous operations correctly in tests and application code.
## Testing
Tested with multiple application scenarios. Agents successfully apply patterns to new code.
## Context
Addresses common async pitfalls like race conditions, improper error handling, and timing issues."
# 9. Cleanup
cd ~ && rm -rf "$temp_dir"
```
## After PR is Merged
Once your PR is merged:
**Option 1: Keep personal version**
- Useful if you want to continue iterating locally
- Your personal version will shadow the core version
- Can later delete personal version to use core
**Option 2: Delete personal version**
```bash
# Remove from personal repo to use core version
rm -rf ~/.config/superpowers/skills/your-skill-name/
cd ~/.config/superpowers
git add skills/your-skill-name/
git commit -m "Remove your-skill-name (now in core)"
git push
```
## Troubleshooting
**"gh: command not found"**
- Install GitHub CLI: https://cli.github.com/
- Authenticate: `gh auth login`
**"Permission denied (publickey)"**
- Check SSH keys: `gh auth status`
- Set up SSH: https://docs.github.com/en/authentication
**"Skill already exists in core"**
- You're creating a modified version
- Consider different skill name or shadow the core version in personal repo
**PR merge conflicts**
- Rebase on latest upstream: `git fetch upstream && git rebase upstream/main`
- Resolve conflicts
- Force push: `git push -f origin your-branch`
## Multi-Skill Contributions
**Do NOT batch multiple skills in one PR.**
Each skill should:
- Have its own feature branch
- Have its own PR
- Be independently reviewable
**Why?** Individual skills can be reviewed, iterated, and merged independently.
## Related Skills
- **skills/meta/writing-skills** - How to create well-tested skills
- **skills/meta/setting-up-personal-superpowers** - Initial setup of personal repo

View File

@@ -1,8 +1,6 @@
---
name: Code Review Reception
description: Receive and act on code review feedback with technical rigor, not performative agreement or blind implementation
when_to_use: When receiving code review feedback from your human partner or external reviewers. Before implementing review suggestions. When PR comments arrive. When feedback seems wrong or unclear.
version: 1.0.0
name: receiving-code-review
description: Use when receiving code review feedback, before implementing suggestions, especially if feedback seems unclear or technically questionable - requires technical rigor and verification, not performative agreement or blind implementation
---
# Code Review Reception
@@ -202,6 +200,10 @@ You understand 1,2,3,6. Unclear on 4,5.
✅ "Understand 1,2,3,6. Need clarification on 4 and 5 before implementing."
```
## GitHub Thread Replies
When replying to inline review comments on GitHub, reply in the comment thread (`gh api repos/{owner}/{repo}/pulls/{pr}/comments/{id}/replies`), not as a top-level PR comment.
## The Bottom Line
**External feedback = suggestions to evaluate, not orders to follow.**

View File

@@ -1,13 +1,11 @@
---
name: Requesting Code Review
description: Dispatch code-reviewer subagent to review implementation against plan or requirements before proceeding
when_to_use: After completing a task. After major feature implementation. Before merging. When executing plans (after each task). When stuck and need fresh perspective.
version: 1.0.0
name: requesting-code-review
description: Use when completing tasks, implementing major features, or before merging to verify work meets requirements
---
# Requesting Code Review
Dispatch code-reviewer subagent to catch issues before they cascade.
Dispatch superpowers:code-reviewer subagent to catch issues before they cascade.
**Core principle:** Review early, review often.
@@ -33,7 +31,7 @@ HEAD_SHA=$(git rev-parse HEAD)
**2. Dispatch code-reviewer subagent:**
Use Task tool with code-reviewer type, fill template at `code-reviewer.md`
Use Task tool with superpowers:code-reviewer type, fill template at `code-reviewer.md`
**Placeholders:**
- `{WHAT_WAS_IMPLEMENTED}` - What you just built
@@ -58,9 +56,9 @@ You: Let me request code review before proceeding.
BASE_SHA=$(git log --oneline | grep "Task 1" | head -1 | awk '{print $1}')
HEAD_SHA=$(git rev-parse HEAD)
[Dispatch code-reviewer subagent]
[Dispatch superpowers:code-reviewer subagent]
WHAT_WAS_IMPLEMENTED: Verification and repair functions for conversation index
PLAN_OR_REQUIREMENTS: Task 2 from docs/plans/deployment-plan.md
PLAN_OR_REQUIREMENTS: Task 2 from docs/superpowers/plans/deployment-plan.md
BASE_SHA: a7981ec
HEAD_SHA: 3df7661
DESCRIPTION: Added verifyIndex() and repairIndex() with 4 issue types
@@ -104,4 +102,4 @@ You: [Fix progress indicators]
- Show code/tests that prove it works
- Request clarification
See template at: skills/collaboration/requesting-code-review/code-reviewer.md
See template at: requesting-code-review/code-reviewer.md

View File

@@ -0,0 +1,275 @@
---
name: subagent-driven-development
description: Use when executing implementation plans with independent tasks in the current session
---
# Subagent-Driven Development
Execute plan by dispatching fresh subagent per task, with two-stage review after each: spec compliance review first, then code quality review.
**Core principle:** Fresh subagent per task + two-stage review (spec then quality) = high quality, fast iteration
## When to Use
```dot
digraph when_to_use {
"Have implementation plan?" [shape=diamond];
"Tasks mostly independent?" [shape=diamond];
"Stay in this session?" [shape=diamond];
"subagent-driven-development" [shape=box];
"executing-plans" [shape=box];
"Manual execution or brainstorm first" [shape=box];
"Have implementation plan?" -> "Tasks mostly independent?" [label="yes"];
"Have implementation plan?" -> "Manual execution or brainstorm first" [label="no"];
"Tasks mostly independent?" -> "Stay in this session?" [label="yes"];
"Tasks mostly independent?" -> "Manual execution or brainstorm first" [label="no - tightly coupled"];
"Stay in this session?" -> "subagent-driven-development" [label="yes"];
"Stay in this session?" -> "executing-plans" [label="no - parallel session"];
}
```
**vs. Executing Plans (parallel session):**
- Same session (no context switch)
- Fresh subagent per task (no context pollution)
- Two-stage review after each task: spec compliance first, then code quality
- Faster iteration (no human-in-loop between tasks)
## The Process
```dot
digraph process {
rankdir=TB;
subgraph cluster_per_task {
label="Per Task";
"Dispatch implementer subagent (./implementer-prompt.md)" [shape=box];
"Implementer subagent asks questions?" [shape=diamond];
"Answer questions, provide context" [shape=box];
"Implementer subagent implements, tests, commits, self-reviews" [shape=box];
"Dispatch spec reviewer subagent (./spec-reviewer-prompt.md)" [shape=box];
"Spec reviewer subagent confirms code matches spec?" [shape=diamond];
"Implementer subagent fixes spec gaps" [shape=box];
"Dispatch code quality reviewer subagent (./code-quality-reviewer-prompt.md)" [shape=box];
"Code quality reviewer subagent approves?" [shape=diamond];
"Implementer subagent fixes quality issues" [shape=box];
"Mark task complete in TodoWrite" [shape=box];
}
"Read plan, extract all tasks with full text, note context, create TodoWrite" [shape=box];
"More tasks remain?" [shape=diamond];
"Dispatch final code reviewer subagent for entire implementation" [shape=box];
"Use superpowers:finishing-a-development-branch" [shape=box style=filled fillcolor=lightgreen];
"Read plan, extract all tasks with full text, note context, create TodoWrite" -> "Dispatch implementer subagent (./implementer-prompt.md)";
"Dispatch implementer subagent (./implementer-prompt.md)" -> "Implementer subagent asks questions?";
"Implementer subagent asks questions?" -> "Answer questions, provide context" [label="yes"];
"Answer questions, provide context" -> "Dispatch implementer subagent (./implementer-prompt.md)";
"Implementer subagent asks questions?" -> "Implementer subagent implements, tests, commits, self-reviews" [label="no"];
"Implementer subagent implements, tests, commits, self-reviews" -> "Dispatch spec reviewer subagent (./spec-reviewer-prompt.md)";
"Dispatch spec reviewer subagent (./spec-reviewer-prompt.md)" -> "Spec reviewer subagent confirms code matches spec?";
"Spec reviewer subagent confirms code matches spec?" -> "Implementer subagent fixes spec gaps" [label="no"];
"Implementer subagent fixes spec gaps" -> "Dispatch spec reviewer subagent (./spec-reviewer-prompt.md)" [label="re-review"];
"Spec reviewer subagent confirms code matches spec?" -> "Dispatch code quality reviewer subagent (./code-quality-reviewer-prompt.md)" [label="yes"];
"Dispatch code quality reviewer subagent (./code-quality-reviewer-prompt.md)" -> "Code quality reviewer subagent approves?";
"Code quality reviewer subagent approves?" -> "Implementer subagent fixes quality issues" [label="no"];
"Implementer subagent fixes quality issues" -> "Dispatch code quality reviewer subagent (./code-quality-reviewer-prompt.md)" [label="re-review"];
"Code quality reviewer subagent approves?" -> "Mark task complete in TodoWrite" [label="yes"];
"Mark task complete in TodoWrite" -> "More tasks remain?";
"More tasks remain?" -> "Dispatch implementer subagent (./implementer-prompt.md)" [label="yes"];
"More tasks remain?" -> "Dispatch final code reviewer subagent for entire implementation" [label="no"];
"Dispatch final code reviewer subagent for entire implementation" -> "Use superpowers:finishing-a-development-branch";
}
```
## Model Selection
Use the least powerful model that can handle each role to conserve cost and increase speed.
**Mechanical implementation tasks** (isolated functions, clear specs, 1-2 files): use a fast, cheap model. Most implementation tasks are mechanical when the plan is well-specified.
**Integration and judgment tasks** (multi-file coordination, pattern matching, debugging): use a standard model.
**Architecture, design, and review tasks**: use the most capable available model.
**Task complexity signals:**
- Touches 1-2 files with a complete spec → cheap model
- Touches multiple files with integration concerns → standard model
- Requires design judgment or broad codebase understanding → most capable model
## Handling Implementer Status
Implementer subagents report one of four statuses. Handle each appropriately:
**DONE:** Proceed to spec compliance review.
**DONE_WITH_CONCERNS:** The implementer completed the work but flagged doubts. Read the concerns before proceeding. If the concerns are about correctness or scope, address them before review. If they're observations (e.g., "this file is getting large"), note them and proceed to review.
**NEEDS_CONTEXT:** The implementer needs information that wasn't provided. Provide the missing context and re-dispatch.
**BLOCKED:** The implementer cannot complete the task. Assess the blocker:
1. If it's a context problem, provide more context and re-dispatch with the same model
2. If the task requires more reasoning, re-dispatch with a more capable model
3. If the task is too large, break it into smaller pieces
4. If the plan itself is wrong, escalate to the human
**Never** ignore an escalation or force the same model to retry without changes. If the implementer said it's stuck, something needs to change.
## Prompt Templates
- `./implementer-prompt.md` - Dispatch implementer subagent
- `./spec-reviewer-prompt.md` - Dispatch spec compliance reviewer subagent
- `./code-quality-reviewer-prompt.md` - Dispatch code quality reviewer subagent
## Example Workflow
```
You: I'm using Subagent-Driven Development to execute this plan.
[Read plan file once: docs/superpowers/plans/feature-plan.md]
[Extract all 5 tasks with full text and context]
[Create TodoWrite with all tasks]
Task 1: Hook installation script
[Get Task 1 text and context (already extracted)]
[Dispatch implementation subagent with full task text + context]
Implementer: "Before I begin - should the hook be installed at user or system level?"
You: "User level (~/.config/superpowers/hooks/)"
Implementer: "Got it. Implementing now..."
[Later] Implementer:
- Implemented install-hook command
- Added tests, 5/5 passing
- Self-review: Found I missed --force flag, added it
- Committed
[Dispatch spec compliance reviewer]
Spec reviewer: ✅ Spec compliant - all requirements met, nothing extra
[Get git SHAs, dispatch code quality reviewer]
Code reviewer: Strengths: Good test coverage, clean. Issues: None. Approved.
[Mark Task 1 complete]
Task 2: Recovery modes
[Get Task 2 text and context (already extracted)]
[Dispatch implementation subagent with full task text + context]
Implementer: [No questions, proceeds]
Implementer:
- Added verify/repair modes
- 8/8 tests passing
- Self-review: All good
- Committed
[Dispatch spec compliance reviewer]
Spec reviewer: ❌ Issues:
- Missing: Progress reporting (spec says "report every 100 items")
- Extra: Added --json flag (not requested)
[Implementer fixes issues]
Implementer: Removed --json flag, added progress reporting
[Spec reviewer reviews again]
Spec reviewer: ✅ Spec compliant now
[Dispatch code quality reviewer]
Code reviewer: Strengths: Solid. Issues (Important): Magic number (100)
[Implementer fixes]
Implementer: Extracted PROGRESS_INTERVAL constant
[Code reviewer reviews again]
Code reviewer: ✅ Approved
[Mark Task 2 complete]
...
[After all tasks]
[Dispatch final code-reviewer]
Final reviewer: All requirements met, ready to merge
Done!
```
## Advantages
**vs. Manual execution:**
- Subagents follow TDD naturally
- Fresh context per task (no confusion)
- Parallel-safe (subagents don't interfere)
- Subagent can ask questions (before AND during work)
**vs. Executing Plans:**
- Same session (no handoff)
- Continuous progress (no waiting)
- Review checkpoints automatic
**Efficiency gains:**
- No file reading overhead (controller provides full text)
- Controller curates exactly what context is needed
- Subagent gets complete information upfront
- Questions surfaced before work begins (not after)
**Quality gates:**
- Self-review catches issues before handoff
- Two-stage review: spec compliance, then code quality
- Review loops ensure fixes actually work
- Spec compliance prevents over/under-building
- Code quality ensures implementation is well-built
**Cost:**
- More subagent invocations (implementer + 2 reviewers per task)
- Controller does more prep work (extracting all tasks upfront)
- Review loops add iterations
- But catches issues early (cheaper than debugging later)
## Red Flags
**Never:**
- Start implementation on main/master branch without explicit user consent
- Skip reviews (spec compliance OR code quality)
- Proceed with unfixed issues
- Dispatch multiple implementation subagents in parallel (conflicts)
- Make subagent read plan file (provide full text instead)
- Skip scene-setting context (subagent needs to understand where task fits)
- Ignore subagent questions (answer before letting them proceed)
- Accept "close enough" on spec compliance (spec reviewer found issues = not done)
- Skip review loops (reviewer found issues = implementer fixes = review again)
- Let implementer self-review replace actual review (both are needed)
- **Start code quality review before spec compliance is ✅** (wrong order)
- Move to next task while either review has open issues
**If subagent asks questions:**
- Answer clearly and completely
- Provide additional context if needed
- Don't rush them into implementation
**If reviewer finds issues:**
- Implementer (same subagent) fixes them
- Reviewer reviews again
- Repeat until approved
- Don't skip the re-review
**If subagent fails task:**
- Dispatch fix subagent with specific instructions
- Don't try to fix manually (context pollution)
## Integration
**Required workflow skills:**
- **superpowers:using-git-worktrees** - REQUIRED: Set up isolated workspace before starting
- **superpowers:writing-plans** - Creates the plan this skill executes
- **superpowers:requesting-code-review** - Code review template for reviewer subagents
- **superpowers:finishing-a-development-branch** - Complete development after all tasks
**Subagents should use:**
- **superpowers:test-driven-development** - Subagents follow TDD for each task
**Alternative workflow:**
- **superpowers:executing-plans** - Use for parallel session instead of same-session execution

View File

@@ -0,0 +1,26 @@
# Code Quality Reviewer Prompt Template
Use this template when dispatching a code quality reviewer subagent.
**Purpose:** Verify implementation is well-built (clean, tested, maintainable)
**Only dispatch after spec compliance review passes.**
```
Task tool (superpowers:code-reviewer):
Use template at requesting-code-review/code-reviewer.md
WHAT_WAS_IMPLEMENTED: [from implementer's report]
PLAN_OR_REQUIREMENTS: Task N from [plan-file]
BASE_SHA: [commit before task]
HEAD_SHA: [current commit]
DESCRIPTION: [task summary]
```
**In addition to standard code quality concerns, the reviewer should check:**
- Does each file have one clear responsibility with a well-defined interface?
- Are units decomposed so they can be understood and tested independently?
- Is the implementation following the file structure from the plan?
- Did this implementation create new files that are already large, or significantly grow existing files? (Don't flag pre-existing file sizes — focus on what this change contributed.)
**Code reviewer returns:** Strengths, Issues (Critical/Important/Minor), Assessment

View File

@@ -0,0 +1,113 @@
# Implementer Subagent Prompt Template
Use this template when dispatching an implementer subagent.
```
Task tool (general-purpose):
description: "Implement Task N: [task name]"
prompt: |
You are implementing Task N: [task name]
## Task Description
[FULL TEXT of task from plan - paste it here, don't make subagent read file]
## Context
[Scene-setting: where this fits, dependencies, architectural context]
## Before You Begin
If you have questions about:
- The requirements or acceptance criteria
- The approach or implementation strategy
- Dependencies or assumptions
- Anything unclear in the task description
**Ask them now.** Raise any concerns before starting work.
## Your Job
Once you're clear on requirements:
1. Implement exactly what the task specifies
2. Write tests (following TDD if task says to)
3. Verify implementation works
4. Commit your work
5. Self-review (see below)
6. Report back
Work from: [directory]
**While you work:** If you encounter something unexpected or unclear, **ask questions**.
It's always OK to pause and clarify. Don't guess or make assumptions.
## Code Organization
You reason best about code you can hold in context at once, and your edits are more
reliable when files are focused. Keep this in mind:
- Follow the file structure defined in the plan
- Each file should have one clear responsibility with a well-defined interface
- If a file you're creating is growing beyond the plan's intent, stop and report
it as DONE_WITH_CONCERNS — don't split files on your own without plan guidance
- If an existing file you're modifying is already large or tangled, work carefully
and note it as a concern in your report
- In existing codebases, follow established patterns. Improve code you're touching
the way a good developer would, but don't restructure things outside your task.
## When You're in Over Your Head
It is always OK to stop and say "this is too hard for me." Bad work is worse than
no work. You will not be penalized for escalating.
**STOP and escalate when:**
- The task requires architectural decisions with multiple valid approaches
- You need to understand code beyond what was provided and can't find clarity
- You feel uncertain about whether your approach is correct
- The task involves restructuring existing code in ways the plan didn't anticipate
- You've been reading file after file trying to understand the system without progress
**How to escalate:** Report back with status BLOCKED or NEEDS_CONTEXT. Describe
specifically what you're stuck on, what you've tried, and what kind of help you need.
The controller can provide more context, re-dispatch with a more capable model,
or break the task into smaller pieces.
## Before Reporting Back: Self-Review
Review your work with fresh eyes. Ask yourself:
**Completeness:**
- Did I fully implement everything in the spec?
- Did I miss any requirements?
- Are there edge cases I didn't handle?
**Quality:**
- Is this my best work?
- Are names clear and accurate (match what things do, not how they work)?
- Is the code clean and maintainable?
**Discipline:**
- Did I avoid overbuilding (YAGNI)?
- Did I only build what was requested?
- Did I follow existing patterns in the codebase?
**Testing:**
- Do tests actually verify behavior (not just mock behavior)?
- Did I follow TDD if required?
- Are tests comprehensive?
If you find issues during self-review, fix them now before reporting.
## Report Format
When done, report:
- **Status:** DONE | DONE_WITH_CONCERNS | BLOCKED | NEEDS_CONTEXT
- What you implemented (or what you attempted, if blocked)
- What you tested and test results
- Files changed
- Self-review findings (if any)
- Any issues or concerns
Use DONE_WITH_CONCERNS if you completed the work but have doubts about correctness.
Use BLOCKED if you cannot complete the task. Use NEEDS_CONTEXT if you need
information that wasn't provided. Never silently produce work you're unsure about.
```

View File

@@ -0,0 +1,61 @@
# Spec Compliance Reviewer Prompt Template
Use this template when dispatching a spec compliance reviewer subagent.
**Purpose:** Verify implementer built what was requested (nothing more, nothing less)
```
Task tool (general-purpose):
description: "Review spec compliance for Task N"
prompt: |
You are reviewing whether an implementation matches its specification.
## What Was Requested
[FULL TEXT of task requirements]
## What Implementer Claims They Built
[From implementer's report]
## CRITICAL: Do Not Trust the Report
The implementer finished suspiciously quickly. Their report may be incomplete,
inaccurate, or optimistic. You MUST verify everything independently.
**DO NOT:**
- Take their word for what they implemented
- Trust their claims about completeness
- Accept their interpretation of requirements
**DO:**
- Read the actual code they wrote
- Compare actual implementation to requirements line by line
- Check for missing pieces they claimed to implement
- Look for extra features they didn't mention
## Your Job
Read the implementation code and verify:
**Missing requirements:**
- Did they implement everything that was requested?
- Are there requirements they skipped or missed?
- Did they claim something works but didn't actually implement it?
**Extra/unneeded work:**
- Did they build things that weren't requested?
- Did they over-engineer or add unnecessary features?
- Did they add "nice to haves" that weren't in spec?
**Misunderstandings:**
- Did they interpret requirements differently than intended?
- Did they solve the wrong problem?
- Did they implement the right feature but wrong way?
**Verify by reading code, not by trusting report.**
Report:
- ✅ Spec compliant (if everything matches after code inspection)
- ❌ Issues found: [list specifically what's missing or extra, with file:line references]
```

View File

@@ -1,9 +1,6 @@
---
name: Systematic Debugging
description: Four-phase debugging framework that ensures root cause investigation before attempting fixes. Never jump to solutions.
when_to_use: When encountering any technical issue, bug, test failure, or unexpected behavior. When tempted to quick-fix symptoms. When debugging feels chaotic or circular. When fixes don't stick. Before proposing any fix. When you notice yourself jumping to solutions.
version: 2.0.0
languages: all
name: systematic-debugging
description: Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes
---
# Systematic Debugging
@@ -114,7 +111,7 @@ You MUST complete each phase before proceeding to the next.
**WHEN error is deep in call stack:**
See skills/root-cause-tracing for backward tracing technique
See `root-cause-tracing.md` in this directory for the complete backward tracing technique.
**Quick version:**
- Where does bad value originate?
@@ -179,7 +176,7 @@ You MUST complete each phase before proceeding to the next.
- Automated test if possible
- One-off test script if no framework
- MUST have before fixing
- See skills/testing/test-driven-development for writing proper failing tests
- Use the `superpowers:test-driven-development` skill for writing proper failing tests
2. **Implement Single Fix**
- Address the root cause identified
@@ -278,13 +275,17 @@ If systematic investigation reveals issue is truly environmental, timing-depende
**But:** 95% of "no root cause" cases are incomplete investigation.
## Integration with Other Skills
## Supporting Techniques
This skill works with:
- skills/root-cause-tracing - How to trace back through call stack
- skills/defense-in-depth - Add validation after finding root cause
- skills/testing/condition-based-waiting - Replace timeouts identified in Phase 2
- skills/verification-before-completion - Verify fix worked before claiming success
These techniques are part of systematic debugging and available in this directory:
- **`root-cause-tracing.md`** - Trace bugs backward through call stack to find original trigger
- **`defense-in-depth.md`** - Add validation at multiple layers after finding root cause
- **`condition-based-waiting.md`** - Replace arbitrary timeouts with condition polling
**Related skills:**
- **superpowers:test-driven-development** - For creating failing test case (Phase 4, Step 1)
- **superpowers:verification-before-completion** - Verify fix worked before claiming success
## Real-World Impact

View File

@@ -1,11 +1,3 @@
---
name: Condition-Based Waiting
description: Replace arbitrary timeouts with condition polling for reliable async tests
when_to_use: When tests use setTimeout/sleep and are flaky or timing-dependent
version: 1.0.0
languages: all
---
# Condition-Based Waiting
## Overview
@@ -87,7 +79,7 @@ async function waitFor<T>(
}
```
See @example.ts for complete implementation with domain-specific helpers (`waitForEvent`, `waitForEventCount`, `waitForEventMatch`) from actual debugging session.
See `condition-based-waiting-example.ts` in this directory for complete implementation with domain-specific helpers (`waitForEvent`, `waitForEventCount`, `waitForEventMatch`) from actual debugging session.
## Common Mistakes

Some files were not shown because too many files have changed in this diff Show More