jondwillis/imessage-plugin

Read-only macOS iMessage/SMS reader plugin for Claude Code

★ 0Forks 0GitHub ↗Compare

README

iMessage Plugin for Claude Code

Read-only access to your macOS iMessage/SMS/RCS history from Claude Code. Browse conversations, search messages, and inspect attachments with natural language.

Landing page | Issues

Install

# 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.md

Usage

Just 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?

How it works

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.

Reading the real message text (attributedBody)

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.

Capabilities

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

Limitations

  • 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 (body is 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

Privacy

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.

Requirements

  • macOS with Messages.app
  • Full Disk Access granted to your terminal app
  • SQLite3 (pre-installed on macOS)
  • Claude Code

License

MIT

Issues