OpenClawSkills
GitHub
Channels β€’ TutorialHeader.readTime

iMessage

Connect to iMessage via imsg (JSON-RPC over stdio): install, configuration, and chat_id routing.

Status: External CLI integration. Gateway will spawn imsg rpc (JSON-RPC over stdio).

Tutorial.step

Quick Setup

1. Ensure Messages is logged in on this Mac.

2. Install imsg:

- brew install steipete/tap/imsg

3. Configure channels.imessage.cliPath and channels.imessage.dbPath in OpenClaw.

4. Start gateway and approve macOS prompts (Automation + Full Disk Access).

Minimal configuration:

Json5
{
  channels: {
    imessage: {
      enabled: true,
      cliPath: "/usr/local/bin/imsg",
      dbPath: "/Users/<you>/Library/Messages/chat.db",
    },
  },
}
Tutorial.step

What It Is

- Provides iMessage channel capabilities via imsg on macOS.

- Deterministic routing: replies always return to iMessage.

- DMs fold into agent's main session; groups are isolated as ''agent:'':imessage:group:''''.

- If a multi-participant thread appears with is_group=false, you can still treat it as a group thread by chat_id via channels.imessage.groups (see "Group-like threads" below).

Tutorial.step

Config Writes

By default, allows iMessage to write updates triggered by /config set|unset back to the config file (requires commands.config: true).

Disable:

Json5
{
  channels: { imessage: { configWrites: false } },
}
Tutorial.step

Dependencies

- macOS with Messages logged in.

- Grant Full Disk Access to OpenClaw and imsg (to read Messages DB).

- Automation permission prompt required when sending messages.

- channels.imessage.cliPath can point to any "stdin/stdout proxy command" (e.g., wrapper script: run imsg rpc via SSH on another Mac).

Tutorial.step

Setup (Fast Path)

1. Ensure Messages is logged in.

2. Configure iMessage and start gateway.

#

Tutorial.step

Use Separate Bot macOS User (Identity Isolation)

If you want the bot to send with a separate iMessage identity (and keep your personal Messages clean), you can use a separate Apple ID + separate macOS user:

1. Create a separate Apple ID (e.g., [email protected]).

- Apple may require a phone number for verification/2FA.

2. Create a macOS user (e.g., openclawhome) and log in as that user.

3. Open Messages under that user and log in to iMessage with the bot Apple ID.

4. Enable Remote Login (System Settings β†’ General β†’ Sharing β†’ Remote Login).

5. Install imsg:

- brew install steipete/tap/imsg

6. Configure SSH so ''ssh ''@localhost true'' succeeds without password.

7. Point channels.imessage.accounts.bot.cliPath to an SSH wrapper that runs imsg under the bot user identity.

First run hint: Sending/receiving may require approving GUI permissions (Automation + Full Disk Access) under the bot user. If imsg rpc appears stuck or exits immediately, switch to that user (you can use screen sharing), run imsg chats --limit 1 / imsg send ... once, approve the prompts, then retry.

Example wrapper (remember ''chmod +x'', and replace '''''' with your username):

Bash
#!/usr/bin/env bash
set -euo pipefail


exec /usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=5 -T '<bot-macos-user>'@localhost \
  "/usr/local/bin/imsg" "$@"

Example configuration:

Json5
{
  channels: {
    imessage: {
      enabled: true,
      accounts: {
        bot: {
          name: "Bot",
          enabled: true,
          cliPath: "/path/to/imsg-bot",
          dbPath: "/Users/<bot-macos-user>/Library/Messages/chat.db",
        },
      },
    },
  },
}

Single-account scenario can use flattened fields (channels.imessage.cliPath, channels.imessage.dbPath), no need to write accounts.

#

Tutorial.step

Remote/SSH Solution (Optional)

If you want to put iMessage on another Mac, let channels.imessage.cliPath point to a wrapper that runs imsg remotely via SSH. OpenClaw only needs stdio.

Example wrapper:

Bash
#!/usr/bin/env bash
exec ssh -T gateway-host imsg "$@"

Remote attachments: When cliPath points to a remote host, attachment paths in the Messages database are local paths on the remote machine. You can set channels.imessage.remoteHost to let OpenClaw automatically fetch attachments via SCP:

Json5
{
  channels: {
    imessage: {
      cliPath: "~/imsg-ssh",
      remoteHost: "user@gateway-host",
      includeAttachments: true,
    },
  },
}

If remoteHost is not set, OpenClaw will try to infer from the SSH command in your wrapper script, but explicit configuration is recommended for reliability.

##

Tutorial.step

Tailscale Connect to Remote Mac (Example)

If gateway runs on a Linux host/VM but iMessage must run on Mac, Tailscale is the simplest bridge: gateway connects to Mac via tailnet, runs imsg via SSH, and fetches attachments via SCP.

Architecture:

Terminal
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          SSH (imsg rpc)          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Gateway host (Linux/VM)      │──────────────────────────────────▢│ Mac with Messages + imsg β”‚
β”‚ - openclaw gateway           β”‚          SCP (attachments)        β”‚ - Messages signed in     β”‚
β”‚ - channels.imessage.cliPath  │◀──────────────────────────────────│ - Remote Login enabled   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β–²
              β”‚ Tailscale tailnet (hostname or 100.x.y.z)
              β–Ό
        user@gateway-host

Configuration example (using Tailscale hostname):

Json5
{
  channels: {
    imessage: {
      enabled: true,
      cliPath: "~/.openclaw/scripts/imsg-ssh",
      remoteHost: "[email protected]",
      includeAttachments: true,
      dbPath: "/Users/bot/Library/Messages/chat.db",
    },
  },
}

Wrapper example (~/.openclaw/scripts/imsg-ssh):

Bash
#!/usr/bin/env bash
exec ssh -T [email protected] imsg "$@"

Notes:

- Ensure Mac is logged into Messages and Remote Login is enabled.

- Use SSH key to ensure ssh [email protected] works without prompts.

- remoteHost should match SSH target for SCP to fetch attachments.

Multi-account: Use ''channels.imessage.accounts'' to configure per account (optional ''name''). See shared structure at ''/gateway/configuration''. Do not commit ''~/.openclaw/openclaw.json'' (it usually contains tokens).

Tutorial.step

Access Control (DM + Groups)

DMs:

- Default: channels.imessage.dmPolicy = "pairing".

- Unknown senders receive a pairing code; messages are not processed before approval (1 hour expiry).

- Approve:

- openclaw pairing list imessage

- ''openclaw pairing approve imessage ''''

- Pairing is the default token exchange for iMessage DMs. See ''Pairing''.

Groups:

- channels.imessage.groupPolicy = open | allowlist | disabled.

- When allowlist, channels.imessage.groupAllowFrom controls which senders can trigger.

- iMessage has no native mention metadata, so mention gating relies on agents.list[].groupChat.mentionPatterns (or messages.groupChat.mentionPatterns).

- With multiple agents, you can override per agent in agents.list[].groupChat.mentionPatterns.

Tutorial.step

How It Works (Behavior)

- imsg streams message events; gateway normalizes them to a common channel envelope.

- Replies always return to the same chat id or handle.

Tutorial.step

Group-like Threads (`is_group=false`)

Some iMessage threads may have multiple participants but still appear with is_group=false (depending on how Messages stores chat identifiers).

If you explicitly configure a chat_id in channels.imessage.groups, OpenClaw will treat that thread as a "group" (session isolation and group policies apply).