Zaileys is a type-safe wrapper around Baileys that makes building WhatsApp bots feel effortless. Create a Client, listen for typed events, and send anything from plain text to interactive buttons and rich AI-style responses with a single chainable builder — authentication, reconnection, and storage are handled for you.
Quick start • Why Zaileys • Install • What you can build • Storage • Runtimes • Docs
Note
This README is a high-level overview. The complete API reference, guides, and recipes live in the documentation site at https://zeative.github.io/zaileys/. Runnable code lives in examples/.
There is no await connect() — the client connects on construction, so every handler you register synchronously is wired up before the first event arrives.
import { Client } from 'zaileys'
const client = new Client()
client.on('qr', ({ qrString }) => console.log('Scan this QR:', qrString))
client.on('connect', ({ me }) => console.log('Connected as', me.id))
client.on('text', async (msg) => {
await msg.reply(`You said: ${msg.text}`)
})That is the whole bot. Scan the printed QR via WhatsApp → Linked Devices, and every text message gets a reply.
Prefer a pairing code? Provide your number:
const client = new Client({ authType: 'pairing', phoneNumber: '6281234567890' })Zaileys ships an official Agent Skill suite so your AI assistant writes, reviews, and debugs zaileys code with best practices — it knows the exact API, common pitfalls, and how to fix errors. Install it straight from this repo:
# Claude Code (native plugin — supports auto-update)
/plugin marketplace add zeative/zaileys
/plugin install zaileys-official@zeative
# npx skills (multi-agent: Claude Code, Codex, Cursor, OpenCode)
npx skills add zeative/zaileys # add -g for a global installThe suite has an orchestrator that auto-routes plus focused scaffold, debug, and review skills. See the full guide → zeative.github.io/zaileys/skill.
- Typed events —
on('text' | 'image' | 'reaction' | 'button-click' | 'group-update' | …)with fully-typed payloads and IntelliSense. No raw Baileys decoding, noany. - One chainable builder —
client.send(jid).text(…).reply(quoted).mentions([…])resolves to the sent message key when awaited. - Rich & interactive out of the box — native buttons, lists, carousels, and Meta-AI-style rich responses written as plain markdown.
- Auto lifecycle — QR or pairing-code login, auto-reconnect with backoff, clean logout, optional
ignoreMe. - Pluggable storage — independent
AuthStoreandMessageStoreinterfaces withfile,memory,sqlite,redis,postgres, andconvexadapters. - Batteries included — command framework, broadcast with rate limiting, scheduled sends, and lazy media processing (image/video/audio/sticker).
- Runs everywhere — dual ESM/CJS with
.d.ts+.d.ctstypes; verified on Node, Bun, Deno, and Termux. - Modern foundation — Baileys
7.0.0-rc13(includes the CVE-2026-48063 spoofing patch), built and type-checked with the native (Go) TypeScript 7 compiler.
npm i zaileys # or: pnpm add zaileys • yarn add zaileys • bun add zaileysRequires Node.js v20+. The file auth store is the zero-config default and needs nothing else.
Termux / Android: install with
npm install zaileys --legacy-peer-deps. A plainnpm installtries to compilesharp(a peer dependency of Baileys, no prebuilt ARM binary) and fails; the flag skips it and Zaileys falls back to the bundledjimppath.pnpm/yarnare unaffected.
Other storage backends are optional peer dependencies — install only the one you use:
npm i better-sqlite3 # sqlite adapters
npm i redis # redis adapters
npm i pg # postgres adapters
npm i convex # convex adapterssharp is an optional accelerator for media/sticker processing; without it Zaileys falls back to a pure-JS path automatically. It is not a Zaileys dependency, but Baileys pulls it in as a peer — on platforms with no prebuilt binary (Termux/Android, some Alpine) install with --legacy-peer-deps to skip it.
await client.send(jid).text('Hello there')
await client.send(jid).image('https://example.com/photo.jpg', { caption: 'Nice shot' })
await client.send(jid).poll('Pick one', ['Red', 'Green', 'Blue'])
await client.send(jid).album([
{ type: 'image', src: './a.jpg' },
{ type: 'image', src: './b.jpg' },
])Reply, URL, copy, call, reminder, location, and address buttons — plus lists and carousels — rendered natively on personal accounts.
await client.send(jid).buttons(
[
{ id: 'yes', text: 'Yes' },
{ type: 'url', text: 'Open docs', url: 'https://github.com/zeative/zaileys' },
{ type: 'copy', text: 'Copy code', code: 'ZAILEYS-2026' },
],
{ title: 'Pick one', text: 'Tap a button below' },
)
client.on('button-click', (ctx) => console.log('tapped:', ctx.buttonId))Toggle { rich: true } and write ordinary markdown — fenced code (syntax-highlighted), tables, images, and ::: directives for products, suggestions, and more.
await client.send(jid).text(
[
'*Daily brief* ☕',
'',
'```ts',
"const client = new Client()",
'```',
'',
':::suggest',
'See changelog | Upgrade guide',
':::',
].join('\n'),
{ rich: true, title: '📰 zaileys' },
)const client = new Client({ commandPrefix: ['/', '!'] })
client.command('ping', (ctx) => ctx.reply('pong 🏓'))
await client.broadcast(jids, (b) => b.text('Announcement'), { rateLimitPerSec: 5 })
await client.scheduleAt(new Date(Date.now() + 60_000), (b) => b.text('Sends in 1 minute'))const key = await client.send(jid).text('Original')
await client.edit(key).text('Edited')
await client.react(key, '👍')
await client.delete(key, { forEveryone: true })
await client.forward(key, otherJid)Auth state and message history use two independent interfaces, so you can mix and match — e.g. auth in SQLite, messages in Redis.
import { Client, SqliteAuthStore, RedisMessageStore } from 'zaileys'
const client = new Client({
auth: new SqliteAuthStore({ database: './auth.db' }),
store: new RedisMessageStore({ url: 'redis://localhost:6379' }),
})| Adapter | Auth store | Message store | Peer dependency |
|---|---|---|---|
file |
FileAuthStore ⭐ |
— | none |
memory |
MemoryAuthStore |
MemoryMessageStore |
none |
sqlite |
SqliteAuthStore |
SqliteMessageStore |
better-sqlite3 |
redis |
RedisAuthStore |
RedisMessageStore |
redis |
postgres |
PostgresAuthStore |
PostgresMessageStore |
pg |
convex |
ConvexAuthStore |
ConvexMessageStore |
convex |
⭐ default. Convex requires deploying the helper functions in
examples/convex/— see that folder's README.
Zaileys ships dual ESM/CJS entry points with type declarations for both module systems, and is verified to load on:
| Runtime | ESM | CJS |
|---|---|---|
Node.js >=20 |
✅ | ✅ |
| Bun | ✅ | ✅ |
Deno (--node-modules-dir) |
✅ | ✅ |
| Termux (Android) | ✅ | ✅ |
Package managers: npm, pnpm, yarn, and bun are all supported.
- 🌐 zeative.github.io/zaileys — full documentation site: guides, API reference, recipes
- 🤖 AI Skill — official Claude Code /
npx skillsskill - 📦 examples/ — runnable bots: quickstart, interactive buttons, AIRich, storage adapters, broadcast
- 🔀 MIGRATION.md — upgrading from v3.x to v4.0.0 (breaking changes, side-by-side snippets)
- 🤝 CONTRIBUTING.md — dev setup, tests, commit convention, release flow
- 🔒 SECURITY.md — vulnerability disclosure and supported versions
- 📝 CHANGELOG.md — release history
Hit a problem or have a feature request? Open an issue.
- Buy me a coffee ☕ • Ko-Fi • Trakteer
- ⭐ Star the repo on GitHub
Distributed under the MIT License. See LICENSE for details.