OpenMessage started with Google Messages because Android already has a clear linked-device model. WhatsApp needed to feel equally native inside the same inbox, or it would just become another side tab. So the goal was not “show WhatsApp history eventually.” The goal was a live route: new messages, typing, media, receipts, search, and replies flowing through the same local runtime as SMS and RCS.
Why a live bridge instead of a periodic importer
A periodic desktop import can make an archive visible, but it does not feel like a messaging product. Messages arrive late. Typing indicators do not exist. Receipts lag. Media is brittle. The UI starts to look unified while the product behavior is still fragmented.
That is why WhatsApp in OpenMessage now runs as a live linked-device session on the user’s own machine. The point was not just protocol coverage. The point was to make the route behave like a first-class part of the app.
The actual shape of the system
The runtime is still local-first. A Go backend owns the message store, transport sessions, search, and MCP surface. The macOS wrapper is mostly there to package the local runtime cleanly with desktop integration like notifications and contact access.
WhatsApp support plugs into that same backend as a live bridge. In practical terms:
- A linked-device WhatsApp session is paired on the local machine.
- Inbound events normalize into the same local conversation and message schema as other routes.
- The web UI and native wrapper update from the same invalidation stream.
- MCP clients connect to the same local state, not a second AI-only cache.
What “local-first” means here
OpenMessage is not trying to become a hosted messaging relay. The desktop app, the search index, the diagnostics, and the transport sessions are designed to live on the user’s machine. That matters both for privacy and for product feel. The app can be responsive because the source of truth is close to the UI.
What shipped with WhatsApp
The first bar was not just text send and receive. WhatsApp support only felt worth shipping once it handled the parts that make a route feel real inside a desktop workspace:
- live inbound and outbound messages
- media send and render
- voice notes
- typing indicators
- read-state rendering
- desktop notifications
- grouped route selection beside SMS and RCS
- assistant access through the built-in MCP runtime
Why the inbox model matters
The UI does not pretend every transport is identical. OpenMessage keeps route selection explicit when it matters, but still groups the experience by person where it helps. That is why one contact can clearly show both SMS and WhatsApp without the product collapsing into two separate apps jammed into one window.
The implementation stack
The live WhatsApp path is built into the OpenMessage runtime rather than bolted on as a remote service. Under the hood, the bridge uses the WhatsApp linked-device model and is integrated into the same Go backend that powers search, diagnostics, the local web app, and MCP. The result is that features like route-aware drafting, local notifications, and media rendering do not need a second architecture just for WhatsApp.
What comes next
Shipping WhatsApp changed OpenMessage from “Google Messages with MCP” into a broader local messaging product. The next work is less about adding another flashy transport immediately and more about trust: pairing quality, reconnect behavior, diagnostics, and making the local runtime easy to understand when something breaks.
That is the real shape of the product now: one local message surface, multiple real routes, and an assistant that can operate on the same inbox you use yourself.