diff --git a/docs/channels/imessage.md b/docs/channels/imessage.md index 296e5775f2c..2876be31372 100644 --- a/docs/channels/imessage.md +++ b/docs/channels/imessage.md @@ -3,26 +3,46 @@ summary: "Legacy iMessage support via imsg (JSON-RPC over stdio). New setups sho read_when: - Setting up iMessage support - Debugging iMessage send/receive -title: iMessage +title: "iMessage" --- # iMessage (legacy: imsg) -> **Recommended:** Use [BlueBubbles](/channels/bluebubbles) for new iMessage setups. -> -> The `imsg` channel is a legacy external-CLI integration and may be removed in a future release. + +For new iMessage deployments, use BlueBubbles. -Status: legacy external CLI integration. Gateway spawns `imsg rpc` (JSON-RPC over stdio). +The `imsg` integration is legacy and may be removed in a future release. + -## Quick setup (beginner) +Status: legacy external CLI integration. Gateway spawns `imsg rpc` and communicates over JSON-RPC on stdio (no separate daemon/port). -1. Ensure Messages is signed in on this Mac. -2. Install `imsg`: - - `brew install steipete/tap/imsg` -3. Configure OpenClaw with `channels.imessage.cliPath` and `channels.imessage.dbPath`. -4. Start the gateway and approve any macOS prompts (Automation + Full Disk Access). + + + Preferred iMessage path for new setups. + + + iMessage DMs default to pairing mode. + + + Full iMessage field reference. + + -Minimal config: +## Quick setup + + + + + + +```bash +brew install steipete/tap/imsg +imsg rpc --help +``` + + + + ```json5 { @@ -36,45 +56,65 @@ Minimal config: } ``` -## What it is + -- iMessage channel backed by `imsg` on macOS. -- Deterministic routing: replies always go back to iMessage. -- DMs share the agent's main session; groups are isolated (`agent::imessage:group:`). -- If a multi-participant thread arrives with `is_group=false`, you can still isolate it by `chat_id` using `channels.imessage.groups` (see “Group-ish threads” below). + -## Config writes +```bash +openclaw gateway +``` -By default, iMessage is allowed to write config updates triggered by `/config set|unset` (requires `commands.config: true`). + -Disable with: + + +```bash +openclaw pairing list imessage +openclaw pairing approve imessage +``` + + Pairing requests expire after 1 hour. + + + + + + + OpenClaw only requires a stdio-compatible `cliPath`, so you can point `cliPath` at a wrapper script that SSHes to a remote Mac and runs `imsg`. + +```bash +#!/usr/bin/env bash +exec ssh -T gateway-host imsg "$@" +``` + + Recommended config when attachments are enabled: ```json5 { - channels: { imessage: { configWrites: false } }, + channels: { + imessage: { + enabled: true, + cliPath: "~/.openclaw/scripts/imsg-ssh", + remoteHost: "user@gateway-host", // used for SCP attachment fetches + includeAttachments: true, + }, + }, } ``` -## Requirements + If `remoteHost` is not set, OpenClaw attempts to auto-detect it by parsing the SSH wrapper script. -- macOS with Messages signed in. -- Full Disk Access for OpenClaw + `imsg` (Messages DB access). -- Automation permission when sending. -- `channels.imessage.cliPath` can point to any command that proxies stdin/stdout (for example, a wrapper script that SSHes to another Mac and runs `imsg rpc`). + + -## Troubleshooting macOS Privacy and Security TCC +## Requirements and permissions (macOS) -If sending/receiving fails (for example, `imsg rpc` exits non-zero, times out, or the gateway appears to hang), a common cause is a macOS permission prompt that was never approved. +- Messages must be signed in on the Mac running `imsg`. +- Full Disk Access is required for the process context running OpenClaw/`imsg` (Messages DB access). +- Automation permission is required to send messages through Messages.app. -macOS grants TCC permissions per app/process context. Approve prompts in the same context that runs `imsg` (for example, Terminal/iTerm, a LaunchAgent session, or an SSH-launched process). - -Checklist: - -- **Full Disk Access**: allow access for the process running OpenClaw (and any shell/SSH wrapper that executes `imsg`). This is required to read the Messages database (`chat.db`). -- **Automation → Messages**: allow the process running OpenClaw (and/or your terminal) to control **Messages.app** for outbound sends. -- **`imsg` CLI health**: verify `imsg` is installed and supports RPC (`imsg rpc --help`). - -Tip: If OpenClaw is running headless (LaunchAgent/systemd/SSH) the macOS prompt can be easy to miss. Run a one-time interactive command in a GUI terminal to force the prompt, then retry: + +Permissions are granted per process context. If gateway runs headless (LaunchAgent/SSH), run a one-time interactive command in that same context to trigger prompts: ```bash imsg chats --limit 1 @@ -82,128 +122,87 @@ imsg chats --limit 1 imsg send "test" ``` -Related macOS folder permissions (Desktop/Documents/Downloads): [/platforms/mac/permissions](/platforms/mac/permissions). + -## Setup (fast path) +## Access control and routing -1. Ensure Messages is signed in on this Mac. -2. Configure iMessage and start the gateway. + + + `channels.imessage.dmPolicy` controls direct messages: -### Dedicated bot macOS user (for isolated identity) + - `pairing` (default) + - `allowlist` + - `open` (requires `allowFrom` to include `"*"`) + - `disabled` -If you want the bot to send from a **separate iMessage identity** (and keep your personal Messages clean), use a dedicated Apple ID + a dedicated macOS user. + Allowlist field: `channels.imessage.allowFrom`. -1. Create a dedicated Apple ID (example: `my-cool-bot@icloud.com`). - - Apple may require a phone number for verification / 2FA. -2. Create a macOS user (example: `openclawhome`) and sign into it. -3. Open Messages in that macOS user and sign into iMessage using the bot Apple ID. -4. Enable Remote Login (System Settings → General → Sharing → Remote Login). -5. Install `imsg`: - - `brew install steipete/tap/imsg` -6. Set up SSH so `ssh @localhost true` works without a password. -7. Point `channels.imessage.accounts.bot.cliPath` at an SSH wrapper that runs `imsg` as the bot user. + Allowlist entries can be handles or chat targets (`chat_id:*`, `chat_guid:*`, `chat_identifier:*`). -First-run note: sending/receiving may require GUI approvals (Automation + Full Disk Access) in the _bot macOS user_. If `imsg rpc` looks stuck or exits, log into that user (Screen Sharing helps), run a one-time `imsg chats --limit 1` / `imsg send ...`, approve prompts, then retry. See [Troubleshooting macOS Privacy and Security TCC](#troubleshooting-macos-privacy-and-security-tcc). + -Example wrapper (`chmod +x`). Replace `` with your actual macOS username: + + `channels.imessage.groupPolicy` controls group handling: -```bash -#!/usr/bin/env bash -set -euo pipefail + - `allowlist` (default when configured) + - `open` + - `disabled` -# Run an interactive SSH once first to accept host keys: -# ssh @localhost true -exec /usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=5 -T @localhost \ - "/usr/local/bin/imsg" "$@" -``` + Group sender allowlist: `channels.imessage.groupAllowFrom`. -Example config: + Runtime fallback: if `groupAllowFrom` is unset, iMessage group sender checks fall back to `allowFrom` when available. -```json5 -{ - channels: { - imessage: { - enabled: true, - accounts: { - bot: { - name: "Bot", - enabled: true, - cliPath: "/path/to/imsg-bot", - dbPath: "/Users//Library/Messages/chat.db", - }, - }, - }, - }, -} -``` + Mention gating for groups: -For single-account setups, use flat options (`channels.imessage.cliPath`, `channels.imessage.dbPath`) instead of the `accounts` map. + - iMessage has no native mention metadata + - mention detection uses regex patterns (`agents.list[].groupChat.mentionPatterns`, fallback `messages.groupChat.mentionPatterns`) + - with no configured patterns, mention gating cannot be enforced -### Remote/SSH variant (optional) + Control commands from authorized senders can bypass mention gating in groups. -If you want iMessage on another Mac, set `channels.imessage.cliPath` to a wrapper that runs `imsg` on the remote macOS host over SSH. OpenClaw only needs stdio. + -Example wrapper: + + - DMs use direct routing; groups use group routing. + - With default `session.dmScope=main`, iMessage DMs collapse into the agent main session. + - Group sessions are isolated (`agent::imessage:group:`). + - Replies route back to iMessage using originating channel/target metadata. -```bash -#!/usr/bin/env bash -exec ssh -T gateway-host imsg "$@" -``` + Group-ish thread behavior: -**Remote attachments:** When `cliPath` points to a remote host via SSH, attachment paths in the Messages database reference files on the remote machine. OpenClaw can automatically fetch these over SCP by setting `channels.imessage.remoteHost`: + Some multi-participant iMessage threads can arrive with `is_group=false`. + If that `chat_id` is explicitly configured under `channels.imessage.groups`, OpenClaw treats it as group traffic (group gating + group session isolation). -```json5 -{ - channels: { - imessage: { - cliPath: "~/imsg-ssh", // SSH wrapper to remote Mac - remoteHost: "user@gateway-host", // for SCP file transfer - includeAttachments: true, - }, - }, -} -``` + + -If `remoteHost` is not set, OpenClaw attempts to auto-detect it by parsing the SSH command in your wrapper script. Explicit configuration is recommended for reliability. +## Deployment patterns -#### Remote Mac via Tailscale (example) + + + Use a dedicated Apple ID and macOS user so bot traffic is isolated from your personal Messages profile. -If the Gateway runs on a Linux host/VM but iMessage must run on a Mac, Tailscale is the simplest bridge: the Gateway talks to the Mac over the tailnet, runs `imsg` via SSH, and SCPs attachments back. + Typical flow: -Architecture: + 1. Create/sign in a dedicated macOS user. + 2. Sign into Messages with the bot Apple ID in that user. + 3. Install `imsg` in that user. + 4. Create SSH wrapper so OpenClaw can run `imsg` in that user context. + 5. Point `channels.imessage.accounts..cliPath` and `.dbPath` to that user profile. -```mermaid -%%{init: { - 'theme': 'base', - 'themeVariables': { - 'primaryColor': '#ffffff', - 'primaryTextColor': '#000000', - 'primaryBorderColor': '#000000', - 'lineColor': '#000000', - 'secondaryColor': '#f9f9fb', - 'tertiaryColor': '#ffffff', - 'clusterBkg': '#f9f9fb', - 'clusterBorder': '#000000', - 'nodeBorder': '#000000', - 'mainBkg': '#ffffff', - 'edgeLabelBackground': '#ffffff' - } -}}%% -flowchart TB - subgraph T[" "] - subgraph Tailscale[" "] - direction LR - Gateway["Gateway host (Linux/VM)

