mirror of
https://github.com/obra/superpowers.git
synced 2026-04-21 08:59:04 +08:00
Add personal superpowers overlay system
Enables users to write and manage their own skills alongside core skills.
## Key Features:
- Auto-setup on first session: Creates ~/.config/superpowers/ git repo
- Two-tier skills: Personal skills shadow core skills when paths match
- Environment variable support: PERSONAL_SUPERPOWERS_DIR, XDG_CONFIG_HOME
- GitHub integration: Optional public repo creation for sharing skills
- CLI-agnostic: Works across Claude Code, Codex CLI, Gemini CLI (future)
## Changes:
- Added hooks/setup-personal-superpowers.sh - Auto-initializes personal repo
- Updated hooks/session-start.sh - Runs setup, offers GitHub repo creation
- Updated list-skills, skills-search - Search both personal and core skills
- Renamed skills/meta/creating-skills → writing-skills
- Added skills/meta/setting-up-personal-superpowers - Setup documentation
- Added skills/meta/sharing-skills - Contribution workflow
- Removed skills/meta/installing-skills - Old ~/.clank system
- Removed all INDEX.md files - Replaced by list-skills tool
- Updated README.md, getting-started - Document personal skills workflow
## Architecture:
~/.config/superpowers/skills/ # Personal (user-created, git-tracked)
${CLAUDE_PLUGIN_ROOT}/skills/ # Core (read-only, from plugin)
Search order: Personal first, core second (first match wins)
This commit is contained in:
@@ -1,13 +1,17 @@
|
||||
---
|
||||
name: Getting Started with Skills
|
||||
description: Skills wiki intro - mandatory workflows, search tool, brainstorming triggers
|
||||
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: 2.0.0
|
||||
version: 3.0.0
|
||||
---
|
||||
|
||||
# Getting Started with Skills
|
||||
|
||||
Your personal wiki of proven techniques, patterns, and tools at `${CLAUDE_PLUGIN_ROOT}/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?
|
||||
|
||||
@@ -28,7 +32,8 @@ ${CLAUDE_PLUGIN_ROOT}/skills/getting-started/list-skills
|
||||
- Load with Read tool only when needed
|
||||
|
||||
**When you see skill references in documentation:**
|
||||
- `skills/path/name` → Use Read tool on `${CLAUDE_PLUGIN_ROOT}/skills/path/name/SKILL.md`
|
||||
- `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
|
||||
@@ -115,14 +120,7 @@ You: Searching past conversations...
|
||||
|
||||
**Why:** Checklists without TodoWrite tracking = steps get skipped. Every time.
|
||||
|
||||
**Examples:** TDD (write test, watch fail, implement, verify), Systematic Debugging (4 phases), Creating Skills (RED-GREEN-REFACTOR)
|
||||
|
||||
## Navigation
|
||||
|
||||
Really, try skills-search first.
|
||||
|
||||
**Categories:** skills/INDEX.md → testing, debugging, coding, architecture, collaboration, meta
|
||||
**Individual skill:** Load from category INDEX
|
||||
**Examples:** TDD (write test, watch fail, implement, verify), Systematic Debugging (4 phases), Writing Skills (RED-GREEN-REFACTOR)
|
||||
|
||||
## How to Read a Skill
|
||||
|
||||
@@ -159,13 +157,15 @@ Your human partner's specific instructions describe WHAT to do, not HOW.
|
||||
|
||||
**Red flags:** "Instruction was specific" • "Seems simple" • "Workflow is overkill"
|
||||
|
||||
## Creating and Updating Skills
|
||||
## Writing and Sharing Skills
|
||||
|
||||
**Before creating OR editing ANY skill:**
|
||||
**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/creating-skills**
|
||||
3. **Check in** - "You asked me to edit [skill]. Should I follow creating-skills process or make the change?"
|
||||
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.**
|
||||
|
||||
@@ -173,11 +173,14 @@ Your human partner's specific instructions describe WHAT to do, not HOW.
|
||||
- "Just a small addition"
|
||||
- "Instruction was specific, so I can proceed"
|
||||
|
||||
**All of these mean: STOP and check in first.**
|
||||
**All of these mean: STOP and follow writing-skills process.**
|
||||
|
||||
Found something valuable? See skills/meta/creating-skills
|
||||
**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? Edit skills/REQUESTS.md (at ${CLAUDE_PLUGIN_ROOT}/skills/REQUESTS.md)
|
||||
**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
|
||||
|
||||
|
||||
@@ -1,22 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
# list-skills - Show all available skill names without descriptions
|
||||
# For Claude to quickly see what exists before searching
|
||||
# Searches personal skills first, then core skills (personal shadows core)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Detect if running from repo or installed location
|
||||
# Detect core skills directory (repo or installed location)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
if [[ "$SCRIPT_DIR" == *"/.claude/plugins/cache/"* ]]; then
|
||||
# Installed as plugin
|
||||
SKILLS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
CORE_SKILLS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
else
|
||||
# Running from repo
|
||||
SKILLS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
CORE_SKILLS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
fi
|
||||
|
||||
# Find all SKILL.md files and extract their paths
|
||||
find "$SKILLS_DIR" -name "SKILL.md" -type f | \
|
||||
sed "s|$SKILLS_DIR/||; s|/SKILL.md||" | \
|
||||
sort
|
||||
# Use PERSONAL_SUPERPOWERS_DIR if set, otherwise XDG_CONFIG_HOME/superpowers, otherwise ~/.config/superpowers
|
||||
PERSONAL_SUPERPOWERS_DIR="${PERSONAL_SUPERPOWERS_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/superpowers}"
|
||||
PERSONAL_SKILLS_DIR="${PERSONAL_SUPERPOWERS_DIR}/skills"
|
||||
|
||||
# Collect all skill paths with deduplication
|
||||
declare -A seen_skills
|
||||
all_skills=()
|
||||
|
||||
# Personal skills first (take precedence)
|
||||
if [[ -d "$PERSONAL_SKILLS_DIR" ]]; then
|
||||
while IFS= read -r file; do
|
||||
skill_path="${file#$PERSONAL_SKILLS_DIR/}"
|
||||
skill_path="${skill_path%/SKILL.md}"
|
||||
if [[ -n "$skill_path" ]]; then
|
||||
seen_skills["$skill_path"]=1
|
||||
all_skills+=("$skill_path")
|
||||
fi
|
||||
done < <(find "$PERSONAL_SKILLS_DIR" -name "SKILL.md" -type f 2>/dev/null || true)
|
||||
fi
|
||||
|
||||
# Core skills (only if not shadowed by personal)
|
||||
while IFS= read -r file; do
|
||||
skill_path="${file#$CORE_SKILLS_DIR/}"
|
||||
skill_path="${skill_path%/SKILL.md}"
|
||||
if [[ -n "$skill_path" ]] && [[ -z "${seen_skills[$skill_path]:-}" ]]; then
|
||||
all_skills+=("$skill_path")
|
||||
fi
|
||||
done < <(find "$CORE_SKILLS_DIR" -name "SKILL.md" -type f 2>/dev/null || true)
|
||||
|
||||
# Sort and output
|
||||
printf "%s\n" "${all_skills[@]}" | sort
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
# skills-search - Find relevant skills using grep patterns
|
||||
# Logs all searches for gap analysis (gardening skill processes the log)
|
||||
# Searches personal skills first, then core skills (personal shadows core)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Detect if running from repo or installed location
|
||||
# Detect core skills directory (repo or installed location)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
if [[ "$SCRIPT_DIR" == *"/.claude/skills/getting-started" ]]; then
|
||||
# Installed location
|
||||
SKILLS_DIR="${HOME}/.claude/skills"
|
||||
if [[ "$SCRIPT_DIR" == *"/.claude/plugins/cache/"* ]]; then
|
||||
# Installed as plugin
|
||||
CORE_SKILLS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
else
|
||||
# Running from repo
|
||||
SKILLS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
CORE_SKILLS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
fi
|
||||
|
||||
LOG_FILE="${HOME}/.superpowers/search-log.jsonl"
|
||||
# Use PERSONAL_SUPERPOWERS_DIR if set, otherwise XDG_CONFIG_HOME/superpowers, otherwise ~/.config/superpowers
|
||||
PERSONAL_SUPERPOWERS_DIR="${PERSONAL_SUPERPOWERS_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/superpowers}"
|
||||
PERSONAL_SKILLS_DIR="${PERSONAL_SUPERPOWERS_DIR}/skills"
|
||||
LOG_FILE="${PERSONAL_SUPERPOWERS_DIR}/search-log.jsonl"
|
||||
|
||||
# Show usage if no arguments
|
||||
if [[ $# -eq 0 ]]; then
|
||||
@@ -40,16 +44,51 @@ timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
query="$*"
|
||||
echo "{\"timestamp\":\"$timestamp\",\"query\":\"$query\"}" >> "$LOG_FILE" 2>/dev/null || true
|
||||
|
||||
# Search all SKILL.md files - both content AND path names
|
||||
# Content search: grep file contents
|
||||
content_matches=$(grep -E -r "$@" "$SKILLS_DIR/" --include="SKILL.md" -l 2>/dev/null || true)
|
||||
# Search both personal and core skills directories
|
||||
# Personal skills take precedence (searched first)
|
||||
|
||||
# Content search: grep file contents from both locations
|
||||
content_matches_personal=""
|
||||
content_matches_core=""
|
||||
if [[ -d "$PERSONAL_SKILLS_DIR" ]]; then
|
||||
content_matches_personal=$(grep -E -r "$@" "$PERSONAL_SKILLS_DIR/" --include="SKILL.md" -l 2>/dev/null || true)
|
||||
fi
|
||||
content_matches_core=$(grep -E -r "$@" "$CORE_SKILLS_DIR/" --include="SKILL.md" -l 2>/dev/null || true)
|
||||
|
||||
# Filename search: find all SKILL.md paths, then grep the paths themselves
|
||||
all_skills=$(find "$SKILLS_DIR/" -name "SKILL.md" -type f 2>/dev/null || true)
|
||||
path_matches=$(echo "$all_skills" | grep -E "$@" 2>/dev/null || true)
|
||||
all_skills_personal=""
|
||||
all_skills_core=""
|
||||
if [[ -d "$PERSONAL_SKILLS_DIR" ]]; then
|
||||
all_skills_personal=$(find "$PERSONAL_SKILLS_DIR/" -name "SKILL.md" -type f 2>/dev/null || true)
|
||||
fi
|
||||
all_skills_core=$(find "$CORE_SKILLS_DIR/" -name "SKILL.md" -type f 2>/dev/null || true)
|
||||
|
||||
# Combine and deduplicate
|
||||
results=$(printf "%s\n%s" "$content_matches" "$path_matches" | sort -u | grep -v '^$' || true)
|
||||
path_matches_personal=$(echo "$all_skills_personal" | grep -E "$@" 2>/dev/null || true)
|
||||
path_matches_core=$(echo "$all_skills_core" | grep -E "$@" 2>/dev/null || true)
|
||||
|
||||
# Combine all matches
|
||||
all_matches=$(printf "%s\n%s\n%s\n%s" "$content_matches_personal" "$content_matches_core" "$path_matches_personal" "$path_matches_core" | grep -v '^$' || true)
|
||||
|
||||
# Deduplicate by skill path (personal shadows core)
|
||||
declare -A seen_skills
|
||||
results=""
|
||||
while IFS= read -r file; do
|
||||
# Extract skill path relative to its base directory
|
||||
if [[ "$file" == "$PERSONAL_SKILLS_DIR"* ]]; then
|
||||
skill_path="${file#$PERSONAL_SKILLS_DIR/}"
|
||||
else
|
||||
skill_path="${file#$CORE_SKILLS_DIR/}"
|
||||
fi
|
||||
skill_path="${skill_path%/SKILL.md}"
|
||||
|
||||
# Only include if we haven't seen this skill path yet
|
||||
if [[ -z "${seen_skills[$skill_path]:-}" ]]; then
|
||||
seen_skills["$skill_path"]=1
|
||||
results="${results}${file}"$'\n'
|
||||
fi
|
||||
done <<< "$all_matches"
|
||||
|
||||
results=$(echo "$results" | grep -v '^$' | sort -u || true)
|
||||
|
||||
if [[ -z "$results" ]]; then
|
||||
echo "❌ No skills found matching: $*"
|
||||
@@ -68,7 +107,12 @@ echo "$results" | while read -r file; do
|
||||
description=$(grep "^description:" "$file" 2>/dev/null | sed 's/description: *//' || echo "")
|
||||
|
||||
# Get relative path without @ prefix or /SKILL.md suffix
|
||||
rel_path="${file#$SKILLS_DIR/}"
|
||||
# Handle both personal and core skills
|
||||
if [[ "$file" == "$PERSONAL_SKILLS_DIR"* ]]; then
|
||||
rel_path="${file#$PERSONAL_SKILLS_DIR/}"
|
||||
else
|
||||
rel_path="${file#$CORE_SKILLS_DIR/}"
|
||||
fi
|
||||
rel_path="skills/${rel_path%/SKILL.md}"
|
||||
|
||||
if [[ -n "$description" ]]; then
|
||||
|
||||
Reference in New Issue
Block a user