#!/usr/bin/env bash # QwenClaw Full Installation Script # Works on Linux, macOS, and Windows (Git Bash/WSL) # # Usage: ./install.sh set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' # No Color # Script directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" echo "" echo -e "${CYAN} ____ _ __ _ _ ${NC}" echo -e "${CYAN} / ___|_ __ __ _ ___| | __ / _(_) | ___ ${NC}" echo -e "${CYAN}| | | '__/ _\` |/ __| |/ /| |_| | |/ _ \ ${NC}" echo -e "${CYAN}| |___| | | (_| | (__| < | _| | | __/ ${NC}" echo -e "${CYAN} \____|_| \__,_|\___|_|\_\|_| |_|_|\___| ${NC}" echo "" echo -e "${CYAN}Full Installation Script${NC}" echo "========================" echo "" # Detect OS OS="$(uname -s)" case "$OS" in Linux*) OS_NAME="Linux";; Darwin*) OS_NAME="macOS";; MINGW*|MSYS*|CYGWIN*) OS_NAME="Windows";; *) OS_NAME="Unknown";; esac echo -e "${YELLOW}Detected OS:${NC} $OS_NAME" echo "" # Function to check if command exists command_exists() { command -v "$1" >/dev/null 2>&1 } # Step 1: Check prerequisites echo -e "${YELLOW}[1/6] Checking prerequisites...${NC}" # Check Git if ! command_exists git; then echo -e "${RED}[ERROR] Git is not installed. Please install Git first.${NC}" exit 1 fi echo -e "${GREEN}[OK]${NC} Git is installed" # Check Bun (install if missing) if ! command_exists bun; then echo -e "${YELLOW}[INFO]${NC} Bun is not installed. Installing..." if [ "$OS_NAME" = "Windows" ]; then echo -e "${YELLOW}[INFO]${NC} Please install Bun manually from: https://bun.sh/install" echo -e "${YELLOW}[INFO]${NC} Run: powershell -c \"irm bun.sh/install.ps1 | iex\"" else curl -fsSL https://bun.sh/install | bash fi # Source bun if installed if [ -f "$HOME/.bun/_bun" ]; then source "$HOME/.bun/_bun" elif [ -f "$HOME/.bun/bin/bun" ]; then export PATH="$HOME/.bun/bin:$PATH" fi if command_exists bun; then echo -e "${GREEN}[OK]${NC} Bun installed successfully" else echo -e "${RED}[ERROR]${NC} Failed to install Bun. Please install manually.${NC}" exit 1 fi else echo -e "${GREEN}[OK]${NC} Bun is installed (v$(bun --version))" fi # Step 2: Install dependencies echo "" echo -e "${YELLOW}[2/6] Installing dependencies...${NC}" bun install echo -e "${GREEN}[OK]${NC} Dependencies installed" # Step 3: Create directories echo "" echo -e "${YELLOW}[3/6] Creating directories...${NC}" if [ "$OS_NAME" = "Windows" ]; then HOME_DIR="$USERPROFILE" else HOME_DIR="$HOME" fi QWEN_DIR="$HOME_DIR/.qwen" QWENCLAW_DATA_DIR="$QWEN_DIR/qwenclaw" mkdir -p "$QWENCLAW_DATA_DIR/jobs" mkdir -p "$QWENCLAW_DATA_DIR/logs" mkdir -p "$QWENCLAW_DATA_DIR/inbox/telegram" echo -e "${GREEN}[OK]${NC} Directories created" # Step 4: Create default settings echo "" echo -e "${YELLOW}[4/6] Creating default configuration...${NC}" SETTINGS_FILE="$QWENCLAW_DATA_DIR/settings.json" if [ ! -f "$SETTINGS_FILE" ]; then cat > "$SETTINGS_FILE" << 'EOF' { "model": "", "api": "", "autoStart": true, "fallback": { "model": "", "api": "" }, "timezone": "UTC", "timezoneOffsetMinutes": 0, "heartbeat": { "enabled": false, "interval": 15, "prompt": "", "excludeWindows": [] }, "telegram": { "token": "", "allowedUserIds": [] }, "security": { "level": "moderate", "allowedTools": [], "disallowedTools": [] }, "web": { "enabled": true, "host": "127.0.0.1", "port": 4632 } } EOF echo -e "${GREEN}[OK]${NC} Default settings created: $SETTINGS_FILE" else echo -e "${YELLOW}[INFO]${NC} Settings already exist, skipping" fi # Step 5: Set up auto-start echo "" echo -e "${YELLOW}[5/6] Configuring auto-start...${NC}" if [ "$OS_NAME" = "Windows" ]; then # Windows: Create startup shortcut STARTUP_FOLDER="$APPDATA\\Microsoft\\Windows\\Start Menu\\Programs\\Startup" if [ -d "$STARTUP_FOLDER" ]; then # Create a batch file for startup STARTUP_BAT="$STARTUP_FOLDER\\QwenClaw Daemon.bat" cat > "$STARTUP_BAT" << EOF @echo off cd /d "$SCRIPT_DIR" start /B bun run start --web EOF echo -e "${GREEN}[OK]${NC} Windows auto-start configured" else echo -e "${YELLOW}[INFO]${NC} Startup folder not found, skipping auto-start" fi elif [ "$OS_NAME" = "Linux" ]; then # Linux: Create systemd service or desktop autostart if command_exists systemctl; then # Systemd service SERVICE_FILE="/etc/systemd/system/qwenclaw.service" if [ -w "/etc/systemd/system" ]; then cat > "$SERVICE_FILE" << EOF [Unit] Description=QwenClaw Daemon After=network.target [Service] Type=simple User=$USER WorkingDirectory=$SCRIPT_DIR ExecStart=$(which bun) run start --web Restart=always RestartSec=10 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable qwenclaw.service echo -e "${GREEN}[OK]${NC} Systemd service created and enabled" else echo -e "${YELLOW}[INFO]${NC} Cannot create systemd service (need sudo)" fi fi # Desktop autostart (for GUI sessions) AUTOSTART_DIR="$HOME/.config/autostart" mkdir -p "$AUTOSTART_DIR" cat > "$AUTOSTART_DIR/qwenclaw.desktop" << EOF [Desktop Entry] Type=Application Name=QwenClaw Daemon Exec=bash -c "cd $SCRIPT_DIR && bun run start --web" Hidden=false NoDisplay=false X-GNOME-Autostart-enabled=true EOF echo -e "${GREEN}[OK]${NC} Desktop auto-start configured" elif [ "$OS_NAME" = "macOS" ]; then # macOS: Create LaunchAgent LAUNCHAGENT_DIR="$HOME/Library/LaunchAgents" mkdir -p "$LAUNCHAGENT_DIR" cat > "$LAUNCHAGENT_DIR/com.qwenclaw.daemon.plist" << EOF Label com.qwenclaw.daemon ProgramArguments $(which bun) run start --web WorkingDirectory $SCRIPT_DIR RunAtLoad KeepAlive StandardOutPath $QWENCLAW_DATA_DIR/qwenclaw.log StandardErrorPath $QWENCLAW_DATA_DIR/qwenclaw.err EOF launchctl load "$LAUNCHAGENT_DIR/com.qwenclaw.daemon.plist" 2>/dev/null || true echo -e "${GREEN}[OK]${NC} macOS LaunchAgent configured" fi # Step 6: Initialize git (optional, for repo management) echo "" echo -e "${YELLOW}[6/6] Finalizing installation...${NC}" if [ ! -d ".git" ]; then git init git checkout -b main 2>/dev/null || true echo -e "${GREEN}[OK]${NC} Git repository initialized" else echo -e "${YELLOW}[INFO]${NC} Git repository already exists" fi # Create example job EXAMPLE_JOB="$QWENCLAW_DATA_DIR/jobs/example-daily-check.md" if [ ! -f "$EXAMPLE_JOB" ]; then cat > "$EXAMPLE_JOB" << 'EOF' --- schedule: 0 9 * * * recurring: true notify: true --- Good morning! Here's your daily check-in: 1. What are today's priorities? 2. Any pending tasks from yesterday? 3. Weather and calendar summary. EOF echo -e "${GREEN}[OK]${NC} Example job created" fi # Summary echo "" echo "========================================" echo -e "${GREEN} Installation Complete!${NC}" echo "========================================" echo "" echo -e "${CYAN}What's configured:${NC}" echo -e " ${GREEN}[OK]${NC} Dependencies installed" echo -e " ${GREEN}[OK]${NC} Directories created" echo -e " ${GREEN}[OK]${NC} Default settings created" echo -e " ${GREEN}[OK]${NC} Auto-start configured" echo -e " ${GREEN}[OK]${NC} Example job created" echo "" echo -e "${CYAN}Quick Start:${NC}" echo -e " ${YELLOW}bun run start --web${NC} - Start daemon" echo -e " ${YELLOW}bun run status${NC} - Check status" echo -e " ${YELLOW}bun run stop${NC} - Stop daemon" echo -e " ${YELLOW}bun run send \"hello\"${NC} - Send prompt" echo "" echo -e "${CYAN}Web Dashboard:${NC}" echo -e " ${YELLOW}http://127.0.0.1:4632${NC}" echo "" echo -e "${CYAN}Configuration:${NC}" echo -e " Edit: ${YELLOW}$SETTINGS_FILE${NC}" echo -e " Jobs: ${YELLOW}$QWENCLAW_DATA_DIR/jobs/${NC}" echo -e " Logs: ${YELLOW}$QWENCLAW_DATA_DIR/logs/${NC}" echo "" echo -e "${CYAN}Documentation:${NC}" echo -e " ${YELLOW}README.md${NC} - Full documentation" echo -e " ${YELLOW}QUICKSTART.md${NC} - Quick reference" echo "" echo -e "The daemon will ${YELLOW}start automatically${NC} when you log in." echo ""