Drive your Claude Code session from WhatsApp — your personal number, no bots, no API keys. The plugin connects to WhatsApp as a linked device (the same protocol as WhatsApp Web, via Baileys) and exposes it to Claude Code as an MCP channel.
> /plugin marketplace add Rich627/whatsapp-claude-plugin> /plugin install whatsapp-channel@whatsapp-claude-plugin
What's inside
Drive your Claude Code session from WhatsApp — your personal number, no bots, no API keys.
The plugin connects to WhatsApp as a linked device (the same protocol as WhatsApp Web, via Baileys) and exposes it to Claude Code as an MCP channel. Incoming messages reach your session in real time; Claude replies from your own number, so recipients see a normal chat. Everything runs locally on your machine — messages travel directly between WhatsApp and your session, with no third-party servers in between. Once paired, it keeps working while your phone is off; only the Claude Code session needs to stay open, and reconnects never require re-pairing.
Published on the Anthropic Official Plugin Marketplace — the first community-built WhatsApp channel plugin reviewed and published by Anthropic.

claude plugin marketplace add Rich627/whatsapp-claude-plugin
claude plugin install whatsapp-channel@whatsapp-claude-plugin
claude --dangerously-load-development-channels plugin:whatsapp-channel@whatsapp-claude-plugin
The --dangerously-load-development-channels flag matters: it registers the plugin as a channel, so an inbound WhatsApp message wakes your session immediately. Without it the tools still load, but nothing wakes the session when messages arrive — they sit unanswered until you (or a watchdog) prompt Claude to check. --channels does not accept this plugin yet (it is not on the research-preview allowlist), so the development flag is currently the only way.
Inside the session, set your number and pair:
/whatsapp-channel:configure <phone> # country code + number, no +
A pairing code is printed on first launch. On your phone: WhatsApp → Settings → Linked Devices → Link a Device → Link with phone number instead → enter the code. No WhatsApp Business API, Meta developer account, or API key is involved — it links to your regular account.
The server is a plain stdio MCP server, so any MCP client can run it. Two things are Claude Code specific and worth knowing before you start:
notifications/claude/channel, a Claude Code extension. MCP has no standard equivalent that reaches the model, and other clients drop unknown notifications silently. Elsewhere the plugin is poll-based: call wait_for_messages (parks up to 40s; the first call on a connection returns whatever is already unreplied, later calls only what arrived since) or catch_up / unreplied. Most tool results also carry a count of unreplied messages, so a client finds out there is traffic on its next call. Three do not: unreplied and wait_for_messages, which just returned those very messages, and catch_up with no arguments, which is that count already./whatsapp-channel:access and friends are Claude Code skills. Use bun scripts/access.ts instead (see Access control from a terminal).Register the server with an absolute path — ${CLAUDE_PLUGIN_ROOT} is substituted by Claude Code only:
Codex CLI (~/.codex/config.toml)
[mcp_servers.whatsapp]
command = "bun"
args = ["run", "--cwd", "/absolute/path/to/whatsapp-channel", "start"]
startup_timeout_sec = 30 # default 10 is tight for a first Baileys connect
tool_timeout_sec = 120 # default 60; wait_for_messages parks for up to 40s
Gemini CLI (~/.gemini/settings.json)
{
"mcpServers": {
"whatsapp": {
"command": "bun",
"args": ["run", "--cwd", "/absolute/path/to/whatsapp-channel", "start"],
"timeout": 600000
}
}
}
Cursor (~/.cursor/mcp.json for all projects, .cursor/mcp.json for one)
{
"mcpServers": {
"whatsapp": {
"type": "stdio",
"command": "bun",
"args": ["run", "--cwd", "/absolute/path/to/whatsapp-channel", "start"]
}
}
}
Only one client at a time can hold the WhatsApp connection: WhatsApp allows one linked-device session per account, and two servers would kick each other off. A second server does not fail silently — it stays up and serves a single whatsapp_unavailable tool naming the process that holds the connection.
Everything the access skill does, without Claude Code:
bun scripts/access.ts status # policy, allowlist, pending codes, groups
bun scripts/access.ts policy pairing # open the door
bun scripts/access.ts pair <code> # approve someone who messaged you
bun scripts/access.ts allow <jid> # add directly
bun scripts/access.ts remove <jid>
bun scripts/access.ts group add <groupJid> [--mention] [--allow jid1,jid2]
bun scripts/access.ts set replyToMode first # ackReaction, textChunkLimit, chunkMode, mentionPatterns
Approving always needs the specific code, even when only one pairing is waiting: anyone can create a pending entry just by messaging the account, so "approve the pending one" is exactly what a prompt-injected request looks like. For the same reason this is a terminal command and deliberately not an MCP tool, so nothing arriving over WhatsApp can reach it.
reply can tag people so they actually get notified — ids are accepted as phone, LID, or full JID, and mentions attach only to the chunk that names them./whatsapp-channel:access in Claude Code, or bun scripts/access.ts anywhere.config.md with a custom personality and conversation memory.## Cron Jobs section in a group's config.md schedules recurring server-side tasks.catch_up with no arguments says how many messages are waiting per chat - counts only, no message text - plus open tasks from tasks.md. Name a chat and it replays that room's recent two-way conversation, so a fresh session resumes mid-flight work without reading every chat it has./whatsapp-channel:doctor checks the server process, device link, singleton lock, and config, then walks you through the fixes — no more guessing why replies stopped.WhatsApp (phone) <──Baileys──> MCP Server <──stdio──> Claude Code
The server (a single Bun process) holds the linked-device connection and forwards inbound messages to the session as channel notifications after they pass the access gate. Claude acts through MCP tools — reply, react, edit_message, download_attachment, status, unreplied, catch_up, list_groups. Runtime state (auth, allowlists, group configs, inbox) lives in ~/.whatsapp-channel/, never in the repo.
Messages sent by Claude appear as coming from your phone number. Use a dedicated number if you want a distinct bot identity.
One-time setup (Apple Silicon, mlx-whisper):
brew install ffmpeg # mlx-whisper uses it to decode audio
python3 -m venv ~/whisper-env
source ~/whisper-env/bin/activate
pip install mlx-whisper
cp scripts/whisper-transcribe.sh ~/whisper-transcribe.sh
chmod +x ~/whisper-transcribe.sh
~/whisper-transcribe.sh path/to/sample.ogg # optional: test
The reference script uses mlx-community/whisper-large-v3-turbo — accurate, fast, multilingual. Swap the model in the script if you prefer a smaller one.
| Issue | Solution |
|---|---|
| Pairing code not showing | Run /whatsapp-channel:configure <phone> first, then relaunch |
| 440 disconnect error | Only one connection per auth state allowed. Kill stale processes: pkill -f "whatsapp.*server" |
| Session not waking on new messages | Most common cause: launched without --dangerously-load-development-channels plugin:whatsapp-channel@whatsapp-claude-plugin. Tools work but inbound pushes are dropped (Channel notifications skipped in the MCP debug log) — relaunch with the flag. |
| Messages not arriving | Known Claude Code client bug (#37933). Server-side is correct, awaiting client fix. |
FAQ
whatsapp-channel is a Claude Code plugin with 4 hand-picked skills for productivity work, indexed on Flowy. Install it with the command on its page. It includes access, configure, doctor. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
Is this plugin yours?
Claim it with GitHubSubmit a pluginPromote it