Automates macOS Messages (iMessage/SMS) via JXA with reliable service→buddy resolution. Use when asked to "automate iMessage", "send Messages via script", "JXA Messages automation", or "read Messages history". Covers send-bug workarounds, UI scripting for attachments, chat.db forensics, and launchd polling bots.
التثبيت
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
Automates macOS Messages (iMessage/SMS) via JXA with reliable service→buddy resolution. Use when asked to "automate iMessage", "send Messages via script", "JXA Messages automation", or "read Messages history". Covers send-bug workarounds, UI scripting for attachments, chat.db forensics, and launchd polling bots.
allowed-tools
["Bash","Read","Write"]
Automating Messages (JXA-first with UI/DB fallbacks)
See references/ui-scripting-attachments.md for the full flow and ObjC pasteboard snippet.
Data access and forensics
Reading messages limitation: The AppleScript/JXA API for Messages is effectively write-only. While send() works reliably, reading messages via chat.messages() or similar methods is broken/unsupported in modern macOS. The only reliable way to read message history is via direct SQLite access to ~/Library/Messages/chat.db.
Security consideration: Reading chat.db requires Full Disk Access permission, which grants broad filesystem access beyond just Messages. This is a significant security trade-off - granting Full Disk Access to scripts or applications exposes all user data. Consider whether reading message history is truly necessary before enabling this permission.
Use SQL against chat.db for history; JXA chat.messages() is unreliable/non-functional.
Requires: System Settings > Privacy & Security > Full Disk Access for your terminal/script.
Remember Cocoa epoch conversion (nanoseconds since 2001-01-01); use sqlite3 -json for structured results.
See references/database-forensics.md for schema notes, typedstream handling, and export tooling.
Example read query (requires Full Disk Access):
sqlite3 ~/Library/Messages/chat.db "SELECT
CASE WHEN m.is_from_me = 1 THEN 'Me' ELSE 'Them' END as sender,
m.text,
datetime(m.date/1000000000 + 978307200, 'unixepoch', 'localtime') as date
FROM message m
JOIN handle h ON m.handle_id = h.rowid
WHERE h.id LIKE '%PHONE_NUMBER%'
ORDER BY m.date DESC LIMIT 10;"
Bots and monitoring
Implement polling daemons with launchd now that on-receive handlers are gone.
Track rowid, query diffs, dispatch actions, and persist state.
See references/monitoring-daemons.md for the polling pattern and plist notes.
Validation Checklist
Automation + Accessibility permissions granted
Service resolves: Messages.services.whose({ serviceType: 'iMessage' })[0] returns object