BREAKING CHANGE: Ralph now runs as background process (non-blocking) Changes: - Enhanced ralph-auto-trigger.sh to spawn Ralph in background - Hook immediately returns to Claude Code (NON-BLOCKING) - Ralph runs via nohup (survives terminal close) - Added PID tracking: ~/.claude/ralph.pid - Added lock file: ~/.claude/ralph.lock - Added log file: ~/.claude/ralph-output.log - Added trigger log: ~/.claude/ralph-trigger.log - Added RALPH_MAX_ITERATIONS environment variable (default: 50) Features: - Background execution: Claude Code continues immediately - Process tracking: PID saved for monitoring/stopping - Lock mechanism: Prevents duplicate Ralph instances - Real-time monitoring: tail -f ~/.claude/ralph-output.log - Graceful cleanup: Auto-cleanup of dead process locks Updated files: - MASTER-PROMPT.md: Enhanced hook script + usage instructions - interactive-install-claude.sh: Enhanced install_ralph() function - ~/.claude/hooks/ralph-auto-trigger.sh: Updated local installation Usage: - Ralph auto-starts in background when agents are requested - Monitor: tail -f ~/.claude/ralph-output.log - Stop: kill $(cat ~/.claude/ralph.pid) - Configure: export RALPH_AUTO_MODE=agents|always|off - Configure: export RALPH_MAX_ITERATIONS=100 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1533 lines
50 KiB
Bash
Executable File
1533 lines
50 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
################################################################################
|
|
# Claude Code Customizations - Interactive Installer
|
|
# Step-by-step installation with user choices for each component
|
|
################################################################################
|
|
|
|
set -e
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
MAGENTA='\033[0;35m'
|
|
CYAN='\033[0;36m'
|
|
BOLD='\033[1m'
|
|
NC='\033[0m'
|
|
|
|
# Configuration
|
|
CLAUDE_DIR="$HOME/.claude"
|
|
BACKUP_DIR="$HOME/.claude-backup-$(date +%Y%m%d_%H%M%S)"
|
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
|
|
# User choices
|
|
USE_ZAI_MODELS=false
|
|
INSTALL_AGENTS=true
|
|
INSTALL_ENGINEERING=true
|
|
INSTALL_MARKETING=true
|
|
INSTALL_PRODUCT=true
|
|
INSTALL_STUDIO_OPS=true
|
|
INSTALL_PROJECT_MGMT=true
|
|
INSTALL_TESTING=true
|
|
INSTALL_DESIGN=true
|
|
INSTALL_BONUS=true
|
|
INSTALL_MCP_TOOLS=true
|
|
INSTALL_VISION_TOOLS=true
|
|
INSTALL_WEB_TOOLS=true
|
|
INSTALL_GITHUB_TOOLS=true
|
|
INSTALL_TLDR=true
|
|
INSTALL_PLUGINS=true
|
|
INSTALL_HOOKS=true
|
|
INSTALL_RALPH=false
|
|
LAUNCH_CLAUDE=false
|
|
|
|
# Counters
|
|
SELECTED_AGENTS=0
|
|
SELECTED_MCP_TOOLS=0
|
|
|
|
################################################################################
|
|
# Helper Functions
|
|
################################################################################
|
|
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
|
|
log_warning() { echo -e "${YELLOW}[!]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[✗]${NC} $1"; }
|
|
|
|
print_header() {
|
|
clear
|
|
echo -e "${CYAN}╔══════════════════════════════════════════════════════════════════╗${NC}"
|
|
echo -e "${CYAN}║${NC} ${BOLD}Claude Code Customizations - Interactive Installer${NC} ${CYAN}║${NC}"
|
|
echo -e "${CYAN}╚══════════════════════════════════════════════════════════════════╝${NC}"
|
|
echo ""
|
|
}
|
|
|
|
confirm() {
|
|
local prompt="$1"
|
|
local default="$2"
|
|
|
|
if [ "$default" = "Y" ]; then
|
|
prompt="$prompt [Y/n]: "
|
|
else
|
|
prompt="$prompt [y/N]: "
|
|
fi
|
|
|
|
read -p "$prompt" response
|
|
|
|
if [ -z "$response" ]; then
|
|
if [ "$default" = "Y" ]; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
[[ "$response" =~ ^[Yy]$ ]]
|
|
}
|
|
|
|
select_multiple() {
|
|
local title="$1"
|
|
shift
|
|
local options=("$@")
|
|
|
|
echo ""
|
|
echo -e "${BOLD}$title${NC}"
|
|
echo "─────────────────────────────────────────────────────────────"
|
|
echo ""
|
|
|
|
local i=1
|
|
for opt in "${options[@]}"; do
|
|
echo " $i) $opt"
|
|
i=$((i+1))
|
|
done
|
|
echo " a) All"
|
|
echo " n) None"
|
|
echo ""
|
|
|
|
while true; do
|
|
read -p "Select options (comma-separated, a=n): " selection
|
|
|
|
if [[ "$selection" =~ ^[Aa]$ ]]; then
|
|
return 0 # All
|
|
elif [[ "$selection" =~ ^[Nn]$ ]]; then
|
|
return 1 # None
|
|
else
|
|
return 0 # Has selections
|
|
fi
|
|
done
|
|
}
|
|
|
|
################################################################################
|
|
# Welcome Screen
|
|
################################################################################
|
|
|
|
show_welcome() {
|
|
print_header
|
|
echo -e "${BOLD}Welcome to Claude Code Customizations Installer!${NC}"
|
|
echo ""
|
|
echo "This installer will guide you through setting up a customized"
|
|
echo "Claude Code environment with:"
|
|
echo ""
|
|
echo " • 40+ specialized agents for development, marketing, and operations"
|
|
echo " • MCP tools for vision analysis, web search, and GitHub integration"
|
|
echo " • Custom skills and plugins"
|
|
echo " • Optimized workflows for rapid 6-day development cycles"
|
|
echo ""
|
|
echo -e "${YELLOW}Note:${NC} You can choose what to install at each step."
|
|
echo ""
|
|
|
|
if ! confirm "Continue with installation?" "Y"; then
|
|
echo "Installation cancelled."
|
|
exit 0
|
|
fi
|
|
}
|
|
|
|
################################################################################
|
|
# Model Selection
|
|
################################################################################
|
|
|
|
select_model() {
|
|
print_header
|
|
echo -e "${BOLD}Step 1: Model Selection${NC}"
|
|
echo "═══════════════════════════════════════════════════════════"
|
|
echo ""
|
|
echo "Choose which API models to use with Claude Code:"
|
|
echo ""
|
|
echo -e " ${GREEN}1${NC}) ${BOLD}Anthropic Claude Models${NC} (official)"
|
|
echo " • claude-sonnet-4.5, claude-opus-4.5, etc."
|
|
echo " • Direct Anthropic API"
|
|
echo " • Base URL: https://api.anthropic.com"
|
|
echo ""
|
|
echo -e " ${CYAN}2${NC}) ${BOLD}Z.AI / GLM Coding Plan Models${NC}"
|
|
echo " • Same Claude models via Z.AI platform"
|
|
echo " • Additional features: usage tracking, feedback, promotions"
|
|
echo " • Base URL: https://api.z.ai/api/anthropic"
|
|
echo " • Includes: 旺仔牛奶 rewards program"
|
|
echo ""
|
|
read -p "Select model provider [1/2]: " model_choice
|
|
|
|
case $model_choice in
|
|
2)
|
|
USE_ZAI_MODELS=true
|
|
log_success "Selected: Z.AI / GLM Coding Plan Models"
|
|
;;
|
|
*)
|
|
USE_ZAI_MODELS=false
|
|
log_success "Selected: Anthropic Claude Models (official)"
|
|
;;
|
|
esac
|
|
|
|
echo ""
|
|
}
|
|
|
|
################################################################################
|
|
# Agent Selection
|
|
################################################################################
|
|
|
|
select_agents() {
|
|
print_header
|
|
echo -e "${BOLD}Step 2: Agent Categories${NC}"
|
|
echo "═══════════════════════════════════════════════════════════"
|
|
echo ""
|
|
echo "Custom agents provide specialized assistance for different tasks."
|
|
echo "Select which categories to install:"
|
|
echo ""
|
|
|
|
if confirm "Install Engineering agents? (AI engineer, frontend/backend dev, DevOps, mobile, rapid prototyper, test writer)" "Y"; then
|
|
INSTALL_ENGINEERING=true
|
|
SELECTED_AGENTS=$((SELECTED_AGENTS + 7))
|
|
else
|
|
INSTALL_ENGINEERING=false
|
|
fi
|
|
|
|
if confirm "Install Marketing agents? (TikTok strategist, growth hacker, content creator, Instagram/Reddit/Twitter)" "Y"; then
|
|
INSTALL_MARKETING=true
|
|
SELECTED_AGENTS=$((SELECTED_AGENTS + 7))
|
|
else
|
|
INSTALL_MARKETING=false
|
|
fi
|
|
|
|
if confirm "Install Product agents? (Sprint prioritizer, feedback synthesizer, trend researcher)" "Y"; then
|
|
INSTALL_PRODUCT=true
|
|
SELECTED_AGENTS=$((SELECTED_AGENTS + 3))
|
|
else
|
|
INSTALL_PRODUCT=false
|
|
fi
|
|
|
|
if confirm "Install Studio Operations agents? (Studio producer, project shipper, analytics, finance, legal, support, coach)" "Y"; then
|
|
INSTALL_STUDIO_OPS=true
|
|
SELECTED_AGENTS=$((SELECTED_AGENTS + 8))
|
|
else
|
|
INSTALL_STUDIO_OPS=false
|
|
fi
|
|
|
|
if confirm "Install Project Management agents? (Experiment tracker, studio producer, project shipper)" "Y"; then
|
|
INSTALL_PROJECT_MGMT=true
|
|
SELECTED_AGENTS=$((SELECTED_AGENTS + 3))
|
|
else
|
|
INSTALL_PROJECT_MGMT=false
|
|
fi
|
|
|
|
if confirm "Install Testing agents? (Test writer/fixer, API tester, performance benchmarker, workflow optimizer)" "Y"; then
|
|
INSTALL_TESTING=true
|
|
SELECTED_AGENTS=$((SELECTED_AGENTS + 5))
|
|
else
|
|
INSTALL_TESTING=false
|
|
fi
|
|
|
|
if confirm "Install Design agents? (UI/UX designer, brand guardian, visual storyteller, whimsy injector)" "Y"; then
|
|
INSTALL_DESIGN=true
|
|
SELECTED_AGENTS=$((SELECTED_AGENTS + 5))
|
|
else
|
|
INSTALL_DESIGN=false
|
|
fi
|
|
|
|
if confirm "Install Bonus agents? (Joker, studio coach)" "Y"; then
|
|
INSTALL_BONUS=true
|
|
SELECTED_AGENTS=$((SELECTED_AGENTS + 2))
|
|
else
|
|
INSTALL_BONUS=false
|
|
fi
|
|
|
|
if [ $SELECTED_AGENTS -eq 0 ]; then
|
|
log_warning "No agents selected - you can add them later manually"
|
|
else
|
|
log_success "Selected $SELECTED_AGENTS agents across multiple categories"
|
|
fi
|
|
|
|
echo ""
|
|
}
|
|
|
|
################################################################################
|
|
# MCP Tools Selection
|
|
################################################################################
|
|
|
|
select_mcp_tools() {
|
|
print_header
|
|
echo -e "${BOLD}Step 3: MCP Tools${NC}"
|
|
echo "═══════════════════════════════════════════════════════════"
|
|
echo ""
|
|
echo "MCP (Model Context Protocol) tools provide advanced capabilities."
|
|
echo "Select which tools to install:"
|
|
echo ""
|
|
|
|
if confirm "Install Vision Analysis tools? (images, videos, UI screenshots, error diagnosis, data visualization, diagrams)" "Y"; then
|
|
INSTALL_VISION_TOOLS=true
|
|
SELECTED_MCP_TOOLS=$((SELECTED_MCP_TOOLS + 8))
|
|
else
|
|
INSTALL_VISION_TOOLS=false
|
|
fi
|
|
|
|
if confirm "Install Web Search tool? (enhanced search with domain filtering, time-based results)" "Y"; then
|
|
INSTALL_WEB_TOOLS=true
|
|
SELECTED_MCP_TOOLS=$((SELECTED_MCP_TOOLS + 1))
|
|
else
|
|
INSTALL_WEB_TOOLS=false
|
|
fi
|
|
|
|
if confirm "Install Web Reader tool? (fetch URLs, convert to markdown)" "Y"; then
|
|
INSTALL_WEB_TOOLS=true
|
|
SELECTED_MCP_TOOLS=$((SELECTED_MCP_TOOLS + 1))
|
|
fi
|
|
|
|
if confirm "Install GitHub Reader tool? (read repos, search docs/issues/commits)" "Y"; then
|
|
INSTALL_GITHUB_TOOLS=true
|
|
SELECTED_MCP_TOOLS=$((SELECTED_MCP_TOOLS + 3))
|
|
else
|
|
INSTALL_GITHUB_TOOLS=false
|
|
fi
|
|
|
|
if command -v python3 &> /dev/null && command -v pip3 &> /dev/null; then
|
|
if confirm "Install TLDR Code Analysis? (95% token reduction, semantic search, program slicing - requires Python)" "Y"; then
|
|
INSTALL_TLDR=true
|
|
SELECTED_MCP_TOOLS=$((SELECTED_MCP_TOOLS + 18))
|
|
else
|
|
INSTALL_TLDR=false
|
|
fi
|
|
else
|
|
log_warning "Python/pip3 not found - skipping TLDR Code Analysis"
|
|
INSTALL_TLDR=false
|
|
fi
|
|
|
|
if [ $SELECTED_MCP_TOOLS -eq 0 ]; then
|
|
log_warning "No MCP tools selected"
|
|
else
|
|
log_success "Selected $SELECTED_MCP_TOOLS MCP tools"
|
|
fi
|
|
|
|
INSTALL_MCP_TOOLS=true
|
|
echo ""
|
|
}
|
|
|
|
################################################################################
|
|
# Plugins Selection
|
|
################################################################################
|
|
|
|
select_plugins() {
|
|
print_header
|
|
echo -e "${BOLD}Step 4: Plugins & Skills${NC}"
|
|
echo "═══════════════════════════════════════════════════════════"
|
|
echo ""
|
|
echo "Plugins extend Claude Code with additional features:"
|
|
echo ""
|
|
echo " • glm-plan-bug: Submit bug/issue feedback to Z.AI"
|
|
echo " • glm-plan-usage: Query your GLM Coding Plan usage statistics"
|
|
echo ""
|
|
|
|
if confirm "Install Z.AI plugins?" "Y"; then
|
|
INSTALL_PLUGINS=true
|
|
log_success "Plugins selected"
|
|
else
|
|
INSTALL_PLUGINS=false
|
|
log_warning "Plugins skipped"
|
|
fi
|
|
|
|
echo ""
|
|
}
|
|
|
|
################################################################################
|
|
# Hooks Selection
|
|
################################################################################
|
|
|
|
select_hooks() {
|
|
print_header
|
|
echo -e "${BOLD}Step 5: Hooks${NC}"
|
|
echo "═══════════════════════════════════════════════════════════"
|
|
echo ""
|
|
echo "Hooks are scripts that run automatically on specific events."
|
|
echo "Do you want to copy existing hooks from the package?"
|
|
echo ""
|
|
|
|
if confirm "Install hooks?" "N"; then
|
|
INSTALL_HOOKS=true
|
|
log_success "Hooks selected"
|
|
else
|
|
INSTALL_HOOKS=false
|
|
log_warning "Hooks skipped"
|
|
fi
|
|
|
|
echo ""
|
|
}
|
|
|
|
################################################################################
|
|
# Ralph Selection
|
|
################################################################################
|
|
|
|
select_ralph() {
|
|
print_header
|
|
echo -e "${BOLD}Step 6: Ralph CLI (Advanced - Optional)${NC}"
|
|
echo "═══════════════════════════════════════════════════════════"
|
|
echo ""
|
|
echo "Ralph CLI provides autonomous agent looping (infinite iterations"
|
|
echo "until task completion). This is an ADVANCED feature for complex"
|
|
echo "multi-step workflows."
|
|
echo ""
|
|
echo " ${CYAN}• PROACTIVELY agents${NC}: Quick, single-pass coordination (built-in)"
|
|
echo " ${CYAN}• Ralph CLI${NC}: Autonomous looping, stateful, requires installation"
|
|
echo ""
|
|
echo "See Step 6 in MASTER-PROMPT.md for full details."
|
|
echo ""
|
|
|
|
if confirm "Install Ralph CLI for autonomous looping? (Optional)" "N"; then
|
|
INSTALL_RALPH=true
|
|
log_success "Ralph CLI selected"
|
|
else
|
|
INSTALL_RALPH=false
|
|
log_warning "Ralph CLI skipped (using built-in PROACTIVELY agents)"
|
|
fi
|
|
|
|
echo ""
|
|
}
|
|
|
|
################################################################################
|
|
# Prerequisites Check
|
|
################################################################################
|
|
|
|
check_prerequisites() {
|
|
print_header
|
|
echo -e "${BOLD}Step 7: Prerequisites Check${NC}"
|
|
echo "═══════════════════════════════════════════════════════════"
|
|
echo ""
|
|
|
|
local errors=0
|
|
|
|
# Check Node.js
|
|
if command -v node &> /dev/null; then
|
|
NODE_VERSION=$(node -v)
|
|
log_success "Node.js installed: $NODE_VERSION"
|
|
else
|
|
log_error "Node.js not found"
|
|
errors=$((errors+1))
|
|
fi
|
|
|
|
# Check npm
|
|
if command -v npm &> /dev/null; then
|
|
NPM_VERSION=$(npm -v)
|
|
log_success "npm installed: $NPM_VERSION"
|
|
else
|
|
log_error "npm not found"
|
|
errors=$((errors+1))
|
|
fi
|
|
|
|
# Check python3
|
|
if command -v python3 &> /dev/null; then
|
|
PYTHON_VERSION=$(python3 --version)
|
|
log_success "Python installed: $PYTHON_VERSION"
|
|
else
|
|
log_warning "Python3 not found (optional)"
|
|
fi
|
|
|
|
# Check npx
|
|
if command -v npx &> /dev/null; then
|
|
log_success "npx available"
|
|
else
|
|
log_warning "npx not found (will be installed with npm)"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
if [ $errors -gt 0 ]; then
|
|
log_error "Some prerequisites are missing. Please install them and try again."
|
|
echo ""
|
|
echo "Install Node.js: https://nodejs.org/"
|
|
echo "Or use nvm: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash"
|
|
echo ""
|
|
exit 1
|
|
fi
|
|
|
|
log_success "Prerequisites check passed"
|
|
echo ""
|
|
sleep 1
|
|
}
|
|
|
|
################################################################################
|
|
# Claude Code Installation
|
|
################################################################################
|
|
|
|
install_claude_code() {
|
|
print_header
|
|
echo -e "${BOLD}Step 8: Claude Code Installation${NC}"
|
|
echo "═══════════════════════════════════════════════════════════"
|
|
echo ""
|
|
|
|
# Check if Claude Code is installed
|
|
if command -v claude-code &> /dev/null; then
|
|
log_success "Claude Code is already installed"
|
|
claude-code --version 2>/dev/null || log_info "Version: unknown"
|
|
echo ""
|
|
return
|
|
fi
|
|
|
|
echo -e "${YELLOW}Claude Code is not installed on this system.${NC}"
|
|
echo ""
|
|
echo "Claude Code is Anthropic's official CLI for Claude."
|
|
echo "You need it to use these customizations."
|
|
echo ""
|
|
echo "Installation options:"
|
|
echo ""
|
|
echo -e " ${GREEN}1${NC}) ${BOLD}Install via npm (recommended)${NC}"
|
|
echo " • Requires Node.js 14+"
|
|
echo " • Command: npm install -g @anthropic-ai/claude-code"
|
|
echo " • Fastest method"
|
|
echo ""
|
|
echo -e " ${GREEN}2${NC}) ${BOLD}Install via curl (alternative)${NC}"
|
|
echo " • Downloads standalone binary"
|
|
echo " • No Node.js required"
|
|
echo ""
|
|
echo -e " ${GREEN}3${NC}) ${BOLD}Manual installation${NC}"
|
|
echo " • Visit: https://claude.ai/download"
|
|
echo " • Choose your platform"
|
|
echo ""
|
|
echo -e " ${YELLOW}0${NC}) Skip installation"
|
|
echo ""
|
|
read -p "Select installation method [1/2/3/0]: " install_choice
|
|
|
|
case $install_choice in
|
|
1)
|
|
echo ""
|
|
log_info "Installing Claude Code via npm..."
|
|
echo ""
|
|
|
|
if command -v npm &> /dev/null; then
|
|
npm install -g @anthropic-ai/claude-code
|
|
|
|
if command -v claude-code &> /dev/null; then
|
|
log_success "Claude Code installed successfully!"
|
|
echo ""
|
|
claude-code --version 2>/dev/null || true
|
|
else
|
|
log_error "Installation failed. Please try manual installation."
|
|
fi
|
|
else
|
|
log_error "npm not found. Please install Node.js first."
|
|
echo "Visit: https://nodejs.org/"
|
|
fi
|
|
;;
|
|
2)
|
|
echo ""
|
|
log_info "Installing Claude Code via curl..."
|
|
echo ""
|
|
|
|
if command -v curl &> /dev/null; then
|
|
# Detect OS and architecture
|
|
OS="$(uname -s)"
|
|
ARCH="$(uname -m)"
|
|
|
|
case "$OS" in
|
|
Linux)
|
|
if [ "$ARCH" = "x86_64" ]; then
|
|
curl -L https://claude.ai/download/claude-code-linux -o /tmp/claude-code
|
|
sudo mv /tmp/claude-code /usr/local/bin/claude-code
|
|
sudo chmod +x /usr/local/bin/claude-code
|
|
log_success "Claude Code installed!"
|
|
else
|
|
log_error "Unsupported architecture: $ARCH"
|
|
fi
|
|
;;
|
|
Darwin)
|
|
if [ "$ARCH" = "arm64" ]; then
|
|
curl -L https://claude.ai/download/claude-code-mac-arm -o /tmp/claude-code
|
|
else
|
|
curl -L https://claude.ai/download/claude-code-mac -o /tmp/claude-code
|
|
fi
|
|
sudo mv /tmp/claude-code /usr/local/bin/claude-code
|
|
sudo chmod +x /usr/local/bin/claude-code
|
|
log_success "Claude Code installed!"
|
|
;;
|
|
*)
|
|
log_error "Unsupported OS: $OS"
|
|
;;
|
|
esac
|
|
else
|
|
log_error "curl not found. Please install curl or use npm method."
|
|
fi
|
|
;;
|
|
3)
|
|
echo ""
|
|
log_info "Please visit https://claude.ai/download to install Claude Code manually"
|
|
echo ""
|
|
echo "After installation, run this script again."
|
|
echo ""
|
|
exit 0
|
|
;;
|
|
0)
|
|
log_warning "Skipping Claude Code installation"
|
|
log_warning "You will need to install it manually to use these customizations"
|
|
;;
|
|
*)
|
|
log_error "Invalid choice"
|
|
;;
|
|
esac
|
|
|
|
echo ""
|
|
sleep 2
|
|
}
|
|
|
|
################################################################################
|
|
# Backup Existing Configuration
|
|
################################################################################
|
|
|
|
backup_config() {
|
|
if [ -d "$CLAUDE_DIR" ]; then
|
|
print_header
|
|
echo -e "${BOLD}Step 8: Backup${NC}"
|
|
echo "═══════════════════════════════════════════════════════════"
|
|
echo ""
|
|
log_info "Existing Claude Code configuration found"
|
|
log_info "Creating backup at: $BACKUP_DIR"
|
|
echo ""
|
|
|
|
cp -r "$CLAUDE_DIR" "$BACKUP_DIR"
|
|
log_success "Backup created successfully"
|
|
echo ""
|
|
sleep 1
|
|
fi
|
|
}
|
|
|
|
################################################################################
|
|
# Installation
|
|
################################################################################
|
|
|
|
create_directories() {
|
|
log_info "Creating directory structure..."
|
|
|
|
mkdir -p "$CLAUDE_DIR"/{agents,plugins/cache,plugins/marketplaces,hooks,debug,file-history,paste-cache,projects,session-env,shell-snapshots,todos}
|
|
|
|
if [ "$INSTALL_ENGINEERING" = true ]; then mkdir -p "$CLAUDE_DIR/agents/engineering"; fi
|
|
if [ "$INSTALL_MARKETING" = true ]; then mkdir -p "$CLAUDE_DIR/agents/marketing"; fi
|
|
if [ "$INSTALL_PRODUCT" = true ]; then mkdir -p "$CLAUDE_DIR/agents/product"; fi
|
|
if [ "$INSTALL_STUDIO_OPS" = true ]; then mkdir -p "$CLAUDE_DIR/agents/studio-operations"; fi
|
|
if [ "$INSTALL_PROJECT_MGMT" = true ]; then mkdir -p "$CLAUDE_DIR/agents/project-management"; fi
|
|
if [ "$INSTALL_TESTING" = true ]; then mkdir -p "$CLAUDE_DIR/agents/testing"; fi
|
|
if [ "$INSTALL_DESIGN" = true ]; then mkdir -p "$CLAUDE_DIR/agents/design"; fi
|
|
if [ "$INSTALL_BONUS" = true ]; then mkdir -p "$CLAUDE_DIR/agents/bonus"; fi
|
|
|
|
log_success "Directories created"
|
|
}
|
|
|
|
fetch_latest_agents() {
|
|
log_info "Checking for agent updates from GitHub..."
|
|
|
|
local GITHUB_REPO="https://github.com/contains-studio/agents"
|
|
local TEMP_AGENT_DIR="/tmp/claude-agents-latest-$RANDOM"
|
|
local UPDATE_FOUND=false
|
|
|
|
# Create temp directory
|
|
mkdir -p "$TEMP_AGENT_DIR"
|
|
|
|
# Try to clone using git
|
|
if command -v git &> /dev/null; then
|
|
if git clone --depth 1 --quiet "$GITHUB_REPO" "$TEMP_AGENT_DIR" 2>/dev/null; then
|
|
UPDATE_FOUND=true
|
|
log_success "Fetched latest agents from GitHub"
|
|
|
|
# Copy updated agents to source directory
|
|
for category in engineering marketing product studio-operations project-management testing design bonus; do
|
|
if [ -d "$TEMP_AGENT_DIR/$category" ]; then
|
|
mkdir -p "$SCRIPT_DIR/agents/$category"
|
|
cp -f "$TEMP_AGENT_DIR/$category"/*.md "$SCRIPT_DIR/agents/$category/" 2>/dev/null || true
|
|
fi
|
|
done
|
|
|
|
# Update README if present
|
|
if [ -f "$TEMP_AGENT_DIR/README.md" ]; then
|
|
cp -f "$TEMP_AGENT_DIR/README.md" "$SCRIPT_DIR/agents/README.md" 2>/dev/null || true
|
|
fi
|
|
|
|
log_info "Local agents updated from GitHub"
|
|
else
|
|
log_warning "Failed to fetch from GitHub (using local agents)"
|
|
fi
|
|
else
|
|
log_warning "Git not found (using local agents)"
|
|
fi
|
|
|
|
# Cleanup
|
|
rm -rf "$TEMP_AGENT_DIR"
|
|
|
|
return 0
|
|
}
|
|
|
|
install_agents() {
|
|
if [ $SELECTED_AGENTS -eq 0 ]; then
|
|
return
|
|
fi
|
|
|
|
log_info "Installing agents..."
|
|
|
|
local source_agents="$SCRIPT_DIR/agents"
|
|
|
|
if [ ! -d "$source_agents" ]; then
|
|
log_warning "Agent source directory not found at $source_agents"
|
|
log_warning "Please ensure you're running this from the correct location"
|
|
return
|
|
fi
|
|
|
|
if [ "$INSTALL_ENGINEERING" = true ]; then
|
|
mkdir -p "$CLAUDE_DIR/agents/engineering"
|
|
cp -r "$source_agents/engineering/"*.md "$CLAUDE_DIR/agents/engineering/" 2>/dev/null || true
|
|
fi
|
|
|
|
if [ "$INSTALL_MARKETING" = true ]; then
|
|
mkdir -p "$CLAUDE_DIR/agents/marketing"
|
|
cp -r "$source_agents/marketing/"*.md "$CLAUDE_DIR/agents/marketing/" 2>/dev/null || true
|
|
fi
|
|
|
|
if [ "$INSTALL_PRODUCT" = true ]; then
|
|
mkdir -p "$CLAUDE_DIR/agents/product"
|
|
cp -r "$source_agents/product/"*.md "$CLAUDE_DIR/agents/product/" 2>/dev/null || true
|
|
fi
|
|
|
|
if [ "$INSTALL_STUDIO_OPS" = true ]; then
|
|
mkdir -p "$CLAUDE_DIR/agents/studio-operations"
|
|
cp -r "$source_agents/studio-operations/"*.md "$CLAUDE_DIR/agents/studio-operations/" 2>/dev/null || true
|
|
fi
|
|
|
|
if [ "$INSTALL_PROJECT_MGMT" = true ]; then
|
|
mkdir -p "$CLAUDE_DIR/agents/project-management"
|
|
cp -r "$source_agents/project-management/"*.md "$CLAUDE_DIR/agents/project-management/" 2>/dev/null || true
|
|
fi
|
|
|
|
if [ "$INSTALL_TESTING" = true ]; then
|
|
mkdir -p "$CLAUDE_DIR/agents/testing"
|
|
cp -r "$source_agents/testing/"*.md "$CLAUDE_DIR/agents/testing/" 2>/dev/null || true
|
|
fi
|
|
|
|
if [ "$INSTALL_DESIGN" = true ]; then
|
|
mkdir -p "$CLAUDE_DIR/agents/design"
|
|
cp -r "$source_agents/design/"*.md "$CLAUDE_DIR/agents/design/" 2>/dev/null || true
|
|
fi
|
|
|
|
if [ "$INSTALL_BONUS" = true ]; then
|
|
mkdir -p "$CLAUDE_DIR/agents/bonus"
|
|
cp -r "$source_agents/bonus/"*.md "$CLAUDE_DIR/agents/bonus/" 2>/dev/null || true
|
|
log_info "Installing agent-updater for automatic sync..."
|
|
fi
|
|
|
|
# Install sync-agents.sh script
|
|
if [ -f "$SCRIPT_DIR/sync-agents.sh" ]; then
|
|
log_info "Installing sync-agents.sh script..."
|
|
cp "$SCRIPT_DIR/sync-agents.sh" "$CLAUDE_DIR/sync-agents.sh"
|
|
chmod +x "$CLAUDE_DIR/sync-agents.sh"
|
|
log_success "sync-agents.sh installed (run: ~/.claude/sync-agents.sh)"
|
|
fi
|
|
|
|
log_success "Agents installed: $SELECTED_AGENTS"
|
|
}
|
|
|
|
install_settings() {
|
|
log_info "Configuring settings..."
|
|
|
|
local settings_file="$CLAUDE_DIR/settings.json"
|
|
|
|
# Determine API base URL and help text
|
|
if [ "$USE_ZAI_MODELS" = true ]; then
|
|
API_BASE="https://api.z.ai/api/anthropic"
|
|
API_NAME="Z.AI / GLM Coding Plan"
|
|
API_HELP="Get your API key from: https://z.ai/ (Official docs: https://docs.z.ai/devpack/tool/claude)"
|
|
API_TOKEN_NAME="Z.AI API Key"
|
|
else
|
|
API_BASE="https://api.anthropic.com"
|
|
API_NAME="Anthropic Claude"
|
|
API_HELP="Get your API key from: https://console.anthropic.com/"
|
|
API_TOKEN_NAME="Anthropic API Key"
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${CYAN}API Configuration${NC}"
|
|
echo "─────────────────────────────────────────────────────────────"
|
|
echo " Provider: $API_NAME"
|
|
echo " Base URL: $API_BASE"
|
|
echo ""
|
|
echo -e "${YELLOW}$API_HELP${NC}"
|
|
echo ""
|
|
|
|
# Check if settings.json exists
|
|
if [ -f "$settings_file" ]; then
|
|
log_warning "settings.json already exists"
|
|
if confirm "Keep existing API token?" "Y"; then
|
|
log_info "Preserving existing configuration"
|
|
else
|
|
echo ""
|
|
read -p "Enter your $API_TOKEN_NAME: " API_TOKEN
|
|
while [ -z "$API_TOKEN" ]; do
|
|
echo -e "${RED}API token cannot be empty${NC}"
|
|
read -p "Enter your $API_TOKEN_NAME: " API_TOKEN
|
|
done
|
|
|
|
# Update existing file
|
|
if [ "$USE_ZAI_MODELS" = true ]; then
|
|
cat > "$settings_file" << EOF
|
|
{
|
|
"env": {
|
|
"ANTHROPIC_AUTH_TOKEN": "$API_TOKEN",
|
|
"ANTHROPIC_BASE_URL": "$API_BASE",
|
|
"API_TIMEOUT_MS": "3000000",
|
|
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
|
|
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "glm-4.5-air",
|
|
"ANTHROPIC_DEFAULT_SONNET_MODEL": "glm-4.7",
|
|
"ANTHROPIC_DEFAULT_OPUS_MODEL": "glm-4.7"
|
|
},
|
|
"enabledPlugins": {}
|
|
}
|
|
EOF
|
|
else
|
|
cat > "$settings_file" << EOF
|
|
{
|
|
"env": {
|
|
"ANTHROPIC_AUTH_TOKEN": "$API_TOKEN",
|
|
"ANTHROPIC_BASE_URL": "$API_BASE",
|
|
"API_TIMEOUT_MS": "3000000",
|
|
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
|
|
},
|
|
"enabledPlugins": {}
|
|
}
|
|
EOF
|
|
fi
|
|
log_success "API token updated"
|
|
fi
|
|
else
|
|
read -p "Enter your $API_TOKEN_NAME: " API_TOKEN
|
|
while [ -z "$API_TOKEN" ]; do
|
|
echo -e "${RED}API token cannot be empty${NC}"
|
|
read -p "Enter your $API_TOKEN_NAME: " API_TOKEN
|
|
done
|
|
|
|
if [ "$USE_ZAI_MODELS" = true ]; then
|
|
cat > "$settings_file" << EOF
|
|
{
|
|
"env": {
|
|
"ANTHROPIC_AUTH_TOKEN": "$API_TOKEN",
|
|
"ANTHROPIC_BASE_URL": "$API_BASE",
|
|
"API_TIMEOUT_MS": "3000000",
|
|
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
|
|
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "glm-4.5-air",
|
|
"ANTHROPIC_DEFAULT_SONNET_MODEL": "glm-4.7",
|
|
"ANTHROPIC_DEFAULT_OPUS_MODEL": "glm-4.7"
|
|
},
|
|
"enabledPlugins": {}
|
|
}
|
|
EOF
|
|
else
|
|
cat > "$settings_file" << EOF
|
|
{
|
|
"env": {
|
|
"ANTHROPIC_AUTH_TOKEN": "$API_TOKEN",
|
|
"ANTHROPIC_BASE_URL": "$API_BASE",
|
|
"API_TIMEOUT_MS": "3000000",
|
|
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
|
|
},
|
|
"enabledPlugins": {}
|
|
}
|
|
EOF
|
|
fi
|
|
log_success "API token configured"
|
|
fi
|
|
|
|
# Add plugins to enabledPlugins if selected
|
|
if [ "$INSTALL_PLUGINS" = true ]; then
|
|
if [ "$USE_ZAI_MODELS" = true ]; then
|
|
# Add Z.AI plugins
|
|
if command -v jq &> /dev/null; then
|
|
temp=$(mktemp)
|
|
jq '.enabledPlugins += {"glm-plan-bug@zai-coding-plugins": true, "glm-plan-usage@zai-coding-plugins": true}' "$settings_file" > "$temp"
|
|
mv "$temp" "$settings_file"
|
|
log_success "Z.AI plugins enabled"
|
|
else
|
|
log_warning "jq not found, plugins not added to settings"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
log_success "Settings configured for $API_NAME"
|
|
|
|
# Version verification and Z.AI documentation reference
|
|
if [ "$USE_ZAI_MODELS" = true ]; then
|
|
echo ""
|
|
echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
|
|
echo -e "${BOLD}Z.AI GLM Configuration${NC}"
|
|
echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
|
|
echo ""
|
|
echo -e "${GREEN}✓ GLM Models Configured:${NC}"
|
|
echo " • glm-4.5-air (Haiku equivalent - fast, efficient)"
|
|
echo " • glm-4.7 (Sonnet/Opus equivalent - high quality)"
|
|
echo ""
|
|
echo -e "${YELLOW}📖 Official Documentation:${NC}"
|
|
echo " https://docs.z.ai/devpack/tool/claude"
|
|
echo ""
|
|
echo -e "${YELLOW}🔍 Verify Installation:${NC}"
|
|
echo " 1. Check version: ${CYAN}claude --version${NC} (recommended: 2.0.14+)"
|
|
echo " 2. Start Claude: ${CYAN}claude${NC}"
|
|
echo " 3. Check status: ${CYAN}/status${NC} (when prompted)"
|
|
echo ""
|
|
echo -e "${YELLOW}🔧 Troubleshooting:${NC}"
|
|
echo " • Close all Claude Code windows and reopen"
|
|
echo " • Or delete ~/.claude/settings.json and reconfigure"
|
|
echo " • Verify JSON format is correct (no missing/extra commas)"
|
|
echo ""
|
|
fi
|
|
}
|
|
|
|
install_local_settings() {
|
|
log_info "Configuring permissions..."
|
|
|
|
local local_settings="$CLAUDE_DIR/settings.local.json"
|
|
|
|
cat > "$local_settings" << 'EOF'
|
|
{
|
|
"permissions": {
|
|
"allow": [
|
|
"Bash(npm install:*)",
|
|
"Bash(npm run content:*)",
|
|
"Bash(npm run build:*)",
|
|
"Bash(grep:*)",
|
|
"Bash(find:*)",
|
|
"Bash(for:*)",
|
|
"Bash(do sed:*)",
|
|
"Bash(done)",
|
|
"Bash(python3:*)",
|
|
"Bash(while read f)",
|
|
"Bash(do echo \"$f%-* $f\")",
|
|
"Bash(ls:*)",
|
|
"Bash(node:*)",
|
|
"Bash(pm2 delete:*)",
|
|
"Bash(pm2 start npm:*)",
|
|
"Bash(pm2 save:*)"
|
|
]
|
|
}
|
|
}
|
|
EOF
|
|
|
|
log_success "Permissions configured"
|
|
}
|
|
|
|
install_mcp_config() {
|
|
if [ "$INSTALL_MCP_TOOLS" = false ] && [ "$INSTALL_TLDR" = false ]; then
|
|
return
|
|
fi
|
|
|
|
log_info "Creating MCP server configuration..."
|
|
|
|
local mcp_config="$CLAUDE_DIR/claude_desktop_config.json"
|
|
local config_needed=false
|
|
|
|
# Check if any MCP tools need configuration
|
|
if [ "$INSTALL_VISION_TOOLS" = true ] || [ "$INSTALL_WEB_TOOLS" = true ] || [ "$INSTALL_GITHUB_TOOLS" = true ] || [ "$INSTALL_TLDR" = true ]; then
|
|
config_needed=true
|
|
fi
|
|
|
|
if [ "$config_needed" = false ]; then
|
|
return
|
|
fi
|
|
|
|
# Start building MCP config
|
|
local mcp_servers="{"
|
|
|
|
# Add vision tools
|
|
if [ "$INSTALL_VISION_TOOLS" = true ]; then
|
|
mcp_servers="${mcp_servers}
|
|
\"zai-vision\": {
|
|
\"command\": \"npx\",
|
|
\"args\": [\"@z_ai/mcp-server\"]
|
|
},"
|
|
fi
|
|
|
|
# Add web search tool
|
|
if [ "$INSTALL_WEB_TOOLS" = true ]; then
|
|
mcp_servers="${mcp_servers}
|
|
\"web-search-prime\": {
|
|
\"command\": \"npx\",
|
|
\"args\": [\"@z_ai/coding-helper\"],
|
|
\"env\": {
|
|
\"TOOL\": \"web-search-prime\"
|
|
}
|
|
},
|
|
\"web-reader\": {
|
|
\"command\": \"npx\",
|
|
\"args\": [\"@z_ai/coding-helper\"],
|
|
\"env\": {
|
|
\"TOOL\": \"web-reader\"
|
|
}
|
|
},"
|
|
fi
|
|
|
|
# Add GitHub tool
|
|
if [ "$INSTALL_GITHUB_TOOLS" = true ]; then
|
|
mcp_servers="${mcp_servers}
|
|
\"github-reader\": {
|
|
\"command\": \"npx\",
|
|
\"args\": [\"@z_ai/coding-helper\"],
|
|
\"env\": {
|
|
\"TOOL\": \"github-reader\"
|
|
}
|
|
},"
|
|
fi
|
|
|
|
# Add TLDR (remove trailing comma before closing)
|
|
if [ "$INSTALL_TLDR" = true ]; then
|
|
# Remove trailing comma from previous entry if exists
|
|
mcp_servers="${mcp_servers%,}"
|
|
mcp_servers="${mcp_servers}
|
|
,
|
|
\"tldr\": {
|
|
\"command\": \"tldr-mcp\",
|
|
\"args\": [\"--project\", \".\"]
|
|
}"
|
|
fi
|
|
|
|
# Remove trailing comma if exists
|
|
mcp_servers="${mcp_servers%,}"
|
|
|
|
# Close JSON
|
|
mcp_servers="${mcp_servers}
|
|
}"
|
|
|
|
# Write config file
|
|
cat > "$mcp_config" << EOF
|
|
{
|
|
"mcpServers": $(echo "$mcp_servers")
|
|
}
|
|
EOF
|
|
|
|
log_success "MCP server configuration created"
|
|
}
|
|
|
|
install_mcp_tools() {
|
|
if [ "$INSTALL_MCP_TOOLS" = false ]; then
|
|
return
|
|
fi
|
|
|
|
log_info "Installing MCP tools..."
|
|
|
|
# Install @z_ai/mcp-server if vision tools selected
|
|
if [ "$INSTALL_VISION_TOOLS" = true ]; then
|
|
if command -v npm &> /dev/null; then
|
|
npm install -g @z_ai/mcp-server 2>/dev/null || {
|
|
log_warning "Global install failed, will use npx"
|
|
}
|
|
log_success "Vision MCP tools installed"
|
|
fi
|
|
fi
|
|
|
|
# Install @z_ai/coding-helper for web/GitHub tools
|
|
if [ "$INSTALL_WEB_TOOLS" = true ] || [ "$INSTALL_GITHUB_TOOLS" = true ]; then
|
|
npm install -g @z_ai/coding-helper 2>/dev/null || {
|
|
log_warning "Global install failed, will use npx"
|
|
}
|
|
log_success "Web/GitHub MCP tools installed"
|
|
fi
|
|
|
|
# Install llm-tldr for code analysis
|
|
if [ "$INSTALL_TLDR" = true ]; then
|
|
if command -v pip3 &> /dev/null; then
|
|
pip3 install llm-tldr 2>/dev/null || {
|
|
log_warning "pip3 install failed, trying pip"
|
|
pip install llm-tldr 2>/dev/null || {
|
|
log_error "Failed to install llm-tldr"
|
|
log_info "Install manually: pip install llm-tldr"
|
|
}
|
|
}
|
|
log_success "TLDR code analysis installed"
|
|
|
|
# Initialize TLDR for current directory if it's a git repo
|
|
if [ -d .git ] || git rev-parse --git-dir > /dev/null 2>&1; then
|
|
log_info "Initializing TLDR for current directory..."
|
|
tldr warm . 2>/dev/null || {
|
|
log_warning "TLDR initialization failed - run 'tldr warm .' manually"
|
|
}
|
|
log_success "TLDR initialized for codebase"
|
|
fi
|
|
else
|
|
log_warning "pip3 not found - skipping TLDR installation"
|
|
fi
|
|
fi
|
|
|
|
log_success "MCP tools configured: $SELECTED_MCP_TOOLS"
|
|
}
|
|
|
|
install_plugins() {
|
|
if [ "$INSTALL_PLUGINS" = false ]; then
|
|
return
|
|
fi
|
|
|
|
log_info "Installing plugins..."
|
|
|
|
# Create plugin registry
|
|
mkdir -p "$CLAUDE_DIR/plugins/cache/zai-coding-plugins"/{glm-plan-bug,glm-plan-usage}
|
|
|
|
local installed_plugins="$CLAUDE_DIR/plugins/installed_plugins.json"
|
|
|
|
if [ "$USE_ZAI_MODELS" = true ]; then
|
|
cat > "$installed_plugins" << EOF
|
|
{
|
|
"version": 2,
|
|
"plugins": {
|
|
"glm-plan-bug@zai-coding-plugins": [
|
|
{
|
|
"scope": "user",
|
|
"installPath": "$CLAUDE_DIR/plugins/cache/zai-coding-plugins/glm-plan-bug/0.0.1",
|
|
"version": "0.0.1",
|
|
"installedAt": "$(date -u +%Y-%m-%dT%H:%M:%S.000Z)",
|
|
"lastUpdated": "$(date -u +%Y-%m-%dT%H:%M:%S.000Z)"
|
|
}
|
|
],
|
|
"glm-plan-usage@zai-coding-plugins": [
|
|
{
|
|
"scope": "user",
|
|
"installPath": "$CLAUDE_DIR/plugins/cache/zai-coding-plugins/glm-plan-usage/0.0.1",
|
|
"version": "0.0.1",
|
|
"installedAt": "$(date -u +%Y-%m-%dT%H:%M:%S.000Z)",
|
|
"lastUpdated": "$(date -u +%Y-%m-%dT%H:%M:%S.000Z)"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
EOF
|
|
fi
|
|
|
|
log_success "Plugins installed"
|
|
}
|
|
|
|
install_hooks() {
|
|
if [ "$INSTALL_HOOKS" = false ]; then
|
|
return
|
|
fi
|
|
|
|
local source_hooks="$SCRIPT_DIR/claude-complete-package/hooks"
|
|
|
|
if [ -d "$source_hooks" ] && [ "$(ls -A $source_hooks 2>/dev/null)" ]; then
|
|
log_info "Installing hooks..."
|
|
cp -r "$source_hooks/"* "$CLAUDE_DIR/hooks/" 2>/dev/null || true
|
|
log_success "Hooks installed"
|
|
fi
|
|
}
|
|
|
|
################################################################################
|
|
# Ralph CLI Installation
|
|
################################################################################
|
|
|
|
install_ralph() {
|
|
if [ "$INSTALL_RALPH" = false ]; then
|
|
return
|
|
fi
|
|
|
|
log_info "Installing Ralph CLI..."
|
|
|
|
# Check if npm is available
|
|
if ! command -v npm &> /dev/null; then
|
|
log_error "npm not found. Cannot install Ralph CLI."
|
|
return
|
|
fi
|
|
|
|
# Install Ralph CLI globally
|
|
if npm install -g @iannuttall/ralph 2>/dev/null; then
|
|
log_success "Ralph CLI installed via npm"
|
|
else
|
|
log_warning "Ralph CLI installation failed. You can install manually later: npm install -g @iannuttall/ralph"
|
|
return
|
|
fi
|
|
|
|
# Create hooks directory
|
|
mkdir -p "$CLAUDE_DIR/hooks"
|
|
|
|
# Create ralph-auto-trigger.sh script (Enhanced with Background Spawning)
|
|
log_info "Creating Ralph auto-trigger hook with background spawning..."
|
|
cat > "$CLAUDE_DIR/hooks/ralph-auto-trigger.sh" << 'RALPH_HOOK_EOF'
|
|
#!/bin/bash
|
|
# Ralph Auto-Trigger Hook - Enhanced with Background Task Spawning
|
|
# Automatically starts Ralph CLI in background when needed
|
|
#
|
|
# Modes (via RALPH_AUTO_MODE environment variable):
|
|
# "always" - Start Ralph for every request
|
|
# "agents" - Only for agent requests (default)
|
|
# "off" - Disable auto-trigger
|
|
#
|
|
# Background Execution:
|
|
# - Ralph runs as background process (non-blocking)
|
|
# - Claude Code continues immediately
|
|
# - Ralph output logged to: ~/.claude/ralph-output.log
|
|
# - Ralph PID tracked in: ~/.claude/ralph.pid
|
|
|
|
set -euo pipefail
|
|
|
|
# Configuration
|
|
CLAUDE_DIR="$HOME/.claude"
|
|
RALPH_STATE_FILE="$CLAUDE_DIR/ralph-loop.local.md"
|
|
RALPH_PID_FILE="$CLAUDE_DIR/ralph.pid"
|
|
RALPH_LOG_FILE="$CLAUDE_DIR/ralph-output.log"
|
|
RALPH_LOCK_FILE="$CLAUDE_DIR/ralph.lock"
|
|
|
|
# Read hook input from stdin
|
|
HOOK_INPUT=$(cat)
|
|
USER_PROMPT=$(echo "$HOOK_INPUT" | jq -r '.prompt // empty' 2>/dev/null || echo "")
|
|
|
|
# Fallback: if no JSON input, use first argument
|
|
if [[ -z "$USER_PROMPT" && $# -gt 0 ]]; then
|
|
USER_PROMPT="$1"
|
|
fi
|
|
|
|
# Get Ralph mode (default: agents)
|
|
RALPH_AUTO_MODE="${RALPH_AUTO_MODE:-agents}"
|
|
RALPH_MAX_ITERATIONS="${RALPH_MAX_ITERATIONS:-50}"
|
|
|
|
# Exit if auto-trigger is disabled
|
|
if [[ "$RALPH_AUTO_MODE" == "off" ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
# Check if Ralph is already running (via lock file)
|
|
if [[ -f "$RALPH_LOCK_FILE" ]]; then
|
|
# Check if process is still alive
|
|
LOCK_PID=$(cat "$RALPH_LOCK_FILE" 2>/dev/null || echo "")
|
|
if [[ -n "$LOCK_PID" ]] && kill -0 "$LOCK_PID" 2>/dev/null; then
|
|
# Ralph is already running, don't start another instance
|
|
exit 0
|
|
else
|
|
# Lock file exists but process is dead, clean up
|
|
rm -f "$RALPH_LOCK_FILE" "$RALPH_PID_FILE"
|
|
fi
|
|
fi
|
|
|
|
# Agent detection list (lowercase for matching)
|
|
AGENTS=(
|
|
"ai-engineer" "backend-architect" "devops-automator" "frontend-developer"
|
|
"mobile-app-builder" "rapid-prototyper" "test-writer-fixer"
|
|
"tiktok-strategist" "growth-hacker" "content-creator" "instagram-curator"
|
|
"reddit-builder" "twitter-engager" "app-store-optimizer"
|
|
"brand-guardian" "ui-designer" "ux-researcher" "visual-storyteller"
|
|
"whimsy-injector" "ui-ux-pro-max"
|
|
"feedback-synthesizer" "sprint-prioritizer" "trend-researcher"
|
|
"experiment-tracker" "project-shipper" "studio-producer" "studio-coach"
|
|
"analytics-reporter" "finance-tracker" "infrastructure-maintainer"
|
|
"legal-compliance-checker" "support-responder"
|
|
"api-tester" "performance-benchmarker" "test-results-analyzer"
|
|
"tool-evaluator" "workflow-optimizer"
|
|
"joker" "agent-updater"
|
|
"explore" "plan" "general-purpose"
|
|
)
|
|
|
|
# Detect agent request (case-insensitive)
|
|
agent_detected=false
|
|
detected_agent=""
|
|
|
|
for agent in "${AGENTS[@]}"; do
|
|
if echo "$USER_PROMPT" | grep -iq "$agent"; then
|
|
agent_detected=true
|
|
detected_agent="$agent"
|
|
break
|
|
fi
|
|
done
|
|
|
|
# Determine if we should start Ralph
|
|
should_trigger=false
|
|
|
|
case "$RALPH_AUTO_MODE" in
|
|
"always")
|
|
# Trigger on all prompts
|
|
should_trigger=true
|
|
;;
|
|
"agents")
|
|
# Only trigger on agent requests OR development keywords
|
|
if [[ "$agent_detected" == true ]]; then
|
|
should_trigger=true
|
|
elif echo "$USER_PROMPT" | grep -qiE "build|create|implement|develop|fix|add|refactor|optimize|write|generate|delegate|autonomous"; then
|
|
should_trigger=true
|
|
detected_agent="general-development"
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
if [[ "$should_trigger" == true ]]; then
|
|
# Create Ralph state file
|
|
mkdir -p "$CLAUDE_DIR"
|
|
|
|
cat > "$RALPH_STATE_FILE" << EOF
|
|
# Ralph Loop State - Auto-Triggered
|
|
# Generated: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
|
|
|
|
**User Request:**
|
|
$USER_PROMPT
|
|
|
|
**Detected Agent:** $detected_agent
|
|
**Mode:** $RALPH_AUTO_MODE
|
|
**Max Iterations:** $RALPH_MAX_ITERATIONS
|
|
**Timestamp:** $(date -Iseconds)
|
|
|
|
## Context
|
|
|
|
This state file was automatically generated by the Ralph auto-trigger hook.
|
|
Ralph CLI will read this file and autonomously execute the request.
|
|
|
|
## Auto-Trigger Details
|
|
|
|
- Triggered by: Claude Code UserPromptSubmit hook
|
|
- Trigger mode: $RALPH_AUTO_MODE
|
|
- Background execution: Yes (non-blocking)
|
|
- Log file: $RALPH_LOG_FILE
|
|
|
|
## Usage
|
|
|
|
Ralph is running autonomously in the background. Monitor progress:
|
|
|
|
bash
|
|
# View Ralph output in real-time
|
|
tail -f ~/.claude/ralph-output.log
|
|
|
|
# Check if Ralph is still running
|
|
ps aux | grep ralph
|
|
|
|
# Stop Ralph manually
|
|
kill $(cat ~/.claude/ralph.pid)
|
|
rm ~/.claude/ralph.lock
|
|
|
|
|
|
EOF
|
|
|
|
# Spawn Ralph in background (NON-BLOCKING)
|
|
if command -v ralph &> /dev/null; then
|
|
# Create log file
|
|
touch "$RALPH_LOG_FILE"
|
|
|
|
# Start Ralph in background with nohup (survives terminal close)
|
|
echo "[$(date -u +"%Y-%m-%d %H:%M:%S UTC")] Starting Ralph in background..." >> "$RALPH_LOG_FILE"
|
|
echo "Mode: $RALPH_AUTO_MODE" >> "$RALPH_LOG_FILE"
|
|
echo "Agent: $detected_agent" >> "$RALPH_LOG_FILE"
|
|
echo "Max iterations: $RALPH_MAX_ITERATIONS" >> "$RALPH_LOG_FILE"
|
|
echo "---" >> "$RALPH_LOG_FILE"
|
|
|
|
# Start Ralph in background
|
|
nohup ralph build "$RALPH_MAX_ITERATIONS" >> "$RALPH_LOG_FILE" 2>&1 &
|
|
RALPH_PID=$!
|
|
|
|
# Save PID for tracking
|
|
echo "$RALPH_PID" > "$RALPH_PID_FILE"
|
|
echo "$RALPH_PID" > "$RALPH_LOCK_FILE"
|
|
|
|
# Log the trigger
|
|
{
|
|
echo "[$(date -u +"%Y-%m-%d %H:%M:%S UTC")] Ralph auto-triggered"
|
|
echo " Mode: $RALPH_AUTO_MODE"
|
|
echo " Agent: $detected_agent"
|
|
echo " PID: $RALPH_PID"
|
|
echo " Log: $RALPH_LOG_FILE"
|
|
} >> "$CLAUDE_DIR/ralph-trigger.log" 2>/dev/null || true
|
|
|
|
# Notify user via stderr (visible in Claude Code)
|
|
echo "🔄 Ralph CLI auto-started in background" >&2
|
|
echo " PID: $RALPH_PID" >&2
|
|
echo " Agent: $detected_agent" >&2
|
|
echo " Monitor: tail -f ~/.claude/ralph-output.log" >&2
|
|
echo " Stop: kill \$(cat ~/.claude/ralph.pid)" >&2
|
|
else
|
|
# Ralph not installed, just create state file
|
|
echo "⚠️ Ralph CLI not installed. State file created for manual use." >&2
|
|
echo " Install: npm install -g @iannuttall/ralph" >&2
|
|
fi
|
|
fi
|
|
|
|
# Exit immediately (NON-BLOCKING - Claude Code continues)
|
|
exit 0
|
|
RALPH_HOOK_EOF
|
|
|
|
chmod +x "$CLAUDE_DIR/hooks/ralph-auto-trigger.sh"
|
|
log_success "Ralph auto-trigger hook created"
|
|
|
|
# Create or update hooks.json
|
|
log_info "Configuring hooks.json..."
|
|
HOOKS_FILE="$CLAUDE_DIR/hooks.json"
|
|
|
|
if [ -f "$HOOKS_FILE" ]; then
|
|
# Backup existing hooks.json
|
|
cp "$HOOKS_FILE" "$HOOKS_FILE.backup.$(date +%Y%m%d-%H%M%S)"
|
|
fi
|
|
|
|
# Create new hooks.json with Ralph hook
|
|
cat > "$HOOKS_FILE" << 'HOOKS_JSON_EOF'
|
|
{
|
|
"description": "User hooks for Ralph auto-trigger and custom behavior",
|
|
"hooks": {
|
|
"UserPromptSubmit": [
|
|
{
|
|
"type": "command",
|
|
"command": "bash",
|
|
"args": ["/home/uroma/.claude/hooks/ralph-auto-trigger.sh", "{{userPrompt}}"]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
HOOKS_JSON_EOF
|
|
|
|
log_success "hooks.json configured for Ralph auto-trigger"
|
|
|
|
# Create environment file for Ralph configuration
|
|
cat > "$CLAUDE_DIR/ralph-config.env" << 'RALPH_ENV_EOF'
|
|
# Ralph CLI Configuration
|
|
# Source this file or add to your shell profile: export RALPH_AUTO_MODE=agents
|
|
|
|
# Ralph auto-trigger mode:
|
|
# - always: Trigger on all prompts
|
|
# - agents: Only trigger on agent requests (default)
|
|
# - off: Disable auto-trigger
|
|
export RALPH_AUTO_MODE="${RALPH_AUTO_MODE:-agents}"
|
|
|
|
# Ralph state file location (auto-created)
|
|
export RALPH_STATE_FILE="$HOME/.claude/ralph-loop.local.md"
|
|
RALPH_ENV_EOF
|
|
|
|
log_success "Ralph configuration saved to $CLAUDE_DIR/ralph-config.env"
|
|
echo ""
|
|
log_info "To enable Ralph auto-trigger, add to your shell profile:"
|
|
echo " source ~/.claude/ralph-config.env"
|
|
echo ""
|
|
log_info "Ralph CLI modes: always (all prompts) | agents (agent prompts only) | off (disabled)"
|
|
}
|
|
|
|
perform_installation() {
|
|
print_header
|
|
echo -e "${BOLD}Step 10: Installation${NC}"
|
|
echo "═══════════════════════════════════════════════════════════"
|
|
echo ""
|
|
|
|
create_directories
|
|
fetch_latest_agents
|
|
install_agents
|
|
install_settings
|
|
install_local_settings
|
|
install_mcp_config
|
|
install_mcp_tools
|
|
install_plugins
|
|
install_hooks
|
|
install_ralph
|
|
|
|
echo ""
|
|
log_success "Installation completed!"
|
|
echo ""
|
|
sleep 1
|
|
}
|
|
|
|
################################################################################
|
|
# Summary & Launch
|
|
################################################################################
|
|
|
|
show_summary() {
|
|
print_header
|
|
echo -e "${BOLD}Installation Summary${NC}"
|
|
echo "╔══════════════════════════════════════════════════════════════════╗${NC}"
|
|
echo "║ ║"
|
|
echo "║ Configuration: ║"
|
|
|
|
if [ "$USE_ZAI_MODELS" = true ]; then
|
|
echo "║ • Model Provider: ${CYAN}Z.AI / GLM Coding Plan${NC} ║"
|
|
else
|
|
echo "║ • Model Provider: ${GREEN}Anthropic Claude (Official)${NC} ║"
|
|
fi
|
|
|
|
echo "║ ║"
|
|
echo "║ Installed Components: ║"
|
|
|
|
if [ $SELECTED_AGENTS -gt 0 ]; then
|
|
echo "║ • Agents: ${GREEN}$SELECTED_AGENTS custom agents${NC} ║"
|
|
fi
|
|
|
|
if [ $SELECTED_MCP_TOOLS -gt 0 ]; then
|
|
echo "║ • MCP Tools: ${CYAN}$SELECTED_MCP_TOOLS tools${NC} ║"
|
|
fi
|
|
|
|
if [ "$INSTALL_PLUGINS" = true ]; then
|
|
echo "║ • Plugins: ${GREEN}Z.AI plugins enabled${NC} ║"
|
|
fi
|
|
|
|
if [ "$INSTALL_HOOKS" = true ]; then
|
|
echo "║ • Hooks: ${GREEN}Installed${NC} ║"
|
|
fi
|
|
|
|
if [ "$INSTALL_RALPH" = true ]; then
|
|
echo "║ • Ralph CLI: ${MAGENTA}Installed (Autonomous Looping)${NC} ║"
|
|
fi
|
|
|
|
echo "║ ║"
|
|
echo "╚══════════════════════════════════════════════════════════════════╝"
|
|
echo ""
|
|
}
|
|
|
|
launch_claude_code() {
|
|
echo ""
|
|
echo -e "${BOLD}Launch Claude Code?${NC}"
|
|
echo ""
|
|
echo "You can launch Claude Code now to start using your customizations."
|
|
echo ""
|
|
|
|
if confirm "Launch Claude Code now?" "N"; then
|
|
echo ""
|
|
log_info "Launching Claude Code..."
|
|
echo ""
|
|
|
|
# Try to launch claude-code
|
|
if command -v claude-code &> /dev/null; then
|
|
exec claude-code
|
|
elif command -v code &> /dev/null; then
|
|
log_info "Trying VS Code command..."
|
|
code
|
|
else
|
|
log_warning "Claude Code command not found"
|
|
echo ""
|
|
echo "Please launch Claude Code manually:"
|
|
echo " • From applications menu"
|
|
echo " • Or run: claude-code"
|
|
echo " • Or run: code"
|
|
fi
|
|
else
|
|
echo ""
|
|
log_info "You can launch Claude Code later with: claude-code"
|
|
fi
|
|
}
|
|
|
|
################################################################################
|
|
# Main Installation Flow
|
|
################################################################################
|
|
|
|
main() {
|
|
show_welcome
|
|
select_model
|
|
select_agents
|
|
select_mcp_tools
|
|
select_plugins
|
|
select_hooks
|
|
select_ralph
|
|
check_prerequisites
|
|
install_claude_code
|
|
backup_config
|
|
perform_installation
|
|
show_summary
|
|
|
|
if [ -n "$BACKUP_DIR" ] && [ -d "$BACKUP_DIR" ]; then
|
|
log_info "Backup saved to: $BACKUP_DIR"
|
|
fi
|
|
|
|
launch_claude_code
|
|
}
|
|
|
|
# Run main
|
|
main "$@"
|