Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Send and receive WhatsApp messages via the unofficial linked-device client pywhats (pip install pywhats) — pair with QR, send text/images, group chat, read receipts, presence/typing, and a long-running JSON event stream. Use when the user wants to script WhatsApp as a linked companion device (like WhatsApp Web), pair a device, send a WhatsApp from Python, or listen for inbound messages. Triggers: 'whatsapp', 'send whatsapp', 'pair whatsapp', 'pywhats', 'linked device', 'whatsapp web client'. NOT
.claude/skills/sanjay3290-whatsapp/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 84% | 0% |
| case-02 | ✗→✓ | ▲ Improved | -28% | 0% |
| case-03 | ✗→✓ | ▲ Improved | -43% | 0% |
| case-05 | ✗→✓ | ▲ Improved | -47% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 11% | 0% |
Drive a WhatsApp account as a linked companion device (like WhatsApp Web) from async Python via pywhats (pre-alpha, text/image only). This is an unofficial multi-device client — not the official WhatsApp Business / Cloud API.
CLI entrypoint: scripts/wa.py (auto-bootstraps a managed venv on first run).
wa.py pair shows an ASCII QR; scan it inWhatsApp → Linked Devices. Credentials persist to $PYWHATS_HOME/<session>.session (+ .signal.db).
15550001234 → 15550001234@s.whatsapp.net;groups use ...@g.us.
wa.py listen prints one JSON object per event.Event handlers run inline on the receive loop. Awaiting send_*, mark_read, get_group_info, download_media, etc. inside a handler deadlocks the connection. Always asyncio.create_task(...). The listen subcommand already does this for --read.
bashscripts/wa.py pair # one-time QR pair scripts/wa.py send-text 15550001234 "hello" # 1:1 text scripts/wa.py send-image 15550001234 photo.jpg --caption hi # 1:1 image scripts/wa.py group-info 120363000000000000@g.us # group metadata JSON scripts/wa.py group-send 120363000000000000@g.us "hi all" # group text scripts/wa.py mark-read 15550001234 MSGID [--sender JID] # blue ticks scripts/wa.py presence available # global presence scripts/wa.py typing 15550001234 composing [--media audio] # typing indicator scripts/wa.py listen --read --events message,receipt # JSONL event stream scripts/wa.py --session work send-text 15550001234 "hi" # named session
| Command | Behavior | |---------|----------| | pair | Fresh link via ASCII QR; idempotent if already paired | | send-text <to> <text> | Send 1:1 text; print message id | | send-image <to> <path> [--caption C] | Send image (jpg/png/webp, ≤16MB); print id | | group-info <gid> | Print group JSON (subject, owner, participants, …) | | group-send <gid> <text> | Resolve members then send group text; print id | | mark-read <chat> <ids...> | Blue-tick; --sender for groups | | presence <available\|unavailable> | Global presence | | typing <to> <composing\|paused> | Chat presence; optional --media audio | | listen | Long-running JSON lines; --read, --events, --subscribe JID (required for presence events) |
Global: --session NAME (default default, or env PYWHATS_SESSION) — goes before the subcommand: wa.py --session work pair.
$PYWHATS_HOME/ # default: ~/.pywhats
venv/ # managed Python + pywhats
default.session # --session default
default.session.signal.db
work.session # --session workOverride home with PYWHATS_HOME. Unpaired / logged-out sessions print a clear message to re-run wa.py --session <name> pair.
If pair reports the device was logged out right after scanning, that is WhatsApp device-churn reaping, not a failure of the skill — the dead session is deleted automatically; follow the recovery steps it prints (remove linked devices, wait 15–20 min, pair once).
references/api.md — every Client method, every event payload, JID construction, and the download_media note.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-04 | pass→pass | 16,163 | 5,043 | -69% | 1 | 1 | 0% | 2,772 | 2,015 | -27% | 0 | 0 | — |
case-01 | fail→pass | 4,733 | 6,220 | +31% | 1 | 1 | 0% | 730 | 1,341 | +84% | 0 | 0 | — |
case-02 | fail→pass | 10,145 | 1,441 | -86% | 1 | 1 | 0% | 1,895 | 1,355 | -28% | 0 | 0 | — |
case-03 | fail→pass | 16,921 | 3,617 | -79% | 1 | 1 | 0% | 3,095 | 1,758 | -43% | 0 | 0 | — |
case-05 | fail→pass | 15,393 | 2,239 | -85% | 1 | 1 | 0% | 2,808 | 1,499 | -47% | 0 | 0 | — |
case-06 | fail→pass | 7,410 | 2,376 | -68% | 1 | 1 | 0% | 1,429 | 1,591 | +11% | 0 | 0 | — |
case-07 | fail→pass | 12,161 | 2,244 | -82% | 1 | 1 | 0% | 2,167 | 1,515 | -30% | 0 | 0 | — |
case-08 | fail→pass | 8,019 | 2,423 | -70% | 1 | 1 | 0% | 1,510 | 1,650 | +9% | 0 | 0 | — |
case-18 | pass→pass | 7,199 | 1,720 | -76% | 1 | 1 | 0% | 1,223 | 1,366 | +12% | 0 | 0 | — |
case-09 | fail→pass | 6,323 | 2,043 | -68% | 1 | 1 | 0% | 1,083 | 1,376 | +27% | 0 | 0 | — |
case-10 | fail→pass | 7,060 | 1,735 | -75% | 1 | 1 | 0% | 1,128 | 1,436 | +27% | 0 | 0 | — |
case-11 | fail→pass | 13,218 | 2,073 | -84% | 1 | 1 | 0% | 2,329 | 1,407 | -40% | 0 | 0 | — |
case-12 | fail→pass | 10,277 | 1,502 | -85% | 1 | 1 | 0% | 1,889 | 1,357 | -28% | 0 | 0 | — |
case-13 | fail→pass | 20,528 | 2,563 | -88% | 1 | 1 | 0% | 3,945 | 1,542 | -61% | 0 | 0 | — |
case-14 | pass→pass | 11,871 | 1,950 | -84% | 1 | 1 | 0% | 2,132 | 1,449 | -32% | 0 | 0 | — |
case-15 | pass→pass | 6,239 | 1,342 | -78% | 1 | 1 | 0% | 1,104 | 1,340 | +21% | 0 | 0 | — |
case-16 | pass→pass | 2,573 | 1,638 | -36% | 1 | 1 | 0% | 425 | 1,419 | +234% | 0 | 0 | — |
case-17 | fail→pass | 13,566 | 2,952 | -78% | 1 | 1 | 0% | 2,145 | 1,629 | -24% | 0 | 0 | — |
case-19 | fail→pass | 8,748 | 1,953 | -78% | 1 | 1 | 0% | 1,648 | 1,383 | -16% | 0 | 0 | — |
case-20 | fail→pass | 15,797 | 1,656 | -90% | 1 | 1 | 0% | 2,979 | 1,343 | -55% | 0 | 0 | — |
case-21 | pass→pass | 8,783 | 8,708 | -1% | 1 | 1 | 0% | 1,836 | 2,761 | +50% | 0 | 0 | — |
case-22 | pass→pass | 11,299 | 7,727 | -32% | 1 | 1 | 0% | 2,432 | 2,783 | +14% | 0 | 0 | — |
case-23 | pass→pass | 10,649 | 8,084 | -24% | 1 | 1 | 0% | 2,081 | 2,620 | +26% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +65 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.