Back to list
SpillwaveSolutions

automating-messages

by SpillwaveSolutions

Agents, Skills and Commands for automating Keynote, Notes, Reminders, Numbers and more using AppleScript and PyXA (JXA too).

9🍴 1📅 Jan 21, 2026

SKILL.md


name: automating-messages description: 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)

Contents

Permissions and scope

  • Grants needed: Automation + Accessibility; Full Disk Access for any chat.db reads.
  • Keep automation scoped and auditable; avoid unsolicited sends and DB writes.
  • Pairs with automating-mac-apps for common setup (permissions, osascript invocation, UI scripting basics).

Default workflow (happy path)

  1. Resolve transport: pick serviceType (iMessage or SMS) before targeting a buddy.
  2. Identify recipient: filter buddies by handle (phone/email). Avoid ambiguous names.
  3. Send via app-level send: pass Buddy object to Messages.send().
  4. Verify window context: activate Messages when mixing with UI steps.
  5. Fallbacks: if send/attachments fail, use UI scripting; for history, use SQL.

Quick recipe (defensive send)

const Messages = Application('Messages');
Messages.includeStandardAdditions = true;

function safeSend(text, handle, svcType = 'iMessage') {
  const svc = Messages.services.whose({ serviceType: svcType })[0];
  if (!svc) throw new Error(`Service ${svcType} missing`);
  const buddy = svc.buddies.whose({ handle })[0];
  if (!buddy) throw new Error(`Buddy ${handle} missing on ${svcType}`);
  Messages.send(text, { to: buddy });
}
  • Wrap with try/catch and log; add small delays when activating UI.
  • For groups, target an existing chat by GUID or fall back to UI scripting; array sends are unreliable.

Attachments and UI fallback

  • Messages lacks a stable JXA attachment API; use clipboard + System Events paste/send.
  • Ensure Accessibility permission, bring app forward, paste file, press Enter.
  • 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
  • Buddy lookup works: svc.buddies.whose({ handle })[0] returns target
  • Test send completes without errors
  • Full Disk Access granted if using chat.db reads

When Not to Use

  • For reading message history without Full Disk Access (AppleScript/JXA cannot read messages)
  • For cross-platform messaging (use platform APIs or third-party services)
  • For business SMS automation (use Twilio or similar APIs)
  • When iMessage/SMS features are not available on the target system
  • For bulk messaging (rate limits and security restrictions apply)
  • When security policy prohibits Full Disk Access grants (required for any read operations)

What to load

  • Control plane and send reliability: references/control-plane.md
  • UI scripting + attachments fallback: references/ui-scripting-attachments.md
  • SQL/history access: references/database-forensics.md
  • Polling bots/launchd: references/monitoring-daemons.md

Score

Total Score

75/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

+10
人気

GitHub Stars 100以上

0/15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon