Initial commit: QwenClaw persistent daemon for Qwen Code

This commit is contained in:
admin
2026-02-26 02:16:18 +04:00
Unverified
commit 80cdad994c
53 changed files with 7285 additions and 0 deletions

58
scripts/autostart.ps1 Normal file
View File

@@ -0,0 +1,58 @@
# QwenClaw Auto-Start Script
# This script ensures QwenClaw daemon is always running
# Run at Windows startup via Task Scheduler
$ErrorActionPreference = "SilentlyContinue"
$QWENCLAW_DIR = Join-Path $env:USERPROFILE "qwenclaw"
$QWEN_DIR = Join-Path $env:USERPROFILE ".qwen"
$DAEMON_PID_FILE = Join-Path $QWEN_DIR "qwenclaw\daemon.pid"
$LOG_FILE = Join-Path $QWEN_DIR "qwenclaw\autostart.log"
function Write-Log {
param([string]$Message)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
"[$timestamp] $Message" | Out-File -FilePath $LOG_FILE -Append
}
Write-Log "QwenClaw auto-start initiated"
# Check if daemon is already running
if (Test-Path $DAEMON_PID_FILE) {
$pidContent = Get-Content $DAEMON_PID_FILE -ErrorAction SilentlyContinue
if ($pidContent) {
try {
$process = Get-Process -Id ([int]$pidContent) -ErrorAction SilentlyContinue
if ($process) {
Write-Log "QwenClaw daemon already running (PID: $pidContent)"
exit 0
}
} catch {
Write-Log "Stale PID file found, cleaning up..."
Remove-Item $DAEMON_PID_FILE -Force -ErrorAction SilentlyContinue
}
}
}
# Wait for Qwen Code to be available (in case of system startup)
Start-Sleep -Seconds 5
# Start daemon in background
Write-Log "Starting QwenClaw daemon from: $QWENCLAW_DIR"
try {
$startInfo = New-Object System.Diagnostics.ProcessStartInfo
$startInfo.FileName = "bun"
$startInfo.Arguments = "run start --web"
$startInfo.WorkingDirectory = $QWENCLAW_DIR
$startInfo.UseShellExecute = $true
$startInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
$startInfo.CreateNoWindow = $true
$process = [System.Diagnostics.Process]::Start($startInfo)
Write-Log "QwenClaw daemon started (PID: $($process.Id))"
} catch {
Write-Log "Failed to start daemon: $($_.Exception.Message)"
}
Write-Log "QwenClaw auto-start completed"

View File

@@ -0,0 +1,7 @@
@echo off
REM QwenClaw Daemon Runner
REM Use this with NSSM or Windows Task Scheduler to run as a service
cd /d "%~dp0.."
bun run start --web
pause

View File

