Skip to main content
Level: Advanced · Tags: Plugins, Dependency injection, WhatsApp, Telegram Features shown: Plugins (definePlugin, install/uninstall, ctx.onDispose, unplug) · Dependency injection (provide, ctx.tools) · Slash commands · Commands and triggers · Terminal simulator

Prerequisites

Node.js 22.12 or newer and an ESM project ("type": "module"), as in Getting started.

The complete bot

How it works

1. definePlugin and install

definePlugin(spec) only types the spec: a name, a version and an install(ctx, config) that registers everything. install must be synchronous (the bot does not await it). config is the second argument of bot.plug(), so one plugin serves several bots with different answers.

2. Sharing a tool with provide

ctx.bot.provide('faq', value) puts value in the bot’s tool registry. Every handler, hook and plugin reads it as ctx.tools.faq: the bot’s own /faqstats command (step 7) uses the plugin’s counters without importing anything from it. See Dependency injection.

3. What unplug undoes for you

Handlers registered through ctx.bot (command, when, onMessage, hooks, flows, nested plugins) are tracked and removed when the plugin is unplugged. That is why hours stops answering after /faqoff.

4. What you undo yourself: ctx.onDispose

Unplug does not know about your timers, connections or the tools you provide()d. Register their cleanup with ctx.onDispose(fn). Here it stops the hourly stats log and deletes ctx.tools.faq, so /faqstats can tell the plugin is gone. report.unref() keeps the timer from holding the process open.

5. uninstall

uninstall(ctx) runs first on unplug, before the automatic rollback and the onDispose callbacks: the place to flush or log a final state.

6. Plugging and unplugging

bot.plug(plugin, config) returns the unplug function (not the bot, so plug calls do not chain). Calling it twice is a no-op. Plugging a second plugin named faq throws unless the spec sets multiple: true.

Sample transcript

Captured with npx botmesh dev bot.js:
Shipping matches shipping: text triggers compare the whole message, normalized (case, accents and extra spaces).

Run it on WhatsApp or Telegram

node bot.js connects to WhatsApp: scan the QR with the phone that will be the bot. For Telegram, install @botmesh/telegram and pass new TelegramProvider({ token: process.env.TELEGRAM_TOKEN }) instead; the plugin does not change. See Channels.

Next steps