whazaa 0.6.7 → 0.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,142 +1,200 @@
1
1
  # Whazaa
2
2
 
3
- WhatsApp MCP server for Claude Code bidirectional self-chat messaging with terminal integration.
4
-
5
- You message yourself on WhatsApp, Claude receives it. Claude responds, you see it on WhatsApp. Your phone becomes a parallel terminal.
3
+ WhatsApp bridge for Claude Code. You message yourself on WhatsApp, Claude receives it. Claude responds, you see it on WhatsApp. Your phone becomes a parallel terminal.
6
4
 
7
5
  ---
8
6
 
9
- ## Features
7
+ ## How it works
8
+
9
+ Whazaa has two components:
10
+
11
+ **Watcher daemon** — a long-running process that owns the WhatsApp connection (via the [Baileys](https://github.com/WhiskeySockets/Baileys) library). It delivers incoming messages to iTerm2 by typing them into your Claude session via AppleScript. It also serves a Unix Domain Socket so MCP server instances can send and receive messages without holding their own connection.
12
+
13
+ **MCP server** — a thin IPC proxy started by Claude Code. It has no direct WhatsApp connection. Every tool call is forwarded to the watcher over the socket and the response returned to Claude.
14
+
15
+ ```
16
+ Your phone
17
+ |
18
+ | WhatsApp (Baileys WebSocket)
19
+ |
20
+ Watcher daemon ←── launchd, auto-restarts
21
+ |
22
+ |── AppleScript ──> iTerm2 ──> Claude Code (types message into terminal)
23
+ |
24
+ |── Unix Domain Socket (/tmp/whazaa-watcher.sock)
25
+ |
26
+ └──> MCP Server (started by Claude Code)
27
+ |
28
+ └──> whatsapp_send / receive / status / wait / login
29
+ ```
10
30
 
11
- - **Bidirectional messaging** send from Claude, receive from your phone
12
- - **Terminal watcher** — incoming messages are typed directly into your Claude Code session via iTerm2
13
- - **Zero configuration** — auto-detects your phone number after first scan
14
- - **First-run QR pairing** — scan once, connects automatically thereafter
15
- - **Markdown support** — `**bold**`, `*italic*`, `` `code` `` converted to WhatsApp format
16
- - **Deduplication** — outgoing messages never echo back as incoming
17
- - **Exponential backoff** — reconnects automatically (1s to 60s)
18
- - **MCP-safe** — all output except JSON-RPC goes to stderr
31
+ The separation means you can have multiple Claude Code sessions open simultaneously. Each MCP server instance registers its `TERM_SESSION_ID` with the watcher, and whichever session most recently sent a message becomes the active recipient for incoming messages.
19
32
 
20
33
  ---
21
34
 
22
- ## Quick Start
35
+ ## Quick start
23
36
 
24
- One command does everything — configures Claude Code, opens a QR code in your browser, and pairs with WhatsApp:
37
+ One command does everything:
25
38
 
26
39
  ```bash
27
40
  npx -y whazaa setup
28
41
  ```
29
42
 
30
- That's it. Restart Claude Code and you're connected.
43
+ This will:
44
+ 1. Add Whazaa to `~/.claude/.mcp.json`
45
+ 2. Open a QR code in your browser
46
+ 3. You scan it with WhatsApp: Settings > Linked Devices > Link a Device
47
+ 4. Credentials are saved to `~/.whazaa/auth/`
48
+
49
+ Restart Claude Code. Whazaa connects automatically from now on.
31
50
 
32
51
  ---
33
52
 
34
- ## What `setup` does
53
+ ## MCP tools
35
54
 
36
- 1. Creates (or updates) `~/.claude/.mcp.json` with the Whazaa MCP entry
37
- 2. Opens a QR code in your browser
38
- 3. You scan it with WhatsApp (Settings → Linked Devices → Link a Device)
39
- 4. Pairing completes, credentials are saved to `~/.whazaa/auth/`
40
- 5. Restart Claude Code — Whazaa connects automatically from now on
55
+ Once configured, Claude Code has five tools available:
41
56
 
42
- ---
57
+ | Tool | Description |
58
+ |------|-------------|
59
+ | `whatsapp_status` | Check connection state and phone number |
60
+ | `whatsapp_send` | Send a message to your WhatsApp self-chat |
61
+ | `whatsapp_receive` | Drain all queued incoming messages |
62
+ | `whatsapp_wait` | Block until a message arrives (up to timeout) |
63
+ | `whatsapp_login` | Trigger a new QR pairing flow |
43
64
 
44
- ## Usage
65
+ ### whatsapp_send
45
66
 
46
- After setup, restart Claude Code. Whazaa connects automatically.
67
+ Sends a message to your self-chat. Supports Markdown formatting converted to WhatsApp format:
47
68
 
48
- Messages go through your WhatsApp self-chat the chat with yourself (sometimes called "Saved Messages" or "Message Yourself").
69
+ - `**bold**` becomes `*bold*`
70
+ - `*italic*` becomes `_italic_`
71
+ - `` `code` `` becomes ` ```code``` `
49
72
 
50
- **Tell Claude to use WhatsApp:**
73
+ ### whatsapp_wait
51
74
 
52
- Just say something like:
53
- - "Message me on WhatsApp when you're done"
54
- - "Continue on WhatsApp"
55
- - "Listen on WhatsApp" — Claude will start the watcher and receive your messages as terminal input
75
+ Efficient alternative to polling. Blocks the tool call until a message arrives or the timeout expires (default 120 seconds, max 300). Use this in the background while working:
56
76
 
57
- **Example:**
58
- 1. In Claude Code: "Refactor the auth module and message me on WhatsApp when done"
59
- 2. Walk away from your desk
60
- 3. Claude finishes and WhatsApps you: "Done. What's next?"
61
- 4. You reply from your phone: "Now run the tests"
62
- 5. Claude reads your reply and runs the tests
77
+ ```
78
+ "Message me on WhatsApp when you're done. I'll wait."
79
+ ```
63
80
 
64
81
  ---
65
82
 
66
- ## Terminal Watcher (macOS + iTerm2)
83
+ ## CLI commands
67
84
 
68
- > **Platform:** The watcher currently requires **macOS** with **iTerm2**. It uses AppleScript (`osascript`) to type into a specific iTerm2 session. Terminal.app and non-macOS platforms are not yet supported — contributions welcome.
85
+ ```bash
86
+ # First-time setup: configure MCP and pair with WhatsApp
87
+ npx -y whazaa setup
69
88
 
70
- The `watch` command bridges WhatsApp messages directly into a Claude Code terminal session. Incoming messages are typed into the terminal via AppleScript automation Claude sees them as regular user input.
89
+ # Start the watcher daemon (manages iTerm2 delivery and IPC)
90
+ npx whazaa watch [session-id]
71
91
 
72
- ### How it works
92
+ # Remove MCP config and stored credentials
93
+ npx -y whazaa uninstall
94
+ ```
73
95
 
74
- 1. Whazaa MCP server writes incoming messages to a log file
75
- 2. The watcher polls the log for new lines (every 2 seconds)
76
- 3. The watcher resolves the target iTerm2 session (see below)
77
- 4. New messages are typed into that session via `osascript`
78
- 5. Claude Code processes them as regular user input
96
+ ---
79
97
 
80
- ### Session resolution
98
+ ## Watcher daemon
81
99
 
82
- The watcher uses a fallback chain to find a usable iTerm2 session:
100
+ The watcher is the core of Whazaa. It runs as a macOS launchd agent so it starts automatically and restarts if it crashes.
83
101
 
84
- 1. **Try the specified session ID** — uses the session ID passed on the command line
85
- 2. **Search by tab name** — if that session is gone, scans all iTerm2 sessions for one whose tab name contains "claude"
86
- 3. **Retry after 2 seconds** — if still not found, waits and tries again (AppleScript may need a moment to connect when the watcher starts fresh from launchd)
87
- 4. **Create a new tab** — if no session is found after the retry, opens a new iTerm2 tab, runs `claude`, waits for it to boot, then uses that session
102
+ ### Starting manually
88
103
 
89
- This means the watcher can recover automatically if you close and reopen your Claude Code tab, or if it was started before iTerm2 was fully ready.
104
+ ```bash
105
+ npx whazaa watch
106
+ ```
90
107
 
91
- ### Managing the watcher
108
+ Pass an iTerm2 session ID to target a specific terminal:
92
109
 
93
- Claude Code manages the watcher automatically — when you say "listen on WhatsApp" or use `/whatsapp on`, it starts the watcher as a macOS launchd agent targeting the current iTerm2 session. The control script is at `scripts/watcher-ctl.sh`:
110
+ ```bash
111
+ npx whazaa watch $ITERM_SESSION_ID
112
+ ```
113
+
114
+ ### launchd setup (auto-start)
115
+
116
+ Claude Code can manage the watcher automatically. Use the control script:
94
117
 
95
118
  ```bash
96
119
  scripts/watcher-ctl.sh start # Install and start as launchd agent
97
- scripts/watcher-ctl.sh stop # Stop and unload the agent
98
- scripts/watcher-ctl.sh status # Show whether the agent is running
120
+ scripts/watcher-ctl.sh stop # Stop and unload
121
+ scripts/watcher-ctl.sh status # Show running state
99
122
  ```
100
123
 
101
- The launchd agent is configured with `KeepAlive: true`, so macOS automatically restarts the watcher if it crashes. It also uses `ProcessType: Interactive` and `LimitLoadToSessionType: Aqua`, which gives the agent access to the macOS GUI session. This is required because AppleScript needs a GUI context to control iTerm2 — without it, `osascript` calls from a launchd background agent would fail silently or be refused by the system.
124
+ The agent uses `KeepAlive: true` and `ProcessType: Interactive`. The Interactive process type and `LimitLoadToSessionType: Aqua` are required so the watcher can access the macOS GUI session and call AppleScript to control iTerm2.
102
125
 
103
- ### Configuration
126
+ ### Session resolution
104
127
 
105
- | Variable | Default | Description |
106
- |----------|---------|-------------|
107
- | `WHAZAA_LOG` | `/tmp/whazaa-incoming.log` | Path to the incoming message log file |
108
- | `WHAZAA_POLL_INTERVAL` | `2` | Seconds between file checks |
128
+ When a message arrives, the watcher delivers it to Claude using this fallback chain:
129
+
130
+ 1. Try the cached session ID but only if Claude is actually running there (not at a shell prompt)
131
+ 2. Search all iTerm2 sessions for one whose tab name contains "claude"
132
+ 3. Create a new iTerm2 tab, `cd $HOME`, run `claude`, wait for it to boot
133
+
134
+ The watcher recovers automatically if you close and reopen your Claude tab.
135
+
136
+ > **Platform requirement:** The watcher requires macOS with [iTerm2](https://iterm2.com/). It uses AppleScript (`osascript`) to type into terminal sessions. Terminal.app and non-macOS platforms are not yet supported.
109
137
 
110
138
  ---
111
139
 
112
- ## Uninstall
140
+ ## WhatsApp commands
113
141
 
114
- ```bash
115
- npx -y whazaa uninstall
142
+ Certain messages sent from your phone are intercepted by the watcher and handled as commands rather than forwarded to Claude.
143
+
144
+ | Command | Description |
145
+ |---------|-------------|
146
+ | `/relocate <path>` or `/r <path>` | Open a new iTerm2 tab in the given directory and start Claude there |
147
+ | `/sessions` or `/s` | List open Claude sessions and offer to switch between them |
148
+
149
+ ### /relocate
150
+
151
+ ```
152
+ /relocate ~/projects/myapp
153
+ /r ~/projects/myapp
116
154
  ```
117
155
 
118
- This removes Whazaa from `~/.claude/.mcp.json` and deletes stored credentials from `~/.whazaa/`. Restart Claude Code to apply.
156
+ If a Claude session is already open in that directory, Whazaa focuses it instead of creating a new tab. Tilde expansion is supported.
157
+
158
+ After relocating, subsequent messages are delivered to the new session.
159
+
160
+ ### /sessions
161
+
162
+ Reply `/s` to get a numbered list of open Claude sessions with their working directories. Reply with a number to switch the active session. Reply `0` or `cancel` to abort.
119
163
 
120
164
  ---
121
165
 
122
- ## Manual Configuration
166
+ ## Multiple sessions
123
167
 
124
- If you prefer to configure manually, add Whazaa to `~/.claude/.mcp.json` (or your project's `.mcp.json`):
168
+ Whazaa supports multiple simultaneous Claude Code windows. Each MCP server instance registers its `TERM_SESSION_ID` when it starts. Whichever session most recently called `whatsapp_send` becomes the active recipient for incoming messages.
125
169
 
126
- ### Using npx (always latest version)
170
+ The watcher maintains a separate incoming message queue for each registered session. If no session has sent a message yet, the first registered session is used.
171
+
172
+ ---
173
+
174
+ ## Configuration
175
+
176
+ | Variable | Default | Description |
177
+ |----------|---------|-------------|
178
+ | `WHAZAA_AUTH_DIR` | `~/.whazaa/auth/` | Directory for WhatsApp session credentials |
179
+
180
+ ---
181
+
182
+ ## Manual MCP configuration
183
+
184
+ If you prefer to configure manually, add to `~/.claude/.mcp.json`:
127
185
 
128
186
  ```json
129
187
  {
130
188
  "mcpServers": {
131
189
  "whazaa": {
132
190
  "command": "npx",
133
- "args": ["whazaa"]
191
+ "args": ["-y", "whazaa"]
134
192
  }
135
193
  }
136
194
  }
137
195
  ```
138
196
 
139
- ### Using bunx
197
+ Using bunx:
140
198
 
141
199
  ```json
142
200
  {
@@ -149,7 +207,7 @@ If you prefer to configure manually, add Whazaa to `~/.claude/.mcp.json` (or you
149
207
  }
150
208
  ```
151
209
 
152
- ### Using a local build
210
+ Using a local build:
153
211
 
154
212
  ```json
155
213
  {
@@ -162,103 +220,59 @@ If you prefer to configure manually, add Whazaa to `~/.claude/.mcp.json` (or you
162
220
  }
163
221
  ```
164
222
 
165
- After updating the MCP config, restart Claude Code. On first run, Whazaa prints a QR code to the Claude Code logs (check Settings → Developer → MCP Logs, or run it manually from a terminal first to complete pairing).
166
-
167
- ---
168
-
169
- ## MCP Tools
170
-
171
- | Tool | Description |
172
- |------|-------------|
173
- | `whatsapp_status` | Report connection state and phone number |
174
- | `whatsapp_send` | Send a message to your own WhatsApp self-chat |
175
- | `whatsapp_receive` | Drain queued incoming messages from your phone |
176
- | `whatsapp_wait` | Block until a message arrives (up to timeout) |
177
- | `whatsapp_login` | Trigger a new QR pairing flow |
178
-
179
- ## CLI Commands
180
-
181
- | Command | Description |
182
- |---------|-------------|
183
- | `whazaa setup` | Interactive setup — configures MCP, pairs with WhatsApp |
184
- | `whazaa watch <session-id>` | Start terminal watcher for iTerm2 session |
185
- | `whazaa uninstall` | Remove MCP config and stored credentials |
186
-
187
- ---
188
-
189
- ## How It Works
190
-
191
- Whazaa uses the [Baileys](https://github.com/WhiskeySockets/Baileys) library to maintain a persistent WebSocket connection to WhatsApp's servers using the same multi-device protocol as WhatsApp Web. It exposes MCP tools over stdin/stdout and routes all Baileys output to stderr to keep the JSON-RPC stream clean.
192
-
193
- **Stale instance cleanup:**
194
- When a new MCP server starts, it automatically finds and kills any existing Whazaa MCP processes (excluding watch processes and itself). This prevents multiple instances from competing for the same WhatsApp auth credentials, which would otherwise cause frequent disconnects as each instance races to own the session.
195
-
196
- **Message flow (incoming):**
197
- 1. You type a message on your phone in the self-chat
198
- 2. Baileys receives it via WebSocket
199
- 3. Whazaa queues it in memory and writes it to the log file
200
- 4. The `watch` process detects the new line and types it into your terminal
201
- 5. Claude Code processes it as user input
202
-
203
- **Message flow (outgoing):**
204
- 1. Claude calls `whatsapp_send` via MCP
205
- 2. Whazaa converts Markdown to WhatsApp formatting
206
- 3. Baileys sends it via WebSocket
207
- 4. The message appears on your phone
208
-
209
- ---
210
-
211
- ## Environment Variables
212
-
213
- | Variable | Default | Description |
214
- |----------|---------|-------------|
215
- | `WHAZAA_AUTH_DIR` | `~/.whazaa/auth/` | Directory for WhatsApp session credentials |
216
- | `WHAZAA_LOG` | `/tmp/whazaa-incoming.log` | Incoming message log file (used by `watch`) |
217
- | `WHAZAA_POLL_INTERVAL` | `2` | Watcher poll interval in seconds |
218
-
219
223
  ---
220
224
 
221
225
  ## Troubleshooting
222
226
 
223
227
  **"Logged out (401)" error**
224
228
 
225
- Your session was invalidated (e.g. you unlinked the device in WhatsApp). Run `npx -y whazaa setup` again to re-pair.
229
+ Your session was invalidated. Run `npx -y whazaa setup` to re-pair.
230
+
231
+ **Tools return "Watcher not running"**
226
232
 
227
- **Messages not received**
233
+ The watcher daemon is not running. Start it with `npx whazaa watch` or use `scripts/watcher-ctl.sh start` to install it as a launchd agent.
228
234
 
229
- Call `whatsapp_receive` to drain the queue. Only messages sent to your own number (the self-chat / "Saved Messages" chat) are captured. If using the watcher, check that it's running: `ps aux | grep "whazaa.*watch"`.
235
+ **Messages not appearing in Claude**
236
+
237
+ Check that the watcher is running: `ps aux | grep "whazaa.*watch"`. Verify the session ID matches your Claude tab: `echo $ITERM_SESSION_ID`.
230
238
 
231
239
  **"iTerm2 wants to control..." security prompt**
232
240
 
233
- On first use, macOS will show a security dialog asking whether to allow the watcher (or `osascript`) to control iTerm2. Click "OK" to allow it. If you accidentally clicked "Don't Allow", go to System Settings Privacy & Security Automation and enable iTerm2 for the relevant app. Without this permission, the watcher cannot type messages into your terminal.
241
+ Click OK. If you clicked "Don't Allow", go to System Settings > Privacy & Security > Automation and enable iTerm2 for the relevant app.
234
242
 
235
- **Watcher not typing into terminal**
243
+ **MCP server disconnects frequently**
236
244
 
237
- Verify the session ID matches your Claude Code tab: `echo $ITERM_SESSION_ID`. The watcher requires iTerm2 on macOS.
245
+ This happens when multiple Whazaa MCP processes compete for the same WhatsApp session. Whazaa automatically kills stale instances on startup. If the problem persists, run `pkill -f "whazaa"` and let Claude Code restart the MCP server.
238
246
 
239
247
  **Connection keeps dropping**
240
248
 
241
- Whazaa uses exponential backoff to reconnect automatically. Check your network connection. If the problem persists, use `whatsapp_login` to re-establish the session.
249
+ Whazaa reconnects automatically with exponential backoff (1s to 60s). Check your network. If the issue persists, call `whatsapp_login` to re-establish the session.
250
+
251
+ ---
242
252
 
243
- **Multiple WhatsApp accounts**
253
+ ## Security
244
254
 
245
- Set `WHAZAA_AUTH_DIR` to a different directory for each account and run separate instances.
255
+ - Session credentials are stored locally in `~/.whazaa/auth/`. Treat them like passwords — they grant full access to your WhatsApp Web session.
256
+ - Whazaa only reads and sends messages in your self-chat. It cannot access other conversations.
257
+ - No data is sent to any third-party service. All communication is directly with WhatsApp's servers via Baileys.
246
258
 
247
259
  ---
248
260
 
249
261
  ## Requirements
250
262
 
251
263
  - Node.js >= 18
252
- - WhatsApp account with multi-device support
253
- - **For the `watch` command:** macOS with [iTerm2](https://iterm2.com/) (uses AppleScript to type into terminal sessions)
264
+ - WhatsApp account (any multi-device support is standard)
265
+ - macOS with [iTerm2](https://iterm2.com/) for the `watch` command and iTerm2 delivery
254
266
 
255
267
  ---
256
268
 
257
- ## Security Notes
269
+ ## Uninstall
270
+
271
+ ```bash
272
+ npx -y whazaa uninstall
273
+ ```
258
274
 
259
- - Session credentials are stored locally in `~/.whazaa/auth/`. Treat them like passwords.
260
- - Whazaa only reads and sends messages in your self-chat. It does not have access to other conversations.
261
- - No data is sent to any third-party service. The connection is directly to WhatsApp's servers via Baileys.
275
+ Removes Whazaa from `~/.claude/.mcp.json` and deletes credentials from `~/.whazaa/`. Restart Claude Code to apply.
262
276
 
263
277
  ---
264
278
 
package/dist/index.d.ts CHANGED
@@ -2,20 +2,25 @@
2
2
  /**
3
3
  * index.ts — Whazaa MCP server entry point
4
4
  *
5
- * Exposes four tools over the Model Context Protocol (stdio transport):
5
+ * Exposes five tools over the Model Context Protocol (stdio transport):
6
6
  *
7
7
  * whatsapp_status — Report connection state and phone number
8
8
  * whatsapp_send — Send a message to your own WhatsApp number
9
9
  * whatsapp_receive — Drain queued incoming messages from your phone
10
+ * whatsapp_wait — Long-poll for the next incoming message
10
11
  * whatsapp_login — Trigger a new QR pairing flow
11
12
  *
13
+ * Architecture: The MCP server is a thin IPC proxy. All WhatsApp operations
14
+ * are forwarded to the watcher daemon (watch.ts) over a Unix Domain Socket
15
+ * at /tmp/whazaa-watcher.sock. The watcher is the sole owner of the Baileys
16
+ * connection. If the watcher is not running, tools return a clear error.
17
+ *
12
18
  * CRITICAL: stdout is the MCP JSON-RPC transport.
13
19
  * - NEVER write non-JSON to stdout.
14
20
  * - All debug output, QR codes, and logs go to stderr.
15
21
  *
16
- * SETUP MODE: When invoked with the "setup" argument (e.g. `npx whazaa setup`),
17
- * the script runs an interactive setup wizard instead of starting the MCP server.
18
- * In setup mode stdout is the terminal — console.log is safe to use.
22
+ * SETUP MODE: When invoked with "setup" argument, runs an interactive setup
23
+ * wizard. In setup mode stdout is the terminal console.log is safe.
19
24
  */
20
25
  export {};
21
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;GAiBG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;GAsBG"}