Conversation
A local macOS bridge, started by the server when IMESSAGE_HANDLES is set. It reads new incoming one-to-one messages from the Messages database (read-only) and replies through Messages via AppleScript, with the reply passed as an argument rather than interpolated into the script. - Only allowlisted phone numbers / Apple ID emails are answered. - One persistent Dot conversation per sender; "/new" starts another. - History is never answered; the cursor advances before replying so a failure never double-answers; stale (>1h) messages and echoes of the bridge's own replies are skipped. - Archived attributedBody text is decoded; Apple nanosecond dates are converted in SQL to avoid overflowing JS numbers. - Settings show the bridge status, including missing Full Disk Access. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Workflow
Text your Dot from your phone. When OpenDots runs natively on a Mac signed in to Messages, it answers allowlisted phone numbers and Apple ID emails. Each sender gets one persistent Dot conversation, which is also visible in the web app. Texting
/newstarts a fresh one.Setup is
IMESSAGE_HANDLES=+15551234567,me@icloud.com, with optionalIMESSAGE_DOT_IDandIMESSAGE_DB_PATH, plus Full Disk Access for the app that launches OpenDots. It's documented indocs/IMESSAGE.md.How it works
IMESSAGE_HANDLESis set and the platform isdarwin. On other platforms the setup status readsunsupported.~/Library/Messages/chat.db, opened read-only, for new incoming messages in one-to-one chats (chat.style = 45). Group chats and the owner's own messages are ignored. Whenmessage.textis empty, the body is decoded from the archivedattributedBody.Platform.turn(), the same server-side path scheduled tasks use. The model gets nothing new: approval-gated client tools aren't available in headless turns.osascript. The handle and reply text are passed as argv, never inserted into the AppleScript source. Markdown is converted to readable plain text first.Safety and robustness:
needs Full Disk Accessin Settings instead of crashing the server.Verification
npm run check-format,lint,typecheck,test(173 passing, 9 new) andbuildall pass.tests/imessage.test.tsbuilds a fixturechat.dbwith the real table layout. It covers:/new, the paused reply, recovery from a failed turn, and the no-access status🤖 Generated with Claude Code