Agent iMessage
An iMessage CLI for AI agents, backed by imsg — a native macOS tool that reads the local Messages database and sends through Messages.app. Apple has no public iMessage API, so this integration runs on a Mac and drives Messages locally. You act as yourself with your own Apple ID; nothing leaves the machine.
Use one of these entrypoints:
- Global install:
agent-imessage ... - One-off execution:
bunx --package agent-messenger agent-imessage ...
Key Concepts
- imsg = a local Swift CLI (
brew install steipete/tap/imsg).agent-imessagespawns it and talks to it over JSON-RPC (stdin/stdout). There is no network and no server — it must run on the Mac signed into iMessage. - On-Mac only = unlike other agent-messenger platforms, this one cannot run remotely or in a container. The agent runs on the Mac itself.
- Permissions = imsg needs Full Disk Access (to read the Messages database) and Automation → Messages (to send). macOS grants these to the parent process — the app/terminal that launches agent-messenger.
- Chat reference = for
message send, a chat id (integer rowid), a portableguid/identifier(e.g.iMessage;-;+15551234567), or a phone/email recipient. Formessage list/react/watch --chat, prefer a chat id — a guid also works but (since imsg has no guid→id lookup) is resolved against the 1000 most recent chats only. - Watch = streams new messages via imsg; resumable from a message rowid with
--since-rowid. - Multi-account = each account is an imsg configuration (binary path / region). Send is single-account (Messages has no from-selector).
- Private API tier = typing, edit/unsend, group management, custom/targeted reactions require
imsg launch(SIP disabled). Basic send/read/watch/standard tapbacks do NOT.
Quick Start
# Guided setup: checks imsg + permissions, saves an account
agent-imessage setup
# Diagnose anytime
agent-imessage doctor
# List chats (source of chat ids/guids)
agent-imessage chat list
# Send (to a chat id, guid, or a phone/email)
agent-imessage message send 42 "Hello from agent-imessage"
agent-imessage message send "+15551234567" "Hi"
# Read recent messages
agent-imessage message list 42 --limit 20
# Watch for new messages (resumable, JSON lines)
agent-imessage message watch --chat all --jsonl
# React to the most recent incoming message (standard tapbacks)
agent-imessage message react 42 love
Setup & Permissions
iMessage runs on the Mac via imsg. One-time setup:
brew install steipete/tap/imsg- Sign Messages.app into your Apple ID (a dedicated Apple ID is recommended).
- Grant Full Disk Access to the app/terminal launching agent-messenger (System Settings → Privacy & Security → Full Disk Access). macOS grants to the parent process.
- Grant Automation → Messages when first prompted (needed to send).
See setup and permissions references for detail.
Configuration is scriptable too:
agent-imessage auth set --bin /opt/homebrew/bin/imsg --region US --current
Environment overrides (runtime only, not persisted): AGENT_IMESSAGE_BIN, AGENT_IMESSAGE_REGION.
Agent Behavior (MANDATORY)
When a command fails, the agent MUST run agent-imessage doctor and act on the suggestion/code rather than telling the user to run commands. If code is imsg_not_found, guide installing imsg. If full_disk_access or automation_denied, surface the exact System Settings path (and that macOS grants to the parent process). Never silently retry the same failing call.
Commands
setup— guided check + save account.doctor [--account <id>] [--test-chat <chatId>]— diagnose imsg + permissions.auth set|list|use|remove|logout— manage accounts (binary path / region).chat list [--limit]/chat search <query> [--limit].message list <chat> [--limit] [--start <iso>]— read history (oldest-last).<chat>= chat id (recommended) or recent-chat guid.message send <chat> <text>—<chat>= chat id/guid or phone/email.message react <chat> <reaction>— standard tapback to the most recent incoming message.message watch [--chat <ref|all>] [--since-rowid <n>] [--jsonl]— stream new messages.whoami— active account + imsg status.
All commands accept --account <id> and --pretty.
Output Format
JSON by default; --pretty for indented output. message watch --jsonl emits one JSON object per line.
Feature Tiers
| Feature | Available | Requires |
| --- | --- | --- |
| List/search chats, send text, read/watch messages | ✅ | imsg core (no SIP) |
| Standard tapbacks, to the most recent incoming message | ✅ | imsg core (no SIP) |
| React to a specific message / custom-emoji tapbacks | ⏳ planned | imsg bridge (imsg launch + SIP) |
| Typing, read receipts, edit/unsend, group management | ⏳ planned | imsg bridge (imsg launch + SIP) |
Error Handling
Errors are JSON with a code and often a suggestion:
| Code | Meaning | Action |
| --- | --- | --- |
| imsg_not_found | imsg binary not runnable | brew install steipete/tap/imsg (or set --bin/AGENT_IMESSAGE_BIN). |
| full_disk_access | Can't read Messages DB | Grant Full Disk Access to the launching app (parent process). |
| automation_denied | Can't control Messages | Grant Automation → Messages in System Settings. |
| not_authenticated | No account configured | Run agent-imessage setup. |
| chat_not_found | Unknown chat ref | Use a chat id/guid from chat list. |
| private_api_required | Feature needs the bridge | Standard send/read/watch/tapbacks work without it; targeted/custom reactions need imsg launch (SIP off). |
| invalid_limit | Bad --limit/--since-rowid | Use an integer 1–100 for --limit; non-negative integer for --since-rowid. |
| send_failed | imsg could not send | Run doctor; on macOS 26 group sends can fail (imsg reports honestly). |
| rpc_error | imsg rpc problem | Run doctor; check the imsg version. |
Troubleshooting
agent-imessage doctoris the fastest diagnostic — it reports imsg version, Full Disk Access, and the bridge tier.- Permissions denied — remember macOS grants Full Disk Access / Automation to the parent process (the terminal or agent runtime), not just
imsg. - Reactions only hit the latest message — that's an imsg/AppleScript limitation without the bridge; reacting to a specific message needs
imsg launch+ SIP off.
Configuration
Account config is stored in ~/.config/agent-messenger/imessage-credentials.json (mode 0600). Relocate via AGENT_MESSENGER_CONFIG_DIR. No secrets are stored — imsg uses macOS permissions, not tokens.