Files
gh-tenequm-claude-plugins-s…/skills/skill/references/installation-workflow.md
2025-11-30 09:01:22 +08:00

13 KiB

Installation Workflow for Claude Skills

Complete guide to previewing, downloading, and installing Claude skills from GitHub.

Installation Process Overview

  1. Preview - Show skill details and requirements
  2. Confirm - Get user approval
  3. Download - Fetch skill files from GitHub
  4. Install - Place in correct directory structure
  5. Verify - Confirm installation success
  6. Setup - Run any required setup steps

Step 1: Preview Skill

Fetch SKILL.md Content

# Get direct link to SKILL.md
skill_url="https://github.com/OWNER/REPO/blob/main/PATH/SKILL.md"
skill_path="PATH/SKILL.md"

# Fetch content (first 50 lines for preview)
gh api repos/OWNER/REPO/contents/$skill_path | \
  jq -r '.content' | base64 -d | head -50

Extract Key Information

# Parse SKILL.md for important details
skill_content=$(gh api repos/OWNER/REPO/contents/$skill_path | jq -r '.content' | base64 -d)

# Extract name (first # heading)
skill_name=$(echo "$skill_content" | grep -m1 '^# ' | sed 's/^# //')

# Extract description (first paragraph after title)
description=$(echo "$skill_content" | sed -n '/^# /,/^$/p' | grep -v '^#' | head -1)

# Extract dependencies
dependencies=$(echo "$skill_content" | grep -A10 -i "dependencies\|requirements\|prerequisites" | head -10)

# Extract usage examples
examples=$(echo "$skill_content" | grep -A10 -i "usage\|example\|quick start" | head -15)

Display Preview

cat <<EOF
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📦 Skill Preview: $skill_name
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

📝 Description:
$description

⭐ Repository: $repo_full_name
🌟 Stars: $stars
🔄 Last Updated: $days_ago days ago

📋 Dependencies:
$dependencies

💡 Usage Example:
$examples

📎 Full Documentation:
$skill_url

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
EOF

Step 2: Confirm Installation

Check Existing Installation

# Determine skill directory name
skill_dir_name=$(echo "$skill_name" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
skill_dir=".claude/skills/$skill_dir_name"

# Check if already installed
if [ -d "$skill_dir" ]; then
  echo "⚠️  Skill '$skill_name' is already installed at: $skill_dir"
  echo ""
  echo "Options:"
  echo "  [U] Update (overwrite existing)"
  echo "  [K] Keep existing (cancel)"
  echo "  [B] Backup and install new"
  echo ""
  read -p "Choose option [U/K/B]: " choice

  case $choice in
    [Uu])
      echo "Overwriting existing installation..."
      ;;
    [Kk])
      echo "Keeping existing installation. Cancelled."
      exit 0
      ;;
    [Bb])
      backup_dir="${skill_dir}.backup.$(date +%s)"
      mv "$skill_dir" "$backup_dir"
      echo "✅ Backed up to: $backup_dir"
      ;;
    *)
      echo "Invalid option. Cancelled."
      exit 1
      ;;
  esac
fi

Get User Confirmation

echo ""
echo "Install '$skill_name' to $skill_dir?"
echo ""
read -p "Continue? [y/N]: " confirm

if [[ ! "$confirm" =~ ^[Yy] ]]; then
  echo "Installation cancelled."
  exit 0
fi

Step 3: Download Skill Files

Determine Skill Structure

Skills can have different structures:

  1. Simple - Single SKILL.md file
  2. Standard - SKILL.md + reference files
  3. Plugin - Nested in skills/ subdirectory
  4. Complex - Multiple files, scripts, dependencies
# Detect structure type
structure_type=$(detect_skill_structure "$repo" "$skill_path")

case $structure_type in
  "simple")
    download_simple_skill "$repo" "$skill_path" "$skill_dir"
    ;;
  "standard")
    download_standard_skill "$repo" "$skill_path" "$skill_dir"
    ;;
  "plugin")
    download_plugin_skill "$repo" "$skill_path" "$skill_dir"
    ;;
  "complex")
    download_complex_skill "$repo" "$skill_path" "$skill_dir"
    ;;
esac

Download Simple Skill (SKILL.md only)

download_simple_skill() {
  local repo=$1
  local skill_path=$2
  local dest_dir=$3

  echo "📥 Downloading simple skill..."

  # Create destination directory
  mkdir -p "$dest_dir"

  # Download SKILL.md
  gh api "repos/$repo/contents/$skill_path" | \
    jq -r '.content' | base64 -d > "$dest_dir/SKILL.md"

  if [ -f "$dest_dir/SKILL.md" ]; then
    echo "✅ Downloaded SKILL.md"
  else
    echo "❌ Failed to download SKILL.md"
    return 1
  fi
}

Download Standard Skill (with references)

