@wirecat/whatsapp-cli 0.1.0 → 0.2.0

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.
Files changed (102) hide show
  1. package/README.md +213 -94
  2. package/dist/adapter/adapter.d.ts +8 -4
  3. package/dist/adapter/adapter.d.ts.map +1 -1
  4. package/dist/adapter/adapter.js +313 -85
  5. package/dist/adapter/adapter.js.map +1 -1
  6. package/dist/adapter/channels.d.ts +43 -0
  7. package/dist/adapter/channels.d.ts.map +1 -0
  8. package/dist/adapter/channels.js +100 -0
  9. package/dist/adapter/channels.js.map +1 -0
  10. package/dist/adapter/checks.d.ts +2 -3
  11. package/dist/adapter/checks.d.ts.map +1 -1
  12. package/dist/adapter/checks.js +1 -2
  13. package/dist/adapter/checks.js.map +1 -1
  14. package/dist/adapter/errors.d.ts +0 -5
  15. package/dist/adapter/errors.d.ts.map +1 -1
  16. package/dist/adapter/errors.js +7 -9
  17. package/dist/adapter/errors.js.map +1 -1
  18. package/dist/adapter/groups.d.ts +5 -1
  19. package/dist/adapter/groups.d.ts.map +1 -1
  20. package/dist/adapter/groups.js +51 -9
  21. package/dist/adapter/groups.js.map +1 -1
  22. package/dist/adapter/map.d.ts +16 -2
  23. package/dist/adapter/map.d.ts.map +1 -1
  24. package/dist/adapter/map.js +56 -7
  25. package/dist/adapter/map.js.map +1 -1
  26. package/dist/adapter/pins.d.ts +11 -0
  27. package/dist/adapter/pins.d.ts.map +1 -0
  28. package/dist/adapter/pins.js +10 -0
  29. package/dist/adapter/pins.js.map +1 -0
  30. package/dist/adapter/polls.d.ts +1 -1
  31. package/dist/adapter/polls.d.ts.map +1 -1
  32. package/dist/adapter/polls.js +2 -2
  33. package/dist/adapter/polls.js.map +1 -1
  34. package/dist/adapter/privacy.d.ts +18 -0
  35. package/dist/adapter/privacy.d.ts.map +1 -0
  36. package/dist/adapter/privacy.js +94 -0
  37. package/dist/adapter/privacy.js.map +1 -0
  38. package/dist/adapter/settings.d.ts +21 -0
  39. package/dist/adapter/settings.d.ts.map +1 -0
  40. package/dist/adapter/settings.js +76 -0
  41. package/dist/adapter/settings.js.map +1 -0
  42. package/dist/bin/wa.js +0 -13
  43. package/dist/bin/wa.js.map +1 -1
  44. package/dist/commands/session.d.ts +18 -7
  45. package/dist/commands/session.d.ts.map +1 -1
  46. package/dist/commands/session.js +92 -93
  47. package/dist/commands/session.js.map +1 -1
  48. package/dist/commands/setup.d.ts.map +1 -1
  49. package/dist/commands/setup.js +77 -129
  50. package/dist/commands/setup.js.map +1 -1
  51. package/dist/commands/update.d.ts.map +1 -1
  52. package/dist/commands/update.js +3 -22
  53. package/dist/commands/update.js.map +1 -1
  54. package/dist/engine/channels.d.ts +100 -0
  55. package/dist/engine/channels.d.ts.map +1 -0
  56. package/dist/engine/channels.js +29 -0
  57. package/dist/engine/channels.js.map +1 -0
  58. package/dist/engine/contract.d.ts +475 -43
  59. package/dist/engine/contract.d.ts.map +1 -1
  60. package/dist/engine/contract.js +178 -11
  61. package/dist/engine/contract.js.map +1 -1
  62. package/dist/engine/go-engine.d.ts.map +1 -1
  63. package/dist/engine/go-engine.js +23 -34
  64. package/dist/engine/go-engine.js.map +1 -1
  65. package/dist/engine/groups.d.ts +26 -14
  66. package/dist/engine/groups.d.ts.map +1 -1
  67. package/dist/engine/groups.js +2 -0
  68. package/dist/engine/groups.js.map +1 -1
  69. package/dist/engine/privacy.d.ts +33 -0
  70. package/dist/engine/privacy.d.ts.map +1 -0
  71. package/dist/engine/privacy.js +23 -0
  72. package/dist/engine/privacy.js.map +1 -0
  73. package/dist/engine/settings.d.ts +45 -0
  74. package/dist/engine/settings.d.ts.map +1 -0
  75. package/dist/engine/settings.js +34 -0
  76. package/dist/engine/settings.js.map +1 -0
  77. package/dist/install/postinstall.d.ts.map +1 -1
  78. package/dist/install/postinstall.js +4 -3
  79. package/dist/install/postinstall.js.map +1 -1
  80. package/dist/messenger.d.ts +3 -4
  81. package/dist/messenger.d.ts.map +1 -1
  82. package/dist/messenger.js +29 -14
  83. package/dist/messenger.js.map +1 -1
  84. package/dist/program.d.ts +5 -1
  85. package/dist/program.d.ts.map +1 -1
  86. package/dist/program.js +10 -38
  87. package/dist/program.js.map +1 -1
  88. package/dist/reasons.d.ts.map +1 -1
  89. package/dist/reasons.js +8 -0
  90. package/dist/reasons.js.map +1 -1
  91. package/dist/update.d.ts +0 -1
  92. package/dist/update.d.ts.map +1 -1
  93. package/dist/update.js +0 -7
  94. package/dist/update.js.map +1 -1
  95. package/dist/version.d.ts +1 -1
  96. package/dist/version.js +1 -1
  97. package/package.json +10 -10
  98. package/skills/whatsapp-cli/SKILL.md +59 -24
  99. package/dist/commands/answer.d.ts +0 -7
  100. package/dist/commands/answer.d.ts.map +0 -1
  101. package/dist/commands/answer.js +0 -11
  102. package/dist/commands/answer.js.map +0 -1
