This project is not affiliated with WhatsApp or Meta.
A Linux-first native client for WhatsApp, built as one daemon and any number
of thin frontends. whatevrd owns the WhatsApp connection (via
whatsmeow), the login session, the SQLite
message store, the media cache and notifications. Frontends own pixels. They
talk over a documented protocol on a unix socket, and writing one is a fun weekend (for me atleast)
whattui is the terminal frontend, and the one frontend for now.
On Arch-based systems, Whatevr is available on the AUR:
yay -S whatevr-binNote: You can install the whatevr or whatevr-git packages also if you want to build yourself
For other systems, for now you can follow the build instructions below:
Build Instructions
whatevr builds through a single top-level justfile that compiles the daemon
(whatevrd) and the terminal frontend (whattui). The daemon must be running for any frontend to work.
whatevrd builds against a fork of whatsmeow and whattui against a fork of
vaxis, both carried as git submodules, so clone with git clone --recursive, or run
git submodule update --init --recursive in an existing checkout.
Daemon: Go 1.26+, just, a C compiler, SQLite and libjpeg-turbo dev files, pkg-config. Terminal frontend: the same Go toolchain, nothing else. Optional at runtime: ffmpeg, for video posters and voice note waveforms.
# Arch
sudo pacman -S --needed base-devel go just sqlite libjpeg-turbo pkgconf
# Fedora
sudo dnf install go just gcc sqlite-devel turbojpeg-devel pkgconf-pkg-config
# Debian 13 "trixie" (needs Go >= 1.26, see Platform support)
sudo apt install golang just gcc libsqlite3-dev libturbojpeg0-dev pkg-configjust build # debug build for local testing
just build-release # optimized release build
just install "$HOME/.local" # user-local release install
# or system-wide:
sudo just install /usrjust install places the whatevrd and whattui binaries and the systemd user
units under the selected prefix.
Make sure the chosen bin directory is on your PATH (e.g. ~/.local/bin).
Other handy targets: just version, just artifacts, and just clean.
Start the daemon, then the frontend:
whatevrd # or run it via systemd (below)
whattuiThe first time, link your phone: whattui shows the QR code to scan, or run
whatevrd pair to print it in any terminal.
whattui is keyboard and mouse driven and needs nothing memorised: ctrl+p
opens the command palette, / in the composer opens the same commands inline,
and ? lists every binding. It looks best in a terminal with the kitty
graphics protocol, and degrades by tier down to 16 colours without moving a
single glyph. whattui --caps prints what it found.
just install ships two mutually exclusive user units: enable one,
never both (they share the same socket path):
- Socket activation (recommended): the daemon starts on demand the moment a frontend connects, and keeps running afterwards.
- Always-on service: the daemon starts at login.
systemctl --user daemon-reload
systemctl --user enable --now whatevrd.socket # socket activation (recommended)
# or
systemctl --user enable --now whatevrd.service # always-onA user-local install puts the units under ~/.local/lib/systemd/user, which
systemd does not search. Copy them into a searched path first (the templated
service needs the binary path substituted):
mkdir -p ~/.config/systemd/user
sed "s|@BINDIR@|$HOME/.local/bin|g" packaging/systemd/whatevrd.service.in \
> ~/.config/systemd/user/whatevrd.service
cp packaging/systemd/whatevrd.socket ~/.config/systemd/user/
systemctl --user daemon-reloadDistro packages install both units to /usr/lib/systemd/user/ (shipped disabled).
Whatevr is very early-stage software. It is usable for development and testing, but the should be treated as EXPERIMENTAL. There is lots of missing functionality that is considered essential, and there WILL be bugs.
The protocol, on the other hand, is stable at version 2: new views, commands and message kinds will be added, but nothing already in PROTOCOL.md changes shape. A frontend written against it today keeps working.
Now with that, here is the current feature map for whatevrd.
Feature Map
| Feature | Status | Notes |
|---|---|---|
| WhatsApp login with QR code | ✅ | |
| Persistent login session | ✅ | |
| Logout | ✅ | |
| Local message database | ✅ | SQLite |
| Older message loading | ✅ | |
| Incoming messages | ✅ | |
| Send text messages | ✅ | |
| Send image messages | ✅ | |
| Reply to messages | ✅ | |
| Message delivery/read status | ✅ | |
| Pin and unpin chats | ✅ | |
| Group chats | ✅ | Basic support + info display |
| Chat avatars | ✅ | |
| Media preview/display | ✅ | Images and cached media |
| Paste image from clipboard | ✅ | |
| Typing indicator | ✅ | Send/receive composing state |
| Online/last-seen presence | ✅ | |
| Offline/history sync progress | ✅ | |
| Desktop notifications | ✅ | Handled by daemon |
| Emoji picker | ✅ | Frontend-local |
| Message search | ✅ | |
| Chat search | ✅ | |
| Contact search/new chat | ✅ | |
| Voice messages | ❌ | |
| Audio playback | ❌ | |
| Video playback | ❌ | |
| View-once messages sending | ❌ | |
| Document/file sending | ❌ | Images/media path exists, general file UX missing |
| Stickers | ✅ | Receive and send stickers |
| Message reactions | ✅ | |
| Composer emoji inline search | ✅ | |
| Edit sent messages | ✅ | Received message edits are handled too |
| Delete messages | ✅ | |
| Forward messages | ✅ | |
| Star/bookmark messages | ✅ | |
| Archive chats | ✅ | |
| Mute chats | ✅ | |
| Pinned messages | ✅ | |
| Group management | ❌ | No create/invite/admin UI |
| Community management | ❌ | |
| Calls | ❌ | Voice/video calls unsupported |
| Status/stories | ❌ | |
| Settings UI | ✅ | |
| Account/profile editing | ✅ | Includes privacy settings |
| Import/export backups | ❌ | |
| DB encryption and keyring integration | ❌ | |
| Daemon SNI (Tray) | ❌ |
Whatevr is one background daemon, whatevrd, and a socket. The daemon owns the
WhatsApp connection, the login session, the local SQLite store, the media cache
and desktop notifications, and serves all of it over
the whatevr protocol. Frontends never speak to WhatsApp directly
and never keep durable state of their own; several can run at once against the
same daemon, and each sees the same rows in the same order because the daemon
computed that order.
The daemon is Go (whatevrd/); the terminal frontend is whattui, in Go on a
fork of vaxis (whattui/). A scriptable CLI is wanted and
unclaimed; that work needs no changes to the daemon.
Whatevr will be Linux-first for now until its stable. I am open to contributions for porting functionality to other platforms as long as they don't affect existing performance and Linux functionality significantly.
PROTOCOL.md is the contract: protobuf frames, each preceded
by its length as a varint, over $XDG_RUNTIME_DIR/whatevr/whatevrd.sock.
Protocol version 2. The schema lives in proto/ and generates for
any language; Go and Python types are checked in. Four ideas carry the whole
thing:
- The daemon owns all state. A frontend does no sorting, merging, dedup or cache invalidation. Ever. It keeps a map of items and renders it.
- You subscribe to views, not endpoints.
subscribetochats,messages,typing,presence… and the daemon sends the contents, then keeps your copy correct forever with keyed upserts and removes. Every item carries a daemon-computedsortkey; ordering is never your problem. - Commands only ever return an id. Send a message and the response is a message id. The message itself arrives through the view you already had open, the same way one from your phone would. There is no second code path.
- Every message renders in every frontend. Each one carries a
fallbackstring, so a client that has never heard of stickers still shows something sensible. Partial frontends are first-class.
The whole surface is slim. examples/frontend.py is a
complete frontend in under 80 lines: it says hello, subscribes to the chat
list, keeps it live, and sends a message.
Whatevr stands on the shoulders of:
- whatsmeow: WhatsApp Web multidevice protocol library that whatevrd runs on a fork of (MPL-2.0)
- vaxis: terminal UI library that whattui runs on a fork of (Apache-2.0)
This program is licensed under the BSD-3-Clause License
macOS 13 or later is supported. The daemon and terminal frontend use native
macOS defaults; no XDG variables or shell configuration are needed to connect.
Install Apple's Command Line Tools (xcode-select --install) and dependencies:
brew install go just jpeg-turbo pkgconf python ffmpegGo 1.26 or later is required. ffmpeg is optional. Both macOS executables use cgo for native path lookup; Swift builds the private notification app. The SQLite Go driver includes SQLite itself, so a separate Homebrew SQLite installation is not required. Clone submodules as described above, then:
just build-release
./build/release/whatevrd
# In another terminal:
./build/release/whattuiTo install without administrator privileges:
just install "$HOME/.local"
# Add $HOME/.local/bin to PATH, or invoke these executables by absolute path.The installation is Whatevr.app in the prefix, holding the notification helper
and whatevrd, with bin/whatevrd linking into it. Spotlight only indexes app
folders, so link it there if you want to open Whatevr from Spotlight:
ln -s "$HOME/.local/Whatevr.app" ~/Applications/Whatevr.appDebug builds (just build, just install-dev) are a separate app, Whatevr
Dev (in.codelif.whatevr.dev), so they never take notification permission
from the installed one. Local builds are ad-hoc signed; they are intended for
use on the build machine. Developer ID signing and notarization are required
separately for public distribution.
Login startup is optional and never enabled by installation:
whatevrd service enable # starts now, at GUI login, and whenever a frontend connects
whatevrd service status
whatevrd service disable # stops the service and removes its LaunchAgentThe LaunchAgent holds the socket, so launchd starts the daemon again whenever a
frontend connects, including after a crash. Stop a manually running daemon before
enabling the service; while the service is enabled, running whatevrd by hand on
the default socket is refused. Enable the service with XDG and WHATEVR_SOCKET
overrides unset, so it uses the same native defaults as normal terminal clients.
The agent uses the executable path as invoked, so a Homebrew bin link keeps
working across upgrades, and a PATH containing the installation prefix, the
detected Homebrew prefix, and system tools. Running whatevrd service enable
again replaces an agent written by an older version or from another prefix.
Disable the service before uninstalling.
Notification authorization is explicit:
whatevrd notifications setup
whatevrd notifications statusAllow notifications in the macOS dialog. If previously denied, enable Whatevr in System Settings → Notifications. Notification clicks select the chat in a connected frontend. If no frontend is open, no terminal is launched. The helper follows system notification/sound settings; a missing helper or denied permission does not prevent messaging. Local rebuilds may require checking notification authorization again because they use ad-hoc signing.
Run whatevrd paths --json to inspect all resolved locations:
| Contents | Default location |
|---|---|
| Databases and WhatsApp session | ~/Library/Application Support/in.codelif.whatevr/daemon |
| Configuration and send guard | ~/Library/Application Support/in.codelif.whatevr/config |
| Development state and captures | ~/Library/Application Support/in.codelif.whatevr/{state,captures} |
| Media and frontend caches | ~/Library/Caches/in.codelif.whatevr/{daemon,tui} |
| Daemon and frontend diagnostics | ~/Library/Logs/in.codelif.whatevr/{daemon,tui} |
| Socket and lock | OS-provided per-user temporary directory, in.codelif.whatevr.{sock,lock} |
The socket uses Darwin's per-user temporary directory, rather than an inherited
TMPDIR, so launchd and terminal sessions agree. The socket sits directly in that
private directory, sockets are mode 0600, and peers must be the same user. Existing Linux-style
macOS data is left untouched; the native location starts as a fresh linked device.
Explicit XDG overrides retain their existing layout, and WHATEVR_SOCKET selects
an absolute socket path. Darwin socket paths must fit within 103 bytes.
Debug mock and capture runs isolate their account state. Their Darwin sockets
use short, deterministic instance directories under the native runtime directory.
Query a mock instance with build/debug/whatevrd paths --json --mock-dir DIR, then
pass its SocketPath to whattui --socket. The capture startup log prints its
WHATEVR_SOCKET. Mock notifications remain disabled unless --mock-notify is set.
just test uses /tmp for temporary test files to keep existing socket test paths
short. Network and wake monitoring use Network.framework and IOKit independently
of the notification app. Linux keeps its XDG, systemd, D-Bus, and netlink support.