#11484: feat: add WhatsApp pairing code login as alternative to QR scanning
channel: whatsapp-web
app: macos
app: web-ui
gateway
stale
Cluster:
WhatsApp Pairing Enhancements
## Summary
- Adds WhatsApp pairing code login as an alternative to QR code scanning
- Users enter their phone number and receive an 8-digit code to type into WhatsApp instead of scanning a QR
- Useful for headless servers, remote access, or when QR codes don't render properly
## How it works
- Passing `phoneNumber` to `web.login.start` automatically switches to pairing code mode
- The pairing code flow reuses the existing `ActiveLogin` / `waitForWebLogin` mechanism — no separate wait method needed
- Dashboard shows a "Pair with Code" button next to the existing QR flow
- The 8-digit code is displayed prominently in the UI
## Test plan
- [x] `pnpm build` passes (all 4 build steps)
- [x] Existing `login-qr.test.ts` passes (QR flow unaffected)
- [x] Tested locally on own OpenClaw instance (headless server via Cloudflare Tunnel)
- [ ] Manual test: trigger pairing code flow via dashboard
- [ ] Manual test: verify QR flow still works as before
- [ ] Manual test: verify "Wait for scan" button works for both flows
## AI Disclosure 🤖
This PR was built with **Claude Code (Claude Opus 4.6)** as a coding assistant.
- **Degree of AI involvement:** Code was AI-assisted, with human review and direction for each change
- **Testing:** Lightly tested — build passes, existing unit tests pass, manual end-to-end testing pending
- **Understanding:** I understand the full scope of the changes — the pairing code flow hooks into Baileys' `requestPairingCode()` API, reuses the existing `ActiveLogin`/`waitForWebLogin` lifecycle, and extends the gateway schema with an optional `phoneNumber` parameter. The UI adds a secondary login path alongside the existing QR flow.
## Greptile Review Feedback
All three issues raised by Greptile have been addressed in follow-up commits:
- **Wrong wait messaging** → Added `mode` field (`"qr"` | `"pairing-code"`) to `ActiveLogin` so `waitForWebLogin` shows correct messages per flow (`c863cbf`)
- **Forces relink unexpectedly** → Removed hardcoded `force: true` in pairing code controller, now defaults to `false` matching QR behavior (`c863cbf`)
- **Pairing code left active** → `ActiveLogin` intentionally stays active after `requestPairingCode` succeeds because `waitForWebLogin` needs it for the connection handshake (documented in commit message) (`c863cbf`)
- **Formatting + Swift models** → Ran formatter and regenerated `GatewayModels.swift` (`c63c4355`)
Most Similar PRs
#13696: feat(cli): add --code option for WhatsApp pairing code login
by asklee-klawd · 2026-02-10
85.3%
#11249: fix(whatsapp): prevent pairing-mode auto-replies to unknown DMs
by liuxiaopai-ai · 2026-02-07
77.4%
#17882: fix: drop WhatsApp pairing reply for unconfigured accounts
by adit-negi · 2026-02-16
76.9%
#13764: feat(whatsapp): add --qr-png option to save QR code as PNG file
by aorfevre · 2026-02-11
73.1%
#6265: feat(whatsapp): add pairing owner notification
by zote · 2026-02-01
72.7%
#9515: fix(web): retry WhatsApp 515 restart up to 3 times with delay
by Sebachowa · 2026-02-05
71.3%
#13285: feat(pairing): add pairingAnonymous option to hide platform branding
by thebtf · 2026-02-10
70.7%
#11868: control-ui: pairing required guided flow (Clairephone V2 Candidate A)
by shojikumaru · 2026-02-08
70.7%
#3071: fix: WhatsApp 515 error retry not triggering
by rabsef-bicrym · 2026-01-28
70.6%
#17425: fix(gateway): auto-approve scope/role upgrades for already-paired d...
by sauerdaniel · 2026-02-15
69.3%