imsg

repository·main·Indexed 22 days ago

https://github.com/openclaw/imsg

A tool for reading, watching, and sending iMessage/SMS from the macOS terminal. It provides stable JSON and JSON-RPC interfaces for automation, agents, and scripts. Features include chat history retrieval, live message streaming, and support for sending text and files. Advanced IMCore features, such as message mutation (edit/unsend), typing indicators, and rich messaging, are available via dylib injection with SIP disabled.

Tokens
29.5K
Snippets
101
Records
184
Agent score
78%

What's inside imsg

  1. Core capabilities of imsg

    main

    imsg is a macOS command-line tool designed for interacting with Messages.app. Its primary capabilities include:

    • Local-first reads: Accesses chats, history, and attachments directly from ~/Library/Messages/chat.db without network round-trips.
    • Live streams: Uses imsg watch to follow filesystem events on chat.db (with a polling fallback) to stream new messages and tapbacks.
    • Messages.app automation: Sends text, attachments, and tapbacks via AppleScript automation.
    • Agent-friendly: Provides stable JSON-RPC over stdio, deterministic JSON schemas, and imsg completions llm for LLM context.
    • Attachment handling: Reports filenames, UTIs, byte counts, and paths. Supports --convert-attachments to provide model-friendly formats (e.g., CAF→M4A, GIF→PNG).
    • Linux support: Offers a read-only preview by inspecting a copied chat.db from macOS (cannot send or mutate).
  2. Understand Linux Read-Only Preview capabilities

    main

    On Linux, imsg operates in a read-only preview mode. It is designed for offline inspection and automation of an existing chat.db database copied from macOS. It is not a full Linux Messages client.

    Supported Operations

    • Inspecting existing chats, groups, and message history.
    • Searching messages within the database.
    • Accessing JSON output that matches the macOS schema (including chat identifiers, participants, message GUIDs, timestamps, text, reactions, and attachment metadata).

    Unsupported Operations

    Because Linux lacks macOS frameworks, Messages.app, and AppleScript automation, the following are not supported:

    • Sending messages (send)
    • Reacting to messages (react)
    • Marking messages as read (read)
    • Typing indicators (typing)
    • Launching the app (launch)
    • IMCore bridge features
    • Contacts name resolution
    • Live access to iMessage or SMS accounts

    Note on Attachments: Attachment paths in chat.db point to macOS home directory locations. Linux can report the metadata, but the actual files will only be accessible if you also copy the attachment tree from the macOS machine.

  3. Understand the v2 IPC mechanism

    main

    The bridge uses a per-request UUID-keyed queue for Inter-Process Communication (IPC) to avoid the race conditions present in the v1 single-file polling method.

    IPC Directory Structure: Requests and responses are stored in ~/Library/Containers/com.apple.MobileSMS/Data/:

    • .imsg-bridge-ready: A PID lock indicating injection is live.
    • .imsg-rpc/in/<uuid>.json: Requests dropped by the CLI.
    • .imsg-rpc/out/<uuid>.json: Responses written by the dylib.
    • .imsg-events.jsonl: Inbound asynchronous events (e.g., typing).

    Debugging: To force the legacy v1 single-file path for debugging, set the environment variable IMSG_BRIDGE_LEGACY_IPC=1.

  4. How group chats are identified in imsg

    main

    In imsg, group chats are distinguished from direct 1:1 chats by the shape of their identifier.

    • Group Chats: The chat.chat_identifier or chat.guid contains the substring ;+; (e.g., iMessage;+;chat1234567890).
    • Direct Chats: Use the format SERVICE;-;TARGET (e.g., iMessage;-;+15551234567) and do not contain ;+;.

    Every chat object includes an is_group boolean to allow you to check this distinction without manual string parsing.

  5. Manage multiple local identities in group chats

    main

    Messages stores hints about which of your local numbers/identities should be used for a chat via account_id, account_login, and last_addressed_handle.

    Important Limitations:

    • imsg exposes these fields for diagnostic purposes, but the send command cannot force a specific outbound number.
    • The underlying AppleScript send mechanism lacks a from selector.
    • To change the default identity for new outbound traffic, you must adjust the settings within the Messages app: Settings → iMessage.
  6. Summary of imsg macOS permission requirements

    main

    The following table summarizes which permissions are required for specific imsg functionalities:

    GateWhat it protectsTriggered by
    Full Disk Access~/Library/Messages/, Mail, Safari history, etc.imsg chats, history, watch, group, or any command opening chat.db
    AutomationOne app driving another via Apple Eventsimsg send, react, read, typing
    ContactsAddress Book entriesName resolution in any read or send command

    Note: Only Full Disk Access is mandatory for basic functionality. The CLI is designed to degrade gracefully and will notify you which gate is missing rather than failing silently.

  7. Linux support status and limitations

    main

    Linux support for imsg is currently in a read-only stage.

    Current Capabilities:

    • SwiftPM build support.
    • Linux-only tests.
    • Release archive generation (imsg-linux-x86_64.tar.gz).
    • Ability to read existing copied Messages databases.

    Unsupported Features (Do not document as supported):

    • Sending messages.
    • Watching messages.
    • Contacts access.
    • IMCore support.

    These features currently depend on macOS-specific frameworks or Messages.app automation and are not implemented for Linux.

  8. JSON output conventions

    main

    When consuming imsg JSON output, follow these data type conventions:

    • Numbers: All numeric fields are JSON numbers. id, chat_id, and byte_size are integers.
    • Timestamps: Times are ISO 8601 with explicit timezone (typically Z).
    • Missing Values: Strings that are not applicable are omitted, not set to null. Use field in obj to check for existence rather than obj.field === null.
    • Booleans: Booleans are explicit true or false (never 0 or 1).
    • Arrays: Arrays are always present in the schema, even if empty.
  9. Inspect scheduled messages and chat backgrounds

    main

    imsg allows you to inspect metadata and scheduled items without launching the Messages app.

    • Scheduled Messages: Use imsg scheduled list --json to read future scheduled rows directly from local history.
    • Chat Backgrounds: Use imsg chat-background status --chat-id <id> --json to read local background metadata, cache presence, and the newest set/clear event without mutating the chat.
    imsg scheduled list --json
    imsg chat-background status --chat-id 42 --json
  10. Understand participants and local identity

    main

    The participants array in a chat object contains external handles only. The local user is not listed in the participants array because Messages stores the local user implicitly per-message.

    To distinguish your own messages from others:

    • Check the is_from_me field on individual messages.
    • For Apple IDs with multiple phone numbers, check destination_caller_id on outgoing messages to see which number Messages used for routing.

    Note on Routing: Fields like account_id, account_login, and last_addressed_handle are read-only diagnostics. You cannot use imsg to force a specific outbound number if an Apple ID has multiple numbers; these fields are provided to audit which number Messages selected.

  11. Understand imsg RPC Objects: Chat and Message

    main

    The imsg RPC interface uses structured objects for Chat and Message entities.

    • Chat: Every field documented in the JSON output → Chat list item section is present in the chats.list RPC response.
    • Message: Follows the JSON output → Message schema. When include_reactions: true is specified, message notifications include reaction extension fields: is_reaction, reaction_type, reaction_emoji, is_reaction_add, and reacted_to_guid.
    • Native Polls: Emitted by messages.history and watch.subscribe. If an inbound native poll has an empty payload title, imsg backfills poll.question using the earliest clean caption row that replies to the poll.
    • Routing Diagnostics: Fields like account_id, account_login, last_addressed_handle, and outgoing destination_caller_id are read-only. Note that the AppleScript send API does not support a from selector.
  12. Choose the correct routing identifier for chats

    main

    When interacting with chats, you can identify them using three different handles. Choose the one that best fits your use case:

    1. chat_id (rowid): Preferred. It is the fastest and most stable identifier within a single Messages database. Use this when both the reader and the sender are on the same machine. Use imsg send --chat-id for sending.
    2. chat_identifier: Portable across different databases or installations. Use this if you store handles externally and need to tolerate a Messages database reset.
    3. chat_guid: Also portable. Use this as a fallback if you only have the portable GUID.