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:
370
skills/meta/gardening-skills-wiki/SKILL.md
Normal file
370
skills/meta/gardening-skills-wiki/SKILL.md
Normal 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.
|
||||
35
skills/meta/gardening-skills-wiki/analyze-search-gaps.sh
Executable file
35
skills/meta/gardening-skills-wiki/analyze-search-gaps.sh
Executable 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."
|
||||
70
skills/meta/gardening-skills-wiki/check-index-coverage.sh
Executable file
70
skills/meta/gardening-skills-wiki/check-index-coverage.sh
Executable 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
|
||||
119
skills/meta/gardening-skills-wiki/check-links.sh
Executable file
119
skills/meta/gardening-skills-wiki/check-links.sh
Executable 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
|
||||
72
skills/meta/gardening-skills-wiki/check-naming.sh
Executable file
72
skills/meta/gardening-skills-wiki/check-naming.sh
Executable 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
|
||||
25
skills/meta/gardening-skills-wiki/garden.sh
Executable file
25
skills/meta/gardening-skills-wiki/garden.sh
Executable 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"
|
||||
Reference in New Issue
Block a user