An Agent Skill for reading and writing WhatsApp from your terminal — plus wa, the thin, testable bash facade it's built on. The skill format is the open standard; Claude Code is what it's been exercised against.
It wraps whatsapp-cli (a whatsmeow-based Go CLI that links as a WhatsApp companion device). The point of the facade is that your workflows call wa, not the binary — so when the transport changes, one file changes.
wa doctor # which binary, which store, how stale, any strays
wa sync # drain new messages into the local DB
wa search "quarterly report" # full-text over local history
wa chat 254712345678@s.whatsapp.net | jq '.[-20:]'Most of this exists because unattended use surfaces failures that interactive use hides.
synccan report success while doing nothing. When the linked-device session dies, the underlying CLI has returned{"success":true,"messages_count":0}. A store of mine went 31 days stale without a single error.wa doctorreports staleness in days, andweekly-sync.shtreats staleness — not exit code — as the health signal.- Decoy stores are the main way to lose data. The binary defaults
--storeto a CWD-relative./storeand creates it unconditionally, so running it from the wrong directory silently makes a second, empty store. You then sync into the decoy while reading the real one.waalways passes--storeexplicitly, anddoctorhunts for strays — including~/store, the one the docs warn about. - Scheduled jobs need pinning.
launchd/crongive you a near-emptyPATH.waauto-discovers the binary from local-only locations, and the plist template pins every path so nothing is resolved at runtime.
# 1. the underlying CLI
go install github.com/vicentereig/whatsapp-cli@latest # lands in ~/go/bin
# 2. this skill
git clone https://github.com/mikrub/whatsapp-agent-skill
cd whatsapp-agent-skill
ln -s "$PWD" ~/.claude/skills/whatsapp # auto-discovered by Claude Code
# 3. pair (scan the QR with WhatsApp → Settings → Linked Devices)
scripts/wa auth
scripts/wa sync 60
scripts/wa doctorwa auth --full-history requests the full archive at pair time rather than the default recent window, and wa history extend backfills older messages on demand. Both rely on features not yet in an upstream release — they exist in a fork and are being submitted upstream, so install upstream unless you need them. wa doctor reports which build you have. Note that --full-history only takes effect while pairing.
| Command | Purpose |
|---|---|
wa auth / wa reauth |
Pair, or force a fresh QR (preserves message history) |
wa doctor |
Health check: binary, store, freshness, stray stores |
wa sync [SECONDS] |
Connect, drain offline messages, exit |
wa chats [LIMIT] |
List chats |
wa chat <JID> [LIMIT] |
Messages in one chat |
wa search "<query>" |
Full-text search |
wa contacts "<query>" |
Find a contact's JID |
wa send <JID> "<msg>" |
Send text — requires human approval, see below |
wa send-image <JID> <PATH> ["caption"] |
Send an image |
wa history extend … |
Backfill older messages on demand |
Config via env: WA_CLI_BIN, WA_STORE, WA_SYNC_TIMEOUT, WA_SCAN_ROOT, WA_DRY_RUN=1 (print the resolved command instead of running it).
The skill instructs the agent never to send a message without the human confirming the exact text first — including when asked to "reply to X" — and to send one message per turn. Preview any send with WA_DRY_RUN=1 before approving.
Read SKILL.md before automating anything. In short:
store/whatsapp.dbholds session keys. Anyone with that file can impersonate your WhatsApp account.store/messages.dbholds your plaintext message history. Both are gitignored; keep them0600in a0700directory.- Don't put the store in a cloud-synced folder unless you accept the tradeoff: it replicates to every linked device, and
reauthrevokes the session while prior revisions of the key database remain in version history. - Don't run a scheduled job out of a synced folder. Deploy to
~/.local/bin— seeexamples/.
bats tests/wa.bats # 39 tests; the live-session ones need WA_LIVE=1Most tests assert the resolved command via WA_DRY_RUN=1; a stub binary on PATH covers signal handling and exit-code propagation.
Used daily against a ~100k-message store. The macOS specifics (launchd, osascript notifications, BSD date/stat) are what's actually exercised — Linux would need small adjustments in weekly-sync.sh and doctor.
Built on whatsapp-cli by @vicentereig, which does the real work of speaking WhatsApp's multi-device protocol via whatsmeow. This is an independent wrapper, not affiliated with or endorsed by either project.
Largely written through agentic development; commits carry Co-Authored-By trailers. Reviewed and run against a real ~100k-message store before publishing.
MIT — see LICENSE.