diff --git a/plugins/claude-code/hooks/common.sh b/plugins/claude-code/hooks/common.sh index 2a3aeb2a..cf33d981 100755 --- a/plugins/claude-code/hooks/common.sh +++ b/plugins/claude-code/hooks/common.sh @@ -173,6 +173,13 @@ kill_orphaned_index() { # --- Watch singleton management --- WATCH_PIDFILE="$MEMSEARCH_DIR/.watch.pid" +WATCH_SUPERPOWERS_PIDFILE="$MEMSEARCH_DIR/.watch-superpowers.pid" + +# Paths to watch for superpowers collection (relative to project root) +_SUPERPOWERS_PATHS=() +for _sp in "docs/superpowers/specs" "docs/superpowers/plans"; do + [ -d "$_PROJECT_DIR/$_sp" ] && _SUPERPOWERS_PATHS+=("$_PROJECT_DIR/$_sp") +done # Kill a process and its entire process group to avoid orphans _kill_tree() { @@ -207,6 +214,35 @@ stop_watch() { fi } +stop_watch_superpowers() { + if [ "${MEMSEARCH_NO_WATCH:-}" = "1" ]; then return 0; fi + if [ -f "$WATCH_SUPERPOWERS_PIDFILE" ]; then + local pid + pid=$(cat "$WATCH_SUPERPOWERS_PIDFILE" 2>/dev/null) + if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then + _kill_tree "$pid" + fi + rm -f "$WATCH_SUPERPOWERS_PIDFILE" + fi +} + +start_watch_superpowers() { + if [ "${MEMSEARCH_NO_WATCH:-}" = "1" ]; then return 0; fi + if [ -z "$MEMSEARCH_CMD" ]; then return 0; fi + if [ ${#_SUPERPOWERS_PATHS[@]} -eq 0 ]; then return 0; fi + + local _uri="${MILVUS_URI:-$($MEMSEARCH_CMD config get milvus.uri 2>/dev/null || echo "")}" + if [[ "$_uri" != http* ]] && [[ "$_uri" != tcp* ]]; then return 0; fi + + stop_watch_superpowers + + local launch_prefix="nohup" + command -v setsid &>/dev/null && launch_prefix="setsid" + + $launch_prefix $MEMSEARCH_CMD watch "${_SUPERPOWERS_PATHS[@]}" --collection superpowers /dev/null & + echo $! > "$WATCH_SUPERPOWERS_PIDFILE" +} + # Start memsearch watch — always stop-then-start to pick up config changes start_watch() { # Skip watch management in child claude -p processes (e.g. stop.sh summarization) diff --git a/plugins/claude-code/hooks/session-end.sh b/plugins/claude-code/hooks/session-end.sh index 6a299859..2e6857c8 100755 --- a/plugins/claude-code/hooks/session-end.sh +++ b/plugins/claude-code/hooks/session-end.sh @@ -5,6 +5,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/common.sh" stop_watch +stop_watch_superpowers kill_orphaned_index exit 0 diff --git a/plugins/claude-code/hooks/session-start.sh b/plugins/claude-code/hooks/session-start.sh index 76260796..2e908607 100755 --- a/plugins/claude-code/hooks/session-start.sh +++ b/plugins/claude-code/hooks/session-start.sh @@ -118,6 +118,7 @@ fi # Start memsearch watch (Server mode) or do one-time index (Lite mode). # start_watch() skips watch for Lite — file lock prevents concurrent access. start_watch +start_watch_superpowers # Lite mode: one-time index since watch is not running. # Runs in background subshell to avoid blocking the hook (ONNX model loading takes ~10s). @@ -136,6 +137,10 @@ if [[ "$MILVUS_URI" != http* ]] && [[ "$MILVUS_URI" != tcp* ]]; then $MEMSEARCH_CMD reset "${_reset_args[@]}" 2>/dev/null || true $MEMSEARCH_CMD index "${_index_args[@]}" 2>/dev/null || true fi + # Index superpowers paths if present (Lite mode only) + if [ ${#_SUPERPOWERS_PATHS[@]} -gt 0 ]; then + $MEMSEARCH_CMD index "${_SUPERPOWERS_PATHS[@]}" --collection superpowers 2>/dev/null || true + fi ) >/dev/null 2>&1 & echo $! > "$INDEX_PIDFILE" fi diff --git a/plugins/claude-code/skills/superpowers-recall/SKILL.md b/plugins/claude-code/skills/superpowers-recall/SKILL.md new file mode 100644 index 00000000..4c028373 --- /dev/null +++ b/plugins/claude-code/skills/superpowers-recall/SKILL.md @@ -0,0 +1,45 @@ +--- +name: superpowers-recall +description: "Search specs and plans from the superpowers knowledge base via memsearch. Use when the user's question could benefit from implementation plans, technical specs, migration details, feature designs, or architectural decisions stored in docs/superpowers/. Especially useful for questions like 'what is the plan for X', 'how should we implement Y', 'what does the spec say about Z', or 'what stage are we on'. Skip when the question is purely about current code state (use Read/Grep) or general session memory (use memory-recall instead)." +context: fork +allowed-tools: Bash +--- + +You are a knowledge retrieval agent for the superpowers specs and plans collection. Your job is to search indexed docs and return the most relevant context to the main conversation. + +## Collection + +Collection name: `superpowers` + +## Your Task + +Search for specs/plans relevant to: $ARGUMENTS + +## Steps + +1. **Search**: Run `memsearch search "" --top-k 5 --json-output --collection superpowers` to find relevant chunks. + - If `memsearch` is not found, try `uvx memsearch` instead. + - Choose a search query that captures the core intent of the user's question. + +2. **Evaluate**: Look at the search results. Skip chunks that are clearly irrelevant or too generic. + +3. **Expand**: For each relevant result, run `memsearch expand --collection superpowers` to get the full markdown section with surrounding context. + +4. **Return results**: Output a curated summary of the most relevant specs/plans. Be concise — only include information that is genuinely useful for the user's current question. + +## When unsure what to search + +If the query is vague, browse the source files directly: + +- `find "$_PROJECT_DIR/docs/superpowers" -name "*.md" | head -20` — list available spec/plan files +- `grep -rh "^## " "$_PROJECT_DIR/docs/superpowers/" | sort -u | head -40` — scan headings across all docs + +Then go back to `memsearch search` with a more specific query. + +## Output Format + +Organize by relevance. For each result include: +- The key information (decisions, design, implementation steps, stage) +- Source reference (file name) for traceability + +If nothing relevant is found, say "No relevant specs or plans found."