cmux-imessage: read-only Messages database reader for the opt-in Messages mirror

Merged
TE
4d ago
+825-0

Leo's ask: "i mean like obviously we already are in an imessage type zone im saying like actual imessage chats with contacts/group chats" ... "hm. could we mirror it?"

This is the first step of an opt-in, off-by-default Messages mirror in cmux NEXT: a read-only reader of the macOS Messages database. It adds no UI and nothing calls it yet. The daemon ops and the page come in the next PR.

What it does

New crate cmux-tui/crates/cmux-imessage:

  • Reader::open(path) opens ~/Library/Messages/chat.db with SQLITE_OPEN_READ_ONLY. It never writes. A TCC denial (no Full Disk Access) returns NotPermitted, a missing file Missing, and a database without the Messages tables Schema.
  • threads(limit): 1:1 and group chats, newest activity first. Each one carries its title (the group name, else the participants), is_group, its participants and a last-message preview.
  • messages(chat_id, before_rowid, limit): one thread's messages, oldest first, paged back by rowid. Text comes from message.text, or is decoded from the attributedBody typedstream that recent macOS versions use instead. Attachment names and MIME types are included; tapbacks and group events are left out.
  • since(rowid, limit) and latest_rowid(): the watermark that live updates will use.

Nothing leaves the Mac. The crate has no network code, and attachment files are never copied.

Tests

Two commits: the failing tests against stubs (9 of 10 red), then the reader (10 of 10 green, clippy -D warnings clean). The fixture databases are built from the Messages schema: group naming and fallback, preview skipping tapbacks, attributedBody short/long/unicode/garbage, paging, the watermark across chats, and the missing/schema/not-permitted errors.

Follow-ups (next PRs): the daemon resource messages.mirror.* with a file-watch change event, the webview page and the off-by-default setting; then sending through Messages.app. Contact names are a follow-up too.

Agent session: agent session

🤖 Generated with Claude Code


Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Adds the cmux-imessage crate: a read-only reader of the macOS Messages database (~/Library/Messages/chat.db) that backs an opt-in, off-by-default Messages mirror in cmux NEXT. Nothing calls it yet; the daemon resource, live-update file watcher, and UI come in the next PRs.

New Features

  • Opens with SQLITE_OPEN_READ_ONLY, never writes, never copies attachment files, and has no network code.
  • Maps a TCC denial to NotPermitted so the UI can ask for Full Disk Access, a missing file to Missing, and an unfamiliar schema to Schema.
  • Lists 1:1 and group threads newest-first with participants, group names, and a last-message preview; skips tapbacks and group events.
  • Pages a thread's messages oldest-first by rowid, decoding text from the attributedBody typedstream when message.text is empty; includes attachment names and MIME types.
  • Provides since() and latest_rowid() as the watermark live updates will use.
  • Tested against fixture databases built from the Messages schema, covering group naming, attributedBody variants, paging, the watermark, and all three open errors.