/ start-orchestrator.sh
start-orchestrator.sh
1 #!/bin/bash 2 # Alpha/Delta Orchestrator — Quick Start Script 3 # 4 # This script sets up and starts the orchestration system. 5 # It handles all dependency installation for Debian/Ubuntu and macOS. 6 # 7 # Run with: curl -fsSL <url> | bash 8 # Or: ./start-orchestrator.sh 9 10 set -e 11 12 # Colors for output 13 RED='\033[0;31m' 14 GREEN='\033[0;32m' 15 YELLOW='\033[1;33m' 16 BLUE='\033[0;34m' 17 CYAN='\033[0;36m' 18 BOLD='\033[1m' 19 NC='\033[0m' # No Color 20 21 # Detect OS 22 detect_os() { 23 if [[ "$OSTYPE" == "linux-gnu"* ]]; then 24 if [ -f /etc/debian_version ]; then 25 OS="debian" 26 PKG_MANAGER="apt-get" 27 elif [ -f /etc/redhat-release ]; then 28 OS="redhat" 29 PKG_MANAGER="dnf" 30 elif [ -f /etc/arch-release ]; then 31 OS="arch" 32 PKG_MANAGER="pacman" 33 else 34 OS="linux" 35 PKG_MANAGER="unknown" 36 fi 37 elif [[ "$OSTYPE" == "darwin"* ]]; then 38 OS="macos" 39 PKG_MANAGER="brew" 40 else 41 OS="unknown" 42 PKG_MANAGER="unknown" 43 fi 44 } 45 46 # Print banner 47 print_banner() { 48 echo -e "${BLUE}" 49 echo "╔═══════════════════════════════════════════════════════════════════════╗" 50 echo "║ ║" 51 echo "║ █████╗ ██╗ ██████╗ ██╗ ██╗ █████╗ ██████╗ ███████╗██╗ ║" 52 echo "║ ██╔══██╗██║ ██╔══██╗██║ ██║██╔══██╗ ██╔═══██╗██╔════╝██║ ║" 53 echo "║ ███████║██║ ██████╔╝███████║███████║ ██║ ██║█████╗ ██║ ║" 54 echo "║ ██╔══██║██║ ██╔═══╝ ██╔══██║██╔══██║ ██║ ██║██╔══╝ ██║ ║" 55 echo "║ ██║ ██║███████╗██║ ██║ ██║██║ ██║ ╚██████╔╝██║ ██║ ║" 56 echo "║ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ║" 57 echo "║ ║" 58 echo "║ Claude Code Development Orchestrator ║" 59 echo "║ ║" 60 echo "╚═══════════════════════════════════════════════════════════════════════╝" 61 echo -e "${NC}" 62 } 63 64 # Check if running as root 65 check_sudo() { 66 if [ "$EUID" -eq 0 ]; then 67 SUDO="" 68 else 69 SUDO="sudo" 70 fi 71 } 72 73 # Install system dependencies 74 install_system_deps() { 75 echo -e "${YELLOW}${BOLD}[1/7] Installing system dependencies...${NC}" 76 77 case $OS in 78 debian) 79 echo -e "${CYAN}Detected Debian/Ubuntu${NC}" 80 $SUDO apt-get update -qq 81 $SUDO apt-get install -y -qq \ 82 git \ 83 curl \ 84 wget \ 85 tmux \ 86 python3 \ 87 python3-pip \ 88 python3-venv \ 89 jq \ 90 build-essential \ 91 2>/dev/null 92 echo -e "${GREEN}✓ System dependencies installed${NC}" 93 ;; 94 redhat) 95 echo -e "${CYAN}Detected RHEL/Fedora${NC}" 96 $SUDO dnf install -y -q \ 97 git \ 98 curl \ 99 wget \ 100 tmux \ 101 python3 \ 102 python3-pip \ 103 jq \ 104 gcc \ 105 2>/dev/null 106 echo -e "${GREEN}✓ System dependencies installed${NC}" 107 ;; 108 arch) 109 echo -e "${CYAN}Detected Arch Linux${NC}" 110 $SUDO pacman -Sy --noconfirm --quiet \ 111 git \ 112 curl \ 113 wget \ 114 tmux \ 115 python \ 116 python-pip \ 117 jq \ 118 base-devel \ 119 2>/dev/null 120 echo -e "${GREEN}✓ System dependencies installed${NC}" 121 ;; 122 macos) 123 echo -e "${CYAN}Detected macOS${NC}" 124 125 # Check for Homebrew 126 if ! command -v brew &> /dev/null; then 127 echo -e "${YELLOW}Installing Homebrew...${NC}" 128 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 129 130 # Add Homebrew to PATH for this session 131 if [[ -f "/opt/homebrew/bin/brew" ]]; then 132 eval "$(/opt/homebrew/bin/brew shellenv)" 133 elif [[ -f "/usr/local/bin/brew" ]]; then 134 eval "$(/usr/local/bin/brew shellenv)" 135 fi 136 fi 137 138 brew install git curl wget tmux python jq 2>/dev/null || true 139 echo -e "${GREEN}✓ System dependencies installed${NC}" 140 ;; 141 *) 142 echo -e "${RED}Unknown OS. Please install manually: git, curl, tmux, python3, pip3, jq${NC}" 143 exit 1 144 ;; 145 esac 146 } 147 148 # Install Node.js (required for Claude Code) 149 install_nodejs() { 150 echo -e "${YELLOW}${BOLD}[2/7] Checking Node.js installation...${NC}" 151 152 if command -v node &> /dev/null; then 153 NODE_VERSION=$(node --version | cut -d'v' -f2 | cut -d'.' -f1) 154 if [ "$NODE_VERSION" -ge 18 ]; then 155 echo -e "${GREEN}✓ Node.js $(node --version) already installed${NC}" 156 return 157 fi 158 fi 159 160 echo -e "${CYAN}Installing Node.js 20.x...${NC}" 161 162 case $OS in 163 debian) 164 curl -fsSL https://deb.nodesource.com/setup_20.x | $SUDO bash - 165 $SUDO apt-get install -y -qq nodejs 2>/dev/null 166 ;; 167 redhat) 168 curl -fsSL https://rpm.nodesource.com/setup_20.x | $SUDO bash - 169 $SUDO dnf install -y -q nodejs 2>/dev/null 170 ;; 171 arch) 172 $SUDO pacman -S --noconfirm nodejs npm 2>/dev/null 173 ;; 174 macos) 175 brew install node@20 2>/dev/null || true 176 ;; 177 esac 178 179 echo -e "${GREEN}✓ Node.js $(node --version) installed${NC}" 180 } 181 182 # Install Claude Code CLI 183 install_claude_code() { 184 echo -e "${YELLOW}${BOLD}[3/7] Installing Claude Code CLI...${NC}" 185 186 if command -v claude &> /dev/null; then 187 echo -e "${GREEN}✓ Claude Code already installed: $(claude --version 2>/dev/null || echo 'version unknown')${NC}" 188 return 189 fi 190 191 echo -e "${CYAN}Installing Claude Code via npm...${NC}" 192 193 # Install globally 194 if [ "$OS" == "macos" ] || [ "$EUID" -eq 0 ]; then 195 npm install -g @anthropic-ai/claude-code 2>/dev/null || { 196 echo -e "${YELLOW}Global install failed, trying with sudo...${NC}" 197 $SUDO npm install -g @anthropic-ai/claude-code 198 } 199 else 200 # Try global, fall back to user install 201 $SUDO npm install -g @anthropic-ai/claude-code 2>/dev/null || { 202 echo -e "${YELLOW}Installing to user directory...${NC}" 203 mkdir -p "$HOME/.local/bin" 204 npm install -g @anthropic-ai/claude-code --prefix "$HOME/.local" 205 export PATH="$HOME/.local/bin:$PATH" 206 } 207 fi 208 209 # Verify installation 210 if command -v claude &> /dev/null; then 211 echo -e "${GREEN}✓ Claude Code installed successfully${NC}" 212 else 213 echo -e "${RED}❌ Claude Code installation failed${NC}" 214 echo -e "${YELLOW}Try manually: npm install -g @anthropic-ai/claude-code${NC}" 215 exit 1 216 fi 217 } 218 219 # Setup Python virtual environment and install packages 220 install_python_deps() { 221 echo -e "${YELLOW}${BOLD}[4/7] Setting up Python environment...${NC}" 222 223 WORKSPACE="${ORCHESTRATOR_WORKSPACE:-$HOME/alpha-delta-workspace}" 224 VENV_PATH="$WORKSPACE/.venv" 225 226 mkdir -p "$WORKSPACE" 227 228 # Create virtual environment 229 if [ ! -d "$VENV_PATH" ]; then 230 echo -e "${CYAN}Creating Python virtual environment...${NC}" 231 python3 -m venv "$VENV_PATH" 232 fi 233 234 # Activate and install packages 235 source "$VENV_PATH/bin/activate" 236 237 echo -e "${CYAN}Installing Python packages...${NC}" 238 pip install --upgrade pip --quiet 239 pip install --quiet \ 240 anthropic \ 241 rich \ 242 aiofiles \ 243 pyyaml 244 245 echo -e "${GREEN}✓ Python environment ready${NC}" 246 } 247 248 # Configure API key 249 configure_api_key() { 250 echo -e "${YELLOW}${BOLD}[5/7] Configuring Anthropic API key...${NC}" 251 252 if [ -n "$ANTHROPIC_API_KEY" ]; then 253 echo -e "${GREEN}✓ ANTHROPIC_API_KEY already set${NC}" 254 return 255 fi 256 257 # Check for saved key 258 KEY_FILE="$HOME/.anthropic_api_key" 259 if [ -f "$KEY_FILE" ]; then 260 export ANTHROPIC_API_KEY=$(cat "$KEY_FILE") 261 echo -e "${GREEN}✓ Loaded API key from $KEY_FILE${NC}" 262 return 263 fi 264 265 echo "" 266 echo -e "${CYAN}Please enter your Anthropic API key:${NC}" 267 echo -e "${YELLOW}(Get one at: https://console.anthropic.com/settings/keys)${NC}" 268 echo "" 269 read -r -s -p "API Key: " api_key 270 echo "" 271 272 if [ -z "$api_key" ]; then 273 echo -e "${RED}❌ API key is required${NC}" 274 exit 1 275 fi 276 277 export ANTHROPIC_API_KEY="$api_key" 278 279 # Offer to save 280 echo "" 281 read -r -p "Save API key for future sessions? (y/n): " save_key 282 if [[ "$save_key" =~ ^[Yy]$ ]]; then 283 echo "$api_key" > "$KEY_FILE" 284 chmod 600 "$KEY_FILE" 285 echo -e "${GREEN}✓ API key saved to $KEY_FILE${NC}" 286 287 # Add to shell profile 288 SHELL_PROFILE="" 289 if [ -f "$HOME/.zshrc" ]; then 290 SHELL_PROFILE="$HOME/.zshrc" 291 elif [ -f "$HOME/.bashrc" ]; then 292 SHELL_PROFILE="$HOME/.bashrc" 293 fi 294 295 if [ -n "$SHELL_PROFILE" ]; then 296 if ! grep -q "ANTHROPIC_API_KEY" "$SHELL_PROFILE"; then 297 echo "" >> "$SHELL_PROFILE" 298 echo "# Anthropic API Key" >> "$SHELL_PROFILE" 299 echo "export ANTHROPIC_API_KEY=\$(cat $KEY_FILE 2>/dev/null)" >> "$SHELL_PROFILE" 300 echo -e "${GREEN}✓ Added to $SHELL_PROFILE${NC}" 301 fi 302 fi 303 fi 304 } 305 306 # Setup workspace and repositories 307 setup_workspace() { 308 echo -e "${YELLOW}${BOLD}[6/7] Setting up workspace...${NC}" 309 310 WORKSPACE="${ORCHESTRATOR_WORKSPACE:-$HOME/alpha-delta-workspace}" 311 312 mkdir -p "$WORKSPACE" 313 cd "$WORKSPACE" 314 315 # Clone or update context repo 316 CONTEXT_REPO="${ORCHESTRATOR_CONTEXT_REPO:-}" 317 if [ -n "$CONTEXT_REPO" ]; then 318 if [ -d "alpha-delta-context/.git" ]; then 319 echo -e "${CYAN}Updating alpha-delta-context...${NC}" 320 cd alpha-delta-context && git pull --ff-only 2>/dev/null && cd .. 321 else 322 echo -e "${CYAN}Cloning alpha-delta-context...${NC}" 323 git clone "$CONTEXT_REPO" alpha-delta-context 2>/dev/null || { 324 echo -e "${YELLOW}Could not clone, creating placeholder...${NC}" 325 mkdir -p alpha-delta-context/{specifications,architecture,governance,decisions} 326 } 327 fi 328 else 329 echo -e "${YELLOW}No ORCHESTRATOR_CONTEXT_REPO set, creating placeholder structure...${NC}" 330 mkdir -p alpha-delta-context/{specifications,architecture,governance,decisions} 331 332 # Create a minimal spec file 333 if [ ! -f "alpha-delta-context/specifications/README.md" ]; then 334 cat > "alpha-delta-context/specifications/README.md" << 'EOF' 335 # Alpha/Delta Protocol Specifications 336 337 Place your technical specifications here. 338 339 The orchestrator will use these documents to: 340 - Plan implementation work 341 - Validate architectural decisions 342 - Keep documentation in sync 343 EOF 344 fi 345 fi 346 347 # Clone or update protocol repo 348 PROTOCOL_REPO="${ORCHESTRATOR_PROTOCOL_REPO:-}" 349 if [ -n "$PROTOCOL_REPO" ]; then 350 if [ -d "alpha-delta-protocol/.git" ]; then 351 echo -e "${CYAN}Updating alpha-delta-protocol...${NC}" 352 cd alpha-delta-protocol && git pull --ff-only 2>/dev/null && cd .. 353 else 354 echo -e "${CYAN}Cloning alpha-delta-protocol...${NC}" 355 git clone "$PROTOCOL_REPO" alpha-delta-protocol 2>/dev/null || { 356 echo -e "${YELLOW}Could not clone, creating placeholder...${NC}" 357 mkdir -p alpha-delta-protocol/crates 358 } 359 fi 360 else 361 echo -e "${YELLOW}No ORCHESTRATOR_PROTOCOL_REPO set, creating placeholder structure...${NC}" 362 mkdir -p alpha-delta-protocol/crates/{alpha-chain,delta-exchange,common} 363 364 # Create minimal Cargo.toml 365 if [ ! -f "alpha-delta-protocol/Cargo.toml" ]; then 366 cat > "alpha-delta-protocol/Cargo.toml" << 'EOF' 367 [workspace] 368 resolver = "2" 369 members = [ 370 "crates/*" 371 ] 372 373 [workspace.package] 374 version = "0.1.0" 375 edition = "2021" 376 EOF 377 fi 378 fi 379 380 # Create orchestrator directories 381 mkdir -p "$WORKSPACE"/{orchestrator-logs,message_bus,workers} 382 383 echo -e "${GREEN}✓ Workspace ready at $WORKSPACE${NC}" 384 } 385 386 # Download and install orchestrator 387 install_orchestrator() { 388 echo -e "${YELLOW}${BOLD}[7/7] Installing orchestrator...${NC}" 389 390 WORKSPACE="${ORCHESTRATOR_WORKSPACE:-$HOME/alpha-delta-workspace}" 391 ORCH_DIR="$WORKSPACE/orchestrator" 392 393 mkdir -p "$ORCH_DIR/prompts" 394 395 # Download orchestrator files (or copy if running from repo) 396 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" 397 398 if [ -f "$SCRIPT_DIR/orchestrator.py" ]; then 399 # Running from repo - copy files 400 echo -e "${CYAN}Copying orchestrator files from local directory...${NC}" 401 cp "$SCRIPT_DIR/orchestrator.py" "$ORCH_DIR/" 402 [ -f "$SCRIPT_DIR/requirements.txt" ] && cp "$SCRIPT_DIR/requirements.txt" "$ORCH_DIR/" 403 [ -d "$SCRIPT_DIR/prompts" ] && cp -r "$SCRIPT_DIR/prompts/"* "$ORCH_DIR/prompts/" 2>/dev/null || true 404 [ -f "$SCRIPT_DIR/ORCHESTRATOR_GUIDE.md" ] && cp "$SCRIPT_DIR/ORCHESTRATOR_GUIDE.md" "$ORCH_DIR/" 405 echo -e "${GREEN}✓ Orchestrator files copied${NC}" 406 else 407 # Try to download from a URL 408 echo -e "${CYAN}Downloading orchestrator from repository...${NC}" 409 410 ORCH_BASE_URL="${ORCHESTRATOR_DOWNLOAD_URL:-https://raw.githubusercontent.com/alpha-delta/orchestrator/main}" 411 412 # Download main files 413 curl -fsSL "$ORCH_BASE_URL/orchestrator.py" -o "$ORCH_DIR/orchestrator.py" 2>/dev/null || { 414 echo -e "${YELLOW}⚠ Could not download orchestrator.py${NC}" 415 echo -e "${YELLOW} Please copy orchestrator.py to: $ORCH_DIR/${NC}" 416 417 # Create minimal placeholder 418 cat > "$ORCH_DIR/orchestrator.py" << 'PLACEHOLDER' 419 #!/usr/bin/env python3 420 """ 421 Alpha/Delta Orchestrator - Placeholder 422 423 Please download the full orchestrator.py from: 424 https://github.com/alpha-delta/orchestrator 425 426 Or copy it manually to this location. 427 """ 428 import sys 429 print("ERROR: Full orchestrator.py not installed") 430 print(f"Please copy orchestrator.py to: {__file__}") 431 sys.exit(1) 432 PLACEHOLDER 433 } 434 435 curl -fsSL "$ORCH_BASE_URL/requirements.txt" -o "$ORCH_DIR/requirements.txt" 2>/dev/null || true 436 curl -fsSL "$ORCH_BASE_URL/ORCHESTRATOR_GUIDE.md" -o "$ORCH_DIR/ORCHESTRATOR_GUIDE.md" 2>/dev/null || true 437 curl -fsSL "$ORCH_BASE_URL/prompts/WORKER_PROMPTS.md" -o "$ORCH_DIR/prompts/WORKER_PROMPTS.md" 2>/dev/null || true 438 fi 439 440 # Create convenience wrapper script 441 cat > "$WORKSPACE/orch" << WRAPPER 442 #!/bin/bash 443 # Alpha/Delta Orchestrator CLI wrapper 444 445 WORKSPACE="$WORKSPACE" 446 VENV_PATH="\$WORKSPACE/.venv" 447 ORCH_DIR="\$WORKSPACE/orchestrator" 448 449 # Load API key if saved 450 if [ -f "\$HOME/.anthropic_api_key" ]; then 451 export ANTHROPIC_API_KEY=\$(cat "\$HOME/.anthropic_api_key") 452 fi 453 454 # Activate virtual environment 455 source "\$VENV_PATH/bin/activate" 456 457 # Run orchestrator 458 cd "\$WORKSPACE" 459 python3 "\$ORCH_DIR/orchestrator.py" "\$@" 460 WRAPPER 461 chmod +x "$WORKSPACE/orch" 462 463 # Create symlink in PATH if possible 464 mkdir -p "$HOME/.local/bin" 465 ln -sf "$WORKSPACE/orch" "$HOME/.local/bin/orch" 2>/dev/null || true 466 467 # Make sure ~/.local/bin is in PATH 468 if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then 469 echo -e "${YELLOW}Adding ~/.local/bin to PATH...${NC}" 470 export PATH="$HOME/.local/bin:$PATH" 471 472 SHELL_PROFILE="" 473 if [ -f "$HOME/.zshrc" ]; then 474 SHELL_PROFILE="$HOME/.zshrc" 475 elif [ -f "$HOME/.bashrc" ]; then 476 SHELL_PROFILE="$HOME/.bashrc" 477 fi 478 479 if [ -n "$SHELL_PROFILE" ]; then 480 if ! grep -q 'PATH.*\.local/bin' "$SHELL_PROFILE"; then 481 echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$SHELL_PROFILE" 482 fi 483 fi 484 fi 485 486 echo -e "${GREEN}✓ Orchestrator installed${NC}" 487 } 488 489 # Print completion message 490 print_completion() { 491 WORKSPACE="${ORCHESTRATOR_WORKSPACE:-$HOME/alpha-delta-workspace}" 492 493 echo "" 494 echo -e "${GREEN}${BOLD}" 495 echo "╔═══════════════════════════════════════════════════════════════════════╗" 496 echo "║ INSTALLATION COMPLETE! 🎉 ║" 497 echo "╚═══════════════════════════════════════════════════════════════════════╝" 498 echo -e "${NC}" 499 echo "" 500 echo -e "${BOLD}Workspace:${NC} $WORKSPACE" 501 echo "" 502 echo -e "${BOLD}Quick Start:${NC}" 503 echo -e " ${CYAN}cd $WORKSPACE${NC}" 504 echo -e " ${CYAN}./orch start${NC} # Start the orchestrator" 505 echo "" 506 echo -e "${BOLD}Commands:${NC}" 507 echo -e " ${CYAN}./orch start${NC} # Start all workers" 508 echo -e " ${CYAN}./orch start --no-planner${NC} # Start without planner" 509 echo -e " ${CYAN}./orch status${NC} # Show system status" 510 echo -e " ${CYAN}./orch add-task \"description\"${NC} # Add a task" 511 echo -e " ${CYAN}./orch respond worker \"answer\"${NC} # Answer a worker's question" 512 echo -e " ${CYAN}./orch logs worker-name${NC} # View worker logs" 513 echo -e " ${CYAN}./orch stop${NC} # Stop all workers" 514 echo "" 515 echo -e "${BOLD}Worker Sessions:${NC}" 516 echo -e " ${CYAN}tmux ls${NC} # List all sessions" 517 echo -e " ${CYAN}tmux attach -t claude-planner${NC} # Attach to planner" 518 echo -e " ${CYAN}tmux attach -t claude-executor-alpha${NC}" 519 echo "" 520 echo -e "${BOLD}Configuration:${NC}" 521 echo " Set these environment variables to use your repos:" 522 echo -e " ${YELLOW}export ORCHESTRATOR_CONTEXT_REPO${NC}=https://your-git/alpha-delta-context.git" 523 echo -e " ${YELLOW}export ORCHESTRATOR_PROTOCOL_REPO${NC}=https://your-git/alpha-delta-protocol.git" 524 echo "" 525 526 # Verify orchestrator.py exists and is complete 527 if [ ! -f "$WORKSPACE/orchestrator/orchestrator.py" ] || [ $(wc -l < "$WORKSPACE/orchestrator/orchestrator.py") -lt 100 ]; then 528 echo -e "${YELLOW}${BOLD}⚠️ Note:${NC}" 529 echo -e " The orchestrator.py file may be a placeholder." 530 echo -e " Please copy the full orchestrator.py to:" 531 echo -e " ${CYAN}$WORKSPACE/orchestrator/orchestrator.py${NC}" 532 echo "" 533 fi 534 535 # Ask to start 536 echo -e "${BLUE}${BOLD}Would you like to start the orchestrator now? (y/n)${NC}" 537 read -r response 538 if [[ "$response" =~ ^[Yy]$ ]]; then 539 echo "" 540 cd "$WORKSPACE" 541 source .venv/bin/activate 542 echo -e "${GREEN}Starting orchestrator...${NC}" 543 echo "" 544 python3 orchestrator/orchestrator.py start 545 else 546 echo "" 547 echo -e "${CYAN}To start later, run:${NC}" 548 echo -e " cd $WORKSPACE && ./orch start" 549 echo "" 550 fi 551 } 552 553 # Main installation flow 554 main() { 555 print_banner 556 557 echo -e "${BOLD}This script will install:${NC}" 558 echo " • System dependencies (git, tmux, python3, curl, jq)" 559 echo " • Node.js 20.x (required for Claude Code CLI)" 560 echo " • Claude Code CLI (@anthropic-ai/claude-code)" 561 echo " • Python packages (anthropic, rich, aiofiles, pyyaml)" 562 echo " • Orchestrator system and workspace" 563 echo "" 564 565 detect_os 566 echo -e "${CYAN}Detected OS: $OS (package manager: $PKG_MANAGER)${NC}" 567 echo "" 568 569 read -r -p "Continue with installation? (y/n): " confirm 570 if [[ ! "$confirm" =~ ^[Yy]$ ]]; then 571 echo "Installation cancelled." 572 exit 0 573 fi 574 575 echo "" 576 check_sudo 577 578 install_system_deps 579 echo "" 580 581 install_nodejs 582 echo "" 583 584 install_claude_code 585 echo "" 586 587 install_python_deps 588 echo "" 589 590 configure_api_key 591 echo "" 592 593 setup_workspace 594 echo "" 595 596 install_orchestrator 597 echo "" 598 599 print_completion 600 } 601 602 # Run main 603 main "$@"