with one click
add-whatsapp
// Add WhatsApp channel via native Baileys adapter. Direct connection — no Chat SDK bridge. Uses QR code or pairing code for authentication.
// Add WhatsApp channel via native Baileys adapter. Direct connection — no Chat SDK bridge. Uses QR code or pairing code for authentication.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | add-whatsapp |
| description | Add WhatsApp channel via native Baileys adapter. Direct connection — no Chat SDK bridge. Uses QR code or pairing code for authentication. |
Adds WhatsApp support via the native Baileys adapter (no Chat SDK bridge).
NanoClaw doesn't ship channels in trunk. This skill copies the native WhatsApp (Baileys) adapter and its whatsapp-auth setup step in from the channels branch. No Chat SDK bridge.
Skip to Credentials if all of these are already in place:
src/channels/whatsapp.ts existssrc/channels/index.ts contains import './whatsapp.js';setup/whatsapp-auth.ts and setup/groups.ts both existsetup/index.ts's STEPS map contains both 'whatsapp-auth': and groups:@whiskeysockets/baileys, qrcode, pino are listed in package.json dependenciesOtherwise continue. Every step below is safe to re-run.
git fetch origin channels
git show origin/channels:src/channels/whatsapp.ts > src/channels/whatsapp.ts
git show origin/channels:setup/whatsapp-auth.ts > setup/whatsapp-auth.ts
git show origin/channels:setup/groups.ts > setup/groups.ts
Append to src/channels/index.ts (skip if already present):
import './whatsapp.js';
In setup/index.ts, add these entries to the STEPS map (skip lines already present):
groups: () => import('./groups.js'),
'whatsapp-auth': () => import('./whatsapp-auth.js'),
pnpm install @whiskeysockets/baileys@7.0.0-rc.9 qrcode@1.5.4 @types/qrcode@1.5.6 pino@9.6.0
pnpm run build
WhatsApp uses linked-device authentication — no API key, just a one-time pairing from your phone.
Check if WhatsApp is already authenticated. If store/auth/creds.json exists, skip to "Shared vs dedicated number".
test -f store/auth/creds.json && echo "WhatsApp auth exists" || echo "No WhatsApp auth"
Check whether the environment is headless (no display server):
[[ -z "$DISPLAY" && -z "$WAYLAND_DISPLAY" && "$OSTYPE" != darwin* ]] && echo "IS_HEADLESS=true" || echo "IS_HEADLESS=false"
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?
Otherwise (macOS, desktop Linux, or WSL) → AskUserQuestion: How do you want to authenticate WhatsApp?
If they chose pairing code:
AskUserQuestion: What is your phone number? (Digits only — country code followed by your 10-digit number, no + prefix, spaces, or dashes. Example: 14155551234 where 1 is the US country code and 4155551234 is the phone number.)
rm -rf store/auth/
For QR code in browser (recommended):
pnpm exec 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:
pnpm exec tsx setup/index.ts --step whatsapp-auth -- --method qr-terminal
(Bash timeout: 150000ms)
Tell the user:
- Open WhatsApp > Settings > Linked Devices > Link a Device
- Scan the QR code displayed in the terminal
For pairing code:
Tell the user to have WhatsApp open on Settings > Linked Devices > Link a Device, ready to tap "Link with phone number instead" — the code expires in ~60 seconds and must be entered immediately.
Run the auth process in the background and poll store/pairing-code.txt for the code:
rm -f store/pairing-code.txt && pnpm exec tsx setup/index.ts --step whatsapp-auth -- --method pairing-code --phone <their-phone-number> > /tmp/wa-auth.log 2>&1 &
Then immediately poll for the code (do NOT wait for the background command to finish):
for i in $(seq 1 20); do [ -f store/pairing-code.txt ] && cat store/pairing-code.txt && break; sleep 1; done
Display the code to the user the moment it appears. Tell them:
Enter this code now — it expires in ~60 seconds.
- Open WhatsApp > Settings > Linked Devices > Link a Device
- Tap Link with phone number instead
- Enter the code immediately
After the user enters the code, poll for authentication to complete:
for i in $(seq 1 60); do grep -q 'STATUS: authenticated' /tmp/wa-auth.log 2>/dev/null && echo "authenticated" && break; grep -q 'STATUS: failed' /tmp/wa-auth.log 2>/dev/null && echo "failed" && break; sleep 2; done
If failed: logged_out → delete store/auth/ and re-run. timeout → ask user, offer retry.
test -f store/auth/creds.json && echo "Authentication successful" || echo "Authentication failed"
AskUserQuestion: Is this a shared phone number (personal WhatsApp) or a dedicated number?
If dedicated, add to .env:
ASSISTANT_HAS_OWN_NUMBER=true
If you're in the middle of /setup, return to the setup flow now.
Otherwise, run /manage-channels to wire this channel to an agent group.
whatsapp<phone>@s.whatsapp.net (e.g. 14155551234@s.whatsapp.net). Groups use <id>@g.us. To find your number: 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')". Groups are auto-discovered — check pnpm exec tsx scripts/q.ts data/v2.db "SELECT platform_id, name FROM messaging_groups WHERE channel_type='whatsapp' AND is_group=1".**bold**→*bold*, *italic*→_italic_, headings→bold, code blocks preservedask_user_question renders with /approve, /reject slash commandsNot supported (WhatsApp linked device limitation): edit messages, delete messages.
QR codes expire after ~60 seconds. Re-run the auth command:
rm -rf store/auth/ && pnpm exec tsx setup/index.ts --step whatsapp-auth -- --method qr-browser
Codes expire in ~60 seconds. Delete auth and retry:
rm -rf store/auth/ && pnpm exec tsx setup/index.ts --step whatsapp-auth -- --method pairing-code --phone <phone>
Ensure: digits only (no +), phone has internet, WhatsApp is updated.
If pairing code keeps failing, switch to QR-browser auth instead:
rm -rf store/auth/ && pnpm exec tsx setup/index.ts --step whatsapp-auth -- --method qr-browser
Signal sessions corrupted from rapid restarts. Clear sessions:
systemctl --user stop nanoclaw
rm store/auth/session-*.json
systemctl --user start nanoclaw
test -f store/auth/creds.jsongrep "Connected to WhatsApp" logs/nanoclaw.log | tail -1pnpm exec tsx scripts/q.ts data/v2.db "SELECT mg.platform_id, mg.name FROM messaging_groups mg JOIN messaging_group_agents mga ON mg.id=mga.messaging_group_id WHERE mg.channel_type='whatsapp'"systemctl --user status nanoclawTwo instances connected with same credentials. Ensure only one NanoClaw process is running.