2026-01-02 01:19:22 +01:00
---
2026-02-03 18:06:54 -08:00
summary: "Legacy iMessage support via imsg (JSON-RPC over stdio). New setups should use BlueBubbles."
2026-01-02 01:19:22 +01:00
read_when:
- Setting up iMessage support
- Debugging iMessage send/receive
2026-01-31 16:04:03 -05:00
title: iMessage
2026-01-02 01:19:22 +01:00
---
2026-02-03 18:06:54 -08:00
# iMessage (legacy: imsg)
2026-01-02 01:19:22 +01:00
2026-02-03 18:06:54 -08:00
> **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.
Status: legacy external CLI integration. Gateway spawns `imsg rpc` (JSON-RPC over stdio).
2026-01-02 01:19:22 +01:00
2026-01-11 02:40:28 +01:00
## Quick setup (beginner)
2026-01-31 21:13:13 +09:00
1. Ensure Messages is signed in on this Mac.
2. Install `imsg` :
2026-01-11 02:40:28 +01:00
- `brew install steipete/tap/imsg`
2026-01-31 21:13:13 +09:00
3. Configure OpenClaw with `channels.imessage.cliPath` and `channels.imessage.dbPath` .
4. Start the gateway and approve any macOS prompts (Automation + Full Disk Access).
2026-01-11 02:40:28 +01:00
Minimal config:
2026-01-31 21:13:13 +09:00
2026-01-11 02:40:28 +01:00
```json5
{
2026-01-13 06:16:43 +00:00
channels: {
imessage: {
enabled: true,
cliPath: "/usr/local/bin/imsg",
2026-01-31 21:13:13 +09:00
dbPath: "/Users/< you > /Library/Messages/chat.db",
},
},
2026-01-11 02:40:28 +01:00
}
```
2026-01-07 00:25:16 +01:00
## What it is
2026-01-31 21:13:13 +09:00
2026-01-13 06:16:43 +00:00
- iMessage channel backed by `imsg` on macOS.
2026-01-07 00:25:16 +01:00
- Deterministic routing: replies always go back to iMessage.
2026-01-11 02:52:50 +00:00
- DMs share the agent's main session; groups are isolated (`agent:<agentId>:imessage:group:<chat_id>` ).
2026-01-13 06:16:43 +00:00
- 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).
2026-01-06 18:25:52 +00:00
2026-01-15 01:41:11 +00:00
## Config writes
2026-01-31 21:13:13 +09:00
2026-01-15 01:41:11 +00:00
By default, iMessage is allowed to write config updates triggered by `/config set|unset` (requires `commands.config: true` ).
Disable with:
2026-01-31 21:13:13 +09:00
2026-01-15 01:41:11 +00:00
```json5
{
2026-01-31 21:13:13 +09:00
channels: { imessage: { configWrites: false } },
2026-01-15 01:41:11 +00:00
}
```
2026-01-02 01:19:22 +01:00
## Requirements
2026-01-31 21:13:13 +09:00
2026-01-02 01:19:22 +01:00
- macOS with Messages signed in.
2026-01-30 03:15:10 +01:00
- Full Disk Access for OpenClaw + `imsg` (Messages DB access).
2026-01-07 00:25:16 +01:00
- Automation permission when sending.
2026-01-13 06:16:43 +00:00
- `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` ).
2026-01-02 01:19:22 +01:00
2026-02-06 19:21:52 -05:00
## Troubleshooting macOS Privacy and Security TCC
2026-02-06 17:35:33 -06:00
2026-02-06 19:21:52 -05:00
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.
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).
2026-02-06 17:35:33 -06:00
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.
2026-02-06 19:21:52 -05:00
- **`imsg` CLI health**: verify `imsg` is installed and supports RPC (`imsg rpc --help` ).
2026-02-06 17:35:33 -06:00
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:
```bash
imsg chats --limit 1
# or
imsg send < handle > "test"
```
2026-02-06 19:21:52 -05:00
Related macOS folder permissions (Desktop/Documents/Downloads): [/platforms/mac/permissions ](/platforms/mac/permissions ).
2026-02-06 17:35:33 -06:00
2026-01-07 00:25:16 +01:00
## Setup (fast path)
2026-01-31 21:13:13 +09:00
1. Ensure Messages is signed in on this Mac.
2. Configure iMessage and start the gateway.
2026-01-02 01:19:22 +01:00
2026-01-08 16:24:28 -06:00
### Dedicated bot macOS user (for isolated identity)
2026-01-31 21:13:13 +09:00
2026-01-08 16:24:28 -06:00
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.
2026-01-31 21:13:13 +09:00
1. Create a dedicated Apple ID (example: `my-cool-bot@icloud.com` ).
2026-01-08 16:24:28 -06:00
- Apple may require a phone number for verification / 2FA.
2026-01-31 21:13:13 +09:00
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` :
2026-01-08 16:24:28 -06:00
- `brew install steipete/tap/imsg`
2026-01-31 21:13:13 +09:00
6. Set up SSH so `ssh <bot-macos-user>@localhost true` works without a password.
7. Point `channels.imessage.accounts.bot.cliPath` at an SSH wrapper that runs `imsg` as the bot user.
2026-01-08 01:18:37 +01:00
2026-02-06 19:21:52 -05:00
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 ).
2026-01-08 16:24:28 -06:00
Example wrapper (`chmod +x` ). Replace `<bot-macos-user>` with your actual macOS username:
2026-01-31 21:13:13 +09:00
2026-01-08 01:18:37 +01:00
```bash
#!/usr/bin/env bash
2026-01-08 16:24:28 -06:00
set -euo pipefail
2026-01-08 01:18:37 +01:00
2026-01-08 16:24:28 -06:00
# Run an interactive SSH once first to accept host keys:
# ssh <bot-macos-user>@localhost true
exec /usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=5 -T < bot-macos-user > @localhost \
"/usr/local/bin/imsg" "$@"
```
2026-01-08 01:18:37 +01:00
2026-01-08 16:24:28 -06:00
Example config:
2026-01-31 21:13:13 +09:00
2026-01-02 01:19:22 +01:00
```json5
{
2026-01-13 06:16:43 +00:00
channels: {
imessage: {
enabled: true,
accounts: {
bot: {
name: "Bot",
enabled: true,
cliPath: "/path/to/imsg-bot",
2026-01-31 21:13:13 +09:00
dbPath: "/Users/< bot-macos-user > /Library/Messages/chat.db",
},
},
},
},
2026-01-02 01:19:22 +01:00
}
```
2026-01-13 06:16:43 +00:00
For single-account setups, use flat options (`channels.imessage.cliPath` , `channels.imessage.dbPath` ) instead of the `accounts` map.
2026-01-08 16:24:28 -06:00
### Remote/SSH variant (optional)
2026-01-31 21:13:13 +09:00
2026-01-30 03:15:10 +01:00
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.
2026-01-08 16:24:28 -06:00
Example wrapper:
2026-01-31 21:13:13 +09:00
2026-01-08 16:24:28 -06:00
```bash
#!/usr/bin/env bash
2026-01-17 00:39:48 +00:00
exec ssh -T gateway-host imsg "$@"
2026-01-08 16:24:28 -06:00
```
2026-01-30 03:15:10 +01:00
**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` :
2026-01-16 15:51:42 -08:00
```json5
{
channels: {
imessage: {
2026-01-31 21:13:13 +09:00
cliPath: "~/imsg-ssh", // SSH wrapper to remote Mac
remoteHost: "user@gateway -host", // for SCP file transfer
includeAttachments: true,
},
},
2026-01-16 15:51:42 -08:00
}
```
2026-01-30 03:15:10 +01:00
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.
2026-01-16 15:51:42 -08:00
2026-01-17 00:39:48 +00:00
#### Remote Mac via Tailscale (example)
2026-01-31 21:13:13 +09:00
2026-01-17 00:39:48 +00:00
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.
Architecture:
2026-01-31 21:13:13 +09:00
2026-02-09 20:57:27 +05:30
```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["< b > Gateway host (Linux/VM)< br > < / b > < br > openclaw gateway< br > channels.imessage.cliPath"]
Mac["< b > Mac with Messages + imsg< br > < / b > < br > Messages signed in< br > 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
2026-01-17 00:39:48 +00:00
```
Concrete config example (Tailscale hostname):
2026-01-31 21:13:13 +09:00
2026-01-17 00:39:48 +00:00
```json5
{
channels: {
imessage: {
enabled: true,
2026-01-30 03:15:10 +01:00
cliPath: "~/.openclaw/scripts/imsg-ssh",
2026-01-17 00:39:48 +00:00
remoteHost: "bot@mac -mini.tailnet-1234.ts.net",
includeAttachments: true,
2026-01-31 21:13:13 +09:00
dbPath: "/Users/bot/Library/Messages/chat.db",
},
},
2026-01-17 00:39:48 +00:00
}
```
2026-01-30 03:15:10 +01:00
Example wrapper (`~/.openclaw/scripts/imsg-ssh` ):
2026-01-31 21:13:13 +09:00
2026-01-17 00:39:48 +00:00
```bash
#!/usr/bin/env bash
exec ssh -T bot@mac -mini.tailnet-1234.ts.net imsg "$@"
```
Notes:
2026-01-31 21:13:13 +09:00
2026-01-17 00:39:48 +00:00
- 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.
2026-01-30 03:15:10 +01:00
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).
2026-01-08 01:18:37 +01:00
2026-01-07 00:25:16 +01:00
## Access control (DMs + groups)
2026-01-31 21:13:13 +09:00
2026-01-07 00:25:16 +01:00
DMs:
2026-01-31 21:13:13 +09:00
2026-01-13 06:16:43 +00:00
- Default: `channels.imessage.dmPolicy = "pairing"` .
2026-01-07 05:06:04 +01:00
- Unknown senders receive a pairing code; messages are ignored until approved (codes expire after 1 hour).
2026-01-07 00:25:16 +01:00
- Approve via:
2026-01-30 03:15:10 +01:00
- `openclaw pairing list imessage`
- `openclaw pairing approve imessage <CODE>`
2026-02-07 15:40:35 -05:00
- Pairing is the default token exchange for iMessage DMs. Details: [Pairing ](/channels/pairing )
2026-01-07 00:25:16 +01:00
Groups:
2026-01-31 21:13:13 +09:00
2026-01-13 06:16:43 +00:00
- `channels.imessage.groupPolicy = open | allowlist | disabled` .
- `channels.imessage.groupAllowFrom` controls who can trigger in groups when `allowlist` is set.
2026-01-09 12:44:23 +00:00
- 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` .
2026-01-07 00:25:16 +01:00
## How it works (behavior)
2026-01-31 21:13:13 +09:00
2026-01-13 06:16:43 +00:00
- `imsg` streams message events; the gateway normalizes them into the shared channel envelope.
2026-01-07 00:25:16 +01:00
- Replies always route back to the same chat id or handle.
2026-01-08 16:24:28 -06:00
## Group-ish threads (`is_group=false`)
2026-01-31 21:13:13 +09:00
2026-01-08 16:24:28 -06:00
Some iMessage threads can have multiple participants but still arrive with `is_group=false` depending on how Messages stores the chat identifier.
2026-01-30 03:15:10 +01:00
If you explicitly configure a `chat_id` under `channels.imessage.groups` , OpenClaw treats that thread as a “group” for:
2026-01-31 21:13:13 +09:00
2026-01-11 02:31:45 +00:00
- session isolation (separate `agent:<agentId>:imessage:group:<chat_id>` session key)
2026-01-08 16:24:28 -06:00
- group allowlisting / mention gating behavior
Example:
2026-01-31 21:13:13 +09:00
2026-01-08 16:24:28 -06:00
```json5
{
2026-01-13 06:16:43 +00:00
channels: {
imessage: {
groupPolicy: "allowlist",
groupAllowFrom: ["+15555550123"],
groups: {
2026-01-31 21:13:13 +09:00
"42": { requireMention: false },
},
},
},
2026-01-08 16:24:28 -06:00
}
```
2026-01-31 21:13:13 +09:00
2026-01-08 16:24:28 -06:00
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 ).
2026-01-07 00:25:16 +01:00
## Media + limits
2026-01-31 21:13:13 +09:00
2026-01-13 06:16:43 +00:00
- Optional attachment ingestion via `channels.imessage.includeAttachments` .
- Media cap via `channels.imessage.mediaMaxMb` .
2026-01-07 00:25:16 +01:00
2026-01-08 04:02:04 +01:00
## Limits
2026-01-31 21:13:13 +09:00
2026-01-13 06:16:43 +00:00
- Outbound text is chunked to `channels.imessage.textChunkLimit` (default 4000).
2026-01-25 13:24:00 +00:00
- Optional newline chunking: set `channels.imessage.chunkMode="newline"` to split on blank lines (paragraph boundaries) before length chunking.
2026-01-13 06:16:43 +00:00
- Media uploads are capped by `channels.imessage.mediaMaxMb` (default 16).
2026-01-08 04:02:04 +01:00
2026-01-07 00:25:16 +01:00
## Addressing / delivery targets
2026-01-31 21:13:13 +09:00
2026-01-02 01:19:22 +01:00
Prefer `chat_id` for stable routing:
2026-01-31 21:13:13 +09:00
2026-01-02 01:19:22 +01:00
- `chat_id:123` (preferred)
2026-01-07 00:25:16 +01:00
- `chat_guid:...`
- `chat_identifier:...`
2026-01-02 01:19:22 +01:00
- direct handles: `imessage:+1555` / `sms:+1555` / `user@example.com`
List chats:
2026-01-31 21:13:13 +09:00
2026-01-02 01:19:22 +01:00
```
imsg chats --limit 20
```
2026-01-07 00:25:16 +01:00
## Configuration reference (iMessage)
2026-01-31 21:13:13 +09:00
2026-01-07 02:04:02 +01:00
Full configuration: [Configuration ](/gateway/configuration )
2026-01-07 00:25:16 +01:00
Provider options:
2026-01-31 21:13:13 +09:00
2026-01-13 06:16:43 +00:00
- `channels.imessage.enabled` : enable/disable channel startup.
- `channels.imessage.cliPath` : path to `imsg` .
- `channels.imessage.dbPath` : Messages DB path.
2026-01-17 00:39:48 +00:00
- `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.
2026-01-13 06:16:43 +00:00
- `channels.imessage.service` : `imessage | sms | auto` .
- `channels.imessage.region` : SMS region.
- `channels.imessage.dmPolicy` : `pairing | allowlist | open | disabled` (default: pairing).
2026-01-18 22:51:09 +00:00
- `channels.imessage.allowFrom` : DM allowlist (handles, emails, E.164 numbers, or `chat_id:*` ). `open` requires `"*"` . iMessage has no usernames; use handles or chat targets.
2026-01-13 06:16:43 +00:00
- `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).
2026-01-15 02:22:29 +00:00
- `channels.imessage.dmHistoryLimit` : DM history limit in user turns. Per-user overrides: `channels.imessage.dms["<handle>"].historyLimit` .
2026-01-13 06:16:43 +00:00
- `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).
2026-01-25 13:24:00 +00:00
- `channels.imessage.chunkMode` : `length` (default) or `newline` to split on blank lines (paragraph boundaries) before length chunking.
2026-01-07 00:25:16 +01:00
Related global options:
2026-01-31 21:13:13 +09:00
2026-01-09 12:44:23 +00:00
- `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns` ).
2026-01-07 00:25:16 +01:00
- `messages.responsePrefix` .