imessage — Claude Code plugin: iMessage bridge
Connects iMessage to Claude: reads chat.db for history, sends via AppleScript. macOS only.
/plugin install imessage@claude-plugins-official
/plugin marketplace add anthropics/claude-plugins-officialWhat imessage does
This plugin turns iMessage into a channel for your assistant. Inbound messages come from ~/Library/Messages/chat.db, polled once a second for ROWID > watermark, so nothing old gets replayed after a restart. Outbound replies go through osascript to Messages.app. No external server, no background process to keep alive.
History and search run as direct SQLite queries against the same database, covering the full conversation rather than only what arrived since boot. Images in inbound messages reach the assistant as local paths (image_path, image_path_2, and so on) it can read. Outbound text gets a Sent by Claude signature unless you set IMESSAGE_APPEND_SIGNATURE=false.
Before the first run you need Full Disk Access. macOS TCC guards chat.db, and without permission the server exits right away with authorization denied. SMS is the other thing to watch: IMESSAGE_ALLOW_SMS defaults to false because SMS sender IDs can be spoofed, and a forged message from your own number would slip past access control. Turn it on only if you accept that. AppleScript sends messages but can't do tapback, edits, or threads — those need Apple's private API.
What it helps with
- text your assistant from iMessage and get the reply in the same thread
- search through past iMessage conversations
- control whose messages reach the assistant
- hand an inbound image to the assistant for review
- send a file by absolute path from a session
Example prompts for the agent
- Allow +15551234567 with /imessage:access
- Show me the recent messages from that chat
- Reply in that chat: the meeting moves to tomorrow
How to install imessage
Plugin marketplace
/plugin install imessage@claude-plugins-official/plugin marketplace add anthropics/claude-plugins-officialStep by step, with commands for each platform: Claude Code plugins: marketplaces, installing, and building your own
Questions about imessage
How do I install imessage in Claude?
Add the marketplace first: /plugin marketplace add anthropics/claude-plugins-official, then install the plugin: /plugin install imessage@claude-plugins-official. After that, exit the session and start claude --channels plugin:imessage@claude-plugins-official.
What does the imessage plugin do?
It bridges iMessage and your Claude assistant: reads chat.db for history and new messages, sends replies through AppleScript. Access control is built in.
Why does the server exit with authorization denied?
Your terminal lacks Full Disk Access, and macOS TCC protects chat.db. Add the terminal under System Settings → Privacy & Security → Full Disk Access.
Source text
imessage · Apache-2.0
# 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 required.
```
/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 (`[email protected]`). 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. Every inbound image in a message is surfaced to the assistant as a local path it can `Read` (`image_path`, `image_path_2`, …). Outbound attachments send as separate messages after the text. |
## Environment variables
| Variable | Default | Effect |
| --- | --- | --- |
| `IMESSAGE_APPEND_SIGNATURE` | `true` | Appends `\nSent by Claude` to outbound messages. Set to `false` to disable. |
| `IMESSAGE_ALLOW_SMS` | `false` | Accept inbound SMS/RCS in addition to iMessage. **Off by default because SMS sender IDs are spoofable** — a forged SMS from your own number would otherwise bypass access control. Only enable if you understand the risk. |
| `IMESSAGE_ACCESS_MODE` | — | Set to `static` to disable runtime pairing and read `access.json` only. |
| `IMESSAGE_STATE_DIR` | `~/.claude/channels/imessage` | Override where `access.json` and pairing state live. |
## 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 `[email protected]`). 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 as conversation threads. Each thread is labelled **DM** or **Group** with its participant list, then timestamped messages (oldest-first). Omit `chat_guid` to see every allowlisted chat at once, or pass one to drill in. Default 100 messages per chat. Reads `chat.db` directly — full native history. |
## 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).
© anthropics · Apache-2.0 · anthropics/claude-plugins-official