Phase 5 / Ep 25: Develop Your First Plugin —— \"Message Counter\"
🎯 Learning Objective: Develop a Plugin from scratch and register it to the Gateway.
1. Goal: Message Counter
Develop a message-counter Plugin to count the number of messages for each user, which can be viewed via the /stats command.
2. Directory Structure
~/.openclaw/plugins/message-counter/
├── manifest.json # Plugin metadata
├── index.js # Main entry point
├── data/
│ └── counts.json # Persistent data
└── README.md
3. manifest.json
{
"name": "message-counter",
"version": "1.0.0",
"description": "Count the number of messages sent by each user",
"author": "your-name",
"main": "index.js",
"hooks": ["onMessage"],
"commands": ["/stats"]
}
4. Core Logic (index.js)
const fs = require('fs');
const path = require('path');
const DATA_FILE = path.join(__dirname, 'data', 'counts.json');
function loadCounts() {
if (fs.existsSync(DATA_FILE)) {
return JSON.parse(fs.readFileSync(DATA_FILE, 'utf8'));
}
return {};
}
function saveCounts(counts) {
fs.writeFileSync(DATA_FILE, JSON.stringify(counts, null, 2));
}
// Hook: Triggered when each message arrives
exports.onMessage = function(message, next) {
const counts = loadCounts();
const userId = message.userId;
counts[userId] = (counts[userId] || 0) + 1;
saveCounts(counts);
next(); // Continue passing to the next Plugin
};
// Command: /stats
exports.commands = {
'/stats': function(message) {
const counts = loadCounts();
const total = Object.values(counts).reduce((a, b) => a + b, 0);
return `📊 Message Statistics\nTotal: ${total} messages\nYour messages: ${counts[message.userId] || 0} messages`;
}
};
5. Register to Gateway
// openclaw.json
{
"plugins": {
"pipeline": ["message-counter"]
}
}
openclaw gateway restart
6. Testing
# Send a few messages
openclaw chat "Test message 1"
openclaw chat "Test message 2"
# View statistics (via Telegram)
# Send /stats
Coming up next: Ep 26, Plugin in Action — Developing a "Notion Synchronizer" to automatically sync conversation summaries to Notion.