From 79130efcb327413c04ae58adeae39665e405cea1 Mon Sep 17 00:00:00 2001
From: Tyler Yust
Date: Thu, 29 Jan 2026 04:20:52 -0800
Subject: [PATCH] Prefer BlueBubbles for iMessage; add BlueBubbles iMessage
skill
---
README.md | 8 +-
docs/channels/bluebubbles.md | 72 +++++++++++-
docs/channels/imessage.md | 5 +-
docs/channels/index.md | 4 +-
docs/gateway/configuration.md | 4 +-
docs/index.md | 5 +-
docs/reference/AGENTS.default.md | 3 +-
docs/reference/templates/TOOLS.dev.md | 10 +-
docs/start/wizard.md | 2 +-
extensions/bluebubbles/package.json | 13 +-
extensions/bluebubbles/src/channel.ts | 9 +-
skills/imessage-bluebubbles/SKILL.md | 124 ++++++++++++++++++++
skills/imsg/SKILL.md | 6 +-
src/channels/plugins/onboarding/imessage.ts | 9 +-
src/channels/registry.ts | 6 +-
src/commands/onboard-channels.ts | 45 ++++++-
src/test-utils/channel-plugins.ts | 2 +-
17 files changed, 287 insertions(+), 40 deletions(-)
create mode 100644 skills/imessage-bluebubbles/SKILL.md
diff --git a/README.md b/README.md
index ec970bb5b4..ddbbbe81b9 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@
**Moltbot** is a *personal AI assistant* you run on your own devices.
-It answers you on the channels you already use (WhatsApp, Telegram, Slack, Discord, Google Chat, Signal, iMessage, Microsoft Teams, WebChat), plus extension channels like BlueBubbles, Matrix, Zalo, and Zalo Personal. It can speak and listen on macOS/iOS/Android, and can render a live Canvas you control. The Gateway is just the control plane — the product is the assistant.
+It answers you on the channels you already use (WhatsApp, Telegram, Slack, Discord, Google Chat, Signal, iMessage, Microsoft Teams, WebChat), plus extension channels like Matrix, Zalo, and Zalo Personal. For iMessage, **BlueBubbles is recommended** (the legacy `imsg` integration is still supported but deprecated for new setups). It can speak and listen on macOS/iOS/Android, and can render a live Canvas you control. The Gateway is just the control plane — the product is the assistant.
If you want a personal, single-user assistant that feels local, fast, and always-on, this is it.
@@ -66,7 +66,7 @@ moltbot gateway --port 18789 --verbose
# Send a message
moltbot message send --to +1234567890 --message "Hello from Moltbot"
-# Talk to the assistant (optionally deliver back to any connected channel: WhatsApp/Telegram/Slack/Discord/Google Chat/Signal/iMessage/BlueBubbles/Microsoft Teams/Matrix/Zalo/Zalo Personal/WebChat)
+# Talk to the assistant (optionally deliver back to any connected channel: WhatsApp/Telegram/Slack/Discord/Google Chat/Signal/iMessage (BlueBubbles)/Microsoft Teams/Matrix/Zalo/Zalo Personal/WebChat)
moltbot agent --message "Ship checklist" --thinking high
```
@@ -139,7 +139,7 @@ Run `moltbot doctor` to surface risky/misconfigured DM policies.
- [Media pipeline](https://docs.molt.bot/nodes/images): images/audio/video, transcription hooks, size caps, temp file lifecycle. Audio details: [Audio](https://docs.molt.bot/nodes/audio).
### Channels
-- [Channels](https://docs.molt.bot/channels): [WhatsApp](https://docs.molt.bot/channels/whatsapp) (Baileys), [Telegram](https://docs.molt.bot/channels/telegram) (grammY), [Slack](https://docs.molt.bot/channels/slack) (Bolt), [Discord](https://docs.molt.bot/channels/discord) (discord.js), [Google Chat](https://docs.molt.bot/channels/googlechat) (Chat API), [Signal](https://docs.molt.bot/channels/signal) (signal-cli), [iMessage](https://docs.molt.bot/channels/imessage) (imsg), [BlueBubbles](https://docs.molt.bot/channels/bluebubbles) (extension), [Microsoft Teams](https://docs.molt.bot/channels/msteams) (extension), [Matrix](https://docs.molt.bot/channels/matrix) (extension), [Zalo](https://docs.molt.bot/channels/zalo) (extension), [Zalo Personal](https://docs.molt.bot/channels/zalouser) (extension), [WebChat](https://docs.molt.bot/web/webchat).
+- [Channels](https://docs.molt.bot/channels): [WhatsApp](https://docs.molt.bot/channels/whatsapp) (Baileys), [Telegram](https://docs.molt.bot/channels/telegram) (grammY), [Slack](https://docs.molt.bot/channels/slack) (Bolt), [Discord](https://docs.molt.bot/channels/discord) (discord.js), [Google Chat](https://docs.molt.bot/channels/googlechat) (Chat API), [Signal](https://docs.molt.bot/channels/signal) (signal-cli), [iMessage](https://docs.molt.bot/channels/bluebubbles) (BlueBubbles, recommended), [iMessage (legacy)](https://docs.molt.bot/channels/imessage) (imsg), [Microsoft Teams](https://docs.molt.bot/channels/msteams) (extension), [Matrix](https://docs.molt.bot/channels/matrix) (extension), [Zalo](https://docs.molt.bot/channels/zalo) (extension), [Zalo Personal](https://docs.molt.bot/channels/zalouser) (extension), [WebChat](https://docs.molt.bot/web/webchat).
- [Group routing](https://docs.molt.bot/concepts/group-messages): mention gating, reply tags, per-channel chunking and routing. Channel rules: [Channels](https://docs.molt.bot/channels).
### Apps + nodes
@@ -170,7 +170,7 @@ Run `moltbot doctor` to surface risky/misconfigured DM policies.
## How it works (short)
```
-WhatsApp / Telegram / Slack / Discord / Google Chat / Signal / iMessage / BlueBubbles / Microsoft Teams / Matrix / Zalo / Zalo Personal / WebChat
+WhatsApp / Telegram / Slack / Discord / Google Chat / Signal / iMessage (BlueBubbles) / iMessage (legacy imsg) / Microsoft Teams / Matrix / Zalo / Zalo Personal / WebChat
│
▼
┌───────────────────────────────┐
diff --git a/docs/channels/bluebubbles.md b/docs/channels/bluebubbles.md
index 5a2ed242b1..9d12f4fd4d 100644
--- a/docs/channels/bluebubbles.md
+++ b/docs/channels/bluebubbles.md
@@ -5,9 +5,9 @@ read_when:
- Troubleshooting webhook pairing
- Configuring iMessage on macOS
---
-# BlueBubbles (macOS REST)
+# iMessage (BlueBubbles)
-Status: bundled plugin that talks to the BlueBubbles macOS server over HTTP. **Recommended for iMessage integration** due to its richer API and easier setup compared to the legacy imsg channel.
+Status: bundled plugin that talks to the BlueBubbles macOS server over HTTP. **Recommended iMessage integration** due to its richer API and easier setup compared to the legacy imsg channel.
## Overview
- Runs on macOS via the BlueBubbles helper app ([bluebubbles.app](https://bluebubbles.app)).
@@ -38,6 +38,74 @@ Status: bundled plugin that talks to the BlueBubbles macOS server over HTTP. **R
4. Point BlueBubbles webhooks to your gateway (example: `https://your-gateway-host:3000/bluebubbles-webhook?password=`).
5. Start the gateway; it will register the webhook handler and start pairing.
+## Keep BlueBubbles running (recommended)
+
+If the BlueBubbles Server app quits or the Mac sleeps, iMessage delivery, webhooks, and advanced actions will stop.
+
+### Prevent sleep
+On macOS (especially VMs), ensure the machine stays awake:
+- One-time: `caffeinate -dims`
+- Permanent: configure your VM/host power settings (or a LaunchAgent that runs `caffeinate`).
+
+### launchd keepalive (re-open BlueBubbles every 5 minutes)
+This LaunchAgent periodically re-opens BlueBubbles + Messages in the background.
+
+1) Create a script at `~/.clawdbot/scripts/keepalive-bluebubbles.sh`:
+
+```bash
+#!/usr/bin/env bash
+set -euo pipefail
+
+# App names vary across builds; try both.
+open -gj -a "BlueBubbles" || open -gj -a "BlueBubbles Server" || true
+open -gj -a "Messages" || true
+```
+
+2) Make it executable:
+
+```bash
+chmod +x ~/.clawdbot/scripts/keepalive-bluebubbles.sh
+```
+
+3) Create a LaunchAgent at `~/Library/LaunchAgents/com.moltbot.bluebubbles.keepalive.plist`:
+
+```xml
+
+
+
+
+ Label
+ com.moltbot.bluebubbles.keepalive
+
+ ProgramArguments
+
+ /bin/bash
+ -lc
+ ~/.clawdbot/scripts/keepalive-bluebubbles.sh
+
+
+ RunAtLoad
+
+
+
+ StartInterval
+ 300
+
+ StandardOutPath
+ /tmp/com.moltbot.bluebubbles.keepalive.out
+ StandardErrorPath
+ /tmp/com.moltbot.bluebubbles.keepalive.err
+
+
+```
+
+4) Load it:
+
+```bash
+launchctl load -w ~/Library/LaunchAgents/com.moltbot.bluebubbles.keepalive.plist
+launchctl list | rg bluebubbles
+```
+
## Onboarding
BlueBubbles is available in the interactive setup wizard:
```
diff --git a/docs/channels/imessage.md b/docs/channels/imessage.md
index 87c37e0995..cb3bc84c8a 100644
--- a/docs/channels/imessage.md
+++ b/docs/channels/imessage.md
@@ -1,11 +1,12 @@
---
-summary: "iMessage support via imsg (JSON-RPC over stdio), setup, and chat_id routing"
+summary: "Legacy iMessage support via imsg (JSON-RPC over stdio). Deprecated for new setups; prefer BlueBubbles."
read_when:
- Setting up iMessage support
- Debugging iMessage send/receive
---
-# iMessage (imsg)
+# iMessage (legacy: imsg)
+> **Deprecated for new setups.** Prefer **[iMessage (BlueBubbles)](/channels/bluebubbles)**.
Status: external CLI integration. Gateway spawns `imsg rpc` (JSON-RPC over stdio).
diff --git a/docs/channels/index.md b/docs/channels/index.md
index 10651e6d15..eab32ce8e6 100644
--- a/docs/channels/index.md
+++ b/docs/channels/index.md
@@ -18,8 +18,8 @@ Text is supported everywhere; media and reactions vary by channel.
- [Google Chat](/channels/googlechat) — Google Chat API app via HTTP webhook.
- [Mattermost](/channels/mattermost) — Bot API + WebSocket; channels, groups, DMs (plugin, installed separately).
- [Signal](/channels/signal) — signal-cli; privacy-focused.
-- [BlueBubbles](/channels/bluebubbles) — **Recommended for iMessage**; uses the BlueBubbles macOS server REST API with full feature support (edit, unsend, effects, reactions, group management — edit currently broken on macOS 26 Tahoe).
-- [iMessage](/channels/imessage) — macOS only; native integration via imsg (legacy, consider BlueBubbles for new setups).
+- [iMessage (BlueBubbles)](/channels/bluebubbles) — **Recommended**; uses the BlueBubbles macOS server REST API with full feature support (edit, unsend, effects, reactions, group management — edit currently broken on macOS 26 Tahoe).
+- [iMessage (legacy: imsg)](/channels/imessage) — macOS only; native integration via imsg (deprecated for new setups).
- [Microsoft Teams](/channels/msteams) — Bot Framework; enterprise support (plugin, installed separately).
- [LINE](/channels/line) — LINE Messaging API bot (plugin, installed separately).
- [Nextcloud Talk](/channels/nextcloud-talk) — Self-hosted chat via Nextcloud Talk (plugin, installed separately).
diff --git a/docs/gateway/configuration.md b/docs/gateway/configuration.md
index 1d270974dc..7f02c2c286 100644
--- a/docs/gateway/configuration.md
+++ b/docs/gateway/configuration.md
@@ -1313,7 +1313,9 @@ Reaction notification modes:
- `all`: all reactions on all messages.
- `allowlist`: reactions from `channels.signal.reactionAllowlist` on all messages (empty list disables).
-### `channels.imessage` (imsg CLI)
+### `channels.imessage` (legacy: imsg CLI)
+
+**Deprecated for new setups.** Prefer **iMessage (BlueBubbles)**: [/channels/bluebubbles](/channels/bluebubbles).
Moltbot spawns `imsg rpc` (JSON-RPC over stdio). No daemon or port required.
diff --git a/docs/index.md b/docs/index.md
index 3d85e0eb04..c5c675a998 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -24,7 +24,7 @@ read_when:
Moltbot assistant setup
-Moltbot bridges WhatsApp (via WhatsApp Web / Baileys), Telegram (Bot API / grammY), Discord (Bot API / channels.discord.js), and iMessage (imsg CLI) to coding agents like [Pi](https://github.com/badlogic/pi-mono). Plugins add Mattermost (Bot API + WebSocket) and more.
+Moltbot bridges WhatsApp (via WhatsApp Web / Baileys), Telegram (Bot API / grammY), Discord (Bot API / channels.discord.js), and iMessage (BlueBubbles recommended; imsg legacy) to coding agents like [Pi](https://github.com/badlogic/pi-mono). Plugins add Mattermost (Bot API + WebSocket) and more.
Moltbot also powers [Clawd](https://clawd.me), the space‑lobster assistant.
## Start here
@@ -81,7 +81,8 @@ Most operations flow through the **Gateway** (`moltbot gateway`), a single long-
- ✈️ **Telegram Bot** — DMs + groups via grammY
- 🎮 **Discord Bot** — DMs + guild channels via channels.discord.js
- 🧩 **Mattermost Bot (plugin)** — Bot token + WebSocket events
-- 💬 **iMessage** — Local imsg CLI integration (macOS)
+- 💬 **iMessage** — BlueBubbles macOS server integration (recommended)
+- 💬 **iMessage (legacy)** — Local imsg CLI integration (macOS)
- 🤖 **Agent bridge** — Pi (RPC mode) with tool streaming
- ⏱️ **Streaming + chunking** — Block streaming + Telegram draft streaming details ([/concepts/streaming](/concepts/streaming))
- 🧠 **Multi-agent routing** — Route provider accounts/peers to isolated agents (workspace + per-agent sessions)
diff --git a/docs/reference/AGENTS.default.md b/docs/reference/AGENTS.default.md
index 290997d58c..60475ce10a 100644
--- a/docs/reference/AGENTS.default.md
+++ b/docs/reference/AGENTS.default.md
@@ -89,7 +89,8 @@ git commit -m "Add Clawd workspace"
- **camsnap** — Capture frames, clips, or motion alerts from RTSP/ONVIF security cams.
- **oracle** — OpenAI-ready agent CLI with session replay and browser control.
- **eightctl** — Control your sleep, from the terminal.
-- **imsg** — Send, read, stream iMessage & SMS.
+- **imessage-bluebubbles** — iMessage via BlueBubbles (recommended): history/search/send/attachments.
+- **imsg** — (legacy) Send, read, stream iMessage & SMS via imsg CLI.
- **wacli** — WhatsApp CLI: sync, search, send.
- **discord** — Discord actions: react, stickers, polls. Use `user:` or `channel:` targets (bare numeric ids are ambiguous).
- **gog** — Google Suite CLI: Gmail, Calendar, Drive, Contacts.
diff --git a/docs/reference/templates/TOOLS.dev.md b/docs/reference/templates/TOOLS.dev.md
index 0bdb964b47..d343a86563 100644
--- a/docs/reference/templates/TOOLS.dev.md
+++ b/docs/reference/templates/TOOLS.dev.md
@@ -11,9 +11,13 @@ It does not define which tools exist; Moltbot provides built-in tools internally
## Examples
-### imsg
-- Send an iMessage/SMS: describe who/what, confirm before sending.
-- Prefer short messages; avoid sending secrets.
+### iMessage (BlueBubbles)
+- Preferred iMessage integration. Confirm before sending.
+- If you need history/search: use the BlueBubbles REST API (chat/query, message/query).
+
+### imsg (legacy)
+- Legacy iMessage/SMS integration on macOS. Deprecated for new setups.
+- Confirm before sending; avoid sending secrets.
### sag
- Text-to-speech: specify voice, target speaker/room, and whether to stream.
diff --git a/docs/start/wizard.md b/docs/start/wizard.md
index 8c27bd8183..d7043d1d73 100644
--- a/docs/start/wizard.md
+++ b/docs/start/wizard.md
@@ -123,7 +123,7 @@ Tip: `--json` does **not** imply non-interactive mode. Use `--non-interactive` (
- Google Chat: service account JSON + webhook audience.
- Mattermost (plugin): bot token + base URL.
- Signal: optional `signal-cli` install + account config.
- - iMessage: local `imsg` CLI path + DB access.
+ - iMessage: BlueBubbles server URL + password (recommended) or legacy local `imsg` CLI path + DB access.
- DM security: default is pairing. First DM sends a code; approve via `moltbot pairing approve ` or use allowlists.
6) **Daemon install**
diff --git a/extensions/bluebubbles/package.json b/extensions/bluebubbles/package.json
index 7ffa398450..c03a23b73d 100644
--- a/extensions/bluebubbles/package.json
+++ b/extensions/bluebubbles/package.json
@@ -9,12 +9,12 @@
],
"channel": {
"id": "bluebubbles",
- "label": "BlueBubbles",
- "selectionLabel": "BlueBubbles (macOS app)",
- "detailLabel": "BlueBubbles",
+ "label": "iMessage (BlueBubbles)",
+ "selectionLabel": "iMessage (BlueBubbles \u2014 recommended)",
+ "detailLabel": "iMessage (BlueBubbles)",
"docsPath": "/channels/bluebubbles",
"docsLabel": "bluebubbles",
- "blurb": "iMessage via the BlueBubbles mac app + REST API.",
+ "blurb": "recommended iMessage integration via the BlueBubbles macOS server + REST API.",
"aliases": [
"bb"
],
@@ -22,7 +22,10 @@
"imessage"
],
"systemImage": "bubble.left.and.text.bubble.right",
- "order": 75
+ "order": 75,
+ "selectionExtras": [
+ "https://bluebubbles.app"
+ ]
},
"install": {
"npmSpec": "@moltbot/bluebubbles",
diff --git a/extensions/bluebubbles/src/channel.ts b/extensions/bluebubbles/src/channel.ts
index f88662dbbd..f9419a98a1 100644
--- a/extensions/bluebubbles/src/channel.ts
+++ b/extensions/bluebubbles/src/channel.ts
@@ -38,14 +38,15 @@ import { sendBlueBubblesMedia } from "./media-send.js";
const meta = {
id: "bluebubbles",
- label: "BlueBubbles",
- selectionLabel: "BlueBubbles (macOS app)",
- detailLabel: "BlueBubbles",
+ label: "iMessage (BlueBubbles)",
+ selectionLabel: "iMessage (BlueBubbles — recommended)",
+ detailLabel: "iMessage (BlueBubbles)",
docsPath: "/channels/bluebubbles",
docsLabel: "bluebubbles",
- blurb: "iMessage via the BlueBubbles mac app + REST API.",
+ blurb: "recommended iMessage integration via the BlueBubbles macOS server + REST API.",
systemImage: "bubble.left.and.text.bubble.right",
aliases: ["bb"],
+ selectionExtras: ["https://bluebubbles.app"],
order: 75,
preferOver: ["imessage"],
};
diff --git a/skills/imessage-bluebubbles/SKILL.md b/skills/imessage-bluebubbles/SKILL.md
new file mode 100644
index 0000000000..f23a7a9ca7
--- /dev/null
+++ b/skills/imessage-bluebubbles/SKILL.md
@@ -0,0 +1,124 @@
+---
+name: imessage-bluebubbles
+description: iMessage via BlueBubbles REST API (list chats, query history/search, send text + attachments).
+homepage: https://bluebubbles.app
+metadata: {"moltbot":{"emoji":"💬","requires":{"bins":["curl","jq"]}}}
+---
+
+# iMessage (BlueBubbles)
+
+Use the **BlueBubbles Server** REST API to query iMessage chats/messages and send messages/attachments.
+
+This is the recommended iMessage integration for Moltbot.
+
+Requirements
+- A macOS host running **BlueBubbles Server**
+- BlueBubbles REST API enabled + password set
+- Network access from this host to the BlueBubbles Server
+
+Environment variables (recommended)
+```bash
+export BLUEBUBBLES_SERVER_URL="http://mac-mini.lan:1234"
+export BLUEBUBBLES_PASSWORD="..."
+```
+
+Quick checks
+- Ping:
+ ```bash
+ curl -s "$BLUEBUBBLES_SERVER_URL/api/v1/ping?password=$BLUEBUBBLES_PASSWORD" | jq
+ ```
+
+Common commands
+
+## List chats (with last message)
+```bash
+curl -sS \
+ -X POST "$BLUEBUBBLES_SERVER_URL/api/v1/chat/query?password=$BLUEBUBBLES_PASSWORD" \
+ -H 'Content-Type: application/json' \
+ --data '{
+ "limit": 50,
+ "offset": 0,
+ "with": ["lastMessage", "chat.participants"],
+ "sort": "lastmessage"
+ }' | jq
+```
+
+## Query message history (by chatGuid)
+```bash
+CHAT_GUID='iMessage;-;+15555550123'
+curl -sS \
+ -X POST "$BLUEBUBBLES_SERVER_URL/api/v1/message/query?password=$BLUEBUBBLES_PASSWORD" \
+ -H 'Content-Type: application/json' \
+ --data "$(jq -n --arg chatGuid "$CHAT_GUID" '{
+ limit: 25,
+ offset: 0,
+ chatGuid: $chatGuid,
+ with: ["chat", "chat.participants", "attachment", "handle", "sms"],
+ sort: "DESC"
+ }')" | jq
+```
+
+## Search messages (SQL where clause)
+BlueBubbles supports server-side filtering via `where` clauses.
+
+Example: search for an exact text match:
+```bash
+curl -sS \
+ -X POST "$BLUEBUBBLES_SERVER_URL/api/v1/message/query?password=$BLUEBUBBLES_PASSWORD" \
+ -H 'Content-Type: application/json' \
+ --data '{
+ "limit": 25,
+ "offset": 0,
+ "with": ["chat", "handle"],
+ "where": [{
+ "statement": "message.text = :text",
+ "args": {"text": "Kara and Mimi"}
+ }],
+ "sort": "DESC"
+ }' | jq
+```
+
+## Send a text message
+Note: prefer using Moltbot's `message` tool when available (it automatically resolves targets and threads).
+
+```bash
+CHAT_GUID='iMessage;-;+15555550123'
+curl -sS \
+ -X POST "$BLUEBUBBLES_SERVER_URL/api/v1/message/text?password=$BLUEBUBBLES_PASSWORD" \
+ -H 'Content-Type: application/json' \
+ --data "$(jq -n --arg chatGuid "$CHAT_GUID" --arg message "hi" '{
+ chatGuid: $chatGuid,
+ tempGuid: "temp-" + (now|tostring),
+ message: $message
+ }')" | jq
+```
+
+## Send an attachment
+```bash
+CHAT_GUID='iMessage;-;+15555550123'
+FILE_PATH='/path/to/pic.jpg'
+
+curl -sS \
+ -X POST "$BLUEBUBBLES_SERVER_URL/api/v1/message/attachment?password=$BLUEBUBBLES_PASSWORD" \
+ -F "attachment=@${FILE_PATH}" \
+ -F "chatGuid=${CHAT_GUID}" \
+ -F "name=$(basename "$FILE_PATH")" \
+ -F "tempGuid=temp-$(date +%s)" \
+ -F "method=private-api" | jq
+```
+
+## Download an attachment
+```bash
+ATTACHMENT_GUID='att-123'
+curl -L \
+ "$BLUEBUBBLES_SERVER_URL/api/v1/attachment/$ATTACHMENT_GUID/download?password=$BLUEBUBBLES_PASSWORD" \
+ -o ./download.bin
+```
+
+Watch / streaming
+- BlueBubbles supports **webhooks** for realtime events.
+- In Moltbot, realtime inbound iMessage is handled by the **BlueBubbles channel plugin** (configure `channels.bluebubbles.webhookPath` and point BlueBubbles webhooks at the gateway).
+
+Notes
+- Confirm recipient + message before sending.
+- Many advanced actions (reactions/edit/unsend/effects/group management) require BlueBubbles **Private API**.
diff --git a/skills/imsg/SKILL.md b/skills/imsg/SKILL.md
index 3b8fceeb2c..dfe839112e 100644
--- a/skills/imsg/SKILL.md
+++ b/skills/imsg/SKILL.md
@@ -1,11 +1,13 @@
---
name: imsg
-description: iMessage/SMS CLI for listing chats, history, watch, and sending.
+description: (Deprecated) iMessage/SMS via imsg CLI (legacy). Use BlueBubbles for new setups.
homepage: https://imsg.to
metadata: {"moltbot":{"emoji":"📨","os":["darwin"],"requires":{"bins":["imsg"]},"install":[{"id":"brew","kind":"brew","formula":"steipete/tap/imsg","bins":["imsg"],"label":"Install imsg (brew)"}]}}
---
-# imsg
+# imsg (legacy)
+
+**Deprecated for new setups.** Prefer **iMessage (BlueBubbles)** for the Moltbot iMessage integration.
Use `imsg` to read and send Messages.app iMessage/SMS on macOS.
diff --git a/src/channels/plugins/onboarding/imessage.ts b/src/channels/plugins/onboarding/imessage.ts
index e6aa4e89c0..07077f7c7d 100644
--- a/src/channels/plugins/onboarding/imessage.ts
+++ b/src/channels/plugins/onboarding/imessage.ts
@@ -86,6 +86,7 @@ async function promptIMessageAllowFrom(params: {
const existing = resolved.config.allowFrom ?? [];
await params.prompter.note(
[
+ "Legacy iMessage integration via imsg (deprecated). New setups: use BlueBubbles.",
"Allowlist iMessage DMs by handle or chat target.",
"Examples:",
"- +15555550123",
@@ -93,7 +94,7 @@ async function promptIMessageAllowFrom(params: {
"- chat_id:123",
"- chat_guid:... or chat_identifier:...",
"Multiple entries: comma-separated.",
- `Docs: ${formatDocsLink("/imessage", "imessage")}`,
+ `Docs: ${formatDocsLink("/channels/imessage", "imessage")}`,
].join("\n"),
"iMessage allowlist",
);
@@ -239,11 +240,13 @@ export const imessageOnboardingAdapter: ChannelOnboardingAdapter = {
await prompter.note(
[
- "This is still a work in progress.",
+ "Legacy iMessage integration via imsg (deprecated).",
+ "New setups: use BlueBubbles instead.",
"Ensure Moltbot has Full Disk Access to Messages DB.",
"Grant Automation permission for Messages when prompted.",
"List chats with: imsg chats --limit 20",
- `Docs: ${formatDocsLink("/imessage", "imessage")}`,
+ `Docs (legacy): ${formatDocsLink("/channels/imessage", "imessage")}`,
+ `Docs (recommended): ${formatDocsLink("/channels/bluebubbles", "bluebubbles")}`,
].join("\n"),
"iMessage next steps",
);
diff --git a/src/channels/registry.ts b/src/channels/registry.ts
index 6afe1996cc..edb99af1c3 100644
--- a/src/channels/registry.ts
+++ b/src/channels/registry.ts
@@ -91,11 +91,11 @@ const CHAT_CHANNEL_META: Record = {
imessage: {
id: "imessage",
label: "iMessage",
- selectionLabel: "iMessage (imsg)",
- detailLabel: "iMessage",
+ selectionLabel: "iMessage (legacy: imsg)",
+ detailLabel: "iMessage (legacy)",
docsPath: "/channels/imessage",
docsLabel: "imessage",
- blurb: "this is still a work in progress.",
+ blurb: "legacy iMessage integration via imsg CLI (deprecated; prefer BlueBubbles).",
systemImage: "message.fill",
},
};
diff --git a/src/commands/onboard-channels.ts b/src/commands/onboard-channels.ts
index 27ec07de4f..204158266d 100644
--- a/src/commands/onboard-channels.ts
+++ b/src/commands/onboard-channels.ts
@@ -385,6 +385,41 @@ export async function setupChannels(
};
});
+ const reorderEntriesByPreferOver = (
+ entries: T[],
+ ): T[] => {
+ const resolved = [...entries];
+ // Prefer-over ordering is a lightweight partial ordering used to make recommended
+ // providers show up before legacy ones (for example BlueBubbles over imessage).
+ for (let pass = 0; pass < 25; pass += 1) {
+ const indexById = new Map();
+ for (let i = 0; i < resolved.length; i += 1) {
+ indexById.set(String(resolved[i]?.meta?.id ?? resolved[i]?.id), i);
+ }
+ let changed = false;
+ for (const entry of resolved) {
+ const preferOver = entry.meta.preferOver ?? [];
+ if (!Array.isArray(preferOver) || preferOver.length === 0) continue;
+ const entryKey = String(entry.meta.id ?? entry.id);
+ const entryIndex = indexById.get(entryKey);
+ if (entryIndex === undefined) continue;
+ for (const otherId of preferOver) {
+ const otherKey = String(otherId);
+ const otherIndex = indexById.get(otherKey);
+ if (otherIndex === undefined) continue;
+ if (entryIndex > otherIndex) {
+ resolved.splice(entryIndex, 1);
+ resolved.splice(otherIndex, 0, entry);
+ changed = true;
+ break;
+ }
+ }
+ if (changed) break;
+ }
+ if (!changed) break;
+ }
+ return resolved;
+ };
const getChannelEntries = () => {
const core = listChatChannels();
const installed = listChannelPlugins();
@@ -405,10 +440,12 @@ export async function setupChannels(
metaById.set(entry.id, entry.meta);
}
}
- const entries = Array.from(metaById, ([id, meta]) => ({
- id: id as ChannelChoice,
- meta,
- }));
+ const entries = reorderEntriesByPreferOver(
+ Array.from(metaById, ([id, meta]) => ({
+ id: id as ChannelChoice,
+ meta,
+ })),
+ );
return {
entries,
catalog,
diff --git a/src/test-utils/channel-plugins.ts b/src/test-utils/channel-plugins.ts
index 3e6bf21127..593d1c13b0 100644
--- a/src/test-utils/channel-plugins.ts
+++ b/src/test-utils/channel-plugins.ts
@@ -31,7 +31,7 @@ export const createIMessageTestPlugin = (params?: {
meta: {
id: "imessage",
label: "iMessage",
- selectionLabel: "iMessage (imsg)",
+ selectionLabel: "iMessage (legacy: imsg)",
docsPath: "/channels/imessage",
blurb: "iMessage test stub.",
aliases: ["imsg"],