diff --git a/CHANGELOG.md b/CHANGELOG.md index e7e9ca5..06d86bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,8 @@ ### Docs +- README: add a documentation index and complete command quick reference. +- Docs: add an overview plus one page for every top-level CLI subcommand. - Maintainers: add CODEOWNERS and maintainer contact info. - Agents: add AGENTS.md for AI agent guidance. (#190 — thanks @adhitShet) diff --git a/README.md b/README.md index feba723..633fea8 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,26 @@ This is a third-party tool that uses the WhatsApp Web protocol via `whatsmeow` a ## Status -Core implementation is in place. See `docs/spec.md` for design notes. +Core implementation is in place. Start with [docs/overview.md](docs/overview.md) for the command map and [docs/spec.md](docs/spec.md) for design notes. + +## Documentation + +- [Overview](docs/overview.md): store model, global flags, common flow, command index. +- [Auth](docs/auth.md): `auth`, `auth status`, `auth logout`. +- [Sync](docs/sync.md): `sync --once`, `sync --follow`, refresh, media download. +- [Messages](docs/messages.md): `messages list/search/show/context`. +- [Send](docs/send.md): `send text/file/react`, recipient resolution, replies. +- [Media](docs/media.md): `media download`. +- [Contacts](docs/contacts.md): `contacts search/show/refresh`, aliases, tags. +- [Chats](docs/chats.md): `chats list/show`. +- [Groups](docs/groups.md): group list, refresh, info, rename, leave, participants, invites, join. +- [History](docs/history.md): `history backfill`. +- [Presence](docs/presence.md): `presence typing/paused`. +- [Doctor](docs/doctor.md): `doctor [--connect]`. +- [Version](docs/version.md): `version`, `--version`. +- [Completion](docs/completion.md): generated shell completions. +- [Help](docs/help.md): `help`, per-command `--help`. +- [Release](docs/release.md): release workflow and artifact expectations. ## Major features @@ -124,12 +143,14 @@ pnpm wacli presence paused --to 1234567890 ## Command surface -- `wacli auth [--follow] [--idle-exit 30s] [--download-media]` +Full command docs live under [docs/overview.md](docs/overview.md). Quick reference: + +- `wacli auth [--follow] [--idle-exit 30s] [--download-media] [--qr-format terminal|text] [--phone PHONE]` - `wacli auth status` - `wacli auth logout` - `wacli sync [--once] [--follow] [--idle-exit 30s] [--max-reconnect 5m] [--download-media] [--refresh-contacts] [--refresh-groups]` -- `wacli messages list [--chat JID] [--sender JID] [--from-me|--from-them] [--asc] [--limit N] [--after DATE] [--before DATE]` -- `wacli messages search [--chat JID] [--from JID] [--has-media] [--type text|image|video|audio|document]` +- `wacli messages list [--chat JID] [--sender JID] [--from-me|--from-them] [--asc] [--limit N] [--after DATE] [--before DATE] [--forwarded]` +- `wacli messages search [--chat JID] [--from JID] [--has-media] [--type text|image|video|audio|document] [--forwarded]` - `wacli messages show --chat JID --id MSG_ID` - `wacli messages context --chat JID --id MSG_ID [--before N] [--after N]` - `wacli send text --to RECIPIENT --message TEXT [--pick N] [--reply-to MSG_ID] [--reply-to-sender JID]` @@ -156,6 +177,8 @@ pnpm wacli presence paused --to 1234567890 - `wacli presence paused --to PHONE_OR_JID` - `wacli doctor [--connect]` - `wacli version` +- `wacli completion bash|zsh|fish|powershell [--no-descriptions]` +- `wacli help [command]` `RECIPIENT` for `send text/file` accepts a JID, phone number, or synced contact/group/chat name. If a name is ambiguous, interactive terminals prompt; scripts can pass `--pick N`. diff --git a/docs/auth.md b/docs/auth.md new file mode 100644 index 0000000..f0a36db --- /dev/null +++ b/docs/auth.md @@ -0,0 +1,33 @@ +# auth + +Read when: pairing a store, checking auth state, logging out, or choosing QR vs phone pairing. + +`wacli auth` connects interactively and bootstraps sync after successful pairing. `wacli sync` never shows a QR code, so use `auth` first for a new store. + +## Commands + +```bash +wacli auth [--follow] [--idle-exit 30s] [--download-media] [--qr-format terminal|text] [--phone PHONE] +wacli auth status +wacli auth logout +``` + +## Notes + +- Default pairing prints a terminal QR code. +- `--qr-format text` prints the raw QR payload for external renderers. +- `--phone PHONE` uses WhatsApp phone-number pairing instead of QR pairing. +- After pairing, auth runs bootstrap sync until idle unless `--follow` is set. +- `auth status` reports whether the local store is authenticated. +- `auth logout` invalidates the linked-device session and requires writable mode. + +## Examples + +```bash +wacli auth +wacli auth --qr-format text +wacli auth --phone "+1 (234) 567-8900" +wacli auth --download-media +wacli auth status --json +wacli auth logout +``` diff --git a/docs/chats.md b/docs/chats.md new file mode 100644 index 0000000..6c6cd23 --- /dev/null +++ b/docs/chats.md @@ -0,0 +1,27 @@ +# chats + +Read when: listing known chats or resolving one chat from the local store. + +`wacli chats` reads chat rows from `wacli.db`. It can use session-backed PN/LID mappings to make historical `@lid` chat rows display as phone-number chats when possible. + +## Commands + +```bash +wacli chats list [--query TEXT] [--limit N] +wacli chats show --jid JID +``` + +## Notes + +- `list` is local and sorted by newest known message timestamp. +- `--query` filters by chat name or JID. +- `show` accepts the stored JID. If a phone JID maps to a historical `@lid` row, it can show that row too. +- Run `wacli sync` or `wacli contacts refresh` to improve chat names. + +## Examples + +```bash +wacli chats list +wacli chats list --query family --limit 20 +wacli chats show --jid 1234567890@s.whatsapp.net +``` diff --git a/docs/completion.md b/docs/completion.md new file mode 100644 index 0000000..9094758 --- /dev/null +++ b/docs/completion.md @@ -0,0 +1,25 @@ +# completion + +Read when: installing shell completions. + +`wacli completion` emits shell completion scripts generated by Cobra. + +## Commands + +```bash +wacli completion bash [--no-descriptions] +wacli completion zsh [--no-descriptions] +wacli completion fish [--no-descriptions] +wacli completion powershell [--no-descriptions] +``` + +## Examples + +```bash +source <(wacli completion bash) +source <(wacli completion zsh) +wacli completion fish | source +wacli completion powershell | Out-String | Invoke-Expression +``` + +For persistent installation paths, run the specific command with `--help`; Cobra prints shell-specific setup instructions. diff --git a/docs/contacts.md b/docs/contacts.md new file mode 100644 index 0000000..a6f829c --- /dev/null +++ b/docs/contacts.md @@ -0,0 +1,34 @@ +# contacts + +Read when: finding synced contacts or managing local contact metadata. + +`wacli contacts` works with contact metadata stored locally. Aliases and tags are local to `wacli`; they do not edit WhatsApp contacts on the phone. + +## Commands + +```bash +wacli contacts search [--limit N] +wacli contacts show --jid JID +wacli contacts refresh +wacli contacts alias set --jid JID --alias NAME +wacli contacts alias rm --jid JID +wacli contacts tags add --jid JID --tag TAG +wacli contacts tags rm --jid JID --tag TAG +``` + +## Notes + +- `search` matches alias, full name, push name, first name, business name, phone, and JID. +- `refresh` imports contacts from the whatsmeow session store into `wacli.db`. +- Local aliases are preferred in contact search and display. +- Tags are local grouping metadata for scripts and future workflows. + +## Examples + +```bash +wacli contacts search Alice +wacli contacts show --jid 1234567890@s.whatsapp.net +wacli contacts refresh +wacli contacts alias set --jid 1234567890@s.whatsapp.net --alias mom +wacli contacts tags add --jid 1234567890@s.whatsapp.net --tag family +``` diff --git a/docs/doctor.md b/docs/doctor.md new file mode 100644 index 0000000..803ad9f --- /dev/null +++ b/docs/doctor.md @@ -0,0 +1,26 @@ +# doctor + +Read when: diagnosing store layout, auth state, FTS/search support, locks, or optional live connectivity. + +`wacli doctor` reports local health information and can optionally connect to WhatsApp. + +## Command + +```bash +wacli doctor [--connect] +``` + +## Notes + +- Without `--connect`, doctor avoids live WhatsApp connection. +- `--connect` requires auth and the store lock. +- Output includes local store counts, auth identity when available, FTS/search state, and lock details. +- Use `--json` for machine-readable diagnostics. + +## Examples + +```bash +wacli doctor +wacli doctor --json +wacli doctor --connect +``` diff --git a/docs/groups.md b/docs/groups.md new file mode 100644 index 0000000..30253c7 --- /dev/null +++ b/docs/groups.md @@ -0,0 +1,44 @@ +# groups + +Read when: listing, refreshing, inspecting, renaming, joining, leaving, inviting, or managing group participants. + +`wacli groups` combines local group rows with live WhatsApp operations. Commands that mutate WhatsApp require writable mode. + +## Commands + +```bash +wacli groups list [--query TEXT] [--limit N] +wacli groups refresh +wacli groups info --jid GROUP_JID +wacli groups rename --jid GROUP_JID --name NAME +wacli groups leave --jid GROUP_JID +wacli groups participants add --jid GROUP_JID --user PHONE_OR_JID [--user ...] +wacli groups participants remove --jid GROUP_JID --user PHONE_OR_JID [--user ...] +wacli groups participants promote --jid GROUP_JID --user PHONE_OR_JID [--user ...] +wacli groups participants demote --jid GROUP_JID --user PHONE_OR_JID [--user ...] +wacli groups invite link get --jid GROUP_JID +wacli groups invite link revoke --jid GROUP_JID +wacli groups join --code INVITE_CODE +``` + +## Notes + +- Group JIDs use the `...@g.us` server. +- `list` reads local rows and hides groups marked left. +- `refresh` fetches joined groups live and updates local rows. +- `info` fetches one group live and persists it. +- `leave` marks the group left locally after WhatsApp confirms. +- Participant users accept phone numbers with common formatting or JIDs. +- Invite `revoke` resets the invite link. + +## Examples + +```bash +wacli groups list --query family +wacli groups refresh +wacli groups info --jid 123456789@g.us +wacli groups rename --jid 123456789@g.us --name "New name" +wacli groups participants add --jid 123456789@g.us --user "+1 (234) 567-8900" +wacli groups invite link get --jid 123456789@g.us +wacli groups join --code AbCdEfGhIjK +``` diff --git a/docs/help.md b/docs/help.md new file mode 100644 index 0000000..eb1d44c --- /dev/null +++ b/docs/help.md @@ -0,0 +1,20 @@ +# help + +Read when: discovering command usage from the CLI itself. + +`wacli help` is the Cobra-provided help command. Every command also accepts `--help`. + +## Commands + +```bash +wacli help [command] +wacli [command] --help +``` + +## Examples + +```bash +wacli help send +wacli send text --help +wacli groups participants add --help +``` diff --git a/docs/history.md b/docs/history.md new file mode 100644 index 0000000..3005554 --- /dev/null +++ b/docs/history.md @@ -0,0 +1,26 @@ +# history + +Read when: trying to fetch older messages for a known chat. + +`wacli history backfill` sends on-demand history sync requests to the primary device. This is best-effort and depends on the phone being online and WhatsApp returning older messages. + +## Command + +```bash +wacli history backfill --chat JID [--count 50] [--requests N] [--wait 1m] [--idle-exit 5s] +``` + +## Limits + +- `--count` defaults to 50 and must be at most 500. +- `--requests` defaults to 1 and must be at most 100. +- Requests are per chat. +- The anchor is the oldest locally stored message in that chat. +- Automatic initial history-sync blob downloads are disabled during backfill; only on-demand responses are processed. + +## Examples + +```bash +wacli history backfill --chat 1234567890@s.whatsapp.net --requests 10 --count 50 +wacli history backfill --chat 123456789@g.us --requests 3 --wait 90s +``` diff --git a/docs/media.md b/docs/media.md new file mode 100644 index 0000000..58eb21a --- /dev/null +++ b/docs/media.md @@ -0,0 +1,26 @@ +# media + +Read when: downloading media from a synced message. + +`wacli media` downloads media referenced by messages already stored in `wacli.db`. + +## Command + +```bash +wacli media download --chat JID --id MSG_ID [--output PATH] +``` + +## Notes + +- The target message must already be synced. +- Media downloads are capped at 100 MiB. +- `--output` may be a file path or directory. +- If `--output` is omitted, media is written under the store media directory. + +## Examples + +```bash +wacli media download --chat 1234567890@s.whatsapp.net --id ABC123 +wacli media download --chat 1234567890@s.whatsapp.net --id ABC123 --output ./downloads +wacli media download --chat 1234567890@s.whatsapp.net --id ABC123 --output ./photo.jpg +``` diff --git a/docs/messages.md b/docs/messages.md new file mode 100644 index 0000000..35b1235 --- /dev/null +++ b/docs/messages.md @@ -0,0 +1,35 @@ +# messages + +Read when: listing, searching, showing, or inspecting local message context. + +`wacli messages` reads from the local store. It does not connect to WhatsApp unless a display path needs session-backed LID mapping. + +## Commands + +```bash +wacli messages list [--chat JID] [--sender JID] [--from-me|--from-them] [--asc] [--limit N] [--after DATE] [--before DATE] [--forwarded] +wacli messages search [--chat JID] [--from JID] [--has-media] [--type text|image|video|audio|document] [--forwarded] [--limit N] [--after DATE] [--before DATE] +wacli messages show --chat JID --id MSG_ID +wacli messages context --chat JID --id MSG_ID [--before N] [--after N] +``` + +## Search + +- Uses SQLite FTS5 when the binary was built with `-tags sqlite_fts5`. +- Falls back to `LIKE` if FTS5 is not available. +- `--type` accepts `text`, `image`, `video`, `audio`, or `document`. +- Time filters accept RFC3339 or `YYYY-MM-DD`. + +## LID mapping + +When a phone-number chat JID maps to a stored `@lid` row, list/search/show/context include the mapped rows so historical LID splits do not hide messages. + +## Examples + +```bash +wacli messages list --chat 1234567890@s.whatsapp.net --asc +wacli messages list --from-me --limit 20 +wacli messages search "invoice" --has-media --type document +wacli messages show --chat 1234567890@s.whatsapp.net --id ABC123 +wacli messages context --chat 1234567890@s.whatsapp.net --id ABC123 --before 3 --after 3 +``` diff --git a/docs/overview.md b/docs/overview.md new file mode 100644 index 0000000..acf162e --- /dev/null +++ b/docs/overview.md @@ -0,0 +1,52 @@ +# wacli overview + +Read when: you need the user-facing command map, global flags, store model, or links to command-specific docs. + +`wacli` is a WhatsApp CLI built on `whatsmeow`. It pairs as a linked WhatsApp Web device, stores message metadata locally, supports offline search, and exposes send/media/group/contact workflows for scripts and humans. + +## Store and output + +- Default store: `~/.local/state/wacli` on Linux, `~/.wacli` elsewhere. +- Existing Linux `~/.wacli` stores are reused when no XDG store exists. +- Override the store with `--store DIR` or `WACLI_STORE_DIR`. +- Human-readable tables are the default. +- Use `--json` for scriptable output. +- Use `--full` to avoid table truncation. +- Write commands acquire the store lock; use `--lock-wait DURATION` to wait. +- Use `--read-only` or `WACLI_READONLY=1` to reject commands that write WhatsApp or local state. + +## Command pages + +- [auth](auth.md) - pair, inspect auth status, logout. +- [sync](sync.md) - sync messages, contacts, groups, and optional media. +- [messages](messages.md) - list, search, show, and contextualize stored messages. +- [send](send.md) - send text, files, replies, and reactions. +- [media](media.md) - download media attached to stored messages. +- [contacts](contacts.md) - search contacts and manage local aliases/tags. +- [chats](chats.md) - list and show known chats. +- [groups](groups.md) - refresh, inspect, rename, leave, join, invite, and manage participants. +- [history](history.md) - request older per-chat history from the primary device. +- [presence](presence.md) - send typing/paused indicators. +- [doctor](doctor.md) - diagnose store, auth, search, and optional live connectivity. +- [version](version.md) - print the CLI version. +- [completion](completion.md) - generate shell completion scripts. +- [help](help.md) - inspect command help from the CLI. + +## Common flow + +```bash +wacli auth +wacli sync --follow +wacli messages search "meeting" +wacli send text --to mom --message "hello" +``` + +## Recipient formats + +Commands that accept `PHONE_OR_JID` accept a WhatsApp JID like `1234567890@s.whatsapp.net`, a group JID like `123456789@g.us`, or a phone number with common formatting such as `+1 (234) 567-8900`. + +`send text` and `send file` also accept synced contact, group, or chat names through `RECIPIENT`. If a name is ambiguous, interactive terminals prompt; scripts can use `--pick N`. + +## History limits + +WhatsApp Web history is best-effort. `wacli sync` stores events WhatsApp provides, and `wacli history backfill` can ask the primary phone for older messages per chat. It cannot guarantee a full account export. diff --git a/docs/presence.md b/docs/presence.md new file mode 100644 index 0000000..a1eebca --- /dev/null +++ b/docs/presence.md @@ -0,0 +1,27 @@ +# presence + +Read when: sending typing, recording, or paused chat indicators. + +`wacli presence` sends ephemeral WhatsApp chat-state updates. It does not send a message. + +## Commands + +```bash +wacli presence typing --to PHONE_OR_JID [--media audio] +wacli presence paused --to PHONE_OR_JID +``` + +## Notes + +- `typing` sends a composing indicator. +- `typing --media audio` sends a recording indicator. +- `paused` clears the composing indicator. +- Recipients accept phone numbers with common formatting or JIDs. + +## Examples + +```bash +wacli presence typing --to 1234567890 +wacli presence typing --to 1234567890 --media audio +wacli presence paused --to 1234567890 +``` diff --git a/docs/release.md b/docs/release.md index 30a7c86..11cf245 100644 --- a/docs/release.md +++ b/docs/release.md @@ -1,5 +1,7 @@ # Release +Read when: cutting a release, debugging release artifacts, or updating the Homebrew tap handoff. + ## GitHub Release Artifacts `wacli` uses GoReleaser (`.goreleaser.yaml` for macOS, `.goreleaser-linux-windows.yaml` for linux/windows) and the GitHub Actions workflow `.github/workflows/release.yml`. diff --git a/docs/send.md b/docs/send.md new file mode 100644 index 0000000..c3d5f1c --- /dev/null +++ b/docs/send.md @@ -0,0 +1,46 @@ +# send + +Read when: sending text, files, quoted replies, or reactions. + +`wacli send` requires authentication, a live connection, and writable mode. Send attempts are bounded and retry once after reconnect for known stale-session/usync timeout failures. + +## Commands + +```bash +wacli send text --to RECIPIENT --message TEXT [--pick N] [--reply-to MSG_ID] [--reply-to-sender JID] +wacli send file --to RECIPIENT --file PATH [--pick N] [--caption TEXT] [--filename NAME] [--mime TYPE] [--reply-to MSG_ID] [--reply-to-sender JID] +wacli send react --to PHONE_OR_JID --id MSG_ID [--reaction TEXT] [--sender JID] +``` + +## Recipients + +- `send text` and `send file` accept a JID, phone number, or synced contact/group/chat name. +- If a name matches multiple recipients, interactive terminals prompt. +- In scripts, use `--pick N` to choose a displayed match. +- Phone numbers may use common formatting such as `+1 (234) 567-8900`. + +## Replies and reactions + +- `--reply-to` quotes a stored message ID. +- For unsynced group replies, pass `--reply-to-sender`. +- `send react` defaults to thumbs-up. +- Pass `--reaction ""` to clear a reaction. +- For group reactions, pass `--sender` for the original message sender. + +## Files + +- File uploads are capped at 100 MiB. +- MIME type is detected automatically unless `--mime` is set. +- `--filename` changes the displayed document name. +- Captions apply to images, videos, and documents. + +## Examples + +```bash +wacli send text --to mom --message "landed" +wacli send text --to "Family" --pick 2 --message "on my way" +wacli send text --to 1234567890 --message "replying" --reply-to ABC123 +wacli send file --to 1234567890 --file ./pic.jpg --caption "hi" +wacli send file --to 1234567890 --file /tmp/report --filename report.pdf +wacli send react --to 1234567890 --id ABC123 --reaction "❤️" +``` diff --git a/docs/spec.md b/docs/spec.md index 800158b..1a25e42 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -1,5 +1,7 @@ # wacli specification (plan) +Read when: changing the CLI contract, store model, sync model, or v1 behavior boundaries. + This document defines the v1 plan for `wacli`: a WhatsApp CLI that syncs messages locally, supports fast search, sending, and contact/group management. Implementation will use `whatsmeow` under the hood. ## Goals diff --git a/docs/sync.md b/docs/sync.md new file mode 100644 index 0000000..995897b --- /dev/null +++ b/docs/sync.md @@ -0,0 +1,30 @@ +# sync + +Read when: running continuous capture, one-shot sync, contact/group refresh, or background media download. + +`wacli sync` requires an existing authenticated store and never displays a QR code. It captures WhatsApp Web events into the local SQLite store. + +## Command + +```bash +wacli sync [--once] [--follow] [--idle-exit 30s] [--max-reconnect 5m] [--download-media] [--refresh-contacts] [--refresh-groups] +``` + +## Modes + +- Default behavior follows continuously. +- `--once` exits after sync becomes idle. +- `--idle-exit` controls idle exit timing in once mode. +- `--max-reconnect 0` keeps reconnecting indefinitely. +- `--download-media` runs a bounded media downloader for sync events. +- `--refresh-contacts` imports contacts from the session store. +- `--refresh-groups` fetches joined groups live and updates the local DB. + +## Examples + +```bash +wacli sync --once +wacli sync --follow --max-reconnect 10m +wacli sync --once --refresh-contacts --refresh-groups +wacli sync --follow --download-media +``` diff --git a/docs/version.md b/docs/version.md new file mode 100644 index 0000000..cb476a5 --- /dev/null +++ b/docs/version.md @@ -0,0 +1,18 @@ +# version + +Read when: checking the installed CLI version. + +`wacli version` prints the CLI version. The root `--version` flag prints the same version through Cobra. + +## Commands + +```bash +wacli version +wacli --version +``` + +## Example + +```bash +wacli version +```