Skip to content

iMessage

Human can send and receive Apple iMessage on macOS. Sends go through AppleScript to Messages.app; receives poll the Messages SQLite database at ~/Library/Messages/chat.db.

  • Build with -DHU_ENABLE_IMESSAGE=ON or -DHU_ENABLE_ALL_CHANNELS=ON
  • macOS only — not supported on Linux or Windows
  • Messages.app installed and signed in to an Apple ID
  • SQLite support enabled (HU_ENABLE_SQLITE)
  • Full Disk Access granted to the human binary (or terminal) in System Settings → Privacy & Security

Add to ~/.human/config.json under channels.imessage:

{
"channels": {
"imessage": {
"default_target": "+15551234567"
}
}
}
FieldTypeDefaultDescription
default_targetstringPhone number or Apple ID used when no explicit target is provided
allow_fromstring[][]Restrict inbound to these handles only ("*" = allow all)
poll_interval_secnumber30How often (seconds) to poll chat.db for new messages
use_imsg_clibooleanfalseUse imsg CLI for send, react, attachments, event-driven watch, and chat validation (recommended)
  • Use E.164 format for phone numbers (e.g. +15551234567)
  • For Apple ID (email) recipients, use the email address
  • The target is also used as the buddy identifier in AppleScript
  • With use_imsg_cli: Sends via imsg send --to TARGET --text MESSAGE --service imessage (<1s). Attachments via imsg send --file. Falls back to AppleScript on failure.
  • Without use_imsg_cli: Uses osascript -e to run AppleScript: tell application "Messages" to send "MESSAGE" to buddy "TARGET"
  • Escapes quotes and backslashes in the message text for AppleScript fallback
  • If a message provides an explicit target, that is used; otherwise default_target is used
  • With use_imsg_cli: Spawns imsg watch --json --since-rowid as a background subprocess for event-driven notifications. Poll interval auto-reduces to 1s. SQL query is skipped when the watch pipe reports no new data.
  • Without use_imsg_cli: Timer-based polling every 3 seconds (configurable via poll_interval_sec)
  • Queries ~/Library/Messages/chat.db for new messages with rich metadata (text, attributedBody, attachments, tapbacks, effects, stickers)
  • Uses handle ID (phone/email) as session key; message text as content
  • Tracks last_rowid to avoid reprocessing
  • With use_imsg_cli: Runs imsg chats --json once at startup to verify the configured default_target exists in active conversations. Logs a warning if not found.
  • macOS only: Returns HU_ERR_NOT_SUPPORTED on non-Apple platforms
  • Full Disk Access required: macOS blocks read access to ~/Library/Messages/ without Full Disk Access
  • Messages.app must be running: AppleScript send requires Messages.app to be available
  • Single default target: Config provides one default; per-message targets can differ when the agent routes replies
  • Read-only SQLite: Opens the database with SQLITE_OPEN_READONLY; does not modify Messages data