---
name: whatsapp-init
description: Initialize, test, and self-heal the WhatsApp connection. Trigger when the user says "set up WhatsApp", "connect WhatsApp", "test the WhatsApp connection", "WhatsApp isn't working", "no QR code", "pair WhatsApp", or right after installing the extension. Calling whatsapp_status here lazily boots the on-demand MCP server + the always-on bridge; the skill then drives pairing and, if a previous install left things corrupted (crash-loop, stale session, orphan processes, QR never appears), runs an escalating heal ladder. Requires the WhatsApp connector tools (whatsapp_*).
---

# WhatsApp init (test connection · pair · self-heal)

This skill is **policy**; the extension is **plumbing**. It owns the order of
operations to get from "just installed / something's broken" to "linked and
ready". The first tool call boots everything: the MCP server is on-demand, and
importing it runs `bootstrap()`, which installs + loads the always-on bridge.
So **calling `whatsapp_status` IS the connection test** — it lazily initializes
the whole stack, then tells you what state you landed in.

Always prefer the MCP tools (`whatsapp_status`, `pair_whatsapp`,
`unpair_whatsapp`, `restart_bridge`). Drop to the shell heal ladder ONLY when the
tools can't reach a healthy state — and never delete user data without the
backup step.

## Step 0 — boot + classify

Call **`whatsapp_status`**. It returns:

```
store_present · service_loaded · bridge_reachable · connected · logged_in · needs_pairing · advice
```

Branch on it:

| State | Meaning | Go to |
|---|---|---|
| `logged_in: true` | Already linked. | **Step 3** (verify) |
| `bridge_reachable: true` & `needs_pairing: true` | Bridge up, no device. | **Step 1** (pair) |
| `service_loaded: true` & `bridge_reachable: false` | Wedged bridge. | **Step 2** (restart) |
| `service_loaded: false` | Still starting / not installed. | wait ~5s, re-run Step 0 once; if still false → **Step 4** (heal) |

If two Step-0 calls in a row both come back `service_loaded: false`, the install
is incomplete or corrupted — go to **Step 4**.

## Step 1 — pair

Call **`pair_whatsapp`**. It returns a QR image (and the bridge also auto-opens a
pairing page in the browser). Tell the user:

> Open WhatsApp → **Settings → Linked Devices → Link a Device**, then scan.

Then poll **`whatsapp_status`** every few seconds until `logged_in: true`
(give it ~60s). If `pair_whatsapp` says *"No QR code is available yet"*, the
bridge is still arming — wait 5s and call it again (up to 3 tries). If still no
QR after that → **Step 4**.

## Step 2 — restart a wedged bridge

Call **`restart_bridge`**, then **`whatsapp_status`** again:
- reachable + `needs_pairing` → **Step 1**.
- reachable + `logged_in` → **Step 3**.
- still unreachable after restart → **Step 4**.

## Step 3 — verify

Confirm with a cheap real call — `list_chats` with a small limit. If it returns,
report **linked and working** and stop. If it errors despite `logged_in: true`,
treat as wedged → **Step 2**.

## Step 4 — heal a corrupted previous install

Reach here only when the tools above can't get to a healthy state. These are the
exact failure modes a bad prior install leaves behind:

- **No QR ever appears** and the bridge log shows a fast repeating
  `401 ... logged out from another device` / `re-arming pairing` loop → a **stale
  device row** survives logout, so the bridge resumes a dead session instead of
  pairing.
- **Many `wa-mcp` processes** (should be exactly one bridge + one live MCP) →
  orphaned MCP servers from past sessions never reaped.
- **`restart_bridge` doesn't stick** → duplicate bridges evicting each other.

Resolve the paths first (macOS shown; on Linux use
`${XDG_DATA_HOME:-$HOME/.local/share}/whatsapp-mcp` and a `systemd --user` unit):

```bash
LABEL=com.whatsapp-mcp.bridge
APP="$HOME/Library/Application Support/whatsapp-mcp"
PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
```

### 4a. Diagnose (read-only first)

```bash
pgrep -fl "whatsapp-mcp/bin/wa" ; echo "----"
tail -20 "$APP/bridge.log"
```

Confirm the symptoms (orphan count > 2, or the 401 loop) before changing
anything.

### 4b. Reap orphans + stop the loop

```bash
launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null   # stop KeepAlive relaunches
pkill -9 -f "whatsapp-mcp/bin/wa-mcp"
pkill -9 -f "whatsapp-mcp/bin/wa-bridge"
```

### 4c. Clear the dead session — BACK UP FIRST, never touch messages.db

`whatsapp.db` holds the device/session; `messages.db` holds history. Only the
former is cleared, and only after a backup:

```bash
[ -f "$APP/store/whatsapp.db" ] && cp "$APP/store/whatsapp.db" "$APP/store/whatsapp.db.bak-$(date +%s)"
rm -f "$APP/store/whatsapp.db" "$APP/store/.anchor-missing" \
      "$APP/store/.qr-opened" "$APP/store/qr.txt" "$APP/store/qr.png"
```

### 4d. Bring it back up clean

```bash
launchctl bootstrap "gui/$(id -u)" "$PLIST"
launchctl kickstart -k "gui/$(id -u)/$LABEL"
```

With the session cleared, the bridge starts with no device → it generates a
fresh QR and opens the pairing page. Return to **Step 1** and confirm
`logged_in: true`.

### When healing isn't enough → reinstall

If Step 4 still can't produce a QR (e.g. the binaries themselves are broken or
the launchd job won't load), the install is beyond self-heal. Tell the user to
**remove and reinstall the extension from the Claude Desktop app** — that lays
down fresh binaries and a clean service.

## Guardrails

- **Never delete `messages.db`** — it is chat history, not session state.
- **Always back up `whatsapp.db`** before clearing it (Step 4c).
- Don't loop forever: each escalation runs once; if Step 4 fails, recommend
  reinstall rather than retrying blindly.
- Don't touch Claude's plugin copies under `local-agent-mode-sessions/.../rpm/` —
  the Desktop app manages those.
