Start

Quickstart

Goal: install imsg, grant the two permissions it needs, and walk through the read → watch → send loop.

#1. Install

brew install steipete/tap/imsg
imsg --version

If you'd rather build from source, follow Install.

On Linux, use the read-only preview with an existing Messages database copied from macOS. The rest of this quickstart is macOS-focused because watching the live database and sending require Messages.app.

#2. Grant Full Disk Access

imsg reads ~/Library/Messages/chat.db directly. macOS protects that file behind Full Disk Access.

  1. System Settings → Privacy & Security → Full Disk Access.
  2. Add the terminal you'll run imsg from (Terminal.app, iTerm2, Ghostty, WezTerm, …).
  3. If your shell launches imsg from another app — an editor, a Node process, an SSH server — grant Full Disk Access to that parent process too.
  4. Quit and re-open the terminal so the new grant takes effect.

Sanity-check:

imsg chats --limit 3

You should see the three most recent conversations. If not, see Permissions.

#3. Read history

# Pick a chat from `imsg chats`, then:
imsg history --chat-id 42 --limit 10
imsg history --chat-id 42 --limit 10 --json | jq -s

--json is one JSON object per line. Pipe it to jq -s to materialize an array, or stream it to whatever consumer you're wiring up.

Filter by date or participant:

imsg history --chat-id 42 \
  --start 2026-05-01T00:00:00Z \
  --end   2026-05-06T00:00:00Z \
  --json

#4. Stream new messages

imsg watch --chat-id 42 --json

Leave it running. Send yourself a message from another device — you'll see the row arrive within a second or so. To include tapbacks:

imsg watch --chat-id 42 --reactions --json

To resume from a saved cursor (useful for agents that store the last seen id):

imsg watch --chat-id 42 --since-rowid 9000 --json

See Watch for debounce tuning, the polling fallback, and the full event schema.

#5. Send a message

Sending requires one more permission:

  1. System Settings → Privacy & Security → Automation → Messages.
  2. Toggle on the terminal (and any wrapper app) so it can drive Messages.app.

Then:

imsg send --to "+14155551212" --text "hi"
imsg send --to "Jane Appleseed" --text "see attached" --file ~/Desktop/note.pdf
imsg send --chat-id 42 --text "same thread"

send --to accepts a phone number, an iMessage email, or a contact name (resolved via Contacts). For groups, prefer --chat-id. See Send for service selection (imessage, sms, auto) and the Tahoe ghost-row failure check.

#6. Where to go next

  • Chats — what each field in a chat object means.
  • JSON output — the stable schema agents should consume.
  • JSON-RPC — same surfaces, but over stdio with a single long-running process.
  • Attachments — metadata, original paths, and CAF/GIF conversion.
  • Linux read-only preview — inspect a copied macOS Messages database on Linux.
  • Troubleshooting — when reads silently return nothing.