diff --git a/docs/announcements/bluebubbles-imessage.md b/docs/announcements/bluebubbles-imessage.md index d63c3d05fa8b..1b216d228583 100644 --- a/docs/announcements/bluebubbles-imessage.md +++ b/docs/announcements/bluebubbles-imessage.md @@ -1,5 +1,5 @@ --- -summary: "BlueBubbles support was removed from OpenClaw. Use the bundled iMessage plugin with imsg for new and migrated iMessage setups." +summary: "BlueBubbles support was removed from OpenClaw. Use the official iMessage plugin with imsg for new and migrated iMessage setups." read_when: - You used the old BlueBubbles channel and need to move to iMessage - You are choosing the supported OpenClaw iMessage setup @@ -9,7 +9,7 @@ title: "BlueBubbles removal and the imsg iMessage path" # BlueBubbles removal and the imsg iMessage path -OpenClaw no longer ships the BlueBubbles channel. iMessage support runs through the bundled `imessage` plugin: the Gateway spawns [`imsg`](https://github.com/steipete/imsg) as a child process, locally or through an SSH wrapper, and talks JSON-RPC over stdin/stdout. No server, no webhook, no port. +OpenClaw no longer ships the BlueBubbles channel. iMessage support runs through the official `@openclaw/imessage` plugin: the Gateway spawns [`imsg`](https://github.com/steipete/imsg) as a child process, locally or through an SSH wrapper, and talks JSON-RPC over stdin/stdout. No server, no webhook, no port. If your config still contains `channels.bluebubbles`, migrate it to `channels.imessage`. The legacy `/channels/bluebubbles` docs URL redirects to [Coming from BlueBubbles](/channels/imessage-from-bluebubbles), which has the full config translation table and cutover checklist. @@ -23,7 +23,13 @@ If your config still contains `channels.bluebubbles`, migrate it to `channels.im ## What to do -1. Install and verify `imsg` on the Messages Mac: +1. Install the official plugin on the Gateway host, then restart the Gateway: + + ```bash + openclaw plugins install @openclaw/imessage + ``` + +2. Install and verify `imsg` on the Messages Mac: ```bash brew install steipete/tap/imsg @@ -32,9 +38,9 @@ If your config still contains `channels.bluebubbles`, migrate it to `channels.im imsg rpc --help ``` -2. Grant Full Disk Access and Automation permissions to the process context that runs `imsg` and OpenClaw. +3. Grant Full Disk Access and Automation permissions to the process context that runs `imsg` and OpenClaw. -3. Translate the old config: +4. Translate the old config: ```json5 { @@ -55,13 +61,13 @@ If your config still contains `channels.bluebubbles`, migrate it to `channels.im } ``` -4. Restart the gateway and verify: +5. Restart the gateway and verify: ```bash openclaw channels status --probe ``` -5. Test DMs, groups, attachments, and any private API actions you depend on before deleting your old BlueBubbles server. +6. Test DMs, groups, attachments, and any private API actions you depend on before deleting your old BlueBubbles server. ## Migration notes diff --git a/docs/channels/access-groups.md b/docs/channels/access-groups.md index 32e47fd670b7..cd634ae93615 100644 --- a/docs/channels/access-groups.md +++ b/docs/channels/access-groups.md @@ -121,7 +121,7 @@ Access groups work in the shared message-channel authorization paths: - channel-specific per-room sender allowlists that use the same sender matching rules (for example Google Chat `groups..users`) - command authorization paths that reuse message-channel sender allowlists -Channel support depends on whether that channel is wired through the shared OpenClaw sender-authorization helpers. Current bundled support includes ClickClack, Discord, Feishu, Google Chat, iMessage, IRC, LINE, Mattermost, Microsoft Teams, Nextcloud Talk, Nostr, QQ Bot, Signal, Slack, SMS, Telegram, WhatsApp, Zalo, and Zalo Personal. Static `message.senders` groups are channel-agnostic, so new message channels get them by using the shared plugin SDK ingress helpers instead of custom allowlist expansion. +Channel support depends on whether that channel is wired through the shared OpenClaw sender-authorization helpers. Current supported channel integrations include ClickClack, Discord, Feishu, Google Chat, iMessage, IRC, LINE, Mattermost, Microsoft Teams, Nextcloud Talk, Nostr, QQ Bot, Signal, Slack, SMS, Telegram, WhatsApp, Zalo, and Zalo Personal. Static `message.senders` groups are channel-agnostic, so new message channels get them by using the shared plugin SDK ingress helpers instead of custom allowlist expansion. ## Discord channel audiences diff --git a/docs/channels/channel-routing.md b/docs/channels/channel-routing.md index 2b5b3cb91161..d6ae5640a2ff 100644 --- a/docs/channels/channel-routing.md +++ b/docs/channels/channel-routing.md @@ -14,7 +14,7 @@ channel converge on the agent's [main session](/concepts/main-session). ## Key terms -- **Channel**: a bundled channel plugin such as `discord`, `googlechat`, `imessage`, `irc`, `line`, `signal`, `slack`, `telegram`, or `whatsapp`, plus installed plugin channels. `webchat` is the internal WebChat UI channel and is not a configurable outbound channel. +- **Channel**: a channel plugin such as `discord`, `googlechat`, `imessage`, `irc`, `line`, `signal`, `slack`, `telegram`, or `whatsapp`. `webchat` is the internal WebChat UI channel and is not a configurable outbound channel. - **AccountId**: per-channel account instance (when supported). - Optional channel default account: `channels..defaultAccount` chooses which account is used when an outbound path does not specify `accountId`. diff --git a/docs/channels/imessage-from-bluebubbles.md b/docs/channels/imessage-from-bluebubbles.md index aa8e01e8d8d5..a2a5d832946c 100644 --- a/docs/channels/imessage-from-bluebubbles.md +++ b/docs/channels/imessage-from-bluebubbles.md @@ -1,13 +1,13 @@ --- -summary: "Translate old BlueBubbles configs to the bundled iMessage plugin: key mapping, group allowlist gates, and cutover verification." +summary: "Translate old BlueBubbles configs to the official iMessage plugin: key mapping, group allowlist gates, and cutover verification." read_when: - - Planning a move from BlueBubbles to the bundled iMessage plugin + - Planning a move from BlueBubbles to the official iMessage plugin - Translating BlueBubbles config keys to iMessage equivalents - Verifying imsg before enabling the iMessage plugin title: "Coming from BlueBubbles" --- -BlueBubbles support was removed. OpenClaw supports iMessage only through the bundled `imessage` plugin, which drives [`steipete/imsg`](https://github.com/steipete/imsg) over JSON-RPC and reaches the same private API surface BlueBubbles had (`react`, `edit`, `unsend`, `reply`, `sendWithEffect`, native polls, group management, attachments). One CLI binary replaces the BlueBubbles server + client app + webhook plumbing: no REST endpoint, no webhook auth. +BlueBubbles support was removed. OpenClaw supports iMessage only through the official `@openclaw/imessage` plugin, which drives [`steipete/imsg`](https://github.com/steipete/imsg) over JSON-RPC and reaches the same private API surface BlueBubbles had (`react`, `edit`, `unsend`, `reply`, `sendWithEffect`, native polls, group management, attachments). One CLI binary replaces the BlueBubbles server + client app + webhook plumbing: no REST endpoint, no webhook auth. This guide migrates old `channels.bluebubbles` configs to `channels.imessage`. There is no other supported migration path. On current OpenClaw a leftover `channels.bluebubbles` block is inert — no runtime reads it. @@ -19,13 +19,14 @@ For the short announcement and operator summary, see [BlueBubbles removal and th The shortest safe path when you already know your old BlueBubbles config: -1. Verify `imsg` directly on the Mac that runs Messages.app (`imsg chats`, `imsg history`, `imsg send`, `imsg rpc --help`). -2. Copy behavior keys from `channels.bluebubbles` to `channels.imessage`: `dmPolicy`, `allowFrom`, `groupPolicy`, `groupAllowFrom`, `groups`, `includeAttachments`, `attachmentRoots`, `mediaMaxMb`, `textChunkLimit`, and `actions`. -3. Drop transport keys that no longer exist: `serverUrl`, `password`, webhook URLs, and BlueBubbles server setup. -4. If the Gateway is not running on the Messages Mac, set `channels.imessage.cliPath` to an SSH wrapper and set `remoteHost` for remote attachment fetches. -5. Enable `channels.imessage`, restart the Gateway, then run `openclaw channels status --probe --channel imessage`. -6. Test one DM, one allowed group, attachments if enabled, and every private API action you expect the agent to use. -7. Delete the BlueBubbles server and the old `channels.bluebubbles` config after the iMessage path is verified. +1. Install the official plugin with `openclaw plugins install @openclaw/imessage`, then restart the Gateway. +2. Verify `imsg` directly on the Mac that runs Messages.app (`imsg chats`, `imsg history`, `imsg send`, `imsg rpc --help`). +3. Copy behavior keys from `channels.bluebubbles` to `channels.imessage`: `dmPolicy`, `allowFrom`, `groupPolicy`, `groupAllowFrom`, `groups`, `includeAttachments`, `attachmentRoots`, `mediaMaxMb`, `textChunkLimit`, and `actions`. +4. Drop transport keys that no longer exist: `serverUrl`, `password`, webhook URLs, and BlueBubbles server setup. +5. If the Gateway is not running on the Messages Mac, set `channels.imessage.cliPath` to an SSH wrapper and set `remoteHost` for remote attachment fetches. +6. Enable `channels.imessage`, restart the Gateway, then run `openclaw channels status --probe --channel imessage`. +7. Test one DM, one allowed group, attachments if enabled, and every private API action you expect the agent to use. +8. Delete the BlueBubbles server and the old `channels.bluebubbles` config after the iMessage path is verified. ## What imsg does @@ -89,7 +90,7 @@ The shortest safe path when you already know your old BlueBubbles config: iMessage and BlueBubbles share most channel-level behavior keys. What changes is transport (REST server vs local CLI) and the group registry key format. -| BlueBubbles | bundled iMessage | Notes | +| BlueBubbles | iMessage plugin | Notes | | ---------------------------------------------------------- | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `channels.bluebubbles.enabled` | `channels.imessage.enabled` | Same semantics (default `true` once the block exists). | | `channels.bluebubbles.serverUrl` | _(removed)_ | No REST server — the plugin spawns `imsg rpc` over stdio. | @@ -102,7 +103,7 @@ iMessage and BlueBubbles share most channel-level behavior keys. What changes is | `channels.bluebubbles.groupPolicy` | `channels.imessage.groupPolicy` | Same values (`allowlist` / `open` / `disabled`); default `allowlist`. | | `channels.bluebubbles.groupAllowFrom` | `channels.imessage.groupAllowFrom` | Same. When unset, iMessage falls back to `allowFrom`; an explicitly empty `groupAllowFrom: []` blocks all groups under `groupPolicy: "allowlist"`. | | `channels.bluebubbles.groups` | `channels.imessage.groups` | Copy the `"*"` wildcard entry verbatim; re-key per-group entries by numeric iMessage `chat_id` — see "Group registry footgun". `requireMention`, `tools`, `toolsBySender`, `systemPrompt` carry over. | -| `channels.bluebubbles.sendReadReceipts` | `channels.imessage.sendReadReceipts` | Default `true`. With the bundled plugin this only fires when the private API probe is up. | +| `channels.bluebubbles.sendReadReceipts` | `channels.imessage.sendReadReceipts` | Default `true`. This only fires when the private API probe is up. | | `channels.bluebubbles.includeAttachments` | `channels.imessage.includeAttachments` | Same shape, same off-by-default. If attachments flowed on BlueBubbles, set this explicitly — inbound photos/media are silently dropped (no `Inbound message` log line) until you do. | | `channels.bluebubbles.attachmentRoots` | `channels.imessage.attachmentRoots` | Local roots; same wildcard rules. | | _(N/A)_ | `channels.imessage.remoteAttachmentRoots` | Only used when `remoteHost` is set for SCP fetches. | @@ -116,7 +117,7 @@ Multi-account configs (`channels.bluebubbles.accounts.*`) translate one-to-one t ## Group registry footgun -The bundled iMessage plugin runs two group gates back to back. A group message must pass both to reach the agent: +The iMessage plugin runs two group gates back to back. A group message must pass both to reach the agent: 1. **Sender / chat-target allowlist** (`channels.imessage.groupAllowFrom`) — matches the sender handle or the chat target (`chat_id:`, `chat_guid:`, `chat_identifier:` entries). When `groupAllowFrom` is unset, this gate falls back to `allowFrom`; an explicit `groupAllowFrom: []` disables that fallback and drops every group message under `groupPolicy: "allowlist"`. 2. **Group registry** (`channels.imessage.groups`) — keyed by numeric iMessage `chat_id`: @@ -188,7 +189,7 @@ This admits the configured senders in any group. Add `groups` entries to scope a ## Action parity at a glance -| Action | legacy BlueBubbles | bundled iMessage | +| Action | legacy BlueBubbles | iMessage plugin | | --------------------------------------------------- | ------------------ | ----------------------------------------------------------------------------- | | Send text / SMS fallback | ✅ | ✅ | | Send media (photo, video, file, voice) | ✅ | ✅ | diff --git a/docs/channels/imessage.md b/docs/channels/imessage.md index fcfa0039e101..9adb81be4d77 100644 --- a/docs/channels/imessage.md +++ b/docs/channels/imessage.md @@ -20,6 +20,14 @@ Status: native external CLI integration. The Gateway spawns `imsg rpc` and speak For the common local setup, OpenClaw setup can offer a user-confirmed Homebrew install or update for `imsg` on the signed-in Messages Mac. Manual setup and SSH-wrapper topologies remain operator-managed: install or update `imsg` in the same user context that will run the Gateway or wrapper. +## Install the plugin + +Install the official iMessage plugin on the Gateway host, then restart the Gateway: + +```bash +openclaw plugins install @openclaw/imessage +``` + Replies, tapbacks, effects, polls, attachments, and group management. @@ -200,7 +208,7 @@ The helper-injection technique uses `imsg`'s own dylib to reach Messages private **Disabling SIP is a real security tradeoff.** SIP is one of macOS's core protections against running modified system code; turning it off system-wide opens up additional attack surface and side effects. Notably, **disabling SIP on Apple Silicon Macs also disables the ability to install and run iOS apps on your Mac**. -Treat this as a deliberate operational choice, especially on a primary personal Mac. For production-quality OpenClaw iMessage, prefer a dedicated Mac or bot macOS user where you are comfortable enabling the bridge. If your threat model cannot tolerate SIP being off anywhere, bundled iMessage is limited to basic mode — text and media send/receive only, no reactions / edit / unsend / effects / group ops. +Treat this as a deliberate operational choice, especially on a primary personal Mac. For production-quality OpenClaw iMessage, prefer a dedicated Mac or bot macOS user where you are comfortable enabling the bridge. If your threat model cannot tolerate SIP being off anywhere, the iMessage plugin is limited to basic mode — text and media send/receive only, no reactions / edit / unsend / effects / group ops. ### Setup diff --git a/docs/channels/index.md b/docs/channels/index.md index 60225e87abfb..fc8b05d00ce3 100644 --- a/docs/channels/index.md +++ b/docs/channels/index.md @@ -9,7 +9,7 @@ title: "Chat channels" OpenClaw can talk to you on any chat app you already use. Each channel connects via the Gateway. Text is supported everywhere; media and reactions vary by channel. -iMessage, Telegram, and the WebChat UI ship with the core install. Channels marked +Telegram and the WebChat UI ship with the core install. Channels marked "official plugin" install with one command (`openclaw plugins install @openclaw/`) or on demand during `openclaw onboard` / `openclaw channels add`, then need a Gateway restart. "External plugin" channels are maintained outside the OpenClaw repo. @@ -20,7 +20,7 @@ restart. "External plugin" channels are maintained outside the OpenClaw repo. - [Discord](/channels/discord) - Discord Bot API + Gateway; supports servers, channels, and DMs (official plugin). - [Feishu](/channels/feishu) - Feishu/Lark bot via WebSocket (official plugin). - [Google Chat](/channels/googlechat) - Google Chat API app via HTTP webhook (official plugin). -- [iMessage](/channels/imessage) - Included in core. Native macOS integration via the `imsg` bridge on a signed-in Mac (or SSH wrapper when the Gateway runs elsewhere), including private API actions for replies, tapbacks, effects, attachments, and group management. +- [iMessage](/channels/imessage) - Native macOS integration via the `imsg` bridge on a signed-in Mac (or SSH wrapper when the Gateway runs elsewhere), including private API actions for replies, tapbacks, effects, attachments, and group management (official plugin). - [IRC](/channels/irc) - Classic IRC servers; channels + DMs with pairing/allowlist controls (official plugin). - [LINE](/channels/line) - LINE Messaging API bot (official plugin). - [Matrix](/channels/matrix) - Matrix protocol (official plugin). diff --git a/docs/concepts/features.md b/docs/concepts/features.md index 8456b0308507..71cdc9424736 100644 --- a/docs/concepts/features.md +++ b/docs/concepts/features.md @@ -32,10 +32,10 @@ title: "Features" **Channels:** -- iMessage, Telegram, and WebChat ship with the core install; every other channel is an +- Telegram and WebChat ship with the core install; every other channel is an official plugin installed with `openclaw plugins install @openclaw/` (or on demand during `openclaw onboard` / `openclaw channels add`) -- Official plugin channels: Discord, Feishu, Google Chat, IRC, LINE, Matrix, Mattermost, +- Official plugin channels: Discord, Feishu, Google Chat, iMessage, IRC, LINE, Matrix, Mattermost, Microsoft Teams, Nextcloud Talk, Nostr, QQ Bot, Raft, Signal, Slack, SMS, Synology Chat, Tlon, Twitch, Voice Call, WhatsApp, Zalo, and Zalo Personal - External plugin channels maintained outside the OpenClaw repo: WeChat, Yuanbao, and Zalo ClawBot diff --git a/docs/docs_map.md b/docs/docs_map.md index 488132c0b0dd..fdc67ce436dd 100644 --- a/docs/docs_map.md +++ b/docs/docs_map.md @@ -524,6 +524,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`. - Route: /channels/imessage - Headings: + - H2: Install the plugin - H2: Quick setup - H2: Requirements and permissions (macOS) - H2: Enabling the imsg private API diff --git a/docs/gateway/config-channels.md b/docs/gateway/config-channels.md index 6c5c6132e386..e2a0330bc4fc 100644 --- a/docs/gateway/config-channels.md +++ b/docs/gateway/config-channels.md @@ -13,7 +13,7 @@ For agents, tools, gateway runtime, and other top-level keys, see [Configuration ## Channels -Each channel starts automatically when its config section exists (unless `enabled: false`). Telegram and iMessage ship inside the core `openclaw` package. Other official channels (Discord, Slack, WhatsApp, Matrix, Microsoft Teams, IRC, Google Chat, Signal, Mattermost, and more) install as separate plugins with `openclaw plugins install `; see [Channels](/channels) for the full list and install specs. +Each channel starts automatically when its config section exists (unless `enabled: false`). Telegram ships inside the core `openclaw` package. Other official channels (iMessage, Discord, Slack, WhatsApp, Matrix, Microsoft Teams, IRC, Google Chat, Signal, Mattermost, and more) install as separate plugins with `openclaw plugins install `; see [Channels](/channels) for the full list and install specs. ### DM and group access diff --git a/docs/gateway/configuration-reference.md b/docs/gateway/configuration-reference.md index dd8615a05148..df7219a5dad6 100644 --- a/docs/gateway/configuration-reference.md +++ b/docs/gateway/configuration-reference.md @@ -32,7 +32,7 @@ Dedicated deep references: ## Channels -Per-channel config keys live in [Configuration - channels](/gateway/config-channels): `channels.*` for Slack, Discord, Telegram, WhatsApp, Matrix, iMessage, and other bundled channels (auth, access control, multi-account, mention gating). +Per-channel config keys live in [Configuration - channels](/gateway/config-channels): `channels.*` for Slack, Discord, Telegram, WhatsApp, Matrix, iMessage, and other channel plugins (auth, access control, multi-account, mention gating). ## Agent defaults, multi-agent, sessions, and messages diff --git a/docs/gateway/health.md b/docs/gateway/health.md index f91b23feba96..74be0fd2a188 100644 --- a/docs/gateway/health.md +++ b/docs/gateway/health.md @@ -39,7 +39,7 @@ health commands above for live connectivity checks. - `channels..healthMonitor.enabled`: disable health-monitor restarts for a specific channel while leaving global monitoring enabled. - `channels..accounts..healthMonitor.enabled`: multi-account override that wins over the channel-level setting. -- These per-channel overrides apply to the built-in channels that expose them today: Discord, Google Chat, iMessage, IRC, Microsoft Teams, Signal, Slack, Telegram, and WhatsApp. +- These per-channel overrides apply to the channels that expose them today: Discord, Google Chat, iMessage, IRC, Microsoft Teams, Signal, Slack, Telegram, and WhatsApp. - A crashing channel is recovered by its own auto-restart backoff first (`auto-restart attempt N/10` in the logs). The health monitor stays out of the way until that ladder ends with `giving up after 10 restart attempts`, then takes over as the last restart owner. ## Inbound ingress health diff --git a/docs/plugins/plugin-inventory.md b/docs/plugins/plugin-inventory.md index 53beb0a3f99f..7fab41aef970 100644 --- a/docs/plugins/plugin-inventory.md +++ b/docs/plugins/plugin-inventory.md @@ -51,7 +51,7 @@ Each entry lists the package, distribution route, and description. ## Core npm package -55 plugins +54 plugins - **[admin-http-rpc](/plugins/reference/admin-http-rpc)** (`@openclaw/admin-http-rpc`) - included in OpenClaw. OpenClaw admin HTTP RPC endpoint. @@ -93,8 +93,6 @@ Each entry lists the package, distribution route, and description. - **[huggingface](/plugins/reference/huggingface)** (`@openclaw/huggingface-provider`) - included in OpenClaw. Adds Hugging Face model provider support to OpenClaw. -- **[imessage](/plugins/reference/imessage)** (`@openclaw/imessage`) - included in OpenClaw. Adds the iMessage channel surface for sending and receiving OpenClaw messages. - - **[linux-canvas](/plugins/reference/linux-canvas)** (`@openclaw/linux-canvas`) - included in OpenClaw. Canvas rendering bridge for the OpenClaw Linux desktop app. - **[linux-node](/plugins/reference/linux-node)** (`@openclaw/linux-node`) - included in OpenClaw. Desktop notifications, camera capture, and location for Linux node hosts. @@ -165,7 +163,7 @@ Each entry lists the package, distribution route, and description. ## Official external packages -90 plugins +91 plugins - **[acpx](/plugins/reference/acpx)** (`@openclaw/acpx`) - npm; ClawHub. OpenClaw ACP runtime backend with plugin-owned session and transport management. @@ -239,6 +237,8 @@ Each entry lists the package, distribution route, and description. - **[groq](/plugins/reference/groq)** (`@openclaw/groq-provider`) - npm; ClawHub: `clawhub:@openclaw/groq-provider`. Adds Groq model provider support to OpenClaw. +- **[imessage](/plugins/reference/imessage)** (`@openclaw/imessage`) - npm; ClawHub: `clawhub:@openclaw/imessage`. Adds the iMessage channel surface for sending and receiving OpenClaw messages. + - **[inworld](/plugins/reference/inworld)** (`@openclaw/inworld-speech`) - npm; ClawHub: `clawhub:@openclaw/inworld-speech`. Inworld streaming text-to-speech (MP3, OGG_OPUS, PCM telephony). - **[irc](/plugins/reference/irc)** (`@openclaw/irc`) - npm; ClawHub: `clawhub:@openclaw/irc`. Adds the IRC channel surface for sending and receiving OpenClaw messages. diff --git a/docs/plugins/reference/imessage.md b/docs/plugins/reference/imessage.md index 8c6b47e0356d..d88eb2cf1157 100644 --- a/docs/plugins/reference/imessage.md +++ b/docs/plugins/reference/imessage.md @@ -12,7 +12,7 @@ Adds the iMessage channel surface for sending and receiving OpenClaw messages. ## Distribution - Package: `@openclaw/imessage` -- Install route: included in OpenClaw +- Install route: npm; ClawHub: `clawhub:@openclaw/imessage` ## Surface diff --git a/extensions/imessage/README.md b/extensions/imessage/README.md new file mode 100644 index 000000000000..d6f7be4ce7bf --- /dev/null +++ b/extensions/imessage/README.md @@ -0,0 +1,29 @@ +# @openclaw/imessage + +Official iMessage channel plugin for OpenClaw, using `imsg` on a signed-in Mac. + +The plugin supports iMessage and SMS DMs and groups, media, replies, tapbacks, +effects, polls, and group management when the `imsg` private API bridge is +available. + +## Install + +```bash +openclaw plugins install @openclaw/imessage +``` + +Restart the Gateway after installing or updating the plugin. + +## Configure + +Follow the iMessage guide for installing `imsg`, granting macOS permissions, +enabling private API actions, and configuring local or remote-Mac operation: + +- https://docs.openclaw.ai/channels/imessage + +## Package + +- Plugin id: `imessage` +- Channel id: `imessage` +- Package: `@openclaw/imessage` +- Minimum OpenClaw host: `2026.7.2` diff --git a/extensions/imessage/package.json b/extensions/imessage/package.json index aced9e71187f..35e2ceb97f19 100644 --- a/extensions/imessage/package.json +++ b/extensions/imessage/package.json @@ -1,15 +1,27 @@ { "name": "@openclaw/imessage", "version": "2026.7.2", - "private": true, "description": "OpenClaw iMessage channel plugin using imsg on a signed-in Mac", + "repository": { + "type": "git", + "url": "https://github.com/openclaw/openclaw" + }, "type": "module", "dependencies": { "typebox": "1.3.6", "zod": "4.4.3" }, "devDependencies": { - "@openclaw/plugin-sdk": "workspace:*" + "@openclaw/plugin-sdk": "workspace:*", + "openclaw": "workspace:*" + }, + "peerDependencies": { + "openclaw": ">=2026.7.2" + }, + "peerDependenciesMeta": { + "openclaw": { + "optional": true + } }, "openclaw": { "extensions": [ @@ -61,11 +73,23 @@ ] } }, + "install": { + "clawhubSpec": "clawhub:@openclaw/imessage", + "npmSpec": "@openclaw/imessage", + "defaultChoice": "npm", + "minHostVersion": ">=2026.7.2", + "allowInvalidConfigRecovery": true + }, "compat": { "pluginApi": ">=2026.7.2" }, "build": { - "openclawVersion": "2026.7.2" + "openclawVersion": "2026.7.2", + "bundledDist": false + }, + "release": { + "publishToClawHub": true, + "publishToNpm": true } }, "pluginInspector": { diff --git a/package.json b/package.json index ef91f544801c..fc5c45b19d30 100644 --- a/package.json +++ b/package.json @@ -276,6 +276,7 @@ "!dist/extensions/gradium/**", "!dist/extensions/groq/**", "!dist/extensions/inworld/**", + "!dist/extensions/imessage/**", "!dist/extensions/irc/**", "!dist/extensions/kilocode/**", "!dist/extensions/kimi-coding/**", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1576a93ababf..c7ac1dfaec3e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1037,6 +1037,9 @@ importers: '@openclaw/plugin-sdk': specifier: workspace:* version: link:../../packages/plugin-sdk + openclaw: + specifier: workspace:* + version: link:../.. extensions/inworld: devDependencies: diff --git a/scripts/lib/bundled-runtime-sidecar-paths.json b/scripts/lib/bundled-runtime-sidecar-paths.json index a54369fbc782..91ca7d2d1114 100644 --- a/scripts/lib/bundled-runtime-sidecar-paths.json +++ b/scripts/lib/bundled-runtime-sidecar-paths.json @@ -3,7 +3,6 @@ "dist/extensions/canvas/runtime-api.js", "dist/extensions/copilot-proxy/runtime-api.js", "dist/extensions/google/runtime-api.js", - "dist/extensions/imessage/runtime-api.js", "dist/extensions/lmstudio/runtime-api.js", "dist/extensions/memory-core/runtime-api.js", "dist/extensions/ollama/runtime-api.js", diff --git a/scripts/lib/official-external-channel-catalog.json b/scripts/lib/official-external-channel-catalog.json index 5b80562e086f..0c865353a5de 100644 --- a/scripts/lib/official-external-channel-catalog.json +++ b/scripts/lib/official-external-channel-catalog.json @@ -309,6 +309,50 @@ } } }, + { + "name": "@openclaw/imessage", + "description": "OpenClaw iMessage channel plugin using imsg on a signed-in Mac", + "source": "official", + "kind": "channel", + "openclaw": { + "channel": { + "id": "imessage", + "label": "iMessage", + "selectionLabel": "iMessage (imsg)", + "detailLabel": "iMessage", + "docsPath": "/channels/imessage", + "docsLabel": "imessage", + "blurb": "Local iMessage/SMS through the imsg bridge, including private API message actions when enabled.", + "aliases": ["imsg"], + "systemImage": "message.fill", + "cliAddOptions": [ + { + "flags": "--cli-path ", + "description": "iMessage CLI path" + }, + { + "flags": "--db-path ", + "description": "iMessage database path" + }, + { + "flags": "--service ", + "description": "iMessage service" + }, + { + "flags": "--region ", + "description": "SMS region" + } + ] + }, + "install": { + "clawhubSpec": "clawhub:@openclaw/imessage", + "npmSpec": "@openclaw/imessage", + "defaultChoice": "npm", + "minHostVersion": ">=2026.7.2", + "allowInvalidConfigRecovery": true + } + } + }, { "name": "@openclaw/irc", "description": "OpenClaw IRC channel plugin", diff --git a/src/cli/plugins-location-bridges.test.ts b/src/cli/plugins-location-bridges.test.ts index 0ff68efde751..af1df2e0f0a8 100644 --- a/src/cli/plugins-location-bridges.test.ts +++ b/src/cli/plugins-location-bridges.test.ts @@ -245,6 +245,39 @@ describe("listPersistedBundledPluginLocationBridges", () => { ]); }); + it("externalizes the shipped bundled iMessage channel while preserving default enablement", async () => { + readPersistedInstalledPluginIndexMock.mockResolvedValue( + makeIndex({ + pluginId: "imessage", + manifestPath: "/app/dist/extensions/imessage/openclaw.plugin.json", + manifestHash: "hash", + source: "/app/dist/extensions/imessage/index.js", + rootDir: "/app/dist/extensions/imessage", + origin: "bundled", + enabled: true, + enabledByDefault: true, + startup: startupInfo, + compat: [], + packageInstall: { + warnings: [], + }, + }), + ); + loadPluginManifestRegistryForInstalledIndexMock.mockReturnValue(makeRegistry("imessage")); + + await expect(listPersistedBundledPluginLocationBridges({})).resolves.toEqual([ + { + bundledPluginId: "imessage", + pluginId: "imessage", + preferredSource: "npm", + npmSpec: "@openclaw/imessage", + clawhubSpec: "clawhub:@openclaw/imessage", + enabledByDefault: true, + channelIds: ["imessage"], + }, + ]); + }); + it("does not create a relocation bridge without persisted or official install metadata", async () => { readPersistedInstalledPluginIndexMock.mockResolvedValue( makeIndex({ diff --git a/src/plugins/official-external-plugin-catalog.test.ts b/src/plugins/official-external-plugin-catalog.test.ts index 10d3603033ba..c0a72b8b101f 100644 --- a/src/plugins/official-external-plugin-catalog.test.ts +++ b/src/plugins/official-external-plugin-catalog.test.ts @@ -2226,6 +2226,25 @@ describe("official external plugin catalog", () => { ).toEqual(["novita"]); }); + it("lists iMessage as an official external channel", () => { + const imessage = expectCatalogEntry("imessage"); + const channel = getOfficialExternalPluginCatalogManifest(imessage)?.channel; + + expect(resolveOfficialExternalPluginId(imessage)).toBe("imessage"); + expect(channel).toMatchObject({ + id: "imessage", + aliases: ["imsg"], + docsPath: "/channels/imessage", + }); + expect(resolveOfficialExternalPluginInstall(imessage)).toEqual({ + clawhubSpec: "clawhub:@openclaw/imessage", + npmSpec: "@openclaw/imessage", + defaultChoice: "npm", + minHostVersion: ">=2026.7.2", + allowInvalidConfigRecovery: true, + }); + }); + it.each([ ["teams-meetings", "@openclaw/teams-meetings", "teams_meetings", "teams"], ["zoom-meetings", "@openclaw/zoom-meetings", "zoom_meetings", "zoom"], diff --git a/test/official-channel-catalog.test.ts b/test/official-channel-catalog.test.ts index afc148c87c22..488945302007 100644 --- a/test/official-channel-catalog.test.ts +++ b/test/official-channel-catalog.test.ts @@ -247,6 +247,29 @@ describe("buildOfficialChannelCatalog", () => { expect(installSource.warnings).toEqual(["npm-spec-floating", "npm-spec-missing-integrity"]); }); + it("keeps iMessage available for cold install after core package externalization", () => { + const repoRoot = makeRepoRoot("openclaw-official-channel-catalog-imessage-"); + const imessage = buildOfficialChannelCatalog({ repoRoot }).entries.find( + (entry) => entry.openclaw?.channel?.id === "imessage", + ); + + expect({ + name: imessage?.name, + aliases: imessage?.openclaw?.channel?.aliases, + install: imessage?.openclaw?.install, + }).toEqual({ + name: "@openclaw/imessage", + aliases: ["imsg"], + install: { + clawhubSpec: "clawhub:@openclaw/imessage", + npmSpec: "@openclaw/imessage", + defaultChoice: "npm", + minHostVersion: ">=2026.7.2", + allowInvalidConfigRecovery: true, + }, + }); + }); + it("preserves ClawHub specs when generating publishable channel catalog entries", () => { const repoRoot = makeRepoRoot("openclaw-official-channel-catalog-clawhub-"); writeJson(path.join(repoRoot, "extensions", "storepack-chat", "package.json"), { diff --git a/test/scripts/bundled-plugin-build-entries.test.ts b/test/scripts/bundled-plugin-build-entries.test.ts index 1c2e6872994b..a33c29e45c2e 100644 --- a/test/scripts/bundled-plugin-build-entries.test.ts +++ b/test/scripts/bundled-plugin-build-entries.test.ts @@ -414,6 +414,14 @@ describe("bundled plugin build entries", () => { expect(artifacts).not.toContain("dist/extensions/volcengine/package.json"); }); + it("excludes the externalized iMessage channel from bundled artifacts", () => { + const entries = listBundledPluginBuildEntries(); + const artifacts = listBundledPluginPackArtifacts(); + + expectNoPrefixMatches(Object.keys(entries), "extensions/imessage/"); + expectNoPrefixMatches(artifacts, "dist/extensions/imessage/"); + }); + it("keeps bundled channel secret contracts on packed top-level sidecars", () => { const artifacts = listBundledPluginPackArtifacts(); const excludedPackageDirs = collectRootPackageExcludedExtensionDirs();