package/README.md CHANGED
@@ -1,10 +1,28 @@
1
- # wa — WhatsApp CLI for AI agents
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/WireCatLabs/whatsapp-cli/main/docs/images/social-preview.png" alt="WhatsApp CLI for AI agents" width="100%">
3
+ </p>
2
4
 
3
- Your personal WhatsApp in the terminal, searchable on your computer, and ready for Claude Code, Codex, Cursor or any
4
- agent — within limits you set.
5
+ # wa — WhatsApp CLI for AI agents
5
6
 
6
- > **Early.** `wa` links, reads into its local store, sends text and files, edits, deletes for everyone, reacts and
7
- > runs groups. What comes next is on the [roadmap](docs/roadmap.md).
7
+ <p align="center">
8
+ Your personal WhatsApp in the terminal, searchable on your computer, and ready for Claude Code,
9
+ Codex, Cursor or any agent — within limits you set.
10
+ </p>
11
+
12
+ <p align="center">
13
+ <a href="https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/README.md">Docs</a> ·
14
+ <a href="https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/recipes.md">Examples</a> ·
15
+ <a href="https://wirecat.dev">WireCat</a>
16
+ </p>
17
+
18
+ <p align="center">
19
+ <a href="https://www.npmjs.com/package/@wirecat/whatsapp-cli"><img src="https://img.shields.io/npm/v/@wirecat/whatsapp-cli" alt="npm"></a>
20
+ <a href="https://github.com/WireCatLabs/whatsapp-cli/actions/workflows/main.yml"><img src="https://github.com/WireCatLabs/whatsapp-cli/actions/workflows/main.yml/badge.svg" alt="CI"></a>
21
+ <a href="https://nodejs.org/"><img src="https://img.shields.io/node/v/@wirecat/whatsapp-cli" alt="Node"></a>
22
+ <a href="https://bun.sh/"><img src="https://img.shields.io/badge/bun-tested-f9f1e1" alt="Bun"></a>
23
+ <a href="https://www.npmjs.com/package/@wirecat/whatsapp-cli"><img src="https://img.shields.io/npm/dm/@wirecat/whatsapp-cli" alt="npm downloads"></a>
24
+ <a href="https://github.com/WireCatLabs/whatsapp-cli/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-blue" alt="License: Apache 2.0"></a>
25
+ </p>
8
26
 
9
27
  An example conversation (invented people, illustrative output):
10
28
 
@@ -18,6 +36,15 @@ Agent: Draft to Alice Example: "Yes, 8 pm." Send it?
18
36
  You: Yes.
19
37
  ```
20
38
 
39
+ > ⚠️ **`wa` is an unofficial client of your real WhatsApp account.** WhatsApp's terms forbid unofficial clients, and
40
+ > WhatsApp may ban an account that uses one. It also bans accounts that send in bulk or write to people who do not
41
+ > know them. `wa` writes only when a command asks, sends at most 30 messages an hour by default, and holds every
42
+ > write when WhatsApp says to slow down or restricts the account. Do not send in bulk, and do not write to strangers.
43
+ > You use `wa` at your own risk. More: [limits](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/limits.md)
44
+
45
+ **Early.** `wa` is new, and some of what it does has not yet been checked against real WhatsApp. The
46
+ [backlog](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/dev/BACKLOG.md) lists the checks still to run.
47
+
21
48
  ## Quick start
22
49
 
23
50
  ```sh
@@ -34,7 +61,7 @@ chats and installs the agent skill.
34
61
  It needs **Node 22.16+ or 24+** on macOS, Linux or Windows. npm also installs the engine, the small program that
35
62
  speaks WhatsApp's protocol, as a separate package for your system.
36
63
 
37
- More: [installation guide](docs/installation.md) · [linking](docs/sessions.md)
64
+ More: [installation guide](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/installation.md) · [linking](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/sessions.md)
38
65
 
39
66
  ## What can you do?
40
67
 
@@ -59,6 +86,13 @@ wa personal review --new # what changed since the last review -
59
86
  wa personal tasks list state:open
