#!/usr/bin/env bash set -euo pipefail # ============================================================================ # OpenClaw + Mem0 One-Click Setup # ============================================================================ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" OPENCLAW_CONFIG_DIR="${OPENCLAW_CONFIG_DIR:-$HOME/.openclaw}" OPENCLAW_PORT="${OPENCLAW_PORT:-18789}" # Colors (disabled if not a terminal) if [ -t 1 ]; then RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' BOLD='\033[1m' NC='\033[0m' else RED='' GREEN='' YELLOW='' BLUE='' BOLD='' NC='' fi info() { echo -e "${BLUE}ℹ${NC} $*"; } ok() { echo -e "${GREEN}✔${NC} $*"; } warn() { echo -e "${YELLOW}⚠${NC} $*"; } error() { echo -e "${RED}✖${NC} $*" >&2; } header() { echo -e "\n${BOLD}$*${NC}"; } # ============================================================================ # Step 1: Check prerequisites # ============================================================================ header "Checking prerequisites..." if ! command -v docker &>/dev/null; then error "Docker is not installed." echo " Install Docker Desktop: https://www.docker.com/products/docker-desktop/" echo " Or Docker Engine: https://docs.docker.com/engine/install/" exit 1 fi if ! docker compose version &>/dev/null; then error "Docker Compose v2 is not available." echo " Ensure you have Docker Compose v2 (comes with Docker Desktop)." echo " Docs: https://docs.docker.com/compose/install/" exit 1 fi if ! docker info &>/dev/null 2>&1; then error "Docker daemon is not running. Please start Docker and try again." exit 1 fi ok "Docker and Docker Compose are available." # Check for port conflict if command -v lsof &>/dev/null && lsof -i :"$OPENCLAW_PORT" &>/dev/null; then warn "Port $OPENCLAW_PORT is already in use." echo " Check what's using it: lsof -i :$OPENCLAW_PORT" echo " Or set a different port: OPENCLAW_PORT=18790 ./setup.sh" exit 1 fi # ============================================================================ # Step 2: Check for existing config # ============================================================================ if [ -f "$OPENCLAW_CONFIG_DIR/openclaw.json" ]; then warn "Existing config found at $OPENCLAW_CONFIG_DIR/openclaw.json" read -rp " Overwrite with new config? [y/N] " overwrite if [[ ! "$overwrite" =~ ^[Yy]$ ]]; then info "Keeping existing config. Skipping config generation." SKIP_CONFIG=true else SKIP_CONFIG=false fi else SKIP_CONFIG=false fi # ============================================================================ # Step 3: Choose mode # ============================================================================ header "Choose your setup mode:" echo "" echo " 1) Platform — Uses Mem0 Cloud (managed storage, dashboard at app.mem0.ai)" echo " 2) OSS — Self-hosted with local Qdrant (fully offline-capable)" echo "" while true; do read -rp "Enter 1 or 2: " mode_choice case "$mode_choice" in 1) MODE="platform"; break ;; 2) MODE="oss"; break ;; *) echo " Please enter 1 or 2." ;; esac done ok "Mode: $MODE" # ============================================================================ # Step 4: Collect API keys # ============================================================================ header "API Key Configuration" MEM0_API_KEY="" OPENAI_API_KEY="" if [ "$MODE" = "platform" ]; then echo " Platform mode requires a Mem0 API key from https://app.mem0.ai" echo "" while true; do read -rp " Mem0 API Key: " MEM0_API_KEY if [ -n "$MEM0_API_KEY" ]; then break; fi warn "API key is required for platform mode." done echo "" read -rp " OpenAI API Key (optional, for agent LLM — press Enter to skip): " OPENAI_API_KEY else echo " OSS mode requires an OpenAI API key for embeddings, LLM, and the agent." echo "" while true; do read -rp " OpenAI API Key: " OPENAI_API_KEY if [ -n "$OPENAI_API_KEY" ]; then break; fi warn "API key is required for OSS mode." done fi ok "API keys configured." # ============================================================================ # Step 5: User ID # ============================================================================ DEFAULT_USER_ID="$(whoami)" read -rp " User ID for memory scoping [${DEFAULT_USER_ID}]: " MEM0_USER_ID MEM0_USER_ID="${MEM0_USER_ID:-$DEFAULT_USER_ID}" ok "User ID: $MEM0_USER_ID" # ============================================================================ # Step 6: Generate .env # ============================================================================ header "Generating configuration..." cat > "$SCRIPT_DIR/.env" < "$OPENCLAW_CONFIG_DIR/openclaw.json" ok "Created $OPENCLAW_CONFIG_DIR/openclaw.json" fi # ============================================================================ # Step 8: Install Mem0 plugin # ============================================================================ header "Installing Mem0 plugin..." COMPOSE_CMD="docker compose" if [ "$MODE" = "oss" ]; then COMPOSE_CMD="docker compose -f docker-compose.yml -f docker-compose.oss.yml" fi cd "$SCRIPT_DIR" if $COMPOSE_CMD run --rm openclaw openclaw plugins install @mem0/openclaw-mem0 2>/dev/null; then ok "Mem0 plugin installed." else warn "Plugin install via Docker failed. This may be normal on first run." echo " You can install manually later:" echo " $COMPOSE_CMD run --rm openclaw openclaw plugins install @mem0/openclaw-mem0" fi # ============================================================================ # Step 9: Copy onboarding skill # ============================================================================ SKILL_DIR="$OPENCLAW_CONFIG_DIR/workspace/skills/mem0-onboarding" mkdir -p "$SKILL_DIR" cp "$SCRIPT_DIR/skills/mem0-onboarding/SKILL.md" "$SKILL_DIR/SKILL.md" ok "Onboarding skill installed." # ============================================================================ # Step 10: Start containers # ============================================================================ header "Starting OpenClaw..." $COMPOSE_CMD up -d # ============================================================================ # Step 11: Health check # ============================================================================ info "Waiting for OpenClaw to be ready..." HEALTH_URL="http://127.0.0.1:${OPENCLAW_PORT}/healthz" TIMEOUT=90 ELAPSED=0 INTERVAL=3 while [ $ELAPSED -lt $TIMEOUT ]; do if curl -sf "$HEALTH_URL" &>/dev/null; then echo "" ok "OpenClaw is ready!" break fi printf "." sleep $INTERVAL ELAPSED=$((ELAPSED + INTERVAL)) done if [ $ELAPSED -ge $TIMEOUT ]; then echo "" warn "Health check timed out after ${TIMEOUT}s." echo " OpenClaw may still be starting. Check logs:" echo " cd $SCRIPT_DIR && $COMPOSE_CMD logs -f" exit 1 fi # ============================================================================ # Done! # ============================================================================ echo "" header "Setup complete!" echo "" echo " Open the web UI: ${BOLD}http://localhost:${OPENCLAW_PORT}${NC}" echo " Mode: ${MODE}" echo " User ID: ${MEM0_USER_ID}" echo " Config: ${OPENCLAW_CONFIG_DIR}/openclaw.json" echo "" echo " ${BLUE}Tip:${NC} Your first chat will trigger the Mem0 onboarding skill." echo " Try telling the agent something about yourself to test memory!" echo "" echo " Useful commands:" echo " View logs: cd $SCRIPT_DIR && $COMPOSE_CMD logs -f" echo " Stop: cd $SCRIPT_DIR && $COMPOSE_CMD down" echo " Restart: cd $SCRIPT_DIR && $COMPOSE_CMD restart" echo ""