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:
- Direct Contacts.app database queries - Failed due to permission issues and complex schema
- AppleScript Contacts queries - Worked but was painfully slow (2+ seconds per lookup)
- 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, andchat_message_jointables - 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: truecauses rounded corners on macOS (even withroundedCorners: false)- Had to use
transparent: falsewithbackgroundColor: '#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
- electron
- react
- sqlite
- tailwind
- typescript
- vite
Log in or sign up for Devpost to join the conversation.