60
87
  ```
61
88
 
89
+ **Run your groups.** *"Use wa CLI. Which questions in Hiking has nobody answered?"*
90
+
91
+ ```sh
92
+ wa personal review chat:Hiking --unanswered
93
+ wa personal chats events Hiking 'time>=7d' # who joined, left, was added or removed
94
+ ```
95
+
62
96
  **Answer, when you say so.**
63
97
 
64
98
  ```sh
@@ -69,37 +103,104 @@ wa personal messages delete "Book club" 3EB0A1B2C3D4E5F6A7B8 --for-everyone
69
103
  wa personal chats mark-read "Book club" # the other side sees it
70
104
  ```
71
105
 
72
- More: [recipes, with a schedule for each](docs/recipes.md) · [using wa](docs/usage.md)
106
+ More: [recipes, with a schedule for each](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/recipes.md) · [using wa](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/usage.md)
73
107
 
74
108
  ## Built for AI agents
75
109
 
110
+ Your agent. Your WhatsApp. Your rules.
111
+
76
112
  - **Agents with a terminal** (Claude Code, Codex, Gemini CLI) run `wa` commands themselves. The bundled
77
- [skill](skills/whatsapp-cli/SKILL.md) tells them how: `wa personal setup --agent …` or `wa skill install` puts it in
78
- place, and `wa skill show` prints it before linking. An agent links with `--qr-file` and shows you the picture; it
79
- never asks for your phone number or a code.
80
- - **Apps without a terminal** (Claude Desktop, Cursor and other MCP clients) connect to `wa personal mcp`.
113
+ [skill](https://github.com/WireCatLabs/whatsapp-cli/blob/main/skills/whatsapp-cli/SKILL.md) tells them how: `wa personal setup --agent …` or `wa skill install` puts it in
114
+ place, and `wa skill show` prints it before linking. An agent links by QR: it pastes the code into the chat as text for you
115
+ to scan, and never asks for your phone number or a code.
116
+ - **Apps without a terminal** (Claude Desktop, Cursor and other MCP clients) connect to `wa personal mcp`. It
117
+ comes with ready prompts: `/catch-up`, `/review`, `/reply`, `/find` and more.
81
118
 
82
119
  ```sh
83
120
  wa personal mcp setup claude-code # or: wa personal mcp setup codex
84
121
  wa personal mcp config # the entry for Claude Desktop, Cursor and others
