Bot Status API
A configurable HTTP service that exposes your OpenClaw bot's operational status as JSON. Designed for dashboard integration, monitoring, and transparency.
What It Provides
- Bot Core: Online status, model, context usage, uptime, heartbeat timing
- Services: Health checks for any HTTP endpoint, CLI tool, or file path
- Email: Unread counts from any email provider (himalaya, gog, etc.)
- Cron Jobs: Reads directly from OpenClaw's
cron/jobs.json
- Docker: Container health via Portainer API
- Dev Servers: Auto-detects running dev servers by process grep
- Skills: Lists installed and available OpenClaw skills
- System: CPU, RAM, Disk metrics from
/proc
Setup
1. Copy the service files
Copy server.js, collectors/, and package.json to your desired location.
2. Create config.json
Copy config.example.json to config.json and customize:
{
"port": 3200,
"name": "MyBot",
"workspace": "/path/to/.openclaw/workspace",
"openclawHome": "/path/to/.openclaw",
"cache": { "ttlMs": 10000 },
"model": "claude-sonnet-4-20250514",
"skillDirs": ["/path/to/openclaw/skills"],
"services": [
{ "name": "myservice", "type": "http", "url": "http://...", "healthPath": "/health" }
]
}
Service Check Types
| Type |
Description |
Config |
http |
Fetch URL, check HTTP 200 |
url, healthPath, method, headers, body |
command |
Run shell command, check exit 0 |
command, timeout |
file-exists |
Check path exists |
path |
3. Run
node server.js
4. Persist (systemd user service)
# ~/.config/systemd/user/bot-status.service
[Unit]
Description=Bot Status API
After=network.target
[Service]
Type=simple
WorkingDirectory=/path/to/bot-status
ExecStart=/usr/bin/node server.js
Restart=always
RestartSec=5
Environment=PORT=3200
Environment=HOME=/home/youruser
Environment=PATH=/usr/local/bin:/usr/bin:/bin
[Install]
WantedBy=default.target
systemctl --user daemon-reload
systemctl --user enable --now bot-status
loginctl enable-linger $USER # survive logout
5. Context/Vitals from OpenClaw
The bot should periodically write vitals to heartbeat-state.json in its workspace:
{
"vitals": {
"contextPercent": 62,
"contextUsed": 124000,
"contextMax": 200000,
"model": "claude-opus-4-5",
"updatedAt": 1770304500000
}
}
Add this to your HEARTBEAT.md so the bot updates it each heartbeat cycle.
Endpoints
| Endpoint |
Description |
GET /status |
Full status JSON (cached) |
GET /health |
Simple {"status":"ok"} |
Architecture
- Zero dependencies — Node.js built-ins only (
http, fs, child_process)
- Non-blocking — All shell commands use async
exec, never execSync
- Background refresh — Cache refreshes on interval, requests always served from cache instantly (~10ms)
- Config-driven — Everything in
config.json, no hardcoded values
1---2name: bot-status-api3description: Deploy a lightweight status API that exposes your OpenClaw bot's runtime health, service connectivity, cron jobs, skills, system metrics, and more. Use when setting up a monitoring dashboard, health endpoint, or status page for an OpenClaw agent. Supports any services via config (HTTP checks, CLI commands, file checks). Zero dependencies — Node.js only.4---56# Bot Status API78A configurable HTTP service that exposes your OpenClaw bot's operational status as JSON. Designed for dashboard integration, monitoring, and transparency.910## What It Provides1112- **Bot Core:** Online status, model, context usage, uptime, heartbeat timing13- **Services:** Health checks for any HTTP endpoint, CLI tool, or file path14- **Email:** Unread counts from any email provider (himalaya, gog, etc.)15- **Cron Jobs:** Reads directly from OpenClaw's `cron/jobs.json`16- **Docker:** Container health via Portainer API17- **Dev Servers:** Auto-detects running dev servers by process grep18- **Skills:** Lists installed and available OpenClaw skills19- **System:** CPU, RAM, Disk metrics from `/proc`2021## Setup2223### 1. Copy the service files2425Copy `server.js`, `collectors/`, and `package.json` to your desired location.2627### 2. Create config.json2829Copy `config.example.json` to `config.json` and customize:3031```json32{33 "port": 3200,34 "name": "MyBot",35 "workspace": "/path/to/.openclaw/workspace",36 "openclawHome": "/path/to/.openclaw",37 "cache": { "ttlMs": 10000 },38 "model": "claude-sonnet-4-20250514",39 "skillDirs": ["/path/to/openclaw/skills"],40 "services": [41 { "name": "myservice", "type": "http", "url": "http://...", "healthPath": "/health" }42 ]43}44```4546### Service Check Types4748| Type | Description | Config |49|------|-------------|--------|50| `http` | Fetch URL, check HTTP 200 | `url`, `healthPath`, `method`, `headers`, `body` |51| `command` | Run shell command, check exit 0 | `command`, `timeout` |52| `file-exists` | Check path exists | `path` |5354### 3. Run5556```bash57node server.js58```5960### 4. Persist (systemd user service)6162```ini63# ~/.config/systemd/user/bot-status.service64[Unit]65Description=Bot Status API66After=network.target6768[Service]69Type=simple70WorkingDirectory=/path/to/bot-status71ExecStart=/usr/bin/node server.js72Restart=always73RestartSec=574Environment=PORT=320075Environment=HOME=/home/youruser76Environment=PATH=/usr/local/bin:/usr/bin:/bin7778[Install]79WantedBy=default.target80```8182```bash83systemctl --user daemon-reload84systemctl --user enable --now bot-status85loginctl enable-linger $USER # survive logout86```8788### 5. Context/Vitals from OpenClaw8990The bot should periodically write vitals to `heartbeat-state.json` in its workspace:9192```json93{94 "vitals": {95 "contextPercent": 62,96 "contextUsed": 124000,97 "contextMax": 200000,98 "model": "claude-opus-4-5",99 "updatedAt": 1770304500000100 }101}102```103104Add this to your HEARTBEAT.md so the bot updates it each heartbeat cycle.105106## Endpoints107108| Endpoint | Description |109|----------|-------------|110| `GET /status` | Full status JSON (cached) |111| `GET /health` | Simple `{"status":"ok"}` |112113## Architecture114115- **Zero dependencies** — Node.js built-ins only (`http`, `fs`, `child_process`)116- **Non-blocking** — All shell commands use async `exec`, never `execSync`117- **Background refresh** — Cache refreshes on interval, requests always served from cache instantly (~10ms)118- **Config-driven** — Everything in `config.json`, no hardcoded values