mirror of
https://github.com/anthropics/claude-plugins-official.git
synced 2026-03-19 23:23:07 +00:00
iMessage bridge for Claude Code. Reads ~/Library/Messages/chat.db directly for history and new-message polling; sends via AppleScript to Messages.app. macOS only. Built-in access control: inbound messages are gated by an allowlist (default: self-chat only), outbound sends are scoped to the same allowlist. The /imessage:access skill manages allowlists and policy. Requires Full Disk Access and Automation TCC grants — both prompted by macOS on first use. Ships full source — server.ts runs locally via bun, started by the .mcp.json command.
76 lines
3.5 KiB
Markdown
76 lines
3.5 KiB
Markdown
# iMessage
|
|
|
|
Connect iMessage to your Claude Code assistant. Reads `~/Library/Messages/chat.db` directly for history, search, and new-message detection; sends via AppleScript to Messages.app. No external server, no background process to keep alive.
|
|
|
|
macOS only.
|
|
|
|
## Quick setup
|
|
> Default: text yourself. Other senders are dropped silently (no auto-reply) until you allowlist them. See [ACCESS.md](./ACCESS.md) for groups and multi-user setups.
|
|
|
|
**1. Grant Full Disk Access.**
|
|
|
|
`chat.db` is protected by macOS TCC. The first time the server reads it, macOS pops a prompt asking if your terminal can access Messages — click **Allow**. The prompt names whatever app launched bun (Terminal.app, iTerm, Ghostty, your IDE).
|
|
|
|
If you click Don't Allow, or the prompt never appears, grant it manually: **System Settings → Privacy & Security → Full Disk Access** → add your terminal. Without this the server exits immediately with `authorization denied`.
|
|
|
|
**2. Install the plugin.**
|
|
|
|
These are Claude Code commands — run `claude` to start a session first.
|
|
|
|
Install the plugin. No env vars needed.
|
|
```
|
|
/plugin install imessage@claude-plugins-official
|
|
```
|
|
|
|
**3. Relaunch with the channel flag.**
|
|
|
|
The server won't connect without this — exit your session and start a new one:
|
|
|
|
```sh
|
|
claude --channels plugin:imessage@claude-plugins-official
|
|
```
|
|
|
|
Check that `/imessage:configure` tab-completes.
|
|
|
|
**4. Text yourself.**
|
|
|
|
iMessage yourself from any device. It reaches the assistant immediately — self-chat bypasses access control.
|
|
|
|
> The first outbound reply triggers an **Automation** permission prompt ("Terminal wants to control Messages"). Click OK.
|
|
|
|
**5. Decide who else gets in.**
|
|
|
|
Nobody else's texts reach the assistant until you add their handle:
|
|
|
|
```
|
|
/imessage:access allow +15551234567
|
|
```
|
|
|
|
Handles are phone numbers (`+15551234567`) or Apple ID emails (`them@icloud.com`). If you're not sure what you want, ask Claude to review your setup.
|
|
|
|
## How it works
|
|
|
|
| | |
|
|
| --- | --- |
|
|
| **Inbound** | Polls `chat.db` once a second for `ROWID > watermark`. Watermark initializes to `MAX(ROWID)` at boot — old messages aren't replayed on restart. |
|
|
| **Outbound** | `osascript` with `tell application "Messages" to send …`. Text and chat GUID pass through argv so there's no escaping footgun. |
|
|
| **History & search** | Direct SQLite queries against `chat.db`. Full history — not just messages since the server started. |
|
|
| **Attachments** | `chat.db` stores absolute filesystem paths. The first inbound image per message is surfaced to the assistant as a local path it can `Read`. Outbound attachments send as separate messages after the text. |
|
|
|
|
## Access control
|
|
|
|
See **[ACCESS.md](./ACCESS.md)** for DM policies, groups, self-chat, delivery config, skill commands, and the `access.json` schema.
|
|
|
|
Quick reference: IDs are **handle addresses** (`+15551234567` or `someone@icloud.com`). Default policy is `allowlist` — this reads your personal `chat.db`. Self-chat always bypasses the gate.
|
|
|
|
## Tools exposed to the assistant
|
|
|
|
| Tool | Purpose |
|
|
| --- | --- |
|
|
| `reply` | Send to a chat. `chat_id` + `text`, optional `files` (absolute paths). Auto-chunks text; files send as separate messages. |
|
|
| `chat_messages` | Fetch recent history from a chat (oldest-first). Reads `chat.db` directly — full native history. Scoped to allowlisted chats. |
|
|
|
|
## What you don't get
|
|
|
|
AppleScript can send messages but not tapback, edit, or thread — those require Apple's private API. If you need them, look at [BlueBubbles](https://bluebubbles.app) (requires disabling SIP).
|