|
|
2 days ago | |
|---|---|---|
| openwiki | 2 days ago | |
| src | 2 days ago | |
| .gitignore | 3 days ago | |
| AGENTS.md | 2 days ago | |
| Cargo.lock | 2 days ago | |
| Cargo.toml | 2 days ago | |
| README.md | 2 days ago | |
| config.toml.global.template | 2 days ago |
Terminal WhatsApp client (ratatui) with per-chat and global AI autoreply via an OpenAI-compatible API.
cargo build --release
Built from Windows with cargo-zigbuild. Zig provides the C cross-compiler and linker for the bundled C code (SQLite, aws-lc-sys, ring).
One-time prerequisites:
rustup target add x86_64-unknown-linux-musl
winget install -e --id zig.zig # or: pip install ziglang
cargo install --locked cargo-zigbuild
Build:
cargo zigbuild --release --target x86_64-unknown-linux-musl
Output: target/x86_64-unknown-linux-musl/release/wh
Verify on Linux:
file wh # ELF 64-bit x86-64, statically linked
chmod +x wh && ./wh
On Linux, config and databases live in ~/.config/wh/ (config.toml, session.db, history.db); on Windows in %APPDATA%\wh.
Copy session.db from Windows to reuse the linked session instead of scanning the QR again.
Settings live in config.toml in the data directory. Start from config.toml.global.template: copy it there and fill openai_api_key and system_prompt. A missing file means defaults; without openai_api_key and system_prompt the app runs as a plain WhatsApp client.
| Key | Default | Description |
|---|---|---|
openai_api_key |
unset | API key of the OpenAI-compatible endpoint (required for AI) |
openai_base_url |
https://ollama.com/v1 |
endpoint base URL |
openai_model |
deepseek-v4.1-flash |
model for autoreplies |
openai_vision_model |
unset | vision model for images; unset disables image understanding |
system_prompt |
unset | responder identity (required for AI) |
ai_log |
false |
append every AI request to ai_requests.log |
cooldown_seconds |
30 |
min seconds between autoreplies in a private chat / to a group message addressed to you (0 = off) |
group_cooldown_seconds |
300 |
same, group messages not addressed to you (0 = off) |
catch_up_seconds |
7200 |
after a restart, answer the last unanswered private message up to this age (0 = off) |
ai_retries |
2 |
retries of a failed AI request, 2s, 4s, ... backoff (0 = off; HTTP 4xx except 429 never retried) |
web_port |
unset | port of the web control panel (1-65535); unset disables it |
| Key | Action |
|---|---|
Tab |
focus list/input |
Enter |
open chat / send |
F2 |
chats/contacts |
| typing (list focused) | filter names; Backspace edits, Esc clears |
Canc/Delete twice |
delete chat locally (history only, not on WhatsApp) |
Ctrl+A |
AI autoreply for the open chat |
Ctrl+Shift+A |
AI autoreply for all chats (persistent; footer shortcut turns green when on) |
Ctrl+Q |
quit |
web_port in config.toml (e.g. web_port = 8080); open http://<host>:<port>/.0.0.0.0 without authentication: use it only on a trusted network (e.g. a VPN).Ctrl+Shift+A), per-chat AI toggle grid (private chats and groups only), "Chiudi bot" button to quit. The page refreshes every 5 seconds; changes show up in the TUI too.GET /api/state (JSON {global_autoreply, chats:[{jid,name,autoreply}], status}); POST /api/global; POST /api/chat with the jid as plain-text body; POST /api/quit. Every POST requires the header X-Wh-Request: 1 (otherwise 403), which blocks cross-site requests from other pages.Example:
curl -X POST -H "X-Wh-Request: 1" http://host:8080/api/global