GrokReply

Inspiration

Replying to iMessages shouldn't feel like a chore. Whether you're juggling conversations, struggling to find the right words, or just want to inject some humor into your texts, we wanted an AI assistant that lives right alongside Messages.app—not in a separate tab or app you have to switch to.

What it does

GrokReply is a macOS companion that generates contextual reply suggestions for your iMessage conversations in real-time. It:

  • Auto-syncs with Messages.app - Detects which conversation you're viewing and pulls the full message history
  • Appears when you need it - Automatically shows/hides when Messages.app is focused
  • Generates 5 distinct reply styles - brief, verbose, witty, rizz (flirty), and jerk (sarcastic roasts)
  • One-click sending - Click any suggestion or press ⌘1-5 to send instantly via AppleScript
  • "More like this" - Generate 4 additional variations of any style you like
  • Emoji toggle - Strip emojis from all suggestions with one click
  • Multi-provider support - Switch between Grok, Claude, and GPT-5

How we built it

Tech Stack:

  • Electron + React + TypeScript
  • Tailwind CSS v4
  • Vite for blazing fast HMR
  • better-sqlite3 for contact caching
  • xAI Grok API (with Claude and GPT-5 fallbacks)

The Architecture:

The app runs as an always-on-top overlay that automatically shows/hides based on Messages.app focus. We use AppleScript to detect the active conversation and query the local chat.db SQLite database for message history.

Challenges we ran into

The Contact Resolution Nightmare

One of the biggest hurdles was resolving phone numbers to human-readable names. Apple's Contacts database uses a complex multi-table schema with computed values that aren't directly queryable. We tried:

  1. Direct Contacts.app database queries - Failed due to permission issues and complex schema
  2. AppleScript Contacts queries - Worked but was painfully slow (2+ seconds per lookup)
  3. AddressBook framework - Required native bindings we didn't have time to set up

Our solution: We built a SQLite caching layer that stores contact lookups locally. The first lookup for a number uses AppleScript, but subsequent lookups are instant from cache. This hybrid approach gives us the reliability of AppleScript with the speed of a local database.

Reading the iMessage Database

macOS heavily protects ~/Library/Messages/chat.db. Getting Full Disk Access permission was just the first hurdle—we also had to:

  • Handle the complex join between message, handle, and chat_message_join tables
  • Deal with the fact that phone numbers can appear in multiple formats (+1, with/without country code, etc.)
  • Parse the attributedBody blob for newer message formats
  • Navigate the conversation GUID format which differs between SMS, iMessage, and group chats

Window Management Hell

Getting the overlay to behave correctly was surprisingly tricky:

  • transparent: true causes rounded corners on macOS (even with roundedCorners: false)
  • Had to use transparent: false with backgroundColor: '#000000' instead
  • The vibrancy effect also adds unwanted rounded corners
  • Focus stealing was a constant battle—we wanted the window visible but not stealing keyboard focus from Messages.app

The Emoji Problem

LLMs have an annoying habit of sprinkling emojis everywhere 🎉✨😊 even when you explicitly tell them not to. For casual texting, this makes responses feel unnatural and try-hard—nobody texts like that.

We added a :) / :| toggle in the header that strips all emojis from suggestions using a comprehensive Unicode regex that covers emoticons, symbols, flags, and all the weird Unicode emoji ranges. Click :) to keep emojis, click :| to banish them. Simple, cute, and surprisingly necessary.

Accomplishments that we're proud of

  • The UI is clean - Minimal, dark, monospace aesthetic that feels native to the terminal-loving developer yet with modern, minimal css glow touches
  • Full conversation context - We look back at up to 15 messages to generate contextually-aware replies, not just responding to the last message
  • It actually works - The AppleScript integration for sending messages is seamless—click and it's sent
  • Five distinct tones - Each style genuinely feels different, from the curt "omw" brief style to the sarcastic jerk roasts

What we learned

  • macOS sandboxing is no joke—getting access to system databases requires careful permission handling
  • AppleScript is ancient but incredibly powerful for macOS automation
  • Electron's window management has many gotchas on macOS specifically
  • Contact resolution is a solved problem that Apple has made unsolvable for third-party developers

What's next for GrokReply

  • Keyboard-only workflow - Full vim-style navigation without touching the mouse
  • Custom tones - Let users define their own reply styles with custom prompts
  • Learning from usage - Track which suggestions you actually send to improve future generations
  • Group chat support - Better handling of multi-person conversations with @mentions
  • Scheduled sending - Queue up messages to send later

Built With

  • electron
  • react
  • typescript
  • tailwindcss
  • vite
  • sqlite
  • xai-grok
  • anthropic-claude
  • openai-gpt5
  • applescript

Built With

Share this project:

Updates