install.sh 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #!/usr/bin/env bash
  2. #
  3. # claude-mods Installer (Linux/macOS)
  4. # Copies commands, skills, agents, and rules to ~/.claude/
  5. # Handles cleanup of deprecated items and command-to-skill migrations.
  6. #
  7. # Usage: ./scripts/install.sh
  8. set -e
  9. BLUE='\033[0;34m'
  10. GREEN='\033[0;32m'
  11. YELLOW='\033[1;33m'
  12. RED='\033[0;31m'
  13. NC='\033[0m'
  14. echo -e "${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
  15. echo -e "${BLUE}║ claude-mods Installer (Unix) ║${NC}"
  16. echo -e "${BLUE}╚══════════════════════════════════════════════════════════════╝${NC}"
  17. echo ""
  18. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  19. PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
  20. CLAUDE_DIR="$HOME/.claude"
  21. # Ensure ~/.claude directories exist
  22. for dir in commands skills agents rules output-styles; do
  23. mkdir -p "$CLAUDE_DIR/$dir"
  24. done
  25. # =============================================================================
  26. # DEPRECATED ITEMS - Remove these from user's config
  27. # =============================================================================
  28. echo -e "${YELLOW}Cleaning up deprecated items...${NC}"
  29. deprecated_items=(
  30. # Removed commands (migrated to skills or deleted)
  31. "$CLAUDE_DIR/commands/review.md" # Migrated to skill
  32. "$CLAUDE_DIR/commands/testgen.md" # Migrated to skill
  33. "$CLAUDE_DIR/commands/conclave.md" # Deprecated
  34. "$CLAUDE_DIR/commands/pulse.md" # Now a skill only
  35. # Removed skills
  36. "$CLAUDE_DIR/skills/conclave" # Deprecated
  37. "$CLAUDE_DIR/skills/claude-code-templates" # Replaced by skill-creator
  38. "$CLAUDE_DIR/skills/agentmail" # Renamed to pigeon (v2.3.0)
  39. )
  40. # Renamed skills: -patterns -> -ops (March 2026)
  41. renamed_skills=(
  42. cli-patterns
  43. mcp-patterns
  44. python-async-patterns
  45. python-cli-patterns
  46. python-database-patterns
  47. python-fastapi-patterns
  48. python-observability-patterns
  49. python-pytest-patterns
  50. python-typing-patterns
  51. rest-patterns
  52. security-patterns
  53. sql-patterns
  54. tailwind-patterns
  55. testing-patterns
  56. )
  57. for old_skill in "${renamed_skills[@]}"; do
  58. old_path="$CLAUDE_DIR/skills/$old_skill"
  59. if [ -d "$old_path" ]; then
  60. rm -rf "$old_path"
  61. echo -e " ${RED}Removed renamed: $old_skill (now ${old_skill%-patterns}-ops)${NC}"
  62. fi
  63. done
  64. for item in "${deprecated_items[@]}"; do
  65. if [ -e "$item" ]; then
  66. rm -rf "$item"
  67. echo -e " ${RED}Removed: $item${NC}"
  68. fi
  69. done
  70. echo ""
  71. # =============================================================================
  72. # COMMANDS - Only copy commands that haven't been migrated to skills
  73. # =============================================================================
  74. echo -e "${BLUE}Installing commands...${NC}"
  75. # Commands that should NOT be copied (migrated to skills)
  76. skip_commands=("review.md" "testgen.md")
  77. for file in "$PROJECT_ROOT/commands"/*.md; do
  78. [ -f "$file" ] || continue
  79. filename=$(basename "$file")
  80. # Skip migrated commands
  81. skip=false
  82. for skip_cmd in "${skip_commands[@]}"; do
  83. if [ "$filename" = "$skip_cmd" ]; then
  84. skip=true
  85. break
  86. fi
  87. done
  88. # Skip archive directory contents
  89. [[ "$file" == *"/archive/"* ]] && continue
  90. if [ "$skip" = false ]; then
  91. cp "$file" "$CLAUDE_DIR/commands/"
  92. echo -e " ${GREEN}$filename${NC}"
  93. fi
  94. done
  95. echo ""
  96. # =============================================================================
  97. # SKILLS - Copy all skill directories
  98. # =============================================================================
  99. echo -e "${BLUE}Installing skills...${NC}"
  100. for skill_dir in "$PROJECT_ROOT/skills"/*/; do
  101. [ -d "$skill_dir" ] || continue
  102. skill_name=$(basename "$skill_dir")
  103. # Remove existing and copy fresh
  104. rm -rf "$CLAUDE_DIR/skills/$skill_name"
  105. cp -r "$skill_dir" "$CLAUDE_DIR/skills/"
  106. echo -e " ${GREEN}$skill_name/${NC}"
  107. done
  108. echo ""
  109. # =============================================================================
  110. # AGENTS - Copy all agent files
  111. # =============================================================================
  112. echo -e "${BLUE}Installing agents...${NC}"
  113. for file in "$PROJECT_ROOT/agents"/*.md; do
  114. [ -f "$file" ] || continue
  115. cp "$file" "$CLAUDE_DIR/agents/"
  116. echo -e " ${GREEN}$(basename "$file")${NC}"
  117. done
  118. echo ""
  119. # =============================================================================
  120. # RULES - Copy all rule files
  121. # =============================================================================
  122. echo -e "${BLUE}Installing rules...${NC}"
  123. for file in "$PROJECT_ROOT/rules"/*.md; do
  124. [ -f "$file" ] || continue
  125. cp "$file" "$CLAUDE_DIR/rules/"
  126. echo -e " ${GREEN}$(basename "$file")${NC}"
  127. done
  128. echo ""
  129. # =============================================================================
  130. # OUTPUT STYLES - Copy all output style files
  131. # =============================================================================
  132. echo -e "${BLUE}Installing output styles...${NC}"
  133. if [ -d "$PROJECT_ROOT/output-styles" ]; then
  134. for file in "$PROJECT_ROOT/output-styles"/*.md; do
  135. [ -f "$file" ] || continue
  136. cp "$file" "$CLAUDE_DIR/output-styles/"
  137. echo -e " ${GREEN}$(basename "$file")${NC}"
  138. done
  139. fi
  140. echo ""
  141. # =============================================================================
  142. # PIGEON - Global install (scripts + hook config hint)
  143. # =============================================================================
  144. echo -e "${BLUE}Installing pigeon (pmail)...${NC}"
  145. # Clean up old agentmail install if present
  146. if [ -d "$CLAUDE_DIR/agentmail" ]; then
  147. rm -rf "$CLAUDE_DIR/agentmail"
  148. echo -e " ${RED}Removed old agentmail/ (renamed to pigeon/)${NC}"
  149. fi
  150. mkdir -p "$CLAUDE_DIR/pigeon"
  151. if [ -f "$PROJECT_ROOT/skills/pigeon/scripts/mail-db.sh" ]; then
  152. cp "$PROJECT_ROOT/skills/pigeon/scripts/mail-db.sh" "$CLAUDE_DIR/pigeon/"
  153. chmod +x "$CLAUDE_DIR/pigeon/mail-db.sh"
  154. echo -e " ${GREEN}mail-db.sh${NC}"
  155. fi
  156. if [ -f "$PROJECT_ROOT/hooks/check-mail.sh" ]; then
  157. cp "$PROJECT_ROOT/hooks/check-mail.sh" "$CLAUDE_DIR/pigeon/"
  158. chmod +x "$CLAUDE_DIR/pigeon/check-mail.sh"
  159. echo -e " ${GREEN}check-mail.sh${NC}"
  160. fi
  161. # Migrate stale agentmail hook path → pigeon
  162. if grep -q "agentmail/check-mail.sh" "$CLAUDE_DIR/settings.json" 2>/dev/null; then
  163. sed -i 's|agentmail/check-mail\.sh|pigeon/check-mail.sh|g' "$CLAUDE_DIR/settings.json"
  164. echo -e " ${GREEN}Migrated agentmail hook → pigeon in settings.json${NC}"
  165. fi
  166. # Check if hook is already configured (pigeon path)
  167. if grep -q "pigeon/check-mail.sh" "$CLAUDE_DIR/settings.json" 2>/dev/null; then
  168. echo -e " ${GREEN}Hook already configured in settings.json${NC}"
  169. else
  170. echo ""
  171. echo -e " ${YELLOW}To enable automatic pmail notifications, add this to ~/.claude/settings.json:${NC}"
  172. echo ""
  173. echo ' "hooks": {'
  174. echo ' "PreToolUse": [{'
  175. echo ' "matcher": "*",'
  176. echo ' "hooks": [{'
  177. echo ' "type": "command",'
  178. echo ' "command": "bash \"$HOME/.claude/pigeon/check-mail.sh\"",'
  179. echo ' "timeout": 5'
  180. echo ' }]'
  181. echo ' }]'
  182. echo ' }'
  183. echo ""
  184. echo -e " ${YELLOW}Without this, pigeon works but you must check manually (pigeon read).${NC}"
  185. fi
  186. echo ""
  187. # =============================================================================
  188. # AUTO-SKILL - Global install (tracking + evaluation hooks)
  189. # =============================================================================
  190. echo -e "${BLUE}Installing auto-skill...${NC}"
  191. mkdir -p "$CLAUDE_DIR/auto-skill"
  192. for script in track-tools.sh evaluate.sh; do
  193. if [ -f "$PROJECT_ROOT/skills/auto-skill/scripts/$script" ]; then
  194. cp "$PROJECT_ROOT/skills/auto-skill/scripts/$script" "$CLAUDE_DIR/auto-skill/"
  195. chmod +x "$CLAUDE_DIR/auto-skill/$script"
  196. echo -e " ${GREEN}$script${NC}"
  197. fi
  198. done
  199. # Check if hooks are already configured
  200. if grep -q "auto-skill" "$CLAUDE_DIR/settings.json" 2>/dev/null; then
  201. echo -e " ${GREEN}Hooks already configured in settings.json${NC}"
  202. else
  203. echo ""
  204. echo -e " ${YELLOW}To enable automatic skill suggestions, add these hooks to ~/.claude/settings.json:${NC}"
  205. echo ""
  206. echo ' "PostToolUse": [{ "matcher": "*", "hooks": [{'
  207. echo ' "type": "command",'
  208. echo ' "command": "bash \"$HOME/.claude/auto-skill/track-tools.sh\"", "timeout": 2'
  209. echo ' }] }],'
  210. echo ' "Stop": [{ "hooks": [{'
  211. echo ' "type": "command",'
  212. echo ' "command": "bash \"$HOME/.claude/auto-skill/evaluate.sh\"", "timeout": 5'
  213. echo ' }] }]'
  214. echo ""
  215. echo -e " ${YELLOW}Without this, /auto-skill still works but won't suggest automatically.${NC}"
  216. fi
  217. echo ""
  218. # =============================================================================
  219. # SUMMARY
  220. # =============================================================================
  221. echo -e "${BLUE}════════════════════════════════════════════════════════════════${NC}"
  222. echo -e " ${GREEN}Installation complete!${NC}"
  223. echo -e "${BLUE}════════════════════════════════════════════════════════════════${NC}"
  224. echo ""
  225. echo -e "${YELLOW}Restart Claude Code to load the new extensions.${NC}"
  226. echo ""