ai-docs/assets/setup.sh

246 lines
6.7 KiB
Bash
Executable File

#!/bin/bash
# AI Assets Installer — Agents & Skills for Cursor, Windsurf, Cline, etc.
# Run from your repo root (where /assets/ lives)
set -euo pipefail
echo "=== AI Assets Installer (Agents & Skills) ==="
echo "Popular tools supported in 2026: Cursor, Windsurf, Cline, RooCode, etc."
echo
ASSETS_DIR="${ASSETS_DIR:-./assets}"
AGENTS_DIR="$ASSETS_DIR/agents"
SKILLS_DIR="$ASSETS_DIR/skills"
GLOBAL_ASSETS_DIR="${GLOBAL_ASSETS_DIR:-$HOME/.agents}"
# ================== PRODUCTS (easy to edit) ==================
# Format: "Display Name:folder_name"
PRODUCTS=(
"Cursor:.cursor"
"Windsurf:.windsurf"
"Cline:.cline"
"RooCode:.roo"
"Continue:.continue"
"VS Code / Copilot:.vscode"
"GitHub / Copilot:.github"
"Claude Code:.claude"
# Add more here, e.g. "Aider:.aider"
)
# ================== SELECT HELPERS ==================
select_items() {
local dir=$1
local type=$2
local items=()
if [ ! -d "$dir" ]; then
echo "⚠️ $dir not found — skipping $type." >&2
return
fi
if [ "$type" = "agents" ]; then
while IFS= read -r item; do
items+=("$item")
done < <(find "$dir" -mindepth 1 -maxdepth 1 -type f -name '*.md' -exec basename {} \; | sort)
else
while IFS= read -r item; do
items+=("$item")
done < <(find "$dir" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | sort)
fi
if [ ${#items[@]} -eq 0 ]; then
echo "No $type found." >&2
return
fi
echo "Available $type (${#items[@]}):" >&2
for i in "${!items[@]}"; do
printf " %2d) %s\n" $((i+1)) "${items[i]}" >&2
done
read -r -p "Select (all / 1,3,5): " sel
if [[ "$sel" =~ ^[Aa][Ll][Ll]$ ]] || [ -z "$sel" ]; then
printf '%s\n' "${items[@]}"
else
local selected=()
IFS=',' read -ra nums <<< "$sel"
for n in "${nums[@]}"; do
idx=$((n-1))
if (( idx >= 0 && idx < ${#items[@]} )); then
selected+=("${items[idx]}")
fi
done
printf '%s\n' "${selected[@]}"
fi
}
# ================== USER CHOICES ==================
INSTALL_TYPE="${INSTALL_TYPE:-}"
INSTALL_MODE="${INSTALL_MODE:-}"
if [ -z "$INSTALL_TYPE" ]; then
echo "=== Step 1: What do you want to install? ==="
echo "1) Agents"
echo "2) Skills"
read -r -p "Choose (1/2): " install_choice
case "$install_choice" in
1) INSTALL_TYPE="agents" ;;
2) INSTALL_TYPE="skills" ;;
*) echo "Invalid selection. Use 1 or 2."; exit 1 ;;
esac
fi
echo -e "\n=== Step 2: Install Mode ==="
if [ -z "$INSTALL_MODE" ]; then
echo "1) Direct copy into product folders (~/.cursor, ~/.claude, ...)"
echo "2) Global install only ($GLOBAL_ASSETS_DIR)"
echo "3) Global install + symlink into product folders"
read -r -p "Choose (1/2/3): " mode
else
mode="$INSTALL_MODE"
fi
GLOBAL_INSTALL=false
SYMLINK_TO_PRODUCTS=false
case "$mode" in
1|direct)
GLOBAL_INSTALL=false
SYMLINK_TO_PRODUCTS=false
;;
2|global)
GLOBAL_INSTALL=true
SYMLINK_TO_PRODUCTS=false
;;
3|symlink|global+symlink|global_symlink|products)
GLOBAL_INSTALL=true
SYMLINK_TO_PRODUCTS=true
;;
*)
echo "Invalid install mode. Use 1, 2, or 3."
exit 1
;;
esac
if [ "$INSTALL_TYPE" = "agents" ]; then
echo -e "\n=== Step 3: Agents ==="
selected_agents=($(select_items "$AGENTS_DIR" "agents"))
selected_skills=()
elif [ "$INSTALL_TYPE" = "skills" ]; then
echo -e "\n=== Step 3: Skills ==="
selected_skills=($(select_items "$SKILLS_DIR" "skills"))
selected_agents=()
else
echo "Invalid INSTALL_TYPE: $INSTALL_TYPE (expected: agents or skills)"
exit 1
fi
echo -e "\n=== Step 4: Target Products ==="
for i in "${!PRODUCTS[@]}"; do
name="${PRODUCTS[i]%%:*}"
printf " %2d) %s\n" $((i+1)) "$name"
done
read -r -p "Select products (all / 1,2,4): " prod_sel
selected_products=()
if [[ "$prod_sel" =~ ^[Aa][Ll][Ll]$ ]] || [ -z "$prod_sel" ]; then
selected_products=("${PRODUCTS[@]}")
else
IFS=',' read -ra pnums <<< "$prod_sel"
for n in "${pnums[@]}"; do
idx=$((n-1))
if (( idx >= 0 && idx < ${#PRODUCTS[@]} )); then
selected_products+=("${PRODUCTS[idx]}")
fi
done
fi
# ================== CONFIRMATION ==================
echo -e "\n=== SUMMARY ==="
echo "Component : $INSTALL_TYPE"
if [ "$INSTALL_TYPE" = "agents" ]; then
echo "Agents : ${selected_agents[*]:-none}"
else
echo "Skills : ${selected_skills[*]:-none}"
fi
echo "Products : $(printf '%s ' "${selected_products[@]%%:*}")"
if [ "$GLOBAL_INSTALL" = false ]; then
echo "Mode : Direct to product folders"
elif [ "$SYMLINK_TO_PRODUCTS" = true ]; then
echo "Mode : Global install + product symlink"
else
echo "Mode : Global install only"
fi
echo "Global Dir : $GLOBAL_ASSETS_DIR"
echo
read -r -p "Install now? (y/N) " confirm
[[ "$confirm" =~ ^[Yy]$ ]] || { echo "Cancelled."; exit 0; }
# ================== DO THE INSTALL ==================
echo -e "\nInstalling...\n"
global_component_copied=false
for entry in "${selected_products[@]}"; do
name="${entry%%:*}"
folder="${entry#*:}"
if [ "$GLOBAL_INSTALL" = true ]; then
base_dir="$GLOBAL_ASSETS_DIR"
product_dir="$HOME/$folder"
else
base_dir="$HOME/$folder"
product_dir="$base_dir"
fi
mkdir -p "$base_dir"
echo "$name ($folder)"
if [ "$GLOBAL_INSTALL" = false ] || [ "$global_component_copied" = false ]; then
if [ "$INSTALL_TYPE" = "agents" ]; then
for item in "${selected_agents[@]}"; do
src="$AGENTS_DIR/$item"
if [ -f "$src" ]; then
dest="$base_dir/agents/$item"
mkdir -p "$(dirname "$dest")"
cp -f "$src" "$dest"
echo " ✓ Agent: $item"
elif [ -d "$src" ]; then
dest="$base_dir/agents/$item"
rm -rf "$dest"
mkdir -p "$(dirname "$dest")"
cp -r "$src" "$dest"
echo " ✓ Agent: $item"
fi
done
fi
if [ "$INSTALL_TYPE" = "skills" ]; then
for item in "${selected_skills[@]}"; do
src="$SKILLS_DIR/$item"
if [ -d "$src" ]; then
dest="$base_dir/skills/$item"
rm -rf "$dest"
mkdir -p "$(dirname "$dest")"
cp -r "$src" "$dest"
echo " ✓ Skill: $item"
fi
done
fi
if [ "$GLOBAL_INSTALL" = true ]; then
global_component_copied=true
fi
fi
# Symlink global content into selected product folder if requested
if [ "$SYMLINK_TO_PRODUCTS" = true ]; then
mkdir -p "$product_dir"
if [ -d "$base_dir/$INSTALL_TYPE" ]; then
ln -sfn "$base_dir/$INSTALL_TYPE" "$product_dir/$INSTALL_TYPE"
echo " → Symlinked $INSTALL_TYPE into $product_dir"
fi
fi
done
echo -e "\n✅ Done! Your $INSTALL_TYPE are now available in the selected tools."
echo " Tip: git add the .cursor/, .windsurf/, etc. folders if you want to version them."