openclaw-watchdog Description: Self-healing monitoring system for OpenClaw gateway. Monitors health, auto-restarts on failure, and sends Telegram alerts. Diagnostics and log analysis run locally on-device. Alert notifications are sent to the user's Telegram bot. Use when user wants to set up gateway monitoring, watchdog, or auto-recovery. Prerequisites - Telegram Bot Token — Create via @BotFather - Telegram Chat ID — Your personal chat ID for receiving alerts - Python 3 — Required for the watchdog service - OpenClaw — Installed and running Trigger Keywords - watchdog, monitoring, auto-fix, ga…

, token):\n print(\"Error: Token format invalid.\", file=sys.stderr)\n sys.exit(1)\n\n# Validate chat_id is numeric (positive or negative)\nif not re.match(r'^-?\\d+

openclaw-watchdog Description: Self-healing monitoring system for OpenClaw gateway. Monitors health, auto-restarts on failure, and sends Telegram alerts. Diagnostics and log analysis run locally on-device. Alert notifications are sent to the user's Telegram bot. Use when user wants to set up gateway monitoring, watchdog, or auto-recovery. Prerequisites - Telegram Bot Token — Create via @BotFather - Telegram Chat ID — Your personal chat ID for receiving alerts - Python 3 — Required for the watchdog service - OpenClaw — Installed and running Trigger Keywords - watchdog, monitoring, auto-fix, ga…

, chat_id):\n print(\"Error: Chat ID must be numeric.\", file=sys.stderr)\n sys.exit(1)\n\ntry:\n data = json.dumps({\n 'chat_id': chat_id,\n 'text': '\\U0001f415 Watch Dog connected successfully! Monitoring your gateway 24/7.'\n }).encode()\n req = urllib.request.Request(\n f'https://api.telegram.org/bot{token}/sendMessage',\n data=data,\n headers={'Content-Type': 'application/json'}\n )\n resp = json.loads(urllib.request.urlopen(req).read())\n if resp.get('ok'):\n print('Test message sent!')\n else:\n print(f\"Error: {resp}\", file=sys.stderr)\n sys.exit(1)\nexcept Exception as e:\n print(f\"Error: {e}\", file=sys.stderr)\n sys.exit(1)\n","content_type":"text/x-python; charset=utf-8","language":"python","size":1226,"content_sha256":"ae363825db08f46f13835c983a49f8dd92d4ffc171e793270b04be00762686e3"},{"filename":"scripts/validate.py","content":"#!/usr/bin/env python3\n\"\"\"Validate a Telegram bot token by calling getMe.\"\"\"\nimport urllib.request, json, sys\n\nif len(sys.argv) \u003c 2:\n print(\"Usage: validate.py \u003ctelegram_token>\", file=sys.stderr)\n sys.exit(1)\n\ntoken = sys.argv[1]\n\n# Validate token format (digits:alphanumeric)\nimport re\nif not re.match(r'^\\d+:[A-Za-z0-9_-]+

openclaw-watchdog Description: Self-healing monitoring system for OpenClaw gateway. Monitors health, auto-restarts on failure, and sends Telegram alerts. Diagnostics and log analysis run locally on-device. Alert notifications are sent to the user's Telegram bot. Use when user wants to set up gateway monitoring, watchdog, or auto-recovery. Prerequisites - Telegram Bot Token — Create via @BotFather - Telegram Chat ID — Your personal chat ID for receiving alerts - Python 3 — Required for the watchdog service - OpenClaw — Installed and running Trigger Keywords - watchdog, monitoring, auto-fix, ga…

, token):\n print(\"Error: Token format invalid. Expected format: 123456:ABC-DEF...\", file=sys.stderr)\n sys.exit(1)\n\ntry:\n resp = json.loads(urllib.request.urlopen(f'https://api.telegram.org/bot{token}/getMe').read())\n if resp.get('ok'):\n print(f\"Token valid: @{resp['result']['username']}\")\n else:\n print(\"Error: Token rejected by Telegram API\", file=sys.stderr)\n sys.exit(1)\nexcept Exception as e:\n print(f\"Error: {e}\", file=sys.stderr)\n sys.exit(1)\n","content_type":"text/x-python; charset=utf-8","language":"python","size":824,"content_sha256":"fd139e12c424f8c60fd1df4b2bea9c983178f8a1af3357e27a5a5afd06d92505"},{"filename":"scripts/watchdog.py","content":"#!/usr/bin/env python3\n\"\"\"\nOpenClaw Watch Dog — Self-healing gateway monitor.\nPings the gateway every 15 seconds, auto-fixes crashes, sends Telegram alerts.\n\"\"\"\n\nimport asyncio\nimport json\nimport logging\nimport os\nimport platform\nimport subprocess\nimport sys\nimport time\nimport hashlib\nimport base64\nfrom pathlib import Path\nfrom datetime import datetime\n\nimport aiohttp\n\n# ---------------------------------------------------------------------------\n# Paths\n# ---------------------------------------------------------------------------\nWATCHDOG_DIR = Path.home() / \".openclaw\" / \"watchdog\"\nCONFIG_FILE = WATCHDOG_DIR / \"config.enc\"\nLOG_FILE = WATCHDOG_DIR / \"watchdog.log\"\nSTATE_FILE = WATCHDOG_DIR / \"state.json\"\nGATEWAY_HEALTH = \"http://127.0.0.1:3117/health\"\nAPPROVE_REINSTALL = WATCHDOG_DIR / \"approve-reinstall\"\n\n# ---------------------------------------------------------------------------\n# Logging\n# ---------------------------------------------------------------------------\nlogging.basicConfig(\n level=logging.INFO,\n format=\"%(asctime)s [%(levelname)s] %(message)s\",\n handlers=[\n logging.FileHandler(LOG_FILE, encoding=\"utf-8\"),\n logging.StreamHandler(),\n ],\n)\nlog = logging.getLogger(\"watchdog\")\n\n# ---------------------------------------------------------------------------\n# Encryption helpers (AES-256-CBC via openssl CLI — no extra deps)\n# ---------------------------------------------------------------------------\n\ndef _machine_password() -> str:\n \"\"\"Derive a machine-specific password from hardware identifiers.\"\"\"\n parts = []\n if platform.system() == \"Darwin\":\n try:\n out = subprocess.check_output(\n [\"ioreg\", \"-rd1\", \"-c\", \"IOPlatformExpertDevice\"], text=True\n )\n for line in out.splitlines():\n if \"IOPlatformUUID\" in line:\n parts.append(line.split('\"')[-2])\n break\n except Exception:\n pass\n # Fallback: hostname + username\n parts.extend([platform.node(), os.getenv(\"USER\", \"openclaw\")])\n return hashlib.sha256(\":\".join(parts).encode()).hexdigest()\n\n\ndef decrypt_config() -> dict:\n \"\"\"Decrypt config.enc → dict.\"\"\"\n if not CONFIG_FILE.exists():\n log.error(\"Config file not found: %s\", CONFIG_FILE)\n sys.exit(1)\n pw = _machine_password()\n try:\n result = subprocess.run(\n [\"openssl\", \"enc\", \"-aes-256-cbc\", \"-d\", \"-pbkdf2\",\n \"-in\", str(CONFIG_FILE), \"-pass\", f\"pass:{pw}\"],\n capture_output=True,\n )\n if result.returncode != 0:\n log.error(\"Decryption failed: %s\", result.stderr.decode())\n sys.exit(1)\n return json.loads(result.stdout.decode())\n except Exception as e:\n log.error(\"Failed to decrypt config: %s\", e)\n sys.exit(1)\n\n\n# ---------------------------------------------------------------------------\n# Telegram\n# ---------------------------------------------------------------------------\n\nasync def send_telegram(session: aiohttp.ClientSession, cfg: dict, text: str):\n \"\"\"Send a Telegram message.\"\"\"\n token = cfg.get(\"telegram_token\", \"\")\n chat_id = cfg.get(\"telegram_chat_id\", \"\")\n if not token or not chat_id:\n log.warning(\"Telegram not configured, skipping alert\")\n return\n url = f\"https://api.telegram.org/bot{token}/sendMessage\"\n try:\n async with session.post(url, json={\n \"chat_id\": chat_id,\n \"text\": text,\n \"parse_mode\": \"HTML\",\n }) as resp:\n if resp.status != 200:\n log.warning(\"Telegram send failed: %s\", await resp.text())\n except Exception as e:\n log.warning(\"Telegram error: %s\", e)\n\n\n# ---------------------------------------------------------------------------\n# Local Diagnostics (no external API calls — logs stay on device)\n# ---------------------------------------------------------------------------\n\ndef diagnose_locally(logs: str) -> str:\n \"\"\"Analyze logs locally using pattern matching. No data leaves the device.\"\"\"\n lines = logs.lower()\n issues = []\n if \"eaddrinuse\" in lines:\n issues.append(\"Port already in use — another process may be bound to the gateway port\")\n if \"enomem\" in lines or \"out of memory\" in lines:\n issues.append(\"Out of memory — consider freeing resources or restarting the machine\")\n if \"enoent\" in lines or \"not found\" in lines:\n issues.append(\"Missing file or binary — OpenClaw may need reinstallation\")\n if \"permission denied\" in lines or \"eacces\" in lines:\n issues.append(\"Permission denied — check file/directory permissions\")\n if \"segfault\" in lines or \"segmentation fault\" in lines:\n issues.append(\"Segmentation fault — possible corrupted installation\")\n if \"module not found\" in lines or \"cannot find module\" in lines:\n issues.append(\"Missing Node.js module — may need manual reinstallation\")\n if not issues:\n issues.append(\"No obvious pattern detected — check logs manually\")\n return \"; \".join(issues)\n\n\n# ---------------------------------------------------------------------------\n# Log collection\n# ---------------------------------------------------------------------------\n\ndef collect_logs(lines: int = 200) -> str:\n \"\"\"Collect last N lines from OpenClaw gateway logs.\"\"\"\n log_paths = [\n Path.home() / \".openclaw\" / \"gateway.log\",\n Path.home() / \".openclaw\" / \"logs\" / \"gateway.log\",\n Path(\"/tmp\") / \"openclaw-gateway.log\",\n ]\n for p in log_paths:\n if p.exists():\n try:\n result = subprocess.run(\n [\"tail\", f\"-{lines}\", str(p)], capture_output=True, text=True\n )\n if result.stdout.strip():\n return result.stdout\n except Exception:\n continue\n\n # Try journalctl on Linux\n if platform.system() == \"Linux\":\n try:\n result = subprocess.run(\n [\"journalctl\", \"--user\", \"-u\", \"openclaw-gateway\", f\"-n{lines}\", \"--no-pager\"],\n capture_output=True, text=True,\n )\n if result.stdout.strip():\n return result.stdout\n except Exception:\n pass\n\n return \"(no logs found)\"\n\n\n# ---------------------------------------------------------------------------\n# Auto-fix\n# ---------------------------------------------------------------------------\n\nasync def attempt_fix(session: aiohttp.ClientSession, cfg: dict, attempt: int) -> bool:\n \"\"\"Try to fix the gateway. Returns True if health check passes after fix.\"\"\"\n log.info(\"Auto-fix attempt #%d\", attempt)\n\n if attempt \u003c= 2:\n # Step 1-2: Simple restart\n log.info(\"Restarting gateway...\")\n await send_telegram(session, cfg, \"🔧 \u003cb>Watch Dog:\u003c/b> Restarting gateway...\")\n try:\n subprocess.run([\"openclaw\", \"gateway\", \"restart\"], timeout=30,\n capture_output=True, text=True)\n except Exception as e:\n log.error(\"Restart command failed: %s\", e)\n return False\n\n await asyncio.sleep(10)\n return await check_health(session)\n\n elif attempt == 3:\n # Step 3: Ask user for permission to reinstall\n log.info(\"Restart attempts exhausted, asking user for reinstall permission...\")\n await send_telegram(session, cfg,\n \"⚠️ \u003cb>Watch Dog:\u003c/b> Gateway restart failed after 2 attempts.\\n\\n\"\n \"Reinstalling OpenClaw might fix the issue.\\n\"\n \"To approve reinstall, run:\\n\"\n \"\u003ccode>touch ~/.openclaw/watchdog/approve-reinstall\u003c/code>\\n\\n\"\n \"I'll check for your approval and proceed if given.\"\n )\n return False\n\n elif attempt \u003c= 5 and APPROVE_REINSTALL.exists():\n # Step 4-5: User approved reinstall\n log.info(\"User approved reinstall, running npm install -g openclaw...\")\n APPROVE_REINSTALL.unlink(missing_ok=True)\n await send_telegram(session, cfg, \"🔧 \u003cb>Watch Dog:\u003c/b> Reinstalling OpenClaw (approved by user)...\")\n try:\n subprocess.run([\"npm\", \"install\", \"-g\", \"openclaw\"], timeout=120,\n capture_output=True, text=True)\n await asyncio.sleep(5)\n subprocess.run([\"openclaw\", \"gateway\", \"start\"], timeout=30,\n capture_output=True, text=True)\n except Exception as e:\n log.error(\"Reinstall failed: %s\", e)\n return False\n\n await asyncio.sleep(10)\n return await check_health(session)\n\n else:\n # No approval or attempts exhausted — notify user\n log.info(\"Waiting for user action...\")\n if attempt == 5:\n await send_telegram(session, cfg,\n \"❌ \u003cb>Watch Dog:\u003c/b> All auto-fix attempts exhausted.\\n\"\n \"Manual intervention required:\\n\"\n \"\u003ccode>openclaw gateway restart\u003c/code>\"\n )\n return False\n\n\n# ---------------------------------------------------------------------------\n# Health check\n# ---------------------------------------------------------------------------\n\nasync def check_health(session: aiohttp.ClientSession) -> bool:\n \"\"\"Ping the gateway health endpoint.\"\"\"\n try:\n async with session.get(GATEWAY_HEALTH, timeout=aiohttp.ClientTimeout(total=10)) as resp:\n return resp.status == 200\n except Exception:\n return False\n\n\n# ---------------------------------------------------------------------------\n# State management\n# ---------------------------------------------------------------------------\n\ndef load_state() -> dict:\n if STATE_FILE.exists():\n try:\n return json.loads(STATE_FILE.read_text())\n except Exception:\n pass\n return {\"consecutive_failures\": 0, \"fix_attempts\": 0, \"last_status\": \"unknown\", \"started_at\": time.time()}\n\n\ndef save_state(state: dict):\n STATE_FILE.write_text(json.dumps(state, indent=2))\n\n\n# ---------------------------------------------------------------------------\n# Main loop\n# ---------------------------------------------------------------------------\n\nasync def main():\n WATCHDOG_DIR.mkdir(parents=True, exist_ok=True)\n\n cfg = decrypt_config()\n state = load_state()\n state[\"started_at\"] = time.time()\n save_state(state)\n\n log.info(\"Watch Dog started — monitoring %s\", GATEWAY_HEALTH)\n\n async with aiohttp.ClientSession() as session:\n await send_telegram(session, cfg, \"🐕 \u003cb>Watch Dog started\u003c/b>\\nMonitoring gateway health every 15s.\")\n\n while True:\n healthy = await check_health(session)\n\n if healthy:\n if state[\"last_status\"] != \"healthy\":\n log.info(\"Gateway is healthy ✓\")\n if state[\"consecutive_failures\"] > 0 or state[\"fix_attempts\"] > 0:\n await send_telegram(session, cfg,\n \"✅ \u003cb>Gateway recovered!\u003c/b>\\n\"\n f\"After {state['fix_attempts']} fix attempt(s).\"\n )\n state[\"consecutive_failures\"] = 0\n state[\"fix_attempts\"] = 0\n state[\"last_status\"] = \"healthy\"\n save_state(state)\n else:\n state[\"consecutive_failures\"] += 1\n state[\"last_status\"] = \"unhealthy\"\n log.warning(\"Health check failed (%d consecutive)\", state[\"consecutive_failures\"])\n\n if state[\"consecutive_failures\"] == 3:\n # First failure notification with diagnostics\n logs = collect_logs()\n diagnosis = diagnose_locally(logs)\n await send_telegram(session, cfg,\n \"🚨 \u003cb>Gateway DOWN!\u003c/b>\\n\"\n f\"3 consecutive failures detected.\\n\\n\"\n f\"\u003cb>AI Diagnosis:\u003c/b>\\n\u003ccode>{diagnosis[:500]}\u003c/code>\\n\\n\"\n \"Attempting auto-fix...\"\n )\n\n if state[\"consecutive_failures\"] >= 3:\n state[\"fix_attempts\"] += 1\n fixed = await attempt_fix(session, cfg, state[\"fix_attempts\"])\n if fixed:\n state[\"consecutive_failures\"] = 0\n state[\"fix_attempts\"] = 0\n state[\"last_status\"] = \"healthy\"\n log.info(\"Auto-fix succeeded!\")\n await send_telegram(session, cfg, \"✅ \u003cb>Auto-fix succeeded!\u003c/b> Gateway is back online.\")\n elif state[\"fix_attempts\"] >= 5:\n await send_telegram(session, cfg,\n \"❌ \u003cb>Auto-fix exhausted\u003c/b> (5 attempts).\\n\"\n \"Manual intervention required!\"\n )\n state[\"fix_attempts\"] = 0\n state[\"consecutive_failures\"] = 0 # Reset to avoid spam\n\n save_state(state)\n\n await asyncio.sleep(15)\n\n\nif __name__ == \"__main__\":\n try:\n asyncio.run(main())\n except KeyboardInterrupt:\n log.info(\"Watch Dog stopped by user\")\n except Exception as e:\n log.exception(\"Watch Dog crashed: %s\", e)\n sys.exit(1)\n","content_type":"text/x-python; charset=utf-8","language":"python","size":13378,"content_sha256":"1da91de857ca4509e42ee93b8b516c4f25a580ab55ae1feac370d3a61959bc56"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"openclaw-watchdog","type":"text"}]},{"type":"paragraph","content":[{"text":"Description:","type":"text","marks":[{"type":"strong"}]},{"text":" Self-healing monitoring system for OpenClaw gateway. Monitors health, auto-restarts on failure, and sends Telegram alerts. Diagnostics and log analysis run locally on-device. Alert notifications are sent to the user's Telegram bot. Use when user wants to set up gateway monitoring, watchdog, or auto-recovery.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Prerequisites","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Telegram Bot Token","type":"text","marks":[{"type":"strong"}]},{"text":" — Create via ","type":"text"},{"text":"@BotFather","type":"text","marks":[{"type":"link","attrs":{"href":"https://t.me/BotFather","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Telegram Chat ID","type":"text","marks":[{"type":"strong"}]},{"text":" — Your personal chat ID for receiving alerts","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Python 3","type":"text","marks":[{"type":"strong"}]},{"text":" — Required for the watchdog service","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"OpenClaw","type":"text","marks":[{"type":"strong"}]},{"text":" — Installed and running","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Trigger Keywords","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"watchdog, monitoring, auto-fix, gateway health, self-healing, auto-recovery, watch dog","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Setup","type":"text"}]},{"type":"paragraph","content":[{"text":"Send the user ONE message with everything they need:","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"paragraph","content":[{"text":"🐕 ","type":"text"},{"text":"Watch Dog — Self-Healing Gateway Monitor","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"Watch Dog is a background service that pings your OpenClaw gateway every 15 seconds. If the gateway goes down, it automatically attempts to restart it and sends you Telegram alerts so you're always in the loop. All diagnostics run locally on your device.","type":"text"}]},{"type":"paragraph","content":[{"text":"To set it up, I need:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Telegram Bot Token","type":"text","marks":[{"type":"strong"}]},{"text":" — Create a bot via ","type":"text"},{"text":"@BotFather","type":"text","marks":[{"type":"link","attrs":{"href":"https://t.me/BotFather","title":null}}]},{"text":" on Telegram, then send me the token (looks like ","type":"text"},{"text":"123456:ABC-DEF...","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Your Telegram Chat ID","type":"text","marks":[{"type":"strong"}]},{"text":" — Send ","type":"text"},{"text":"/start","type":"text","marks":[{"type":"code_inline"}]},{"text":" to your bot, then visit ","type":"text"},{"text":"https://api.telegram.org/bot\u003cYOUR_TOKEN>/getUpdates","type":"text","marks":[{"type":"code_inline"}]},{"text":" to find your chat ID","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Send me the token and chat ID and I'll handle the rest (including a test run to make sure everything works)!","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"After Receiving Credentials","type":"text"}]},{"type":"paragraph","content":[{"text":"Run these steps in order:","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"1. Validate credentials","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python3 ~/.openclaw/workspace/openclaw-watchdog/scripts/validate.py \"$TELEGRAM_TOKEN\"","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"2. Run setup script","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"chmod +x ~/.openclaw/workspace/openclaw-watchdog/scripts/setup.sh\n~/.openclaw/workspace/openclaw-watchdog/scripts/setup.sh \\\n --telegram-token \"$TELEGRAM_TOKEN\" \\\n --telegram-chat-id \"$TELEGRAM_CHAT_ID\"","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"3. Connect via Telegram (Pairing)","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python3 ~/.openclaw/workspace/openclaw-watchdog/scripts/test-message.py \"$TELEGRAM_TOKEN\" \"$TELEGRAM_CHAT_ID\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Wait for user to confirm they received the Telegram message before proceeding.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"4. Verify it's running","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Check service status\nif [[ \"$(uname)\" == \"Darwin\" ]]; then\n launchctl list | grep openclaw.watchdog\nelse\n systemctl --user status openclaw-watchdog\nfi\n\n# Check logs\ntail -20 ~/.openclaw/watchdog/watchdog.log","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"5. Confirm to user","type":"text"}]},{"type":"paragraph","content":[{"text":"Tell them Watch Dog is active, what it monitors, and that they'll get Telegram alerts if anything goes wrong.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"How It Works","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Pings ","type":"text"},{"text":"localhost:3117/health","type":"text","marks":[{"type":"code_inline"}]},{"text":" every 15 seconds","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"After 3 consecutive failures, attempts ","type":"text"},{"text":"openclaw gateway restart","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Up to 2 restart attempts, then asks user for reinstall permission via Telegram","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"User approves by running: ","type":"text"},{"text":"touch ~/.openclaw/watchdog/approve-reinstall","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Without approval, only sends notifications — no destructive actions","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Local pattern-matching diagnostics (no logs sent externally)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Runs as macOS LaunchAgent or Linux systemd user service","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Credentials encrypted with AES-256 using machine-specific key","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Uninstall","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"if [[ \"$(uname)\" == \"Darwin\" ]]; then\n launchctl unload ~/Library/LaunchAgents/com.openclaw.watchdog.plist 2>/dev/null\n rm -f ~/Library/LaunchAgents/com.openclaw.watchdog.plist\nelse\n systemctl --user stop openclaw-watchdog 2>/dev/null\n systemctl --user disable openclaw-watchdog 2>/dev/null\n rm -f ~/.config/systemd/user/openclaw-watchdog.service\nfi\nrm -rf ~/.openclaw/watchdog","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"openclaw-watchdog","author":"@skillopedia","source":{"stars":3,"repo_name":"openclaw-watchdog","origin_url":"https://github.com/abdullah4ai/openclaw-watchdog/blob/HEAD/SKILL.md","repo_owner":"abdullah4ai","body_sha256":"906111217e06ada46143a57eb90d54c483d7ca5809f5a032abaad09f69d60eb0","cluster_key":"80bff8e8fd7fea09310c5964d57415011e80154d5f1d93eb423b799c6bec2242","clean_bundle":{"format":"clean-skill-bundle-v1","source":"abdullah4ai/openclaw-watchdog/SKILL.md","attachments":[{"id":"b1ab6e7c-d84e-5793-ab1e-183ed3358038","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b1ab6e7c-d84e-5793-ab1e-183ed3358038/attachment.md","path":"references/troubleshooting.md","size":2213,"sha256":"e825cf992bd87de126cb2858e1e5720008608098e2181c935735451dab815cf8","contentType":"text/markdown; charset=utf-8"},{"id":"3646e2d6-e5eb-5728-b368-c4683dfd2248","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3646e2d6-e5eb-5728-b368-c4683dfd2248/attachment.sh","path":"scripts/setup.sh","size":6328,"sha256":"aeab7a4d43aeeb11ae6ebb4d9429d1ebe9bbd9023f1fd3d3c7676515ec67d670","contentType":"application/x-sh; charset=utf-8"},{"id":"e087b366-1ccc-5128-88d9-5c7b2be6bbe1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e087b366-1ccc-5128-88d9-5c7b2be6bbe1/attachment.py","path":"scripts/test-message.py","size":1226,"sha256":"ae363825db08f46f13835c983a49f8dd92d4ffc171e793270b04be00762686e3","contentType":"text/x-python; charset=utf-8"},{"id":"ec3bb4a3-a3e0-5dd7-a7b9-275ad180d977","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ec3bb4a3-a3e0-5dd7-a7b9-275ad180d977/attachment.py","path":"scripts/validate.py","size":824,"sha256":"fd139e12c424f8c60fd1df4b2bea9c983178f8a1af3357e27a5a5afd06d92505","contentType":"text/x-python; charset=utf-8"},{"id":"e19c5dcb-8364-51c4-aa00-5c933a7a3dec","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e19c5dcb-8364-51c4-aa00-5c933a7a3dec/attachment.py","path":"scripts/watchdog.py","size":13378,"sha256":"1da91de857ca4509e42ee93b8b516c4f25a580ab55ae1feac370d3a61959bc56","contentType":"text/x-python; charset=utf-8"}],"bundle_sha256":"6a74876ffbef5c32192332b8a6d25a693fc0fbe12604b59d7fbf9c17485b475e","attachment_count":5,"text_attachments":5,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"devops-infrastructure","category_label":"DevOps"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"devops-infrastructure","homepage":"https://github.com/Abdullah4AI/openclaw-watchdog","metadata":{"openclaw":{"emoji":"🐕","install":[{"id":"setup","kind":"script","label":"Install watchdog service (LaunchAgent/systemd user)","script":"scripts/setup.sh","service":true,"persistence":"user-level"}],"requires":{"env":["TELEGRAM_TOKEN","TELEGRAM_CHAT_ID"],"bins":["python3","openssl"]},"disableModelInvocation":true}},"import_tag":"clean-skills-v1","description":"Self-healing monitoring system for OpenClaw gateway. Auto-detects failures, fixes crashes, and sends Telegram alerts."}},"renderedAt":1782988168891}

openclaw-watchdog Description: Self-healing monitoring system for OpenClaw gateway. Monitors health, auto-restarts on failure, and sends Telegram alerts. Diagnostics and log analysis run locally on-device. Alert notifications are sent to the user's Telegram bot. Use when user wants to set up gateway monitoring, watchdog, or auto-recovery. Prerequisites - Telegram Bot Token — Create via @BotFather - Telegram Chat ID — Your personal chat ID for receiving alerts - Python 3 — Required for the watchdog service - OpenClaw — Installed and running Trigger Keywords - watchdog, monitoring, auto-fix, ga…