85
122
  ```
86
123
 
87
- More: [the MCP server](docs/mcp.md) · [from the browser](docs/remote.md)
124
+ The profile can send by default, so `mcp setup` stops first. Check the profile's permissions, then run it again with
125
+ `--allow-writes`.
88
126
 
89
- ## How it differs from tg and max
127
+ More: [the MCP server](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/mcp.md) · [from the browser](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/remote.md)
90
128
 
91
- `wa` is part of the [WireCat](https://wirecat.dev) family, beside [tg](https://github.com/WireCatLabs/tg-cli) for
92
- Telegram and [max](https://github.com/WireCatLabs/max-cli) for MAX. All three share their commands, their store and
93
- their agent tools, so what you learn in one works in the others. WhatsApp is different in three ways:
129
+ ## Why wa?
94
130
 
95
- - **History comes from your phone.** WhatsApp's servers keep no history to ask for. Your phone sends your recent
96
- chats once, when `wa` links, and `wa serve` keeps receiving new ones. Older messages of one chat can be asked of the
97
- phone, 50 at a time, while WhatsApp is open on it (`wa personal messages sync`). Every read answers from the local
98
- store and never connects.
99
- - **One connection per device.** WhatsApp allows one. While `wa serve` runs, other commands for the same profile,
100
- a send included, run through its connection. On Windows they are refused until `serve` stops, for now.
101
- - **Unofficial.** WhatsApp's terms forbid unofficial clients, and WhatsApp may ban an account that uses one. `wa`
102
- never sends in bulk or to strangers, never sends "online" or "typing", and marks nothing read unless you ask.
131
+ - **Your own account, as a linked device.** `wa` links the way WhatsApp Web does. It sees your chats, groups and
132
+ contacts, and speaks as you, not as a business account or a bot.
133
+ - **Local-first search.** Everything received is kept on your computer. Every read and search answers from there and
134
+ never connects.
135
+ - **Made for agents.** One operation per call, the same JSON shape every time with `--json`, a fixed exit code for
136
+ each kind of failure, an MCP server and a skill.
137
+ - **Safe by default.** Reading marks nothing read and sends no "online" or "typing". A profile decides which actions
138
+ an agent may take, which chats it may send to, and how many messages an hour (30 by default). When a send's outcome
139
+ is unknown, `wa` says so and never repeats it by itself.
140
+
141
+ ## Your account
142
+
143
+ `wa` works in your name, as one more linked device of your WhatsApp account.
144
+
145
+ ```sh
146
+ wa personal chats list --limit 5
147
+ wa personal messages list "Book club" --limit 20
148
+ wa personal messages send "Book club" "The minutes" --file minutes.pdf
149
+ wa personal polls create "Book club" "Which day?" Monday Tuesday
150
+ wa personal messages download "Book club" 3EB0A1B2C3D4E5F6A7B8 --output-dir ~/Downloads
151
+ wa personal messages transcribe "Book club" 3EB0A1B2C3D4E5F6A7B8 --local # a voice note as text
152
+ ```
153
+
154
+ The message id `3EB0A1B2C3D4E5F6A7B8` is made up; take a real one from `messages list -v`.
155
+
156
+ - **Read.** Chats and messages from the local store, one message with its neighbours, other people's unread
157
+ messages (`wa personal inbox`), everything since the last review (`wa personal review`), new messages as they
158
+ arrive (`wa personal watch`), older messages of one chat asked of your phone (`wa personal messages sync`), and
159
+ the posts of the channels you follow (`wa personal chats join` with a channel link, then `messages sync`).
160
+ - **Write.** Markdown, replies, one file, photo, video or voice note per message, a photo and a video as one album,
161
+ edits of your own messages within 20 minutes, forwards, reactions, polls and votes, pins (each one tells the
162
+ members), deleting for you or for everyone, and marking a chat read.
163
+ - **Your chat list.** Mute, archive, pin or mark a chat unread, star a message, and delete or clear a chat on your
164
+ own devices; nobody in the chat is told.
165
+ - **Voice on your computer.** WhatsApp has no speech recognition of its own, so `wa` runs a speech model on this
166
+ machine, downloaded only when you ask.
167
+ - **People.** A person's profile, blocking, whether a number has WhatsApp, the phone's address book into the store,
168
+ and your own names and notes for people.
169
+ - **Your account.** Your own name, about line and profile photo (`wa personal account update`).
170
+ - **Privacy.** Who sees your last seen, online, profile photo and about line, whether you send read receipts, who
171
+ may add you to groups and whose calls ring (`wa personal account privacy`).
172
+
173
+ More files in one message than a photo and a video are not built yet:
174
+ [not in wa yet](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/usage.md#not-in-wa-yet).
175
+
176
+ More: [using wa](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/usage.md) · [privacy](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/usage.md#privacy) · [one person](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/people.md)
177
+
178
+ ## Log in and profiles
179
+
180
+ `wa` links to your account as a device, the way WhatsApp Web does. There is no password and no app to register: you
181
+ link once, from the phone, and the device keys go to one file only your user can read.
182
+
183
+ ```sh
184
+ wa personal session start # a QR code: WhatsApp → Settings → Linked devices → Link a device
185
+ wa personal session start phone # or your number, then a pairing code you type on the phone
186
+ wa personal account show # who this profile is linked as
187
+ wa account list # every profile here, and who each is linked as
188
+ wa personal session end # unlink, and delete the device keys here
189
+ ```
190
+
191
+ Several accounts are several profiles, and the profile is **the first word**, not an option:
192
+
193
+ ```sh
194
+ wa personal chats list # profile "personal"
195
+ wa work chats list # profile "work"
196
+ export WA_PROFILE=work # or for the whole shell session
197
+ ```
198
+
199
+ `wa` never picks a profile for you, not even the only one: a command that uses an account and has no profile named
200
+ stops and lists the profiles on this computer. Name one or set `WA_PROFILE`. Each profile is a linked device of its
201
+ own, with its own one connection.
202
+
203
+ More: [linking, devices and profiles](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/sessions.md) · [profiles](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/profiles.md)
103
204
 
104
205
  ## The local store and search
105
206
 
@@ -114,13 +215,15 @@ wa personal messages evidence "Project Alpha" --json # bounded evidence for a
114
215
  wa personal store backup ~/wa-backup.db # a copy, safe while the store is in use
115
216
  ```
116
217
 
117
- More: [search](docs/search.md) · [the local store](docs/archive.md) · [query language](docs/query-language.md)
218
+ More: [search](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/search.md) · [the local store](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/archive.md) · [query language](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/query-language.md)
118
219
 
119
220
  ## Groups you run
120
221
 
121
222
  ```sh
122
223
  wa personal review chat:Hiking --unanswered # questions nobody answered
123
224
  wa personal review 'chat:Hiking date>7d' # the week: decisions, promises, open questions
225
+ wa personal chats events Hiking 'time>=7d' # who joined, left, was added or removed, and by whom
226
+ wa personal chats inspect https://chat.whatsapp.com/AAAAAAAAAAAAAAAAAAAAAA # where an invite leads, without joining
124
227
  wa personal stats chats show Hiking --offline # the group's activity, from the local store
125
228
  wa personal chats create "Hiking 2027" 100000000000002@lid # a new group, with people you know
126
229
  wa personal chats members add 120363000000000001@g.us 100000000000002@lid
@@ -128,54 +231,49 @@ wa personal chats update 120363000000000001@g.us --join-approval on
128
231
  wa personal chats requests list 120363000000000001@g.us
129
232
  ```
130
233
 
