| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- #!/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
|