About whatsapp
whatsapp (pywhats) is an unofficial client for controlling a linked WhatsApp device through async Python and a CLI. It supports text and images, event listening, and multiple account sessions.
Key features
- 01Pair and resume sessions with QR codes
- 02Send one-to-one text and images
- 03Send group text and view group details
- 04Listen to a JSON event stream
- 05Manage presence, read status, and typing
Use cases
- 01Send text or images to individual chats from scripts
- 02Message groups and retrieve group details
- 03Listen for chat events and process incoming messages
- 04Switch between sessions for multiple WhatsApp accounts
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ sanjay3290/ ai-skills --skill whatsappAfter installing, type/whatsappin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
README.mdreferences/api.mdscripts/_bootstrap.shwa.pyDetails
From the project READMEWhatsApp (pywhats)
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).
Mental model
- Pairing = one-time QR scan.
wa.py pairshows an ASCII QR; scan it in WhatsApp → Linked Devices. Credentials persist to$PYWHATS_HOME/<session>.session(+.signal.db). - Resuming = silent. Later commands reconnect with the same session — no QR.
- JIDs address chats. Bare phone
15550001234→[email protected]; groups use[email protected]. - Events are how you receive.
wa.py listenprints one JSON object per event.
⚠️ Never bare-await Client calls inside a handler
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.
Commands
scripts/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 [email protected] # group metadata JSON
scripts/wa.py group-send [email protected] "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.
Sessions / multi-account
$PYWHATS_HOME/ # default: ~/.pywhats
venv/ # managed Python + pywhats
default.session # --session default
default.session.signal.db
work.session # --session work
Override 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).
Full reference
references/api.md — every Client method, every event
payload, JID construction, and the download_media note.