add-whatsapp
Scannednpx machina-cli add skill qwibitai/nanoclaw/add-whatsapp --openclawAdd WhatsApp Channel
This skill adds WhatsApp support to NanoClaw. It installs the WhatsApp channel code, dependencies, and guides through authentication, registration, and configuration.
Phase 1: Pre-flight
Check current state
Check if WhatsApp is already configured. If store/auth/ exists with credential files, skip to Phase 4 (Registration) or Phase 5 (Verify).
ls store/auth/creds.json 2>/dev/null && echo "WhatsApp auth exists" || echo "No WhatsApp auth"
Detect environment
Check whether the environment is headless (no display server):
[[ -z "$DISPLAY" && -z "$WAYLAND_DISPLAY" && "$OSTYPE" != darwin* ]] && echo "IS_HEADLESS=true" || echo "IS_HEADLESS=false"
Ask the user
Use AskUserQuestion to collect configuration. Adapt auth options based on environment:
If IS_HEADLESS=true AND not WSL → AskUserQuestion: How do you want to authenticate WhatsApp?
- Pairing code (Recommended) - Enter a numeric code on your phone (no camera needed, requires phone number)
- QR code in terminal - Displays QR code in the terminal (can be too small on some displays)
Otherwise (macOS, desktop Linux, or WSL) → AskUserQuestion: How do you want to authenticate WhatsApp?
- QR code in browser (Recommended) - Opens a browser window with a large, scannable QR code
- Pairing code - Enter a numeric code on your phone (no camera needed, requires phone number)
- QR code in terminal - Displays QR code in the terminal (can be too small on some displays)
If they chose pairing code:
AskUserQuestion: What is your phone number? (Include country code without +, e.g., 1234567890)
Phase 2: Verify Code
Apply the skill to install the WhatsApp channel code and dependencies:
npx tsx scripts/apply-skill.ts .claude/skills/add-whatsapp
Verify the code was placed correctly:
test -f src/channels/whatsapp.ts && echo "WhatsApp channel code present" || echo "ERROR: WhatsApp channel code missing — re-run skill apply"
Verify dependencies
node -e "require('@whiskeysockets/baileys')" 2>/dev/null && echo "Baileys installed" || echo "Installing Baileys..."
If not installed:
npm install @whiskeysockets/baileys qrcode qrcode-terminal
Validate build
npm run build
Build must be clean before proceeding.
Phase 3: Authentication
Clean previous auth state (if re-authenticating)
rm -rf store/auth/
Run WhatsApp authentication
For QR code in browser (recommended):
npx tsx setup/index.ts --step whatsapp-auth -- --method qr-browser
(Bash timeout: 150000ms)
Tell the user:
A browser window will open with a QR code.
- Open WhatsApp > Settings > Linked Devices > Link a Device
- Scan the QR code in the browser
- The page will show "Authenticated!" when done
For QR code in terminal:
npx tsx setup/index.ts --step whatsapp-auth -- --method qr-terminal
Tell the user to run npm run auth in another terminal, then:
- Open WhatsApp > Settings > Linked Devices > Link a Device
- Scan the QR code displayed in the terminal
For pairing code:
npx tsx setup/index.ts --step whatsapp-auth -- --method pairing-code --phone <their-phone-number>
(Bash timeout: 150000ms). Display PAIRING_CODE from output.
Tell the user:
A pairing code will appear. Enter it within 60 seconds — codes expire quickly.
- Open WhatsApp > Settings > Linked Devices > Link a Device
- Tap Link with phone number instead
- Enter the code immediately
If the code expires, re-run the command — a new code will be generated.
If failed: qr_timeout → re-run. logged_out → delete store/auth/ and re-run. 515 → re-run. timeout → ask user, offer retry.
Verify authentication succeeded
test -f store/auth/creds.json && echo "Authentication successful" || echo "Authentication failed"
Configure environment
Channels auto-enable when their credentials are present — WhatsApp activates when store/auth/creds.json exists.
Sync to container environment:
mkdir -p data/env && cp .env data/env/env
Phase 4: Registration
Configure trigger and channel type
Get the bot's WhatsApp number: node -e "const c=require('./store/auth/creds.json');console.log(c.me.id.split(':')[0].split('@')[0])"
AskUserQuestion: Is this a shared phone number (personal WhatsApp) or a dedicated number (separate device)?
- Shared number - Your personal WhatsApp number (recommended: use self-chat or a solo group)
- Dedicated number - A separate phone/SIM for the assistant
AskUserQuestion: What trigger word should activate the assistant?
- @Andy - Default trigger
- @Claw - Short and easy
- @Claude - Match the AI name
AskUserQuestion: What should the assistant call itself?
- Andy - Default name
- Claw - Short and easy
- Claude - Match the AI name
AskUserQuestion: Where do you want to chat with the assistant?
Shared number options:
- Self-chat (Recommended) - Chat in your own "Message Yourself" conversation
- Solo group - A group with just you and the linked device
- Existing group - An existing WhatsApp group
Dedicated number options:
- DM with bot (Recommended) - Direct message the bot's number
- Solo group - A group with just you and the bot
- Existing group - An existing WhatsApp group
Get the JID
Self-chat: JID = your phone number with @s.whatsapp.net. Extract from auth credentials:
node -e "const c=JSON.parse(require('fs').readFileSync('store/auth/creds.json','utf-8'));console.log(c.me?.id?.split(':')[0]+'@s.whatsapp.net')"
DM with bot: Ask for the bot's phone number. JID = NUMBER@s.whatsapp.net
Group (solo, existing): Run group sync and list available groups:
npx tsx setup/index.ts --step groups
npx tsx setup/index.ts --step groups --list
The output shows JID|GroupName pairs. Present candidates as AskUserQuestion (names only, not JIDs).
Register the chat
npx tsx setup/index.ts --step register \
--jid "<jid>" \
--name "<chat-name>" \
--trigger "@<trigger>" \
--folder "whatsapp_main" \
--channel whatsapp \
--assistant-name "<name>" \
--is-main \
--no-trigger-required # Only for main/self-chat
For additional groups (trigger-required):
npx tsx setup/index.ts --step register \
--jid "<group-jid>" \
--name "<group-name>" \
--trigger "@<trigger>" \
--folder "whatsapp_<group-name>" \
--channel whatsapp
Phase 5: Verify
Build and restart
npm run build
Restart the service:
# macOS (launchd)
launchctl kickstart -k gui/$(id -u)/com.nanoclaw
# Linux (systemd)
systemctl --user restart nanoclaw
# Linux (nohup fallback)
bash start-nanoclaw.sh
Test the connection
Tell the user:
Send a message to your registered WhatsApp chat:
- For self-chat / main: Any message works
- For groups: Use the trigger word (e.g., "@Andy hello")
The assistant should respond within a few seconds.
Check logs if needed
tail -f logs/nanoclaw.log
Troubleshooting
QR code expired
QR codes expire after ~60 seconds. Re-run the auth command:
rm -rf store/auth/ && npx tsx src/whatsapp-auth.ts
Pairing code not working
Codes expire in ~60 seconds. To retry:
rm -rf store/auth/ && npx tsx src/whatsapp-auth.ts --pairing-code --phone <phone>
Enter the code immediately when it appears. Also ensure:
- Phone number includes country code without
+(e.g.,1234567890) - Phone has internet access
- WhatsApp is updated to the latest version
If pairing code keeps failing, switch to QR-browser auth instead:
rm -rf store/auth/ && npx tsx setup/index.ts --step whatsapp-auth -- --method qr-browser
"conflict" disconnection
This happens when two instances connect with the same credentials. Ensure only one NanoClaw process is running:
pkill -f "node dist/index.js"
# Then restart
Bot not responding
Check:
- Auth credentials exist:
ls store/auth/creds.json - Chat is registered:
sqlite3 store/messages.db "SELECT * FROM registered_groups WHERE jid LIKE '%whatsapp%' OR jid LIKE '%@g.us' OR jid LIKE '%@s.whatsapp.net'" - Service is running:
launchctl list | grep nanoclaw(macOS) orsystemctl --user status nanoclaw(Linux) - Logs:
tail -50 logs/nanoclaw.log
Group names not showing
Run group metadata sync:
npx tsx setup/index.ts --step groups
This fetches all group names from WhatsApp. Runs automatically every 24 hours.
After Setup
If running npm run dev while the service is active:
# macOS:
launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist
npm run dev
# When done testing:
launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist
# Linux:
# systemctl --user stop nanoclaw
# npm run dev
# systemctl --user start nanoclaw
Removal
To remove WhatsApp integration:
- Delete auth credentials:
rm -rf store/auth/ - Remove WhatsApp registrations:
sqlite3 store/messages.db "DELETE FROM registered_groups WHERE jid LIKE '%@g.us' OR jid LIKE '%@s.whatsapp.net'" - Sync env:
mkdir -p data/env && cp .env data/env/env - Rebuild and restart:
npm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw(macOS) ornpm run build && systemctl --user restart nanoclaw(Linux)
Source
git clone https://github.com/qwibitai/nanoclaw/blob/main/.claude/skills/add-whatsapp/SKILL.mdView on GitHub Overview
Adds WhatsApp as a channel in NanoClaw, handling installation, authentication, and configuration. It can replace existing channels or run alongside them, and supports authentication via a pairing code or QR code depending on the environment.
How This Skill Works
Phase 1 performs pre-flight checks, environment detection, and an interactive flow to determine the best authentication method. Phase 2 installs the channel code and dependencies, then Phase 3 handles authentication via browser QR, terminal QR, or pairing code. The skill uses the Baileys library and builds the channel before going live.
When to Use It
- Replace all current channels with WhatsApp to unify messaging on a single surface
- Add WhatsApp alongside existing channels for a hybrid multi-channel setup
- Operate in a headless environment where pairing code is preferred
- Use QR in browser for desktop environments with a large, scannable QR
- Choose between pairing code, QR-terminal, or QR-browser based on operator environment
Quick Start
- Step 1: Apply the skill to add WhatsApp to the project using npx tsx scripts/apply-skill.ts .claude/skills/add-whatsapp
- Step 2: Verify the channel code exists by checking for src/channels/whatsapp.ts and confirming success
- Step 3: Start authentication with your chosen method, for example npx tsx setup/index.ts --step whatsapp-auth -- --method qr-browser or --method pairing-code --phone <number>
Best Practices
- Verify any existing WhatsApp auth state before applying the skill
- Run pre-flight checks and ensure dependencies are installed
- Check that the channel file exists after apply and build cleanly
- Test the build with npm run build before enabling the channel
- Document and securely manage credentials under store/auth
Example Use Cases
- A customer support bot routing WhatsApp messages to agents via the new WhatsApp channel
- E commerce order updates and notifications delivered through WhatsApp
- Internal IT alerts and on-call notices sent over WhatsApp alongside other channels
- Headless prototype using pairing code for quick onboarding
- Demo environment showcasing QR browser authentication for onboarding