Added a Right-Hand Sidebar (RHS) panel to the Mattermost plugin that shows live agent activity in a dedicated, always-visible panel. - New RHSPanel component with SessionCard views per active session - registerAppBarComponent adds 'Agent Status' icon to toolbar - Subscribes to WebSocket updates via global listener - Shows active sessions with live elapsed time, tool calls, token count - Shows recent completed sessions below active ones - Responsive CSS matching Mattermost design system The RHS panel solves the scroll-out-of-view problem: the status dashboard stays visible regardless of chat scroll position.
Live Status v4
Real-time Mattermost progress updates for OpenClaw agent sessions.
Version 4 replaces the manual v1 live-status CLI with a transparent infrastructure daemon.
Agents no longer need to call live-status. The watcher auto-updates Mattermost as they work.
Architecture
Two rendering modes (auto-detected):
Plugin Mode (preferred)
When the Mattermost plugin is installed, updates stream via WebSocket:
- Custom post type
custom_livestatuswith terminal-style React rendering - Zero Mattermost post API calls during streaming (no "(edited)" label)
- Auto-scroll, collapsible sub-agents, theme-compatible
REST API Fallback
When the plugin is unavailable, updates use the Mattermost REST API:
- Blockquote-formatted posts updated via PUT
- Shows "(edited)" label (Mattermost API limitation)
OpenClaw Gateway
Agent Sessions
-> writes {uuid}.jsonl as they run
status-watcher daemon (SINGLE PROCESS)
-> fs.watch + polling fallback on transcript directory
-> Multiplexes all active sessions
-> Auto-detects plugin (GET /health every 60s)
-> Plugin mode: POST/PUT/DELETE to plugin REST endpoint
-> Plugin broadcasts via WebSocket to React component
-> REST fallback: PUT to Mattermost post API
-> Shared HTTP connection pool (keep-alive, maxSockets=4)
-> Throttled updates (leading edge + trailing flush, 500ms)
-> Circuit breaker for API failure resilience
-> Graceful shutdown (SIGTERM -> mark all boxes "interrupted")
-> Sub-agent nesting (child sessions under parent status box)
Mattermost Plugin (com.openclaw.livestatus)
-> Go server: REST API + KV store + WebSocket broadcast
-> React webapp: custom post type renderer
-> Terminal-style UI with auto-scroll
gateway:startup hook
-> hooks/status-watcher-hook/handler.js
-> Checks PID file; spawns daemon if not running
Mattermost API (fallback)
-> PUT /api/v4/posts/{id} (in-place edits, unlimited)
-> Shared http.Agent (keepAlive, maxSockets=4)
-> Circuit breaker: open after 5 failures, 30s cooldown
Install
Prerequisites
- Node.js 22.x
- OpenClaw gateway running
- Mattermost bot token
One-command install
cd /path/to/MATTERMOST_OPENCLAW_LIVESTATUS
bash install.sh
This installs npm dependencies and deploys the gateway:startup hook.
The daemon starts automatically on the next gateway restart.
Manual start (without gateway restart)
Set required env vars, then:
node src/watcher-manager.js start
Configuration
All config via environment variables. No hardcoded values.
Required
| Variable | Description |
|---|---|
MM_TOKEN |
Mattermost bot token |
MM_URL |
Mattermost base URL (e.g. https://slack.solio.tech) |
TRANSCRIPT_DIR |
Path to agent sessions directory |
SESSIONS_JSON |
Path to sessions.json |
Optional
| Variable | Default | Description |
|---|---|---|
THROTTLE_MS |
500 |
Min interval between Mattermost updates |
IDLE_TIMEOUT_S |
60 |
Inactivity before marking session complete |
MAX_SESSION_DURATION_S |
1800 |
Hard timeout per session (30 min) |
MAX_STATUS_LINES |
15 |
Max lines in status box (oldest dropped) |
MAX_ACTIVE_SESSIONS |
20 |
Concurrent status box limit |
MAX_MESSAGE_CHARS |
15000 |
Mattermost post truncation limit |
HEALTH_PORT |
9090 |
Health endpoint port (0 = disabled) |
LOG_LEVEL |
info |
Logging level (pino) |
PID_FILE |
/tmp/status-watcher.pid |
PID file location |
CIRCUIT_BREAKER_THRESHOLD |
5 |
Failures before circuit opens |
CIRCUIT_BREAKER_COOLDOWN_S |
30 |
Cooldown before half-open probe |
TOOL_LABELS_FILE |
(built-in) | External tool labels JSON override |
DEFAULT_CHANNEL |
none | Fallback channel for non-MM sessions |
PLUGIN_URL |
none | Plugin endpoint URL (enables plugin mode) |
PLUGIN_SECRET |
none | Shared secret for plugin authentication |
PLUGIN_ENABLED |
true |
Enable/disable plugin auto-detection |
Status Box Format
[ACTIVE] main | 38s
Reading live-status source code...
exec: ls /agents/sessions [OK]
Analyzing agent configurations...
exec: grep -r live-status [OK]
Writing new implementation...
Sub-agent: proj035-planner
Reading protocol...
Analyzing JSONL format...
[DONE] 28s
Plan ready. Awaiting approval.
[DONE] 53s | 12.4k tokens
Daemon Management
# Start
node src/watcher-manager.js start
# Stop (graceful shutdown)
node src/watcher-manager.js stop
# Status
node src/watcher-manager.js status
# Pass-through via legacy CLI
live-status start-watcher
live-status stop-watcher
# Health check
curl http://localhost:9090/health
Deployment Options
Hook (default)
The gateway:startup hook in hooks/status-watcher-hook/ auto-starts the daemon.
No configuration needed beyond deploying the hook.
systemd
# Copy service file
cp deploy/status-watcher.service /etc/systemd/system/
# Create env file
cat > /etc/status-watcher.env <<EOF
MM_TOKEN=your_token
MM_URL=https://slack.solio.tech
TRANSCRIPT_DIR=/home/node/.openclaw/agents/main/sessions
SESSIONS_JSON=/home/node/.openclaw/agents/main/sessions/sessions.json
EOF
systemctl enable --now status-watcher
Docker
docker build -f deploy/Dockerfile -t status-watcher .
docker run -d \
-e MM_TOKEN=your_token \
-e MM_URL=https://slack.solio.tech \
-e TRANSCRIPT_DIR=/sessions \
-e SESSIONS_JSON=/sessions/sessions.json \
-v /home/node/.openclaw/agents:/sessions:ro \
-p 9090:9090 \
status-watcher
Upgrade from v1
v1 required agents to call live-status create/update/complete manually.
AGENTS.md contained a large "Live Status Protocol (MANDATORY)" section.
What changes
- The daemon handles all updates — no manual calls needed.
- AGENTS.md protocol section can be removed (see
docs/v1-removal-checklist.md). skill/SKILL.mdis now 9 lines: "status is automatic".live-statusCLI still works for manual use but prints a deprecation notice.
Migration steps
- Run
bash install.shto deploy v4. - Restart the gateway (hook activates).
- Verify the daemon is running:
curl localhost:9090/health - After 1+ hours of verified operation, remove the v1 AGENTS.md sections
(see
docs/v1-removal-checklist.mdfor exact sections to remove).
Troubleshooting
Daemon not starting:
- Check PID file:
cat /tmp/status-watcher.pid - Check env vars:
MM_TOKEN,MM_URL,TRANSCRIPT_DIR,SESSIONS_JSONmust all be set - Start manually and check logs:
node src/watcher-manager.js start
No status updates appearing:
- Check health endpoint:
curl localhost:9090/health - Check circuit breaker state (shown in health response)
- Verify
MM_TOKENhas permission to post in the target channel
Duplicate status boxes:
- Multiple daemon instances — check PID file, kill extras
node src/watcher-manager.js statusshows if it's running
Session compaction:
- When JSONL is truncated, the watcher detects it (stat.size < lastOffset)
- Offset resets, status box shows
[session compacted - continuing] - No crash, no data loss
Development
# Run all tests
npm test
# Run unit tests only
npm run test-unit
# Run integration tests only
npm run test-integration
# Lint + format + test
make check
Project Structure
src/
watcher-manager.js Entrypoint; PID file; graceful shutdown
status-watcher.js JSONL file watcher (inotify)
session-monitor.js sessions.json poller (2s interval)
status-box.js Mattermost post manager (throttle, circuit breaker)
status-formatter.js Status box text renderer
circuit-breaker.js Circuit breaker state machine
config.js Env var config with validation
logger.js pino wrapper
health.js HTTP health endpoint
tool-labels.js Tool name -> label resolver
tool-labels.json Built-in tool label defaults
live-status.js Legacy CLI (deprecated; backward compat)
hooks/
status-watcher-hook/ gateway:startup hook (auto-start daemon)
deploy/
status-watcher.service systemd unit file
Dockerfile Container deployment
test/
unit/ Unit tests (59 tests)
integration/ Integration tests (36 tests)