Skip to content

Messages (trill)

trill is your Messages, native. A fast, flat, keyboard-first client for iMessage, SMS, and RCS in a real macOS window — it reads your real conversations straight from Apple’s chat.db (always read-only) and sends by driving Messages.app. It’s themed in nebelung like the rest of the house, ships by default in the rice, and also stands alone on any Mac.

trill rides in the rice by default (nebelhaus.trill.enable = true — see options). To install it standalone, or on a Mac without the rice:

Terminal window
brew install --cask nebelhaus/tap/trill

The app is signed with our Apple Developer ID and notarized by Apple, so the cask installs it and it opens straight away — no Gatekeeper prompt. If you build or copy the app by hand instead of via the cask, macOS may quarantine your copy; clear it yourself:

Terminal window
xattr -dr com.apple.quarantine /Applications/Trill.app

trill opens in Synthetic Fixture mode (deterministic sample data, no permissions). Switch the provider to Messages in Settings to read your real conversations. It asks for only what a given feature needs, when it needs it:

  1. Full Disk Access — required to read ~/Library/Messages/chat.db. Grant it to the Trill app bundle (not Terminal) in System Settings → Privacy & Security → Full Disk Access. Selecting the Messages provider runs a read-only probe first and links you here if the grant is missing. macOS only hands the new access to a fresh process, so trill offers a Relaunch Trill button rather than making you quit and reopen it yourself.

  2. Automation (“control Messages”) — prompted the first time you send. This is how trill sends without ever writing to chat.db.

  3. Contacts (optional) — grants names and contact photos. Without it, names still resolve by reading the local AddressBook (covered by Full Disk Access); only photos are missing.

  4. Notifications (optional) — prompted on first launch with the live provider, for incoming-message banners with inline reply.

Grant something while trill is in the background and it re-checks on return, so Automation and Contacts start working the moment you switch back — no Recheck button, no restart. Full Disk Access is the one exception, hence the relaunch.

trill is a triage tool, not just a viewer — everything Messages can’t do:

  • Read everything — iMessage/SMS/RCS threads, reactions grouped by emoji, quoted replies with jump-to-original, edited/unsent markers, inline image thumbnails, Quick Look on attachments, group avatars, and a Dock unread badge.
  • Send — text and attachments (paperclip / drag-drop / paste), ⌘N to compose to any contact with autocomplete, and a 5-second undo-send window.
  • Search — ⌘K command palette to jump anywhere, ⇧⌘F global message search with operators (from:, in:group, has:link, has:image, before:/ after:, is:unread), and ⌘F find-in-thread (⌘G / ⇧⌘G to step matches).
  • Universal Library (⌘⇧L) — one browser for every image, link, file, and saved message across all conversations, with jump-to-source.
  • Organize — folders/tags, VIP (always-notify + always-pin), snooze, archive, mute, and service filters (toggle iMessage/SMS/RCS), all composable and local-only.
  • Triage — ⇧⌘R filters to threads whose last message is from them and still unanswered; a per-thread stats panel shows counts, reply-time medians, and most-active hours.
  • Compose faster — snippets and slash-commands (/shrug, /date, …) from one /-trigger picker, fill-in-the-blank templates, and persistent drafts (with a Drafts filter to find the ones you abandoned).
  • Scroll back without asking — threads load 100 messages at a time and fetch the next page automatically as you near the top. Load Earlier Messages is still there if you’d rather drive.
  • Stay ambient — a menu-bar mini-inbox with unread count, conversation tabs (⌘T) to keep several threads open, and ⌘[ / ⌘] to walk recently-viewed threads.

trill ships an in-app cheat-sheet — press ⌘/ any time. The essentials:

KeysAction
⌘KCommand palette (jump to any thread/action)
⇧⌘FGlobal message search
⌘F / ⌘GFind in thread / next match
⌘⇧LUniversal Library
⌘NCompose to a contact
⌘T / ⌘⇧] ⌘⇧[New tab / switch tabs
⌘[ / ⌘]Back / forward through recent threads
⇧⌘RNeeds-reply filter
⌘JJump to date
⌘+ / ⌘− / ⌘0Zoom

trill ships all four nebelung variants compiled in — dark or latte, normal or high contrast — and picks between them in Settings ▸ Theme: Follow macOS, Dark, or Light, plus which palette each polarity uses. Nothing to rebuild, and it applies the moment you pick it. The accent, display density, and zoom live in the same pane.

Anything else is a file. Drop a flat name → "#hex" JSON — nebelung’s own *.hex.json, or a stock Catppuccin flavor — into ~/.config/trill/themes/ and it appears in those menus:

Terminal window
mkdir -p ~/.config/trill/themes
curl -o ~/.config/trill/themes/my-palette.json https://example.com/palette.json

A file shadows a built-in of the same name, so naming yours nebelung.json replaces trill’s idea of nebelung. That’s how the rice keeps an installed trill current: on nebelhaus it writes every rendered variant there and names the pair your theme.flavor / theme.contrast select, so trill follows the house palette. Your own pick in Settings still wins.

trill exports threads to Markdown, plain text, or HTML — a single thread and date-range from the conversation header (-up-arrow button), or every conversation as one Markdown file per thread in a .zip from Settings → Export. The bulk export is framed as “ready to hand to an LLM”: it’s the clean corpus for feeding your own history to a model. It’s read-only throughout — nothing is sent anywhere or written back to chat.db.

Messages → Writing Style Profile… builds a portrait of how you actually write — across everyone, or for one thread from the conversation toolbar. Copy it or save it as Markdown.

It’s computed on your Mac by counting things, not by asking a model: no AI, no network, nothing leaves the machine. The output is meant for you to paste into an assistant yourself, so it can write in your voice without ever being handed your messages.

  • trill displays tapbacks, threaded replies, and edits, but can’t send them — the native (AppleScript) send path has no automation surface for them, so those actions aren’t offered rather than faked.
  • Attachments your Mac has offloaded to iCloud show as “In iCloud” rather than downloading on demand — fetching them is Messages.app’s job, and trill says so instead of pretending the file is missing.
  • It reads chat.db; it does not sync, relay, or push. There’s no server and no network messaging (a future BlueBubbles relay is designed-for but not built).
  • Any future AI/summarization feature is gated on a separate privacy review — local-first, nothing leaves the device without an explicit decision.
  • “Messages” provider won’t turn on — it needs Full Disk Access on the Trill app bundle (not Terminal). Grant it in System Settings, then reselect the provider.
  • First send does nothing / prompts forever — approve the Automation (“control Messages”) prompt; that’s the send path.
  • Names show as numbers — grant Contacts (or rely on AddressBook via Full Disk Access); photos need Contacts specifically.
  • Gatekeeper blocks a hand-copied buildxattr -dr com.apple.quarantine /Applications/Trill.app (the cask does this for you).
  • Full guide to the app’s design and roadmap lives in the trill repo (README, ARCHITECTURE.md, docs/).