download_standard_skill() {
  local repo=$1
  local skill_path=$2
  local dest_dir=$3

  echo "📥 Downloading standard skill..."

  # Get skill directory path from SKILL.md path
  skill_dir_path=$(dirname "$skill_path")

  # Get all files in skill directory
  gh api "repos/$repo/contents/$skill_dir_path?recursive=1" | \
    jq -r '.tree[] | select(.type == "blob") | .path' | \
    while read file_path; do
      # Calculate relative path
      rel_path=${file_path#$skill_dir_path/}
      dest_file="$dest_dir/$rel_path"

      # Create subdirectories
      mkdir -p "$(dirname "$dest_file")"

      # Download file
      gh api "repos/$repo/contents/$file_path" | \
        jq -r '.content' | base64 -d > "$dest_file"

      echo "  ✓ $rel_path"
    done

  echo "✅ Downloaded all skill files"
}

Download Plugin Skill (nested structure)

download_plugin_skill() {
  local repo=$1
  local skill_path=$2
  local dest_dir=$3

  echo "📥 Downloading plugin skill..."
  echo "   (This may take a moment...)"

  # Clone repository to temporary location
  temp_dir=$(mktemp -d)
  gh repo clone "$repo" "$temp_dir" -- --depth 1 --quiet

  # Extract skill directory from SKILL.md path
  # Example: skills/playwright-skill/SKILL.md -> skills/playwright-skill
  skill_subdir=$(dirname "$skill_path")

  # Copy skill directory to destination
  if [ -d "$temp_dir/$skill_subdir" ]; then
    cp -r "$temp_dir/$skill_subdir/"* "$dest_dir/"
    echo "✅ Copied skill from $skill_subdir"
  else
    echo "❌ Skill directory not found: $skill_subdir"
    rm -rf "$temp_dir"
    return 1
  fi

  # Cleanup
  rm -rf "$temp_dir"
}

Download Complex Skill (with setup)

download_complex_skill() {
  local repo=$1
  local skill_path=$2
  local dest_dir=$3

  echo "📥 Downloading complex skill..."

  # Use plugin download method
  download_plugin_skill "$repo" "$skill_path" "$dest_dir"

  # Check for dependencies
  if [ -f "$dest_dir/package.json" ]; then
    echo ""
    echo "📦 This skill has npm dependencies."
    echo "   Run: cd $dest_dir && npm install"
  fi

  if [ -f "$dest_dir/requirements.txt" ]; then
    echo ""
    echo "🐍 This skill has Python dependencies."
    echo "   Run: cd $dest_dir && pip install -r requirements.txt"
  fi

  if [ -f "$dest_dir/setup.sh" ]; then
    echo ""
    echo "🔧 This skill has a setup script."
    read -p "   Run setup.sh now? [y/N]: " run_setup
    if [[ "$run_setup" =~ ^[Yy] ]]; then
      (cd "$dest_dir" && bash setup.sh)
    fi
  fi
}

Step 4: Verify Installation

Check Required Files

verify_installation() {
  local skill_dir=$1
  local errors=0

  echo ""
  echo "🔍 Verifying installation..."

  # Check SKILL.md exists
  if [ ! -f "$skill_dir/SKILL.md" ]; then
    echo "  ❌ Missing SKILL.md"
    ((errors++))
  else
    echo "  ✅ SKILL.md present"
  fi

  # Check file permissions
  if [ ! -r "$skill_dir/SKILL.md" ]; then
    echo "  ❌ SKILL.md not readable"
    ((errors++))
  else
    echo "  ✅ File permissions OK"
  fi

  # Check for reference files (optional but good)
  if [ -d "$skill_dir/references" ]; then
    ref_count=$(find "$skill_dir/references" -type f | wc -l)
    echo "  ✅ Found $ref_count reference files"
  fi

  # Check for examples (optional)
  if [ -d "$skill_dir/examples" ]; then
    example_count=$(find "$skill_dir/examples" -type f | wc -l)
    echo "  ✅ Found $example_count example files"
  fi

  return $errors
}

Validate SKILL.md Content

validate_skill_content() {
  local skill_file=$1

  # Check for required sections
  local has_title=$(grep -q '^# ' "$skill_file" && echo "yes" || echo "no")
  local has_description=$(grep -qi 'description\|what.*does' "$skill_file" && echo "yes" || echo "no")
  local has_usage=$(grep -qi 'usage\|example\|how.*use' "$skill_file" && echo "yes" || echo "no")

  if [ "$has_title" = "yes" ] && [ "$has_description" = "yes" ]; then
    echo "  ✅ SKILL.md structure valid"
    return 0
  else
    echo "  ⚠️  SKILL.md may be incomplete (missing title or description)"
    return 1
  fi
}

Step 5: Post-Installation

Run Setup Scripts

# Check for and run setup
if [ -f "$skill_dir/setup.sh" ]; then
  echo ""
  echo "🔧 Running setup script..."
  (cd "$skill_dir" && bash setup.sh)

  if [ $? -eq 0 ]; then
    echo "✅ Setup completed successfully"
  else
    echo "⚠️  Setup script had warnings (check above)"
  fi
fi

Install Dependencies

# npm dependencies
if [ -f "$skill_dir/package.json" ]; then
  echo ""
  echo "📦 Installing npm dependencies..."
  (cd "$skill_dir" && npm install --silent)
  echo "✅ npm dependencies installed"
fi

# Python dependencies
if [ -f "$skill_dir/requirements.txt" ]; then
  echo ""
  echo "🐍 Installing Python dependencies..."
  pip install -q -r "$skill_dir/requirements.txt"
  echo "✅ Python dependencies installed"
fi

Create Usage Instructions

cat <<EOF

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Installation Complete!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

📁 Installed to: $skill_dir

🚀 Usage:
   Invoke the skill by typing: /$skill_dir_name
   Or let Claude auto-invoke when relevant

📖 Documentation:
   Read: $skill_dir/SKILL.md
   Examples: $skill_dir/examples/ (if available)

🔄 Update:
   Re-run installation to update to latest version

❌ Uninstall:
   rm -rf $skill_dir

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
EOF

Complete Installation Script

#!/bin/bash

install_skill() {
  local repo=$1
  local skill_path=$2
  local skill_name=$3

  # 1. Determine destination
  skill_dir_name=$(echo "$skill_name" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
  skill_dir=".claude/skills/$skill_dir_name"

  # 2. Preview
  echo "Fetching skill preview..."
  skill_content=$(gh api "repos/$repo/contents/$skill_path" | jq -r '.content' | base64 -d)
  description=$(echo "$skill_content" | sed -n '/^# /,/^$/p' | grep -v '^#' | head -1)

  echo ""
  echo "📦 $skill_name"
  echo "📝 $description"
  echo "📁 Will install to: $skill_dir"
  echo ""

  # 3. Confirm
  read -p "Install this skill? [y/N]: " confirm
  [[ ! "$confirm" =~ ^[Yy] ]] && { echo "Cancelled."; return 1; }

  # 4. Check existing
  if [ -d "$skill_dir" ]; then
    read -p "Skill exists. Overwrite? [y/N]: " overwrite
    [[ ! "$overwrite" =~ ^[Yy] ]] && { echo "Cancelled."; return 1; }
    rm -rf "$skill_dir"
  fi

  # 5. Download
  mkdir -p "$skill_dir"

  # Detect if plugin format or simple
  if [[ "$skill_path" == *"/skills/"* ]]; then
    # Plugin format - clone and extract
    temp_dir=$(mktemp -d)
    gh repo clone "$repo" "$temp_dir" -- --depth 1 --quiet
    skill_subdir=$(dirname "$skill_path")
    cp -r "$temp_dir/$skill_subdir/"* "$skill_dir/"
    rm -rf "$temp_dir"
  else
    # Simple format - direct download
    gh api "repos/$repo/contents/$skill_path" | \
      jq -r '.content' | base64 -d > "$skill_dir/SKILL.md"
  fi

  # 6. Verify
  if [ -f "$skill_dir/SKILL.md" ]; then
    echo "✅ Installation successful!"
    echo "📁 Location: $skill_dir"
    echo "🚀 Use: /$skill_dir_name"
  else
    echo "❌ Installation failed"
    return 1
  fi
}

# Usage:
# install_skill "lackeyjb/playwright-skill" "skills/playwright-skill/SKILL.md" "playwright-skill"

Error Handling

Common Issues

Issue: Repository not found

if ! gh api "repos/$repo" &>/dev/null; then
  echo "❌ Repository not found or not accessible: $repo"
  echo "   Check if the repository exists and is public"
  exit 1
fi

Issue: SKILL.md not found

if ! gh api "repos/$repo/contents/$skill_path" &>/dev/null; then
  echo "❌ SKILL.md not found at: $skill_path"
  echo "   Searching for SKILL.md in repository..."

  # Try to find it
  found_paths=$(gh api "repos/$repo/git/trees/main?recursive=1" | \
    jq -r '.tree[] | select(.path | contains("SKILL.md")) | .path')

  if [ -n "$found_paths" ]; then
    echo "   Found SKILL.md at:"
    echo "$found_paths" | sed 's/^/     /'
  else
    echo "   No SKILL.md found in repository"
  fi
  exit 1
fi

Issue: Permission denied

if [ ! -w ".claude/skills" ]; then
  echo "❌ Cannot write to .claude/skills directory"
  echo "   Check permissions: ls -la .claude/skills"
  exit 1
fi

Issue: Network/API error

if ! ping -c 1 api.github.com &>/dev/null; then
  echo "❌ Cannot reach GitHub API"
  echo "   Check your internet connection"
  exit 1
fi

Summary: The installation workflow ensures safe, verified installation of Claude skills with proper error handling, user confirmation, and post-installation setup.