Putting a product surface inside an iMessage group chat
Our crew's running talk lives in one iMessage thread. Every fitness app we tried asked us to move it somewhere else: install a second social app, open it, keep opening it. Nobody did. So the question turned technical. Can you get a real product surface into iMessage itself, when Apple gives you nothing resembling a server-side API for sending or reading messages?
Fyt answers runs and gym sessions into the group chat today, so yes. This is the option space we walked, the route that works, and the bill for it.
The option space
There are three doors, and Apple only labels two of them.
- iMessage apps and extensions. The blessed path. You get a sanctioned UI inside the compose area, and it dies the moment you want something to post itself. An extension runs when a user taps into it. It does not wake up because a run finished twenty minutes ago on a watch. If your product is passive announcement, this is the wrong tool no matter how supported it is.
- Messages for Business. A real API with real server access, and it is a customer-support channel by design. It models a one-to-one thread between a person and a business identity. A group chat between friends is not a thing it can represent.
- A Mac driving Messages.app. Messages on macOS keeps a SQLite database at
~/Library/Messages/chat.dband the app itself can be driven from the outside. Read the database for inbound, drive the app for outbound, and you have both directions in an existing group thread. This is the only route that gets you there, and it is the one Apple never promised anyone.
The one that works
Fyt runs the third option. A relay process on a Mac mini polls chat.db for new rows and forwards them to the API; outbound announcements come back through the same box and go out by driving Messages.app. The bot in the chat is called runbot, it has been there since the first version, and the iOS and watchOS app grew out of it rather than replacing it. The phone records the run. The Mac announces it.
Everything above the relay is ordinary: a Fastify API, Postgres, a job queue. The unusual part is that the entire social surface of the product rests on one consumer machine reading a database Apple never documented and automating an app Apple never intended to be automated.
What breaks
- The schema is not yours.
chat.dbcolumn layouts and text encoding shift between macOS releases. Treat every read as a parse that can fail, and keep fixtures of real rows so you notice when a system update moves something before your users do. - Outbound can vanish under you. A macOS update changed how scripted group sends behave and took our announcements down while the rest of the product ran fine. When the surface is unofficial, an OS update is a breaking API change with no changelog and no deprecation window.
- Attribution is the hard identity problem. Mapping a message in a thread to an account is fiddly, people text from numbers and addresses you have not seen, and getting it wrong in a group chat is loud and public.
- Delivery is best-effort, so design like it. A dropped announcement must be an annoyance, never a lost workout. The database is the record. The chat is the broadcast.
- Keep the chat surface thin. We shipped gym logging as text in the chat, because the whole premise was that the chat is the product. We retired it on 2026-07-09 and moved logging into the app. Chat is right for announcements and questions and wrong for structured input, and we paid weeks to find where that line sits.
- The Mac is a single point of failure with a power cable. Watchdogs, backups, and a plan for the day it reboots while you are somewhere else.
Would we do it again
Yes, with eyes open. The zero-install property is the product: one person in the group installs Fyt, and everyone else just sees runs show up in the thread they already read. No sanctioned Apple surface offers that today. The price is owning an integration Apple can move under you at any point, and the mitigation is the boring one, which is designing so the chat never holds the only copy of anything.
Fyt is on the App Store for iOS 17 and watchOS. If you are building on a surface like this and want to compare notes, the chat works: text runbot@fyt.life.