type: overview title: Quickstart description: What the wh WhatsApp terminal client with per-chat and global AI autoreply (system prompt in SOUL.md, reply delay, image descriptions, voice-note transcriptions) does, how to build and run it, and where to find each topic in this wiki. tags: [overview, quickstart, rust, whatsapp, tui, ai, web-panel, pairing, transcription] sources:
651d1fb6c9
resource: repo://Cargo.toml9fec9d1af4
resource: repo://src/app.rs043e6252ba
resource: repo://src/autoreply.rs2a737474d8
resource: repo://src/config.rsb55a21a31e
resource: repo://src/main.rs
generated: { by: "opencode", at: "2026-10-24T16:39:50.206Z" }
---wh (Cargo.toml:1-5) is a Rust terminal client for WhatsApp. It links as a
companion device by QR code, shows chats and contacts in a
ratatui interface, stores messages locally in
SQLite and can answer incoming messages automatically with an
OpenAI-compatible model — chat by chat or for all chats at once — in private
chats and in groups (broadcasts, status and newsletters excluded). An
optional web control panel lets a
browser toggle the autoreplies, pair WhatsApp from the QR shown in the page,
request a new pairing and stop the bot.
cargo build --release
cargo run --release
cargo test
The crate uses edition 2024. whatsapp-rust is built with
default-features = false because its default simd feature needs nightly
(Cargo.toml:8-10). TLS uses ring only: reqwest is built with
rustls-no-provider and the ring provider is installed when the AI client
is built, avoiding the large aws-lc-sys C build (Cargo.toml:13-16); this
keeps the Linux musl cross-compile with cargo-zigbuild (see README.md)
fast. The release profile only strips symbols, without LTO
(Cargo.toml:31-33). [lints.rust] linker_messages = "allow"
(Cargo.toml:35-37) silences the informational MSVC linker line printed
because the binary exports symbols.
wh --version (or -V) prints wh <version> (<git commit>) and exits; the
same version is shown at the bottom right of the main screen
(src/main.rs:32-48, build.rs).
On first start the app shows a QR code: scan it from WhatsApp → Linked
devices. The session is kept in session.db, so later starts connect
directly; F8 twice (on any screen) or the web panel's "Nuovo QR" unlinks
the device, empties session.db and shows a new QR without restarting
(WhatsApp relink and pairing). Main keys:
Tab switches list/input, Enter opens a chat or sends, typing in the list
filters it, PgUp/PgDn/Home/End move through the list, F2
chats/contacts, F3 toggles autoreply for the selected chat (list focus) or
the open chat (input focus), F4 toggles the global autoreply ("AI tutte"),
Canc twice deletes the selected chat locally, F10 quits and clears the
screen (key bindings).
Settings live in config.toml inside the data directory
<platform config dir>/wh (on Windows %APPDATA%\wh, on Linux
~/.config/wh), next to session.db and history.db
(src/config.rs:55-68, src/config.rs:206-210); the repository's
config.toml.global.template lists every key. The system prompt is not a
key: it is the file SOUL.md in the same folder (start from
soul.md.template), and the optional VISION.md replaces the built-in
request used to describe images. The three files are checked every 2
seconds and reloaded when they change, without restarting; only web_port
needs a restart
(live reload). The two databases are separate by design:
session.db is the WhatsApp library's session and key store, history.db
holds the app's chats, messages, autoreply flags and image descriptions.
Without openai_api_key and a non-blank SOUL.md the app still runs as a
plain WhatsApp client. Optional keys tune the reply delay
(reply_delay_seconds), the startup catch-up (catch_up_seconds), AI
retries (ai_retries), the vision model (openai_vision_model), an AI
request log (ai_log, written to ai_requests.log in the same folder) and
the web panel port (web_port, unauthenticated, all interfaces). Four more
transcribe_* keys enable voice-note transcription against any
OpenAI-compatible audio/transcriptions endpoint (off by default; Groq with
whisper-large-v3-turbo as the default endpoint and model). The old
keys system_prompt, cooldown_seconds and group_cooldown_seconds are
ignored. Keys and defaults:
Configuration and data.
The first unanswered message of an enabled chat starts a
reply_delay_seconds wait; messages arriving meanwhile join the same reply.
Images are described once by the vision model and only their descriptions
reach the AI; voice notes are transcribed once (when transcribe_key is
set, Groq by default) and their text enters the reply context. The reply is
dropped if the owner answered by hand, and the model can stay silent by
calling the no_reply tool, whose use is decided by SOUL.md. Details:
AI auto-reply workflow.
main prints the version and exits for --version; otherwise it loads the
config, opens the history, starts the WhatsApp client, the optional web
panel, the configuration watcher and an input thread, then runs the
draw/receive loop until quit (src/main.rs:44-72, see
Runtime and event loop).
| Task | Page | Source |
|---|---|---|
| Startup, version flag, channels, threads, config watcher, main loop | Runtime and event loop | src/main.rs, src/config_watch.rs, build.rs |
| Events, state, keys, filter, chat deletion, config reload, relink, reply orchestration, background tasks | Application state | src/app.rs |
| Screens, rendering, message formatting, footer version | Terminal UI | src/ui.rs |
| WhatsApp session, relink, events, JIDs, media | WhatsApp client | src/whatsapp.rs |
AI HTTP requests, no_reply tool, image descriptions, retries, errors |
AI client | src/ai.rs |
| Web control panel: routes, security, pairing QR, browser page | Web control panel | src/web.rs, src/web_page.html |
| When and how the AI replies (global/per-chat, groups, reply delay, owner-answered drop, images, catch-up, context) | AI auto-reply workflow | src/autoreply.rs, src/app.rs |
| Pairing, F8 / "Nuovo QR" relink, session reset, new QR in TUI and web | WhatsApp relink and pairing | src/app.rs, src/whatsapp.rs, src/web.rs |
| Local SQLite messages, chats, contacts, settings, image descriptions | History store | src/history.rs |
Config keys, SOUL.md / VISION.md, live reload, data dir, build profile, security notes |
Configuration and data | src/config.rs, src/config_watch.rs |
| Test suites, the ignored live relink test and how to run them | Unit tests | src/*.rs |