#!/usr/bin/env bash # claudemax-watchdog.sh — keep local Claude/Gemini loops alive without stale tmux assumptions set -uo pipefail export PATH="/opt/homebrew/bin:$HOME/.local/bin:$HOME/.hermes/bin:/usr/local/bin:$PATH" LOG="$HOME/.hermes/logs/claudemax-watchdog.log" GITEA_URL="http://143.198.27.163:3000" GITEA_TOKEN=$(tr -d '[:space:]' < "$HOME/.hermes/gitea_token_vps" 2>/dev/null || true) REPO_API="$GITEA_URL/api/v1/repos/Timmy_Foundation/the-nexus" MIN_OPEN_ISSUES=10 CLAUDE_WORKERS=2 GEMINI_WORKERS=1 log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] CLAUDEMAX: $*" >> "$LOG" } start_loop() { local name="$1" local pattern="$2" local cmd="$3" local pid pid=$(pgrep -f "$pattern" 2>/dev/null | head -1 || true) if [ -n "$pid" ]; then log "$name alive (PID $pid)" return 0 fi log "$name not running. Restarting..." nohup bash -lc "$cmd" >/dev/null 2>&1 & sleep 2 pid=$(pgrep -f "$pattern" 2>/dev/null | head -1 || true) if [ -n "$pid" ]; then log "Restarted $name (PID $pid)" else log "ERROR: failed to start $name" fi } run_optional_script() { local label="$1" local script_path="$2" if [ -x "$script_path" ]; then bash "$script_path" 2>&1 | while read -r line; do log "$line" done else log "$label skipped — missing $script_path" fi } claude_quota_blocked() { local cutoff now mtime f now=$(date +%s) cutoff=$((now - 43200)) for f in "$HOME"/.hermes/logs/claude-*.log; do [ -f "$f" ] || continue mtime=$(stat -f %m "$f" 2>/dev/null || echo 0) if [ "$mtime" -ge "$cutoff" ] && grep -q "You've hit your limit" "$f" 2>/dev/null; then return 0 fi done return 1 } if [ -z "$GITEA_TOKEN" ]; then log "ERROR: missing Gitea token at ~/.hermes/gitea_token_vps" exit 1 fi if claude_quota_blocked; then log "Claude quota exhausted recently — not starting claude-loop until quota resets or logs age out" else start_loop "claude-loop" "bash .*claude-loop.sh" "bash ~/.hermes/bin/claude-loop.sh $CLAUDE_WORKERS >> ~/.hermes/logs/claude-loop.log 2>&1" fi start_loop "gemini-loop" "bash .*gemini-loop.sh" "bash ~/.hermes/bin/gemini-loop.sh $GEMINI_WORKERS >> ~/.hermes/logs/gemini-loop.log 2>&1" OPEN_COUNT=$(curl -s --max-time 10 -H "Authorization: token $GITEA_TOKEN" \ "$REPO_API/issues?state=open&type=issues&limit=100" 2>/dev/null \ | python3 -c "import sys, json; print(len(json.loads(sys.stdin.read() or '[]')))" 2>/dev/null || echo 0) log "Open issues: $OPEN_COUNT (minimum: $MIN_OPEN_ISSUES)" if [ "$OPEN_COUNT" -lt "$MIN_OPEN_ISSUES" ]; then log "Backlog running low. Checking replenishment helper..." run_optional_script "claudemax-replenish" "$HOME/.hermes/bin/claudemax-replenish.sh" fi run_optional_script "autodeploy-matrix" "$HOME/.hermes/bin/autodeploy-matrix.sh" log "Watchdog complete."