131
- Renaming a group, members and admins, the invite link, join requests and who may send or add people are commands
132
- too. The members see each change, so each passes the profile's permissions and hourly limit. `wa` adds only people in
133
- your address book or that you have written to: WhatsApp bans accounts that add strangers.
234
+ Renaming a group, its photo, members and admins, the invite link, join requests and who may send or add people are
235
+ commands too. The members see each change, so each passes the profile's permissions and hourly limit. `wa` adds only
236
+ people in your address book or that you have written to: WhatsApp bans accounts that add strangers.
134
237
 
135
- More: [groups](docs/groups.md)
238
+ More: [groups](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/groups.md)
136
239
 
137
- ## Output for scripts and agents
240
+ ## Agent setup in detail
138
241
 
139
- With `--json` a command prints only data, as one JSON value. `--jsonl` prints one object per line. Every list has
140
- one shape:
242
+ **The skill.** Claude Code reads `~/.claude/skills/whatsapp-cli/`; Codex and Gemini CLI read
243
+ `~/.agents/skills/whatsapp-cli/`. Start a new agent session if it does not see the skill.
141
244
 
142
- ```json
143
- { "items": [ … ], "page": { "limit": 20, "has_more": true }, "meta": { … } }
245
+ ```sh
246
+ wa skill install --for all # both folders, without linking
247
+ wa skill show # the complete instructions, without installing them
144
248
  ```
145
249
 
146
- An error goes to stderr as one line, with stdout empty, and the command exits with a fixed code: `4` link the
147
- profile, `5` the profile may not do this, `6` chat or message not found, `8` a limit, `12` another command holds the
148
- device, `14` unknown whether a message went. `wa commands --json` is the whole command tree.
250
+ **The MCP server.** The profile's `permissions` decide which tools it offers. `readonly` stops the agent from
251
+ changing anything; at `ask` the server shows no form, so set up approval in your agent app.
149
252
 
150
- More: [CLI contract](docs/cli-contract.md) · [every command and exit code](docs/commands.md)
253
+ ```sh
254
+ claude mcp add wa -- wa personal mcp # Claude Code, by hand
255
+ wa personal mcp doctor # check the local MCP server
256
+ ```
151
257
 
152
- ## Log in and profiles
258
+ **From the browser.** ChatGPT or Claude in the browser reach `wa personal mcp --http --public-url` behind your tunnel,
259
+ after a login with a one-time access code from your terminal.
153
260
 
154
- `wa` links to your account as a device, the way WhatsApp Web does. There is no password and no app to register: you
155
- link once, from the phone, and the device keys go to one file only your user can read.
261
+ More: [the MCP server](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/mcp.md) · [from the browser](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/remote.md)
156
262
 
157
- ```sh
158
- wa personal session start # a QR code: WhatsApp → Settings → Linked devices → Link a device
159
- wa personal session start phone # or your number, then a pairing code you type on the phone
160
- wa personal session start --qr-file login.png # the QR code as a picture, for an agent to show you
161
- wa personal account show # who this profile is linked as
162
- wa account list # every profile here, and who each is linked as
163
- wa personal session end # unlink, and delete the device keys here
164
- ```
263
+ ## Output for scripts and agents
165
264
 
166
- Several accounts are several profiles, and the profile is **the first word**, not an option:
265
+ With `--json` a command prints only data, as one JSON value. `--jsonl` prints one object per line. Every list has
266
+ one shape:
167
267
 
168
- ```sh
169
- wa personal chats list # profile "personal"
170
- wa work chats list # profile "work"
171
- export WA_PROFILE=work # or for the whole shell session
268
+ ```json
269
+ { "items": [ … ], "page": { "limit": 20, "has_more": true }, "meta": { … } }
172
270
  ```
173
271
 
174
- `wa` never picks a profile for you, not even the only one: a command that uses an account and has no profile named
175
- stops and lists the profiles on this computer. Name one or set `WA_PROFILE`. Each profile is a linked device of its
176
- own, with its own one connection.
272
+ An error goes to stderr as one line, with stdout empty, and the command exits with a fixed code: `4` link the
273
+ profile, `5` the profile may not do this, `6` chat or message not found, `8` a limit, `12` another command holds the
274
+ device, `14` unknown whether a message went. `wa commands --json` is the whole command tree.
177
275
 
178
- More: [linking, devices and profiles](docs/sessions.md) · [profiles](docs/profiles.md)
276
+ More: [CLI contract](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/cli-contract.md) · [every command and exit code](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/commands.md)
179
277
 
180
278
  ## Settings and permissions
181
279
 
@@ -185,10 +283,11 @@ wa personal config set permissions.messages.send ask # a question in the termi
185
283
  wa personal config set sends_per_hour 10 # at most 10 sends an hour (30 by default)
186
284
  wa personal recipients add "Book club" # the first add turns the recipient list on
187
285
  wa personal sends list # every attempt: sent, refused, failed or not known
