Mainstream messaging
Переход с BlueBubbles
Встроенный Plugin imessage теперь обращается к тому же набору приватных API, что и BlueBubbles (react, edit, unsend, reply, sendWithEffect, управление группами, вложения), управляя steipete/imsg через JSON-RPC. Если у вас уже есть Mac с установленным imsg, можно отказаться от сервера BlueBubbles и позволить Plugin обращаться к Messages.app напрямую.
Поддержка BlueBubbles удалена. OpenClaw поддерживает iMessage только через imsg. Это руководство предназначено для миграции старых конфигураций channels.bluebubbles на channels.imessage; другого поддерживаемого пути миграции нет.
Контрольный список миграции
Используйте этот список, если вы уже знаете свою старую конфигурацию BlueBubbles и хотите пройти самый короткий безопасный путь:
- Проверьте
imsgнапрямую на Mac, где запущен Messages.app (imsg chats,imsg history,imsg sendиimsg rpc --help). - Скопируйте ключи поведения из
channels.bluebubblesвchannels.imessage:dmPolicy,allowFrom,groupPolicy,groupAllowFrom,groups,includeAttachments,attachmentRoots,mediaMaxMb,textChunkLimit,coalesceSameSenderDmsиactions. - Удалите транспортные ключи, которых больше нет:
serverUrl,password, URL-адреса Webhook и настройку сервера BlueBubbles. - Если Gateway не запущен на Mac с Messages, задайте для
channels.imessage.cliPathSSH-обертку и задайтеremoteHostдля удаленной загрузки вложений. - При остановленном Gateway включите
channels.imessage, затем выполнитеopenclaw channels status --probe --channel imessage. - Проверьте одно личное сообщение, одну разрешенную группу, вложения, если они включены, и каждое действие приватного API, которое, как вы ожидаете, будет использовать агент.
- Удалите сервер BlueBubbles и старую конфигурацию
channels.bluebubblesпосле проверки пути iMessage.
Когда эта миграция имеет смысл
- Вы уже запускаете
imsgна том же Mac (или на доступном по SSH), где выполнен вход в Messages.app. - Вам нужен один компонент вместо нескольких — без отдельного сервера BlueBubbles, REST-эндпоинта для аутентификации и Webhook-обвязки. Один двоичный файл CLI вместо сервера, клиентского приложения и помощника.
- Вы используете поддерживаемую сборку macOS /
imsg, где проверка приватного API сообщаетavailable: true.
Что делает imsg
imsg — это локальный CLI для macOS Messages. OpenClaw запускает imsg rpc как дочерний процесс и обменивается JSON-RPC через stdin/stdout. Здесь нет HTTP-сервера, URL-адреса Webhook, фонового демона, launch agent или порта, который нужно открывать.
- Чтение выполняется из
~/Library/Messages/chat.dbс использованием дескриптора SQLite только для чтения. - Входящие сообщения в реальном времени поступают из
imsg watch/watch.subscribe, который отслеживает события файловой системыchat.dbс резервным опросом. - Отправка использует автоматизацию Messages.app для обычного текста и файлов.
- Расширенные действия используют
imsg launch, чтобы внедрить помощникimsgв Messages.app. Именно это открывает уведомления о прочтении, индикаторы набора, расширенную отправку, редактирование, отмену отправки, ответы в ветках, tapback-реакции и управление группами. - Сборки Linux могут просматривать скопированный
chat.db, но не могут отправлять сообщения, отслеживать живую базу данных Mac или управлять Messages.app. Для OpenClaw iMessage запускайтеimsgна Mac, где выполнен вход, или через SSH-обертку к этому Mac.
Перед началом
-
Установите
imsgна Mac, где запущен Messages.app:bash brew install steipete/tap/imsgimsg --versionimsg chats --limit 3Если
imsg chatsзавершается с ошибкойunable to open database file, пустым выводом илиauthorization denied, предоставьте Full Disk Access терминалу, редактору, процессу Node, службе Gateway или родительскому SSH-процессу, который запускаетimsg, затем перезапустите этот родительский процесс. -
Проверьте поверхности чтения, наблюдения, отправки и RPC перед изменением конфигурации OpenClaw:
bash imsg chats --limit 10 --json | jq -simsg history --chat-id 42 --limit 10 --attachments --json | jq -simsg watch --chat-id 42 --reactions --jsonimsg send --chat-id 42 --text "OpenClaw imsg test"imsg rpc --helpЗамените
42на реальный идентификатор чата изimsg chats. Для отправки требуется разрешение Automation для Messages.app. Если OpenClaw будет работать через SSH, выполните эти команды через ту же SSH-обертку или в том же пользовательском контексте, который будет использовать OpenClaw. Если чтение и проверки работают, но отправка завершается ошибкой AppleEvents-1743, проверьте, не было ли разрешение Automation назначено/usr/libexec/sshd-keygen-wrapper; см. Отправка через SSH-обертку завершается ошибкой AppleEvents -1743. -
Включите мост приватного API, если нужны расширенные действия:
bash imsg launchimsg status --jsonДля
imsg launchтребуется отключенный SIP. Базовая отправка, история и наблюдение работают безimsg launch; расширенные действия — нет. -
После добавления включенной конфигурации
channels.imessageпроверьте мост через OpenClaw:bash openclaw channels status --probeВам нужно
imessage.privateApi.available: true. Если отображаетсяfalse, сначала исправьте это — см. Обнаружение возможностей.channels status --probeпроверяет только настроенные и включенные учетные записи. -
Сделайте снимок конфигурации:
bash cp ~/.openclaw/openclaw.json5 ~/.openclaw/openclaw.json5.bak
Перенос конфигурации
iMessage и BlueBubbles имеют много общих настроек уровня канала. Изменяющиеся ключи в основном относятся к транспорту (REST-сервер против локального CLI). Ключи поведения (dmPolicy, groupPolicy, allowFrom и т. д.) сохраняют тот же смысл.
| BlueBubbles | встроенный iMessage | Примечания |
|---|---|---|
channels.bluebubbles.enabled |
channels.imessage.enabled |
Та же семантика. |
channels.bluebubbles.serverUrl |
(удалено) | REST-сервера нет — Plugin запускает imsg rpc через stdio. |
channels.bluebubbles.password |
(удалено) | Аутентификация Webhook не требуется. |
| (неявно) | channels.imessage.cliPath |
Путь к imsg (по умолчанию imsg); используйте скрипт-обертку для SSH. |
| (неявно) | channels.imessage.dbPath |
Необязательное переопределение Messages.app chat.db; автоматически определяется, если не указано. |
| (неявно) | channels.imessage.remoteHost |
host или user@host — требуется только когда cliPath является SSH-оберткой и нужны загрузки вложений через SCP. |
channels.bluebubbles.dmPolicy |
channels.imessage.dmPolicy |
Те же значения (pairing / allowlist / open / disabled). |
channels.bluebubbles.allowFrom |
channels.imessage.allowFrom |
Одобрения сопряжения переносятся по handle, а не по токену. |
channels.bluebubbles.groupPolicy |
channels.imessage.groupPolicy |
Те же значения (allowlist / open / disabled). |
channels.bluebubbles.groupAllowFrom |
channels.imessage.groupAllowFrom |
То же самое. |
channels.bluebubbles.groups |
channels.imessage.groups |
Скопируйте это дословно, включая любую wildcard-запись groups: { "*": { ... } }. Групповые requireMention, tools, toolsBySender переносятся. При groupPolicy: "allowlist" пустой или отсутствующий блок groups без предупреждения отбрасывает каждое групповое сообщение — см. «Ловушка реестра групп» ниже. |
channels.bluebubbles.sendReadReceipts |
channels.imessage.sendReadReceipts |
По умолчанию true. Со встроенным Plugin это срабатывает только когда активна проверка private API. |
channels.bluebubbles.includeAttachments |
channels.imessage.includeAttachments |
Та же форма, так же отключено по умолчанию. Если у вас вложения передавались в BlueBubbles, нужно явно заново задать это в блоке iMessage — неявно это не переносится, и входящие фото/медиа будут без предупреждения отбрасываться без строки журнала Inbound message, пока вы этого не сделаете. |
channels.bluebubbles.attachmentRoots |
channels.imessage.attachmentRoots |
Локальные корни; те же правила wildcard. |
| (Н/Д) | channels.imessage.remoteAttachmentRoots |
Используется только когда remoteHost задан для загрузок через SCP. |
channels.bluebubbles.mediaMaxMb |
channels.imessage.mediaMaxMb |
По умолчанию 16 MB в iMessage (в BlueBubbles было 8 MB). Задайте явно, если хотите сохранить более низкий лимит. |
channels.bluebubbles.textChunkLimit |
channels.imessage.textChunkLimit |
По умолчанию 4000 в обоих случаях. |
channels.bluebubbles.coalesceSameSenderDms |
channels.imessage.coalesceSameSenderDms |
То же включение по желанию. Только для личных сообщений — групповые чаты в обоих каналах сохраняют мгновенную отправку каждого сообщения. Расширяет стандартную задержку входящих сообщений до 7000 мс, если включено без явного messages.inbound.byChannel.imessage или глобального messages.inbound.debounceMs. См. документацию iMessage § Объединение разделенных отправок личных сообщений. |
channels.bluebubbles.enrichGroupParticipantsFromContacts |
(Н/Д) | iMessage уже считывает отображаемые имена отправителей из chat.db. |
channels.bluebubbles.actions.* |
channels.imessage.actions.* |
Переключатели для отдельных действий: reactions, edit, unsend, reply, sendWithEffect, renameGroup, setGroupIcon, addParticipant, removeParticipant, leaveGroup, sendAttachment. |
Конфигурации с несколькими учетными записями (channels.bluebubbles.accounts.*) переводятся один к одному в channels.imessage.accounts.*.
Ловушка реестра групп
Встроенный Plugin iMessage запускает два отдельных шлюза allowlist для групп подряд. Оба должны пройти, чтобы групповое сообщение дошло до агента:
- Allowlist отправителей / целевых чатов (
channels.imessage.groupAllowFrom) — проверяетсяisAllowedIMessageSender. Сопоставляет входящие сообщения по handle отправителя,chat_guid,chat_identifierилиchat_id. Та же форма, что и в BlueBubbles. - Реестр групп (
channels.imessage.groups) — проверяетсяresolveChannelGroupPolicyизinbound-processing.ts:199. ПриgroupPolicy: "allowlist"этот шлюз требует одно из следующего:- wildcard-запись
groups: { "*": { ... } }(задаетallowAll = true), или - явную запись для конкретного
chat_idвgroups.
- wildcard-запись
Если шлюз 1 проходит, а шлюз 2 не проходит, сообщение отбрасывается. Plugin выводит два сигнала уровня warn, так что на стандартном уровне журналирования это больше не происходит молча:
- Одноразовый
warnпри запуске для каждой учетной записи, когда заданоgroupPolicy: "allowlist", ноchannels.imessage.groupsпустой (нет wildcard"*", нет записей для отдельныхchat_id) — срабатывает до поступления любых сообщений. - Одноразовый
warnдля каждогоchat_idпри первом отбрасывании конкретной группы во время выполнения, с указанием chat_id и точного ключа, который нужно добавить вgroups, чтобы разрешить ее.
DM продолжают работать, потому что проходят по другому пути кода.
Это самый распространенный сценарий сбоя миграции BlueBubbles → встроенный iMessage: операторы копируют groupAllowFrom и groupPolicy, но пропускают блок groups, потому что groups: { "*": { "requireMention": true } } в BlueBubbles выглядит как несвязанная настройка упоминаний. На самом деле она критична для проверки реестра.
Минимальная конфигурация, чтобы сообщения в группах продолжали проходить после groupPolicy: "allowlist":
{ channels: { imessage: { groupPolicy: "allowlist", groupAllowFrom: ["+15555550123", "chat_guid:any;-;..."], groups: { "*": { requireMention: true }, }, }, },}requireMention: true под * безвреден, если шаблоны упоминаний не настроены: runtime устанавливает canDetectMention = false и досрочно обходит отбрасывание по упоминанию в inbound-processing.ts:512. Если шаблоны упоминаний настроены (agents.list[].groupChat.mentionPatterns), это работает ожидаемым образом.
Если в логах gateway есть imessage: dropping group message from chat_id=<id> или строка запуска imessage: groupPolicy="allowlist" but channels.imessage.groups is empty, значит отбрасывает проверка 2 — добавьте блок groups.
Пошагово
-
Добавьте блок iMessage рядом с существующим блоком BlueBubbles. Держите его отключенным, пока Gateway все еще маршрутизирует трафик BlueBubbles:
json5 { channels: { bluebubbles: { enabled: true, // ... existing config ... }, imessage: { enabled: false, cliPath: "/opt/homebrew/bin/imsg", dmPolicy: "pairing", allowFrom: ["+15555550123"], // copy from bluebubbles.allowFrom groupPolicy: "allowlist", groupAllowFrom: [], // copy from bluebubbles.groupAllowFrom groups: { "*": { requireMention: true } }, // copy from bluebubbles.groups — silently drops groups if missing, see "Group registry footgun" above actions: { reactions: true, edit: true, unsend: true, reply: true, sendWithEffect: true, sendAttachment: true, }, }, },} -
Проверьте до того, как трафик станет важен — остановите Gateway, временно включите блок iMessage и убедитесь через CLI, что iMessage сообщает о работоспособности:
bash openclaw gateway stop# edit config: channels.imessage.enabled = trueopenclaw channels status --probe --channel imessage # expect imessage.privateApi.available: truechannels status --probeпроверяет только настроенные и включенные аккаунты. Не перезапускайте Gateway с одновременно включенными BlueBubbles и iMessage, если вы не хотите намеренно запустить оба монитора каналов. Если вы не переключаетесь немедленно, перед перезапуском Gateway снова установитеchannels.imessage.enabledвfalse. Используйте прямые командыimsgиз раздела Перед началом, чтобы проверить Mac перед включением трафика OpenClaw. -
Переключитесь. Когда включенный аккаунт iMessage сообщает о работоспособности, удалите конфигурацию BlueBubbles и оставьте iMessage включенным:
json5 { channels: { imessage: { enabled: true /* ... */ }, },}Перезапустите gateway. Входящий трафик iMessage теперь проходит через встроенный Plugin.
-
Проверьте DM. Отправьте агенту личное сообщение; убедитесь, что ответ доставлен.
-
Проверьте группы отдельно. DM и группы проходят по разным путям кода — успешная работа DM не доказывает, что группы маршрутизируются. Отправьте агенту сообщение в сопряженном групповом чате и убедитесь, что ответ доставлен. Если группа замолкает (нет ответа агента, нет ошибки), проверьте лог gateway на
imessage: dropping group message from chat_id=<id>или строку запускаimessage: groupPolicy="allowlist" but channels.imessage.groups is empty— обе появляются на стандартном уровне логирования. Если появляется любая из них, ваш блокgroupsотсутствует или пуст — см. «Ловушка реестра групп» выше. -
Проверьте поверхность действий — из сопряженного DM попросите агента поставить реакцию, отредактировать, отменить отправку, ответить, отправить фотографию и (в группе) переименовать группу / добавить или удалить участника. Каждое действие должно нативно примениться в Messages.app. Если любое из них выдает "iMessage
<action>requires the imsg private API bridge", снова выполнитеimsg launchи обновитеchannels status --probe. -
Удалите сервер и конфигурацию BlueBubbles, когда DM, группы и действия iMessage будут проверены. OpenClaw не будет использовать
channels.bluebubbles.
Краткий обзор паритета действий
| Действие | устаревший BlueBubbles | встроенный iMessage |
|---|---|---|
| Отправка текста / резервная отправка SMS | ✅ | ✅ |
| Отправка медиа (фото, видео, файл, голос) | ✅ | ✅ |
Ответ в ветке (reply_to_guid) |
✅ | ✅ (закрывает #51892) |
Tapback (react) |
✅ | ✅ |
| Редактирование / отмена отправки (получатели macOS 13+) | ✅ | ✅ |
| Отправка с экранным эффектом | ✅ | ✅ (закрывает часть #9394) |
| Жирный / курсив / подчеркивание / зачеркивание в форматированном тексте | ✅ | ✅ (форматирование типизированными фрагментами через attributedBody) |
| Переименование группы / установка иконки группы | ✅ | ✅ |
| Добавление / удаление участника, выход из группы | ✅ | ✅ |
| Отчеты о прочтении и индикатор набора | ✅ | ✅ (зависит от проверки private API) |
| Объединение DM от одного отправителя | ✅ | ✅ (только DM; включается через channels.imessage.coalesceSameSenderDms) |
| Восстановление входящих после перезапуска | ✅ (повтор webhook + загрузка истории) | ✅ (автоматически: повтор пропущенных через since_rowid + дедупликация; более широкое окно локально) |
iMessage восстанавливает сообщения, пропущенные во время простоя gateway: при запуске он повторяет с последнего отправленного rowid через imsg watch.subscribe since_rowid и дедуплицирует по GUID, а ограничение возраста устаревшего бэклога подавляет «взрыв бэклога» от Push-flush. Это работает через RPC-соединение imsg, поэтому подходит и для удаленных настроек SSH cliPath; локальные настройки получают более широкое окно восстановления, потому что могут читать chat.db. См. Восстановление входящих после перезапуска bridge или gateway.
Сопряжение, сессии и привязки ACP
- Подтверждения сопряжения переносятся по handle. Вам не нужно заново подтверждать известных отправителей —
channels.imessage.allowFromраспознает те же строки+15555550123/user@example.com, которые использовал BlueBubbles. - Сессии остаются ограниченными парой агент + чат. DM сворачиваются в основную сессию агента при стандартном
session.dmScope=main; групповые сессии остаются изолированными поchat_id. Ключи сессий отличаются (agent:<id>:imessage:group:<chat_id>и эквивалент BlueBubbles) — старая история разговоров под ключами сессий BlueBubbles не переносится в сессии iMessage. - Привязки ACP, ссылающиеся на
match.channel: "bluebubbles", нужно обновить на"imessage". Формыmatch.peer.id(chat_id:,chat_guid:,chat_identifier:, простой handle) идентичны.
Канала отката нет
Поддерживаемого runtime BlueBubbles, на который можно переключиться обратно, нет. Если проверка iMessage не проходит, установите channels.imessage.enabled: false, перезапустите Gateway, исправьте блокер imsg и повторите переключение.
Кэш ответов хранится в состоянии Plugin в SQLite. openclaw doctor --fix импортирует и архивирует старый sidecar imessage/reply-cache.jsonl, если он присутствует.
См. также
- Удаление BlueBubbles и путь iMessage через imsg — краткое объявление и сводка для операторов.
- iMessage — полный справочник канала iMessage, включая настройку
imsg launchи обнаружение возможностей. /channels/bluebubbles— устаревший URL, который перенаправляет на это руководство по миграции.- Сопряжение — аутентификация DM и поток сопряжения.
- Маршрутизация каналов — как gateway выбирает канал для исходящих ответов.