Read-only access to your macOS iMessage/SMS/RCS history from Claude Code. Browse conversations, search messages, and inspect attachments with natural language.
# From Claude Code — add the marketplace, then install the plugin
/plugin marketplace add jondwillis/imessage-plugin
/plugin install imessage@jondwillis-imessage-plugin
# Or copy the command file directly to your user commands
mkdir -p ~/.claude/commands
cp commands/imessage.md ~/.claude/commands/imessage.mdJust describe what you want:
/imessage show my recent conversations
/imessage show messages from +15551234567
/imessage search for "dinner" in my messages
/imessage show messages from last week with [email protected]
/imessage list group chats
/imessage show attachments in my chat with Alice
/imessage who did I text most this month?
The plugin gives Claude a library of SQL query templates for the Messages database at ~/Library/Messages/chat.db. When you describe what you want, Claude picks the right template, fills in your parameters, and runs it via sqlite3 -readonly. No intermediate server — the data never leaves your machine.
Tool access is scoped to Bash(sqlite3:*) only, and every query runs against a read-only SQLite handle. The plugin cannot send, modify, or delete messages.
On modern macOS/iOS, Apple stores most message text in the attributedBody BLOB (a
typedstream archive) and leaves the plain message.text column NULL — often for
the overwhelming majority of a chat. A naïve WHERE text LIKE '%...%' search is blind
to those messages: it returns zero rows because it searched a mostly-empty column, not
because nothing matched. That makes "no results" dangerously easy to misread as "never
happened."
This plugin ships lib/decode.sql, a pure-SQLite decoder loaded with .read that
exposes a msg temp view with an always-decoded body column. Every read and search
goes through body, so it covers both storage formats. The decoder was validated
byte-for-byte against a typedstream parser across an entire chat.db
(53,517/53,517 blob-only messages matched), and needs no Python, Perl, or other
dependency — just the sqlite3 already on your Mac.
The command prompt also includes explicit "report results honestly" guidance: zero rows is never reported as "never happened," surprising negatives trigger a coverage check instead of a conclusion, and the assistant states the exact scope it searched rather than inflating it.
| Object | Operations |
|---|---|
| Conversations | List recent, Search by display name |
| Messages | Read paginated (25/page), Keyword search (per-chat or global), Date-range filter |
| Contacts | List recent, Lookup by phone/email, Show last-message date |
| Group chats | List, Search, List members |
| Attachments | List, Filename/mime/size metadata |
| Filters | Exclude tapback reactions by default |
| Text decoding | Decodes attributedBody so search/read see all messages, not just the few with a non-NULL text column |
- Read-only: cannot send, edit, or delete messages
- No contact names: the database stores phone numbers and emails only — Claude lists recent handles so you can identify who's who
- Tapbacks filtered: reaction messages (👍, ❤️, etc.) are hidden by default; ask explicitly if you want them
- Retracted/attachment-only messages: even after decoding, a small set has no text (
bodyis NULL) — Claude will note this when it shows them - First run requires granting Full Disk Access to your terminal app in System Settings > Privacy & Security > Full Disk Access
Your messages are personal. This plugin:
- Runs every query with
sqlite3 -readonly— the database cannot be modified - Sends no data to any external service — queries and results stay local between Claude Code and your machine
- Scopes tool access to
Bash(sqlite3:*)— no arbitrary shell commands
If you're using Claude Code with a cloud-hosted model, message contents you ask Claude to read will be sent to that model as part of the conversation. Keep this in mind when querying sensitive threads.
- macOS with Messages.app
- Full Disk Access granted to your terminal app
- SQLite3 (pre-installed on macOS)
- Claude Code