286
+ wa personal config show # what is set, and where it came from
188
287
  ```
189
288
 
190
- More: [permissions](docs/permissions.md) · [profiles](docs/profiles.md) · [configuration](docs/configuration.md) ·
191
- [limits](docs/limits.md)
289
+ More: [permissions](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/permissions.md) · [profiles](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/profiles.md) · [configuration](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/configuration.md) ·
290
+ [limits](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/limits.md)
192
291
 
193
292
  ## Limits
194
293
 
@@ -197,7 +296,7 @@ from what WhatsApp bans. A profile sends at most 30 messages an hour by default.
197
296
  profile; another one is refused with exit code `12` and names the holder, unless `serve` runs and carries it on its
198
297
  connection. There is nothing to download in bulk: reads answer from the local store.
199
298
 
200
- More: [limits and waits](docs/limits.md)
299
+ More: [limits and waits](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/limits.md)
201
300
 
202
301
  ## Security
203
302
 
@@ -208,7 +307,7 @@ More: [limits and waits](docs/limits.md)
208
307
  text.
209
308
  - Nothing `wa` sends to WhatsApp names this tool: it links as a desktop browser.
210
309
 
211
- To report a vulnerability: [SECURITY.md](SECURITY.md). More: [security](docs/security.md)
310
+ To report a vulnerability: [SECURITY.md](https://github.com/WireCatLabs/whatsapp-cli/blob/main/SECURITY.md). More: [security](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/security.md)
212
311
 
213
312
  ## When something goes wrong
214
313
 
@@ -218,40 +317,60 @@ wa personal doctor --online # also connect once and read the account
218
317
  wa personal runs list # recorded runs
219
318
  ```
220
319
 