@@ -0,0 +1,46 @@
# QwenClaw Windows Startup Installer (Startup Folder Method)
# This method does NOT require admin privileges
# Run this ONCE to register QwenClaw to start automatically with Windows
$ErrorActionPreference = "Stop"
$SCRIPT_NAME = "QwenClaw Daemon"
$SCRIPT_PATH = Join-Path $PSScriptRoot "autostart.ps1"
$LOG_DIR = Join-Path $env:USERPROFILE ".qwen\qwenclaw"
$STARTUP_FOLDER = [Environment]::GetFolderPath("Startup")
Write-Host "QwenClaw Windows Startup Installer" -ForegroundColor Cyan
Write-Host "===================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Using Windows Startup Folder method (no admin required)" -ForegroundColor Yellow
Write-Host ""
# Ensure log directory exists
if (-not (Test-Path $LOG_DIR)) {
New-Item -ItemType Directory -Path $LOG_DIR -Force | Out-Null
Write-Host "[OK] Created log directory: $LOG_DIR" -ForegroundColor Green
}
# Create a shortcut in the Startup folder
$shortcutPath = Join-Path $STARTUP_FOLDER "$SCRIPT_NAME.lnk"
try {
$WScript = New-Object -ComObject WScript.Shell
$shortcut = $WScript.CreateShortcut($shortcutPath)
$shortcut.TargetPath = "PowerShell.exe"
$shortcut.Arguments = "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$SCRIPT_PATH`""
$shortcut.WorkingDirectory = Split-Path $SCRIPT_PATH -Parent
$shortcut.Description = "Automatically starts QwenClaw daemon when user logs on"
$shortcut.IconLocation = "powershell.exe,0"
$shortcut.Save()
Write-Host "[OK] Startup shortcut created: $shortcutPath" -ForegroundColor Green
Write-Host ""
Write-Host "QwenClaw will now start automatically when you log in to Windows." -ForegroundColor Green
Write-Host ""
Write-Host "To verify: Open Shell:Startup folder and look for '$SCRIPT_NAME'" -ForegroundColor Cyan
Write-Host "To disable: Delete the shortcut from the Startup folder" -ForegroundColor Cyan
} catch {
Write-Host "[ERROR] Failed to create startup shortcut: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}

View File

@@ -0,0 +1,75 @@
#!/usr/bin/env node
/**
* QwenClaw Startup Hook for Qwen Code
* This script is called when Qwen Code starts
* It ensures the QwenClaw daemon is running
*/
import { spawn } from "child_process";
import { existsSync, readFileSync } from "fs";
import { join } from "path";
const QWENCLAW_DIR = join(process.env.USERPROFILE || process.env.HOME || "", "qwenclaw");
const QWEN_DIR = join(process.env.USERPROFILE || process.env.HOME || "", ".qwen");
const PID_FILE = join(QWEN_DIR, "qwenclaw", "daemon.pid");
const SETTINGS_FILE = join(QWEN_DIR, "qwenclaw", "settings.json");
function log(message) {
console.log(`[QwenClaw] ${message}`);
}
function isDaemonRunning() {
if (!existsSync(PID_FILE)) return false;
try {
const pid = parseInt(readFileSync(PID_FILE, "utf-8").trim(), 10);
if (isNaN(pid)) return false;
// Check if process exists
process.kill(pid, 0);
return true;
} catch {
return false;
}
}
function startDaemon() {
if (isDaemonRunning()) {
log("Daemon already running, skipping auto-start");
return;
}
log("Auto-starting QwenClaw daemon...");
try {
const child = spawn("bun", ["run", "start", "--web"], {
cwd: QWENCLAW_DIR,
detached: true,
stdio: "ignore",
windowsHide: true,
});
child.unref();
log(`Daemon started (PID: ${child.pid})`);
} catch (err) {
log(`Failed to start daemon: ${err.message}`);
}
}
// Check if auto-start is enabled in settings
function isAutoStartEnabled() {
if (!existsSync(SETTINGS_FILE)) return true; // Default to enabled
try {
const settings = JSON.parse(readFileSync(SETTINGS_FILE, "utf-8"));
return settings.autoStart !== false; // Default to true
} catch {
return true;
}
}
// Main
if (isAutoStartEnabled()) {
// Delay slightly to not block Qwen Code startup
setTimeout(startDaemon, 2000);
}

124
scripts/setup.ps1 Normal file
View File

@@ -0,0 +1,124 @@
# QwenClaw Setup Script
# Run this ONCE to set up QwenClaw with persistent auto-start
$ErrorActionPreference = "Stop"
Write-Host ""
Write-Host " ____ _ __ _ _ " -ForegroundColor Cyan
Write-Host " / ___|_ __ __ _ ___| | __ / _(_) | ___ " -ForegroundColor Cyan
Write-Host "| | | '__/ _` |/ __| |/ /| |_| | |/ _ \ " -ForegroundColor Cyan
Write-Host "| |___| | | (_| | (__| < | _| | | __/ " -ForegroundColor Cyan
Write-Host " \____|_| \__,_|\___|_|\_\|_| |_|_|\___| " -ForegroundColor Cyan
Write-Host ""
Write-Host "Persistent Daemon Setup" -ForegroundColor Cyan
Write-Host "=======================" -ForegroundColor Cyan
Write-Host ""
$QWENCLAW_DIR = Join-Path $env:USERPROFILE "qwenclaw"
$QWEN_DIR = Join-Path $env:USERPROFILE ".qwen"
# Step 1: Check prerequisites
Write-Host "[1/4] Checking prerequisites..." -ForegroundColor Yellow
try {
$bunVersion = bun --version 2>&1
Write-Host " Bun detected: v$bunVersion" -ForegroundColor Green
} catch {
Write-Host " [ERROR] Bun is not installed. Install from https://bun.sh" -ForegroundColor Red
exit 1
}
# Step 2: Install dependencies
Write-Host ""
Write-Host "[2/4] Installing dependencies..." -ForegroundColor Yellow
Set-Location $QWENCLAW_DIR
bun install
# Step 3: Create directories
Write-Host ""
Write-Host "[3/4] Creating directories..." -ForegroundColor Yellow
$dirs = @(
(Join-Path $QWEN_DIR "qwenclaw"),
(Join-Path $QWEN_DIR "qwenclaw\jobs"),
(Join-Path $QWEN_DIR "qwenclaw\logs"),
(Join-Path $QWEN_DIR "qwenclaw\inbox")
)
foreach ($dir in $dirs) {
if (-not (Test-Path $dir)) {
New-Item -ItemType Directory -Path $dir -Force | Out-Null
Write-Host " Created: $dir" -ForegroundColor Green
}
}
# Step 4: Set up Windows startup
Write-Host ""
Write-Host "[4/4] Setting up Windows auto-start..." -ForegroundColor Yellow
$installScript = Join-Path $QWENCLAW_DIR "scripts\install-startup.ps1"
& $installScript
# Create initial settings
Write-Host ""
Write-Host "Creating default settings..." -ForegroundColor Yellow
$settingsPath = Join-Path $QWEN_DIR "qwenclaw\settings.json"
if (-not (Test-Path $settingsPath)) {
$settings = @{
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
}
}
$settings | ConvertTo-Json -Depth 10 | Out-File -FilePath $settingsPath -Encoding utf8
Write-Host " Created: $settingsPath" -ForegroundColor Green
}
# Summary
Write-Host ""
Write-Host "========================================" -ForegroundColor Green
Write-Host " QwenClaw Setup Complete!" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
Write-Host ""
Write-Host "What's configured:" -ForegroundColor Cyan
Write-Host " [OK] Dependencies installed" -ForegroundColor Green
Write-Host " [OK] Directories created" -ForegroundColor Green
Write-Host " [OK] Windows auto-start enabled" -ForegroundColor Green
Write-Host " [OK] Default settings created" -ForegroundColor Green
Write-Host ""
Write-Host "Quick Commands:" -ForegroundColor Cyan
Write-Host " bun run start - Start daemon manually" -ForegroundColor White
Write-Host " bun run status - Check daemon status" -ForegroundColor White
Write-Host " bun run stop - Stop daemon" -ForegroundColor White
Write-Host ""
Write-Host "Web Dashboard:" -ForegroundColor Cyan
Write-Host " http://127.0.0.1:4632" -ForegroundColor White
Write-Host ""
Write-Host "The daemon will start automatically when you log in to Windows." -ForegroundColor Green
Write-Host ""