openclaw gateway
channels.imessage.cliPath"] - Mac["Mac with Messages + imsg

Messages signed in
Remote Login enabled"] - end - Gateway -- SSH (imsg rpc) --> Mac - Mac -- SCP (attachments) --> Gateway - direction BT - User["user@gateway-host"] -- "Tailscale tailnet (hostname or 100.x.y.z)" --> Gateway -end -``` + First run may require GUI approvals (Automation + Full Disk Access) in that bot user session. -Concrete config example (Tailscale hostname): +
+ + + Common topology: + + - gateway runs on Linux/VM + - iMessage + `imsg` runs on a Mac in your tailnet + - `cliPath` wrapper uses SSH to run `imsg` + - `remoteHost` enables SCP attachment fetches + + Example: ```json5 { @@ -219,122 +218,134 @@ Concrete config example (Tailscale hostname): } ``` -Example wrapper (`~/.openclaw/scripts/imsg-ssh`): - ```bash #!/usr/bin/env bash exec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@" ``` -Notes: + Use SSH keys so both SSH and SCP are non-interactive. -- Ensure the Mac is signed in to Messages, and Remote Login is enabled. -- Use SSH keys so `ssh bot@mac-mini.tailnet-1234.ts.net` works without prompts. -- `remoteHost` should match the SSH target so SCP can fetch attachments. + -Multi-account support: use `channels.imessage.accounts` with per-account config and optional `name`. See [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) for the shared pattern. Don't commit `~/.openclaw/openclaw.json` (it often contains tokens). + + iMessage supports per-account config under `channels.imessage.accounts`. -## Access control (DMs + groups) + Each account can override fields such as `cliPath`, `dbPath`, `allowFrom`, `groupPolicy`, `mediaMaxMb`, and history settings. -DMs: + +
-- Default: `channels.imessage.dmPolicy = "pairing"`. -- Unknown senders receive a pairing code; messages are ignored until approved (codes expire after 1 hour). -- Approve via: - - `openclaw pairing list imessage` - - `openclaw pairing approve imessage ` -- Pairing is the default token exchange for iMessage DMs. Details: [Pairing](/channels/pairing) +## Media, chunking, and delivery targets -Groups: + + + - inbound attachment ingestion is optional: `channels.imessage.includeAttachments` + - remote attachment paths can be fetched via SCP when `remoteHost` is set + - outbound media size uses `channels.imessage.mediaMaxMb` (default 16 MB) + -- `channels.imessage.groupPolicy = open | allowlist | disabled`. -- `channels.imessage.groupAllowFrom` controls who can trigger in groups when `allowlist` is set. -- Mention gating uses `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`) because iMessage has no native mention metadata. -- Multi-agent override: set per-agent patterns on `agents.list[].groupChat.mentionPatterns`. + + - text chunk limit: `channels.imessage.textChunkLimit` (default 4000) + - chunk mode: `channels.imessage.chunkMode` + - `length` (default) + - `newline` (paragraph-first splitting) + -## How it works (behavior) + + Preferred explicit targets: -- `imsg` streams message events; the gateway normalizes them into the shared channel envelope. -- Replies always route back to the same chat id or handle. + - `chat_id:123` (recommended for stable routing) + - `chat_guid:...` + - `chat_identifier:...` -## Group-ish threads (`is_group=false`) + Handle targets are also supported: -Some iMessage threads can have multiple participants but still arrive with `is_group=false` depending on how Messages stores the chat identifier. + - `imessage:+1555...` + - `sms:+1555...` + - `user@example.com` -If you explicitly configure a `chat_id` under `channels.imessage.groups`, OpenClaw treats that thread as a “group” for: +```bash +imsg chats --limit 20 +``` -- session isolation (separate `agent::imessage:group:` session key) -- group allowlisting / mention gating behavior + + -Example: +## Config writes + +iMessage allows channel-initiated config writes by default (for `/config set|unset` when `commands.config: true`). + +Disable: ```json5 { channels: { imessage: { - groupPolicy: "allowlist", - groupAllowFrom: ["+15555550123"], - groups: { - "42": { requireMention: false }, - }, + configWrites: false, }, }, } ``` -This is useful when you want an isolated personality/model for a specific thread (see [Multi-agent routing](/concepts/multi-agent)). For filesystem isolation, see [Sandboxing](/gateway/sandboxing). +## Troubleshooting -## Media + limits + + + Validate the binary and RPC support: -- Optional attachment ingestion via `channels.imessage.includeAttachments`. -- Media cap via `channels.imessage.mediaMaxMb`. - -## Limits - -- Outbound text is chunked to `channels.imessage.textChunkLimit` (default 4000). -- Optional newline chunking: set `channels.imessage.chunkMode="newline"` to split on blank lines (paragraph boundaries) before length chunking. -- Media uploads are capped by `channels.imessage.mediaMaxMb` (default 16). - -## Addressing / delivery targets - -Prefer `chat_id` for stable routing: - -- `chat_id:123` (preferred) -- `chat_guid:...` -- `chat_identifier:...` -- direct handles: `imessage:+1555` / `sms:+1555` / `user@example.com` - -List chats: - -``` -imsg chats --limit 20 +```bash +imsg rpc --help +openclaw channels status --probe ``` -## Configuration reference (iMessage) + If probe reports RPC unsupported, update `imsg`. -Full configuration: [Configuration](/gateway/configuration) + -Provider options: + + Check: -- `channels.imessage.enabled`: enable/disable channel startup. -- `channels.imessage.cliPath`: path to `imsg`. -- `channels.imessage.dbPath`: Messages DB path. -- `channels.imessage.remoteHost`: SSH host for SCP attachment transfer when `cliPath` points to a remote Mac (e.g., `user@gateway-host`). Auto-detected from SSH wrapper if not set. -- `channels.imessage.service`: `imessage | sms | auto`. -- `channels.imessage.region`: SMS region. -- `channels.imessage.dmPolicy`: `pairing | allowlist | open | disabled` (default: pairing). -- `channels.imessage.allowFrom`: DM allowlist (handles, emails, E.164 numbers, or `chat_id:*`). `open` requires `"*"`. iMessage has no usernames; use handles or chat targets. -- `channels.imessage.groupPolicy`: `open | allowlist | disabled` (default: allowlist). -- `channels.imessage.groupAllowFrom`: group sender allowlist. -- `channels.imessage.historyLimit` / `channels.imessage.accounts.*.historyLimit`: max group messages to include as context (0 disables). -- `channels.imessage.dmHistoryLimit`: DM history limit in user turns. Per-user overrides: `channels.imessage.dms[""].historyLimit`. -- `channels.imessage.groups`: per-group defaults + allowlist (use `"*"` for global defaults). -- `channels.imessage.includeAttachments`: ingest attachments into context. -- `channels.imessage.mediaMaxMb`: inbound/outbound media cap (MB). -- `channels.imessage.textChunkLimit`: outbound chunk size (chars). -- `channels.imessage.chunkMode`: `length` (default) or `newline` to split on blank lines (paragraph boundaries) before length chunking. + - `channels.imessage.dmPolicy` + - `channels.imessage.allowFrom` + - pairing approvals (`openclaw pairing list imessage`) -Related global options: + -- `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`). -- `messages.responsePrefix`. + + Check: + + - `channels.imessage.groupPolicy` + - `channels.imessage.groupAllowFrom` + - `channels.imessage.groups` allowlist behavior + - mention pattern configuration (`agents.list[].groupChat.mentionPatterns`) + + + + + Check: + + - `channels.imessage.remoteHost` + - SSH/SCP key auth from the gateway host + - remote path readability on the Mac running Messages + + + + + Re-run in an interactive GUI terminal in the same user/session context and approve prompts: + +```bash +imsg chats --limit 1 +imsg send "test" +``` + + Confirm Full Disk Access + Automation are granted for the process context that runs OpenClaw/`imsg`. + + + + +## Configuration reference pointers + +- [Configuration reference - iMessage](/gateway/configuration-reference#imessage) +- [Gateway configuration](/gateway/configuration) +- [Pairing](/channels/pairing) +- [BlueBubbles](/channels/bluebubbles)