| name | wa |
| description | Read and send WhatsApp messages via SQLite DB access and a verified send script. Use when user says "check WhatsApp", "read WhatsApp", "messages from X", "send WhatsApp to X", "message X on WhatsApp", or any WhatsApp read/send task.
|
WhatsApp Skill
CRITICAL: Sending Rules
NEVER send without explicit confirmation. Wrong-number sends leak confidential info.
- Block unverified sends via a PreToolUse hook (see hooks/).
- NEVER construct phone numbers from memory.
- Discussion/brainstorming is NOT a send instruction. Only "send", "go", "send it" counts.
Only send flow:
- Run your verified send script (dry run: resolves JID, shows phone, exits without sending)
- Show the user the resolved phone number
- Wait for explicit "yes" / "send" / "go"
- Run with
--confirmed flag
Reading Messages
Step 1: Copy the DB
DB_SOURCE="<PATH_TO_WHATSAPP_CHATSTORE_SQLITE>"
cp "$DB_SOURCE" /tmp/wa-chat.sqlite
If the copy fails, the source is unavailable. Do not proceed; tell the user.
Step 2: Find a contact
sqlite3 /tmp/wa-chat.sqlite "
SELECT ZCONTACTJID, ZCONTACTIDENTIFIER, ZPARTNERNAME
FROM ZWACHATSESSION
WHERE ZPARTNERNAME LIKE '%Name%';
"
Step 3: Read DM messages
sqlite3 /tmp/wa-chat.sqlite "
SELECT ZFROMJID, ZTEXT, datetime(ZMESSAGEDATE + 978307200, 'unixepoch') as msg_time
FROM ZWAMESSAGE
WHERE ZFROMJID LIKE '%PHONE_OR_LID%'
ORDER BY ZMESSAGEDATE DESC
LIMIT 20;
"
Replace PHONE_OR_LID with phone digits or LID from step 2 (no +, no spaces).
Step 4: Read group messages
sqlite3 /tmp/wa-chat.sqlite "
SELECT ZMEMBERJID, ZTEXT, datetime(ZMESSAGEDATE + 978307200, 'unixepoch') as msg_time
FROM ZWAMESSAGE
WHERE ZCHATSESSION IN (
SELECT Z_PK FROM ZWACHATSESSION WHERE ZPARTNERNAME LIKE '%GroupName%'
)
ORDER BY ZMESSAGEDATE DESC
LIMIT 20;
"
Step 5: Read full conversation (both sides)
sqlite3 /tmp/wa-chat.sqlite "
SELECT
CASE WHEN ZFROMJID IS NULL THEN 'Me' ELSE ZFROMJID END as sender,
ZTEXT,
datetime(ZMESSAGEDATE + 978307200, 'unixepoch') as msg_time
FROM ZWAMESSAGE
WHERE ZCHATSESSION IN (
SELECT Z_PK FROM ZWACHATSESSION WHERE ZCONTACTJID LIKE '%PHONE_OR_LID%'
)
AND ZTEXT IS NOT NULL
ORDER BY ZMESSAGEDATE DESC
LIMIT 30;
"
Outgoing messages have ZFROMJID = NULL.
Common Tasks
"What did X say lately?"
- Copy DB
- Find contact JID
- Run full conversation query with LIMIT 20
- Show messages newest-first, formatted as
[time] sender: text
"Any new WhatsApp messages?"
- Copy DB
- Query all sessions ordered by last message time:
sqlite3 /tmp/wa-chat.sqlite "
SELECT ZPARTNERNAME, datetime(ZLASTMESSAGEDATE + 978307200, 'unixepoch') as last_msg
FROM ZWACHATSESSION
ORDER BY ZLASTMESSAGEDATE DESC
LIMIT 20;
"
"Send X a message saying Y"
- Draft the message, show user for review
- Run verified send script (dry run)
- Show resolved phone number
- Wait for explicit send confirmation
- Run with
--confirmed
Troubleshooting
DB copy fails: Source is unavailable (mount down, app not running). Tell user.
ZTEXT is NULL: Message may be media-only (image, video, audio, sticker).
Contact not found: Try partial name, try phone digits, try ZCONTACTIDENTIFIER column.
Timestamp offset: 978307200 is Apple Cocoa epoch (Jan 1 2001). This is correct for WhatsApp Desktop on macOS.