Initial commit: Superpowers plugin v1.0.0

Core skills library as Claude Code plugin:
- Testing skills: TDD, async testing, anti-patterns
- Debugging skills: Systematic debugging, root cause tracing
- Collaboration skills: Brainstorming, planning, code review
- Meta skills: Creating and testing skills

Features:
- SessionStart hook for context injection
- Skills-search tool for discovery
- Commands: /brainstorm, /write-plan, /execute-plan
- Data directory at ~/.superpowers/
This commit is contained in:
Jesse Vincent
2025-10-09 12:57:31 -07:00
commit dd013f6c1d
80 changed files with 12889 additions and 0 deletions

View File

@@ -0,0 +1,370 @@
---
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

@@ -0,0 +1,35 @@
#!/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

@@ -0,0 +1,70 @@
#!/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

@@ -0,0 +1,119 @@
#!/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

@@ -0,0 +1,72 @@
#!/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

@@ -0,0 +1,25 @@
#!/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"