221
- More: [troubleshooting by symptom](docs/troubleshooting.md) · [diagnostics](docs/diagnostics.md)
320
+ More: [troubleshooting by symptom](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/troubleshooting.md) · [diagnostics](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/diagnostics.md)
321
+
322
+ ## How it differs
323
+
324
+ `wa` shares its commands, its store and its agent tools with tg and max, so what you learn in one works in the
325
+ others. WhatsApp is different in three ways:
326
+
327
+ - **History comes from your phone.** WhatsApp's servers keep no history to ask for. Your phone sends your recent
328
+ chats once, when `wa` links, and `wa serve` keeps receiving new ones. Older messages of one chat can be asked of the
329
+ phone, 50 at a time, while WhatsApp is open on it (`wa personal messages sync`). Every read answers from the local
330
+ store and never connects.
331
+ - **One connection per device.** WhatsApp allows one. While `wa serve` runs, other commands for the same profile,
332
+ a send included, run through its connection. On Windows they are refused until `serve` stops, for now.
333
+ - **Unofficial.** The risk of a ban is in the warning at the top of this page. `wa` never sends "online" or
334
+ "typing", and marks nothing read unless you ask.
335
+
336
+ ## Part of WireCat
337
+
338
+ [WireCat](https://wirecat.dev) is an open-source, local-first context layer for AI agents. `wa` sits beside
339
+ [tg](https://github.com/WireCatLabs/tg-cli) for Telegram and [max](https://github.com/WireCatLabs/max-cli) for MAX, in
340
+ the same local store.
222
341
 
223
342
  ## Technical docs
224
343
 
225
- Every page is in [`docs/`](docs/README.md):
344
+ Every page is in [`docs/`](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/README.md):
226
345
 
227
346
  | Page | Answers |
228
347
  |---|---|
229
- | [index](docs/index.md) | The docs site's start page: what `wa` is, the first minute, where to go next |
230
- | [installation](docs/installation.md) | How do I install it, and what does it need? |
231
- | [usage](docs/usage.md) | How do I link, read, send and change a message — in that order? |
232
- | [sessions](docs/sessions.md) | How does linking work: QR or pairing code, one connection per device, profiles, unlinking? |
233
- | [archive](docs/archive.md) | What does the local store keep, how is it filled, and how do I export and back it up? |
234
- | [search](docs/search.md) | How do I find a message by its words, sender, chat, date, file or label, save a search and count? |
235
- | [attachments](docs/attachments.md) | Sending, saving and forwarding files; their text, and voice notes as text |
236
- | [query-language](docs/query-language.md) | Every search field, operator, preset, limit and the JSON answer |
237
- | [groups](docs/groups.md) | How do I keep up with a group, and run one? |
238
- | [people](docs/people.md) | One person: what the store holds about them, your own names and notes |
239
- | [mcp](docs/mcp.md) | How do I connect Claude Desktop, Cursor or another client without a terminal? |
240
- | [remote](docs/remote.md) | ChatGPT or Claude in the browser, through a login and a tunnel |
241
- | [recipes](docs/recipes.md) | What can an agent do for me every day, and how do I run it on a schedule? |
242
- | [commands](docs/commands.md) | Every command, option and exit code — **generated** from the program |
243
- | [configuration](docs/configuration.md) | How do I configure common behaviour? |
244
- | [permissions](docs/permissions.md) | What a profile may read, what asks first, and what may go ahead |
245
- | [profiles](docs/profiles.md) | Several accounts on one computer, and how a command picks one |
246
- | [configuration-reference](docs/configuration-reference.md) | Every key, default, scope and variable |
247
- | [cli-contract](docs/cli-contract.md) | Invocation, output, errors, headless runs, bounds and previews |
248
- | [limits](docs/limits.md) | Limits, waits and the one connection per device |
249
- | [diagnostics](docs/diagnostics.md) | What did a command do, and what is never recorded? |
250
- | [troubleshooting](docs/troubleshooting.md) | Something does not work: what the screen says, and what to do |
251
- | [security](docs/security.md) | What does `wa` keep on my computer, and what can go wrong? |
252
- | [roadmap](docs/roadmap.md) | What is coming next? |
253
-
254
- What each version changed: [CHANGELOG.md](CHANGELOG.md).
348
+ | [index](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/index.md) | The docs site's start page: what `wa` is, the first minute, where to go next |
349
+ | [installation](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/installation.md) | How do I install it, and what does it need? |
350
+ | [usage](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/usage.md) | How do I link, read, send and change a message — in that order? |
351
+ | [sessions](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/sessions.md) | How does linking work: QR or pairing code, one connection per device, profiles, unlinking? |
352
+ | [archive](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/archive.md) | What does the local store keep, how is it filled, and how do I export and back it up? |
353
+ | [search](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/search.md) | How do I find a message by its words, sender, chat, date, file or label, save a search and count? |
354
+ | [attachments](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/attachments.md) | Sending, saving and forwarding files; their text, and voice notes as text |
355
+ | [query-language](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/query-language.md) | Every search field, operator, preset, limit and the JSON answer |
356
+ | [groups](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/groups.md) | How do I keep up with a group, and run one? |
357
+ | [people](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/people.md) | One person: what the store holds about them, your own names and notes |
358
+ | [mcp](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/mcp.md) | How do I connect Claude Desktop, Cursor or another client without a terminal? |
359
+ | [remote](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/remote.md) | ChatGPT or Claude in the browser, through a login and a tunnel |
360
+ | [recipes](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/recipes.md) | What can an agent do for me every day, and how do I run it on a schedule? |
361
+ | [commands](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/commands.md) | Every command, option and exit code — **generated** from the program |
362
+ | [configuration](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/configuration.md) | How do I configure common behaviour? |
363
+ | [permissions](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/permissions.md) | What a profile may read, what asks first, and what may go ahead |
364
+ | [profiles](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/profiles.md) | Several accounts on one computer, and how a command picks one |
365
+ | [configuration-reference](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/configuration-reference.md) | Every key, default, scope and variable |
366
+ | [cli-contract](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/cli-contract.md) | Invocation, output, errors, headless runs, bounds and previews |
367
+ | [limits](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/limits.md) | Limits, waits and the one connection per device |
368
+ | [diagnostics](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/diagnostics.md) | What did a command do, and what is never recorded? |
369
+ | [troubleshooting](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/troubleshooting.md) | Something does not work: what the screen says, and what to do |
370
+ | [security](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/security.md) | What does `wa` keep on my computer, and what can go wrong? |
371
+ | [roadmap](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/roadmap.md) | What is coming next? |
372
+
373
+ What each version changed: [CHANGELOG.md](https://github.com/WireCatLabs/whatsapp-cli/blob/main/CHANGELOG.md).
255
374
 
256
375
  ## Development
257
376
 
@@ -260,13 +379,13 @@ pnpm install
260
379
  pnpm lint && pnpm typecheck && pnpm test
261
380
  pnpm engine:build && pnpm engine:test # the Go engine; needs Go
262
381
  pnpm generate # rewrites docs/commands.md from the command tree
263
- bin/wa personal chats list # everything under .wa/ in this checkout, never the real profile
382
+ bin/wa personal chats list # config, state and device under .wa/; a worktree's store too
264
383
  ```
265
384
 
266
385
  Everything that is not specific to WhatsApp — the commands, the store, the send guard, the MCP server — lives in
267
386
  [cli-core](https://github.com/WireCatLabs/cli-core), shared with tg and max.
268
387
 
269
- More: [ARCHITECTURE](docs/dev/ARCHITECTURE.md) · [TESTING](docs/dev/TESTING.md)
388
+ More: [ARCHITECTURE](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/dev/ARCHITECTURE.md) · [TESTING](https://github.com/WireCatLabs/whatsapp-cli/blob/main/docs/dev/TESTING.md)
270
389
 
271
390
  ## Contributing
272
391
 
@@ -276,8 +395,8 @@ Custom automation with WhatsApp, other messengers and AI agents: [info@neirox.ai
276
395
 
277
396
  ## License
278
397
 
279
- The CLI is [Apache-2.0](LICENSE). The engine is not: the Go program in [`engine/`](engine/) and the
280
- `@wirecat/whatsapp-engine-*` packages that carry it are [GPL-3.0-only](engine/LICENSE), because the engine links
398
+ The CLI is [Apache-2.0](https://github.com/WireCatLabs/whatsapp-cli/blob/main/LICENSE). The engine is not: the Go program in [`engine/`](https://github.com/WireCatLabs/whatsapp-cli/tree/main/engine) and the
399
+ `@wirecat/whatsapp-engine-*` packages that carry it are [GPL-3.0-only](https://github.com/WireCatLabs/whatsapp-cli/blob/main/engine/LICENSE), because the engine links
281
400
  go.mau.fi/libsignal, which is under the GNU General Public License 3.0, through whatsmeow. The two are separate
282
401
  programs: `wa` starts the engine as a child process and talks to it only over stdin and stdout. Each engine package
283
402
  says where its source is and lists every Go module it links in `THIRD_PARTY_NOTICES`.
@@ -1,9 +1,13 @@
1
1
  import { type MarkdownFormatting } from "@wirecat/cli-core";
2
- import type { LiveUpdates, MessageEditing, MessageMedia, MessageReactions, MessengerCore, PushedHistory, ReadState, ServerReads, StoredMessages } from "@wirecat/cli-core/cli";
2
+ import type { LiveUpdates, MessageEditing, MessageMedia, MessagePins, MessageReactions, MessageStars, MessengerCore, PassiveUpdates, PushedHistory, ReadState, ServerReads, StoredMessages } from "@wirecat/cli-core/cli";
3
3
  import { type WhatsAppEngine } from "../engine/contract.js";
4
- import { type Words } from "./checks.js";
4
+ import type { Words } from "./checks.js";
5
5
  import { type GroupAdapter } from "./groups.js";
6
6
  import { type PollAdapter } from "./polls.js";
7
- export type WhatsAppAdapter = MessengerCore & LiveUpdates & PushedHistory & Pick<MessageEditing, "edit" | "delete" | "forward"> & Pick<MessageMedia, "download"> & MessageReactions & ReadState & Pick<ServerReads, "history"> & MarkdownFormatting & PollAdapter & GroupAdapter;
8
- export declare const whatsAppAdapter: (engine: WhatsAppEngine, stored?: StoredMessages, words?: Words) => WhatsAppAdapter;
7
+ import { type PrivacyAdapter } from "./privacy.js";
8
+ import { type SettingsAdapter } from "./settings.js";
9
+ export type WhatsAppAdapter = MessengerCore & LiveUpdates & PassiveUpdates & PushedHistory & Pick<MessageEditing, "edit" | "delete" | "forward"> & Pick<MessageMedia, "download"> & MessageReactions & MessageStars & ReadState & Pick<ServerReads, "history"> & MarkdownFormatting & PollAdapter & GroupAdapter & PrivacyAdapter & MessagePins & SettingsAdapter;
10
+ export declare const whatsAppAdapter: (engine: WhatsAppEngine, stored?: StoredMessages, words?: Words,
11
+ /** Where a skipped pushed event is said — a warning, so `--quiet` drops it. The diagnostic stream if not given. */
12
+ warn?: (message: string) => void) => WhatsAppAdapter;
9
13
  //# sourceMappingURL=adapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/adapter.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,kBAAkB,EAKxB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,SAAS,EAGT,WAAW,EACX,cAAc,EACf,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EASL,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAa,KAAK,KAAK,EAAE,MAAM,aAAa,CAAA;AAGnD,OAAO,EAAE,KAAK,YAAY,EAAgB,MAAM,aAAa,CAAA;AAE7D,OAAO,EAAE,KAAK,WAAW,EAA2C,MAAM,YAAY,CAAA;AAEtF,MAAM,MAAM,eAAe,GAAG,aAAa,GACzC,WAAW,GACX,aAAa,GACb,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC,GACnD,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,GAC9B,gBAAgB,GAChB,SAAS,GACT,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,GAC5B,kBAAkB,GAClB,WAAW,GACX,YAAY,CAAA;AAsId,eAAO,MAAM,eAAe,WAClB,cAAc,WACd,cAAc,UACf,KAAK,KACX,eA+PF,CAAA"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/adapter.ts"],"names":[],"mappings":"AAMA,OAAO,EAGL,KAAK,kBAAkB,EAKxB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,aAAa,EACb,SAAS,EAGT,WAAW,EACX,cAAc,EACf,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EASL,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAGxC,OAAO,EAAE,KAAK,YAAY,EAAgB,MAAM,aAAa,CAAA;AAa7D,OAAO,EAAE,KAAK,WAAW,EAA2C,MAAM,YAAY,CAAA;AACtF,OAAO,EAAE,KAAK,cAAc,EAAkB,MAAM,cAAc,CAAA;AAClE,OAAO,EAAuB,KAAK,eAAe,EAAkC,MAAM,eAAe,CAAA;AAEzG,MAAM,MAAM,eAAe,GAAG,aAAa,GACzC,WAAW,GACX,cAAc,GACd,aAAa,GACb,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC,GACnD,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,GAC9B,gBAAgB,GAChB,YAAY,GACZ,SAAS,GACT,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,GAC5B,kBAAkB,GAClB,WAAW,GACX,YAAY,GACZ,cAAc,GACd,WAAW,GACX,eAAe,CAAA;AAqMjB,eAAO,MAAM,eAAe,WAClB,cAAc,WACd,cAAc,UACf,KAAK;AACZ,mHAAmH;OAC7G,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,KAC9B,eAwcF,CAAA"}