View File

@@ -0,0 +1,37 @@
# QwenClaw Windows Startup Uninstaller
# Run this to remove QwenClaw from Windows startup
$ErrorActionPreference = "Stop"
$TASK_NAME = "QwenClaw Daemon"
$STARTUP_FOLDER = [Environment]::GetFolderPath("Startup")
Write-Host "QwenClaw Windows Startup Uninstaller" -ForegroundColor Cyan
Write-Host "====================================" -ForegroundColor Cyan
Write-Host ""
# Remove shortcut from Startup folder
$shortcutPath = Join-Path $STARTUP_FOLDER "$TASK_NAME.lnk"
if (Test-Path $shortcutPath) {
Remove-Item $shortcutPath -Force
Write-Host "[OK] Startup shortcut removed: $shortcutPath" -ForegroundColor Green
} else {
Write-Host "[INFO] No startup shortcut found." -ForegroundColor Yellow
}
# Also try to remove Task Scheduler task (if it exists from previous install)
$existingTask = Get-ScheduledTask -TaskName $TASK_NAME -ErrorAction SilentlyContinue
if ($existingTask) {
try {
Unregister-ScheduledTask -TaskName $TASK_NAME -Confirm:$false
Write-Host "[OK] Scheduled task '$TASK_NAME' removed successfully!" -ForegroundColor Green
} catch {
Write-Host "[INFO] Could not remove scheduled task (may require admin)" -ForegroundColor Yellow
}
}
Write-Host ""
Write-Host "QwenClaw will no longer start automatically with Windows." -ForegroundColor Yellow
Write-Host "You can still start it manually with: bun run start" -ForegroundColor Cyan