Getting Started
Requirements
- Node.js 22+ (download)
- pnpm (recommended) or npm/yarn
- A phone with WhatsApp (for the Baileys transport)
Don't have pnpm?
Install it with:
npm install -g pnpmESM-only packages
@botmesh/core and the transport packages ship as pure ESM — there is no CommonJS build. Your project needs "type": "module" in its package.json (or a .mjs file extension). On Node >= 22.12 you can also require() them via Node's experimental require(esm) support, but the examples below use plain import.
Alpha — published under the alpha tag
botmesh is in alpha: every package is on npm, but only under the alpha dist-tag (changeset publish does not create latest). An install without a tag will not resolve, so always write pnpm add @botmesh/core@alpha. Once a stable version ships, the tag can be dropped.
Scaffold a project with create-botmesh
The fastest start is the create-botmesh CLI, which generates a runnable project. To run it from a checkout of this monorepo instead, point it outside the repo (pnpm --filter create-botmesh build && node packages/create-botmesh/lib/cli.js ../my-bot; a target inside the botmesh monorepo is refused unless you pass --force):
npm create botmesh@alpha my-bot
npm create botmesh@alpha my-bot -- --template telegram --yes| Template | What you get |
|---|---|
baileys (default) | WhatsApp via Baileys: scan a QR to link |
meta | WhatsApp Cloud API (webhook; needs Meta credentials and a public URL) |
telegram | Telegram Bot API (long-polling; needs a @BotFather token) |
ai | Baileys + @botmesh/ai business-scoped support autoresponder (ANTHROPIC_API_KEY) |
games | Guess the number, hangman, trivia, tic-tac-toe, rock-paper-scissors; scores in ctx.user |
support | Tickets per user, FAQ menu and human handoff |
store | Catalog, per-user cart with a 7-day TTL and a checkout flow |
restaurant | Menu, delivery/pickup orders, "repeat my last order", table reservations |
clinic | Appointment booking (specialty, day, time), list/cancel appointments |
ai-full | Business-scoped AI + keyword/regex intents + SQLite store + scheduler + slash commands + handoff (ANTHROPIC_API_KEY) |
The use-case templates (games to ai-full) run on Baileys. The transport templates (baileys, meta, telegram, ai) install the built-in slash commands (/help, /reset, /cancel, /id, /ping), so /reset or /cancel escapes their sample menu flow.
| Flag | Meaning |
|---|---|
-t, --template <name> | One of the templates above (baileys when non-interactive) |
--name <name> | Package name (default: derived from the directory) |
-y, --yes | Skip prompts and use defaults |
--overwrite | Allow scaffolding into a non-empty directory |
--force | Allow a directory inside the botmesh monorepo itself (refused by default) |
-h, --help | Show help |
Every project gets package.json (with npm start and npm run dev, the terminal simulator), src/bot.js, .env.example, .gitignore, README.md and an AGENTS.md with instructions for AI coding agents: the current v2 API, what does not exist (addAnswer, capture...) and the commands to run.
npm run dev needs no credentials. npm start in the meta, telegram, ai and ai-full projects checks the variables it cannot run without and, when .env is missing or incomplete, stops with one line naming them (Missing TELEGRAM_TOKEN: copy .env.example to .env ...) before connecting anything.
The generated package.json depends on the published @botmesh/* packages under the alpha dist-tag (^2.0.0-alpha.2 for the core, ^0.2.0-alpha.0 for the rest; the exact ranges come from create-botmesh/src/versions.ts, generated at build time). There is no latest yet, so installing them by hand needs @alpha. To point those dependencies at your local checkout of the monorepo instead, use workspace: ranges.
To set everything up by hand instead, follow the steps below.
Step 1 — Install the framework
The engine (@botmesh/core) is transport-agnostic: you pair it with a provider package. For WhatsApp over Baileys 7 (unofficial, QR login):
mkdir my-bot
cd my-bot
pnpm init
pnpm add @botmesh/core@alpha @botmesh/baileys@alphaOther transports behind the same IProvider contract:
| Transport | Package | Status | Notes |
|---|---|---|---|
| WhatsApp (Baileys 7) | @botmesh/baileys | Alpha | Unofficial, QR login — what this guide uses |
| WhatsApp Cloud API | @botmesh/meta | Alpha | Official Meta API, webhook-based, no ban risk |
| Telegram | @botmesh/telegram | Alpha | Bot API, long-poll or webhook |
| Facebook Messenger | @botmesh/messenger | Experimental | Meta Graph Send API, webhook-based |
| Instagram DM | @botmesh/instagram | Experimental | Meta Graph, webhook-based |
| Discord | @botmesh/discord | Experimental | Gateway websocket + REST |
Alpha packages are published on npm under the alpha dist-tag (install with @alpha). Experimental ones are real, tested implementations that stay private (unpublished) for now and may change. More experimental providers (Evolution API, WPPConnect, Twilio, HighLevel, Gupshup, Email and TikTok) and a capability matrix are in Channels.
Then add "type": "module" to the generated package.json so Node treats your files as ESM:
{
"type": "module"
}Step 2 — Create your bot
Create a bot.js file. In v2, constructing a bot requires a provider — WhatsApp session/auth options live on the provider, not on the bot:
import { Bot } from '@botmesh/core'
import { BaileysProvider } from '@botmesh/baileys'
const bot = new Bot({
provider: new BaileysProvider({
session: 'my-bot',
qr: { terminal: true, small: true },
}),
})
bot.on('ready', () => console.log('✅ Bot connected!'))
bot.when('hola', async (ctx) => {
await ctx.reply('👋 Hello! I am your bot.')
})
await bot.start()Step 3 — Run and scan the QR
node bot.jsYou'll see a QR code in your terminal. Open it on your phone:
- Open WhatsApp
- Go to Settings → Linked Devices
- Tap Link a Device
- Scan the QR code
Done! Your bot is connected. Send "hola" (exactly, that's the default matching mode) from another phone and you'll get a reply.
Don't scan with the same phone
The QR is scanned with the phone that will be the bot, not the one sending messages.
Other transports, same bot code
Only the provider changes — when/flow/hooks/plugins are identical on every transport. For the official WhatsApp Cloud API:
import { Bot } from '@botmesh/core'
import { CloudAPIProvider } from '@botmesh/meta'
const bot = new Bot({
provider: new CloudAPIProvider({
accessToken: process.env.META_TOKEN ?? '',
phoneNumberId: process.env.META_PHONE_ID ?? '',
verifyToken: process.env.META_VERIFY_TOKEN ?? '',
appSecret: process.env.META_APP_SECRET, // required: verifies X-Hub-Signature-256
}),
})(The Cloud API is webhook-based: pass the raw request body of each inbound POST to provider.ingest(rawBody, headers) from your HTTP server — the signature is computed over the exact bytes Meta sent. Without appSecret the constructor throws; allowUnsignedWebhooks: true exists only for isolated local development.) See Channels for every other transport and Webhook server to mount webhook providers.
Next steps
- Your first bot — a complete bot with commands, media and flows
- Core concepts — understand how everything works
- Terminal simulator — chat with your bot with no phone (
npx botmesh dev src/bot.js) - Examples — ready-to-copy recipes