Initial commit: QwenClaw persistent daemon for Qwen Code
This commit is contained in:
312
install.sh
Normal file
312
install.sh
Normal file
@@ -0,0 +1,312 @@
|
||||
#!/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
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.qwenclaw.daemon</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>$(which bun)</string>
|
||||
<string>run</string>
|
||||
<string>start</string>
|
||||
<string>--web</string>
|
||||
</array>
|
||||
<key>WorkingDirectory</key>
|
||||
<string>$SCRIPT_DIR</string>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
<key>StandardOutPath</key>
|
||||
<string>$QWENCLAW_DATA_DIR/qwenclaw.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>$QWENCLAW_DATA_DIR/qwenclaw.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
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 ""
|
||||
Reference in New Issue
Block a user