OpenClaw iMessage deployment patterns
A dedicated bot macOS user, a remote Mac over Tailscale with an SSH wrapper, multi-account overrides, and direct-message history seeding
iMessage has a hard constraint the other channels do not: the messages live in a signed-in Messages app on a Mac. OpenClaw’s deployment patterns are about where that Mac sits relative to the Gateway and whose identity it uses. The docs describe four: a dedicated bot user, a remote Mac reached over a tailnet, several accounts on one Gateway, and how much DM history a new session starts with. Here they are with the config each needs.
Identity and topology
- A dedicated Apple ID and macOS user isolate bot traffic from a personal Messages profile: create or sign in the user, sign Messages in with the bot Apple ID there, install imsg in that user, create an SSH wrapper so OpenClaw can run imsg in that user context, and point the account’s CLI and database paths at that profile; the first run may need automation and Full Disk Access approvals inside that user session.
- The common remote topology runs the Gateway on Linux or a VM with iMessage and imsg on a Mac in the tailnet: the CLI path is an absolute Gateway-local wrapper script that executes imsg over SSH, the remote host enables inbound fetches and owner-only outbound staging over SSH and SCP, and the database path refers to the Mac and is never rewritten against the Gateway user’s home.
- The docs’ example wrapper is a one-line shell script that executes SSH in non-tty mode to the bot user on the tailnet host with the imsg arguments passed through; the host key must be trusted first by connecting once so the known-hosts file is populated.
- Per-account config under the accounts map lets each iMessage account override the CLI and database paths, the allow-from list, DM and group policies, the media cap, history settings and attachment root allowlists; omitted policies inherit the channel root, explicit ones win, and when neither scope sets them DMs use pairing and groups use the allowlist.
Use SSH keys so both SSH and SCP are non-interactive.
History seeding
A DM history limit seeds new direct-message sessions with recent decoded imsg history for that conversation, with per-sender overrides including zero to disable history for one sender. The history is fetched on demand from imsg rather than kept by OpenClaw, leaving the global limit unset disables global seeding, and a positive per-sender limit still enables seeding for that sender alone.
What to check
- For the remote pattern, run the same imsg commands through the wrapper before configuring OpenClaw, since permissions are granted to the parent process that launches imsg and an SSH session has a different parent than a terminal.
- For the dedicated-user pattern, expect the GUI approval prompts to appear in the bot user’s session, not yours, so log in there once to accept them.
- For several accounts, remember that each account can point at a different Mac or user profile through its own paths, which is how one Gateway can serve two identities.
OpenClaw on iMessage is the channel post these patterns serve, and OpenClaw iMessage media and attachments the attachment rules that depend on the remote host setting.
On Diali
iMessage is not among the channels Diali connects today: WhatsApp, Telegram, Discord, Slack, Mattermost, Matrix, SMS and voice. Connect your first channel in five minutes explains how those are linked, and Diali security the boundary that applies to each.
Why a separate identity
Running the bot as its own Apple ID means a runaway automation or a mistaken allowlist can never send from your personal number, and it keeps the private-API bridge and its system tradeoffs on a Mac that is not your daily machine. Hosted OpenClaw on Diali is the assistant and OpenClaw remote access the general treatment of reaching a Gateway across machines.
- Bot user, bot Apple ID, bot Mac.
- Wrapper path local; host and database paths remote.
- History is fetched on demand, per sender if you like.
Stop reading about it, build one
Set up an agent, pick a channel, and have it working inside the app you already keep open.
