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)