A standalone Swift library and CLI that lets you and your agents send/receive messages and fully automate iMessage locally on your Mac.
Reads chat.db and works with automation and accessibility APIs – similar to Codex Computer Use but surgical and faster. Designed to run with the normal macOS security model (System Integrity Protection (SIP) enabled) since it does not hook into low-level private APIs or make any network calls. Uses your Apple ID logged in to Messages.app. ~95% feature parity on macOS Tahoe.
This library powers the iMessage integration on Beeper for macOS. N-API bindings for Node/Electron are powered by node-swift.
What it won't do: expose more features if you disable SIP, allow automating multiple iMessage accounts, work on Windows/Linux. Also see TODOs.
| Feature | platform-imessage | BlueBubbles (SIP enabled) |
|---|---|---|
Read chats and messages from chat.db |
✅ | ✅ |
| Realtime message updates | ✅ | ✅ |
| Receive tapbacks, stickers, mentions, replies | ✅ | ✅ |
| Send text messages | ✅ | ✅ |
| Send attachments | ✅ | ✅ |
| Create 1:1 chats | ✅ | ✅ |
| Create group chats | ✅ | ❌* |
| Send replies / quoted messages | ✅ | ❌* |
| Send / remove tapbacks/reactions | ✅ | ❌* |
| Edit sent messages | ✅ | ❌* |
| Undo send | ✅ | ❌* |
| Mark chats read / unread in Messages.app | ✅ | ❌* |
| Send typing indicators | ✅ | ❌* |
| Notify anyway / Focus bypass | ✅ | ❌* |
| Search messages | ✅ | Partial* |
| Group management: rename, add/remove members, leave, update photo | Planned | ❌* |
| Rich sends: effects, subjects, attachment captions | Planned | ❌* |
| Self-hosted relay, REST API, push notifications | No | ✅ |
* BlueBubbles supports this through its Private API helper, which requires disabling SIP.
- Install:
brew install beeper/tap/imessage-cli- Or build from source:
git clone https://github.com/beeper/platform-imessage
cd platform-imessage
swift run imessage-cli # builds the Swift CLI if needed, launches authorization flow (Accessibility, Contacts, Messages data access, Automation), then opens the REPLMessages data access requires Full Disk Access on macOS 27 and later. On macOS 26 and earlier, setup requests access to the Messages folder, with Full Disk Access available as a fallback.
- Run one-off commands:
swift run imessage-cli current-user # fetch logged-in user
swift run imessage-cli chats # fetch chats as YAML by default
swift run imessage-cli --json chats # fetch chats as JSON (also: --yaml, --format json/yaml/yml)
swift run imessage-cli messages sjobs@apple.com # fetch messages for an existing chat
swift run imessage-cli send 'any;-;sjobs@apple.com' "hello from shell" # text an email
swift run imessage-cli send sjobs@apple.com "hello from shell" # text an existing email chat by address
swift run imessage-cli send +14155551234 "hello from shell" # text an existing phone chat by number
swift run imessage-cli send-file +14155551234 ./image.png # send a file
swift run imessage-cli create-chat +14155551234 --message "hey this is steve" # start a new chat with a number or email
swift run imessage-cli create-chat +15551234567 +15557654321 --message "new group" # create a group chat
swift run imessage-cli reply C0FFEE12-CAFE-4BAD-8ACE-1234FACE5678 "sounds good" # reply to an existing message
swift run imessage-cli reply latest "sounds good" # reply to the latest message (also: latest-1, last-message, lastMessage, latestMessage)
swift run imessage-cli reply latest-1 "sounds good" # reply to the message before the latest message
swift run imessage-cli reply +14155551234 latest "sounds good" # reply to the latest message in a chat
swift run imessage-cli reply +14155551234 latest-1 "sounds good" # reply to the message before the latest message in a chat
swift run imessage-cli reply-file C0FFEE12-CAFE-4BAD-8ACE-1234FACE5678 ./doc.pdf # send a file as a reply
swift run imessage-cli react C0FFEE12-CAFE-4BAD-8ACE-1234FACE5678 laugh # haha react to a message
swift run imessage-cli react C0FFEE12-CAFE-4BAD-8ACE-1234FACE5678 heart # heart a message
swift run imessage-cli react +14155551234 latest heart # heart the latest message in a chat
swift run imessage-cli react +14155551234 latest-1 heart # heart the message before the latest message in a chat
swift run imessage-cli unreact C0FFEE12-CAFE-4BAD-8ACE-1234FACE5678 laugh # remove laugh from message
swift run imessage-cli edit C0FFEE12-CAFE-4BAD-8ACE-1234FACE5678 "updated text" # edit a message
swift run imessage-cli search "project status" # search messages
swift run imessage-cli select-chat sjobs@apple.com # select chat in messages.app
swift run imessage-cli activity-status sjobs@apple.com # print typing and DND/notify-anyway status
swift run imessage-cli typing sjobs@apple.com on # send typing indicator
swift run imessage-cli mark-read sjobs@apple.com
swift run imessage-cli mark-unread sjobs@apple.com
swift run imessage-cli mute sjobs@apple.com
swift run imessage-cli unmute sjobs@apple.com
swift run imessage-cli notify-anyway sjobs@apple.com # if the recipient is on DND, hit the "notify anyway" button if present
swift run imessage-cli delete-chat sjobs@apple.com # delete the entire chatOr continue in the swift run imessage-cli shell:
imessage> messages sjobs@apple.com
imessage> send sjobs@apple.com "hello from shell"
imessage> help
imessage> help create-chat
imessage> quitThe shell will automatically subscribe to real-time events (incoming messages, etc.) unless you pass --no-events.
Note
For arrow-up recall, in development, commands you run are recorded in plain text to .cli.history.json at the repo root. This includes the plaintext of any messages sent via send/reply/edit. Released builds do not persist shell history unless IMESSAGE_CLI_HISTORY_FILE is set.
Requirements: macOS 11 or later, Swift 5.9 or later
dependencies: [
.package(url: "https://github.com/beeper/platform-imessage.git", from: "0.1.0"),
]targets: [
.target(
name: "YourTarget",
dependencies: [
.product(name: "IMessage", package: "platform-imessage"),
]
),
]- Set up with:
yarn
yarn build:swift --debug --standalone
yarn build:cli:js
- Run with
yarn cli:js. Also seesrc/cli/main.ts
- beeper/imessage – Matrix bridge that connects to Apple servers directly by identifying as an iMessage-capable Apple device
- mautrix/imessage – Matrix bridge that has a few different backends (SIP-disabled private APIs, BlueBubbles server, etc.)
- lrhodin/imessage – Matrix bridge using rustpush & bridgev2
- pypush – Original tech behind beeper/imessage
- rustpush – Rust port of pypush