OpenClawSkills
GitHub
Channels • TutorialHeader.readTime

BlueBubbles

Connect iMessage via BlueBubbles macOS Server (REST): send/receive, typing state, reactions, and advanced actions.

Status: built-in plugin that talks to BlueBubbles macOS Server over HTTP. Because the API is richer and setup is smoother, BlueBubbles is the recommended iMessage integration (preferred over the legacy imsg channel).

Tutorial.step

Overview

- Runs on macOS: the BlueBubbles helper app (bluebubbles.app).

- Recommended/tested: macOS Sequoia (15). macOS Tahoe (26) works, but message edit is currently broken on Tahoe, and group icon updates may report success but not sync.

- OpenClaw uses the REST API (e.g. GET /api/v1/ping, POST /message/text, POST /chat/:id/*).

- Inbound messages arrive via a webhook; outbound replies, typing, read receipts, and tapbacks are done via REST calls.

- Attachments and stickers enter the inbound media pipeline (surfaced to the agent when possible).

- Pairing/allowlist works like other channels (/start/pairing): channels.bluebubbles.allowFrom + pairing code.

- Reactions are injected as system events (like Slack/Telegram), so the agent can mention them before replying.

- Advanced capabilities: edit, unsend, reply-to-message, message effects, and group management.

Tutorial.step

Quick Start

1. Install BlueBubbles Server on your Mac (follow bluebubbles.app/install).

2. Enable the Web API in BlueBubbles settings and set a password.

3. Run openclaw onboard and choose BlueBubbles, or configure it manually:

Json5
{
  channels: {
    bluebubbles: {
      enabled: true,
      serverUrl: "http://192.168.1.100:1234",
      password: "example-password",
      webhookPath: "/bluebubbles-webhook",
    },
  },
}

4. Point the BlueBubbles webhook to your Gateway (example: https://your-gateway-host:3000/bluebubbles-webhook?password=<password>).

5. Start the Gateway; it registers the webhook handler and begins the pairing flow.

Tutorial.step

Onboarding

BlueBubbles supports an interactive wizard:

Terminal
openclaw onboard

The wizard will ask:

- Server URL (required): BlueBubbles server address (e.g. http://192.168.1.100:1234)

- Password (required): API password from BlueBubbles Server settings

- Webhook path (optional): defaults to /bluebubbles-webhook

- DM policy: pairing, allowlist, open, or disabled

- Allow list: phone numbers, emails, or chat targets

You can also add it via the CLI:

Terminal
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
Tutorial.step

Access Control (DM + groups)

DMs:

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

- Unknown senders receive a pairing code; messages are ignored until approved (codes expire after 1 hour).

- Approve via:

- openclaw pairing list bluebubbles

- openclaw pairing approve bluebubbles &lt;CODE&gt;

- Pairing is the default token exchange. Details: /start/pairing

Groups:

- channels.bluebubbles.groupPolicy = open | allowlist | disabled (default allowlist).

- When allowlist, channels.bluebubbles.groupAllowFrom controls who can trigger the agent in groups.

Tutorial.step

Mention gating (groups)

BlueBubbles group mention gating matches iMessage/WhatsApp behavior:

- Mentions are detected via agents.list[].groupChat.mentionPatterns (or messages.groupChat.mentionPatterns).

- When a group's requireMention is enabled, the agent only replies when mentioned.

- Trusted control-command senders can bypass mention gating.

Per-group configuration:

Json5
{
  channels: {
    bluebubbles: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["+15555550123"],
      groups: {
        "*": { requireMention: true },
        "iMessage;-;chat123": { requireMention: false },
      },
    },
  },
}
Tutorial.step

Command gating

- Control commands (e.g. /config, /model) require authorization.

- Authorization is determined by allowFrom and groupAllowFrom.

- Authorized senders can run control commands in groups without @mention.

Tutorial.step

Typing state + read receipts

- Typing state: sent automatically before and during reply generation.

- Read receipts: controlled by channels.bluebubbles.sendReadReceipts (default true).

- Typing is cleared by BlueBubbles after send or timeout (manual stop via DELETE is unreliable).

Json5
{
  channels: {
    bluebubbles: {
      sendReadReceipts: false
    },
  },
}
Tutorial.step

Advanced actions

When enabled, BlueBubbles supports advanced message actions:

Json5
{
  channels: {
    bluebubbles: {
      actions: {
        reactions: true,
        edit: true,
        unsend: true,
        reply: true,
        sendWithEffect: true,
        renameGroup: true,
        setGroupIcon: true,
        addParticipant: true,
        removeParticipant: true,
        leaveGroup: true,
        sendAttachment: true,
      },
    },
  },
}

Action list:

- react: add/remove tapback (messageId, emoji, remove)

- edit: edit a sent message (messageId, text) (macOS 13+; currently broken on macOS 26 Tahoe)

- unsend: unsend a message (messageId) (macOS 13+)

- reply: reply to a specific message (messageId, text, to)

- sendWithEffect: send with iMessage effects (text, to, effectId)

- renameGroup: rename a group (chatGuid, displayName)

- setGroupIcon: set group icon (chatGuid, media) (may report success but not sync on macOS 26 Tahoe)

- addParticipant: add a participant (chatGuid, address)

- removeParticipant: remove a participant (chatGuid, address)

- leaveGroup: leave a group (chatGuid)

- sendAttachment: send media/attachments (to, buffer, filename, asVoice)

- Voice note: set asVoice: true and provide MP3 or CAF audio to send an iMessage voice note. BlueBubbles converts MP3 to CAF for voice notes.

Tutorial.step

Message IDs (short vs full)

To save tokens, OpenClaw may expose a "short message id" in context (e.g. 1, 2).

- MessageSid / ReplyToId may be a short ID.

- MessageSidFull / ReplyToIdFull are provider full IDs.

- Short IDs are an in-memory cache; they become invalid after restarts or eviction.

- Actions accept both short and full messageId, but will error if a short ID is no longer available.

For long-lived automation/storage, use full IDs:

- Templates: <code>'{'{MessageSidFull}'}'</code>, <code>'{'{ReplyToIdFull}'}'</code>

- Context: MessageSidFull / ReplyToIdFull in inbound payloads

See /gateway/configuration for template variables.

Tutorial.step

Block streaming

Control whether replies are sent in one piece or streamed in blocks:

Json5
{
  channels: {
    bluebubbles: {
      blockStreaming: true
    },
  },
}
Tutorial.step

Media and limits

- Inbound attachments are downloaded and stored in the media cache.

- Limit: channels.bluebubbles.mediaMaxMb (default 8 MB).

- Outbound text is chunked by channels.bluebubbles.textChunkLimit (default 4000 chars).

Tutorial.step

Configuration reference

Full config: /gateway/configuration

Provider options:

- channels.bluebubbles.enabled

- channels.bluebubbles.serverUrl

- channels.bluebubbles.password

- channels.bluebubbles.webhookPath (default /bluebubbles-webhook)

- channels.bluebubbles.dmPolicy: pairing | allowlist | open | disabled (default pairing)

- channels.bluebubbles.allowFrom: DM allowlist (handles, emails, E.164, chat_id:*, chat_guid:*)

- channels.bluebubbles.groupPolicy: open | allowlist | disabled (default allowlist)

- channels.bluebubbles.groupAllowFrom

- channels.bluebubbles.groups (per-group overrides like requireMention)

- channels.bluebubbles.sendReadReceipts (default true)

- channels.bluebubbles.blockStreaming (default true)

- channels.bluebubbles.textChunkLimit (default 4000)

- channels.bluebubbles.chunkMode: length (default) / newline

- channels.bluebubbles.mediaMaxMb (default 8)

- channels.bluebubbles.historyLimit (group context message limit; disable with 0)

- channels.bluebubbles.dmHistoryLimit

- channels.bluebubbles.actions

- channels.bluebubbles.accounts

Related global options:

- agents.list[].groupChat.mentionPatterns (or messages.groupChat.mentionPatterns)

- messages.responsePrefix

Tutorial.step

Addresses and targets

For stable routing, prefer chat_guid:

- chat_guid:iMessage;-;+15555550123 (preferred for group chats)

- chat_id:123

- chat_identifier:...

- Direct handles: +15555550123, [email protected]

- If no DM chat exists for a handle, OpenClaw creates one via POST /api/v1/chat/new (requires BlueBubbles Private API).

Tutorial.step

Security

- Webhook requests are authenticated by comparing guid/password in query params or headers to channels.bluebubbles.password; requests from localhost are also accepted.

- Treat the API password and webhook endpoint as credentials (do not leak them).

- Trusting localhost means a same-host reverse proxy may bypass passwords unintentionally. If you proxy the Gateway, enforce auth at the proxy layer and configure gateway.trustedProxies. See Gateway security.

- If you expose the BlueBubbles server outside your LAN, enable HTTPS and configure firewall rules.

Tutorial.step

Troubleshooting

- Typing/read events stopped working: check BlueBubbles webhook logs and confirm the Gateway path matches channels.bluebubbles.webhookPath.

- Pairing codes expire after 1 hour: openclaw pairing list bluebubbles / openclaw pairing approve bluebubbles &lt;code&gt;.

- Reactions require the BlueBubbles Private API (POST /api/v1/message/react); confirm your server version exposes it.

- edit/unsend require macOS 13+ and a compatible BlueBubbles server; on macOS 26 (Tahoe), edit is currently unavailable due to Private API changes.

- Group icon updates may be flaky on macOS 26 (Tahoe): the API may return success but the icon doesn’t sync.

- OpenClaw automatically hides actions known to be unavailable for your macOS version. If you still see edit on macOS 26 (Tahoe), disable it manually: channels.bluebubbles.actions.edit=false.

- Status/health: openclaw status --all or openclaw status --deep.

For an overview of how channels work, see Channels and Plugins.