Mainstream messaging
Si vienes de BlueBubbles
El Plugin imessage incluido ahora accede a la misma superficie de API privada que BlueBubbles (react, edit, unsend, reply, sendWithEffect, administración de grupos, adjuntos) controlando steipete/imsg mediante JSON-RPC. Si ya ejecutas un Mac con imsg instalado, puedes prescindir del servidor BlueBubbles y dejar que el Plugin se comunique directamente con Messages.app.
Se eliminó la compatibilidad con BlueBubbles. OpenClaw admite iMessage solo mediante imsg. Esta guía sirve para migrar configuraciones antiguas de channels.bluebubbles a channels.imessage; no hay ninguna otra ruta de migración compatible.
Lista de verificación de migración
Usa esta lista de verificación cuando ya conozcas tu configuración antigua de BlueBubbles y quieras la ruta segura más corta:
- Verifica
imsgdirectamente en el Mac que ejecuta Messages.app (imsg chats,imsg history,imsg sendyimsg rpc --help). - Copia las claves de comportamiento de
channels.bluebubblesachannels.imessage:dmPolicy,allowFrom,groupPolicy,groupAllowFrom,groups,includeAttachments,attachmentRoots,mediaMaxMb,textChunkLimit,coalesceSameSenderDmsyactions. - Elimina las claves de transporte que ya no existen:
serverUrl,password, URL de Webhook y la configuración del servidor BlueBubbles. - Si el Gateway no se está ejecutando en el Mac de Messages, establece
channels.imessage.cliPathen un envoltorio SSH y configuraremoteHostpara las recuperaciones remotas de adjuntos. - Con el Gateway detenido, habilita
channels.imessagey luego ejecutaopenclaw channels status --probe --channel imessage. - Prueba un DM, un grupo permitido, adjuntos si están habilitados y cada acción de API privada que esperas que use el agente.
- Elimina el servidor BlueBubbles y la configuración antigua de
channels.bluebubblesdespués de verificar la ruta de iMessage.
Cuándo tiene sentido esta migración
- Ya ejecutas
imsgen el mismo Mac (o en uno accesible por SSH) donde Messages.app tiene una sesión iniciada. - Quieres una pieza móvil menos: sin servidor BlueBubbles separado, sin endpoint REST que autenticar, sin conexiones de Webhook. Un único binario CLI en lugar de un servidor + aplicación cliente + auxiliar.
- Estás en una versión compatible de macOS /
imsgdonde la sonda de API privada informaavailable: true.
Qué hace imsg
imsg es una CLI local de macOS para Messages. OpenClaw inicia imsg rpc como proceso hijo y se comunica mediante JSON-RPC por stdin/stdout. No hay servidor HTTP, URL de Webhook, daemon en segundo plano, agente de lanzamiento ni puerto que exponer.
- Las lecturas provienen de
~/Library/Messages/chat.dbusando un identificador SQLite de solo lectura. - Los mensajes entrantes en vivo provienen de
imsg watch/watch.subscribe, que sigue eventos del sistema de archivos dechat.dbcon una alternativa de sondeo. - Los envíos usan automatización de Messages.app para texto normal y envíos de archivos.
- Las acciones avanzadas usan
imsg launchpara inyectar el auxiliarimsgen Messages.app. Eso es lo que desbloquea confirmaciones de lectura, indicadores de escritura, envíos enriquecidos, edición, anulación de envío, respuesta en hilo, tapbacks y administración de grupos. - Las compilaciones para Linux pueden inspeccionar un
chat.dbcopiado, pero no pueden enviar, observar la base de datos en vivo del Mac ni controlar Messages.app. Para OpenClaw iMessage, ejecutaimsgen el Mac con la sesión iniciada o mediante un envoltorio SSH hacia ese Mac.
Antes de empezar
-
Instala
imsgen el Mac que ejecuta Messages.app:brew install steipete/tap/imsg imsg --version imsg chats --limit 3Si
imsg chatsfalla conunable to open database file, salida vacía oauthorization denied, concede Acceso total al disco al terminal, editor, proceso de Node, servicio Gateway o proceso padre SSH que iniciaimsg, y luego vuelve a abrir ese proceso padre. -
Verifica las superficies de lectura, observación, envío y RPC antes de cambiar la configuración de OpenClaw:
imsg chats --limit 10 --json | jq -s imsg history --chat-id 42 --limit 10 --attachments --json | jq -s imsg watch --chat-id 42 --reactions --json imsg send --chat-id 42 --text "OpenClaw imsg test" imsg rpc --helpSustituye
42por un id de chat real deimsg chats. El envío requiere permiso de Automatización para Messages.app. Si OpenClaw se ejecutará mediante SSH, ejecuta estos comandos con el mismo envoltorio SSH o contexto de usuario que usará OpenClaw. -
Habilita el puente de API privada cuando necesites acciones avanzadas:
imsg launch imsg status --jsonimsg launchrequiere que SIP esté deshabilitado. El envío básico, el historial y la observación funcionan sinimsg launch; las acciones avanzadas no. -
Después de agregar una configuración
channels.imessagehabilitada, verifica el puente mediante OpenClaw:openclaw channels status --probeQuieres
imessage.privateApi.available: true. Si informafalse, corrige eso primero; consulta Detección de capacidades.channels status --probesolo sondea cuentas configuradas y habilitadas. -
Toma una instantánea de tu configuración:
cp ~/.openclaw/openclaw.json5 ~/.openclaw/openclaw.json5.bak
Traducción de configuración
iMessage y BlueBubbles comparten mucha configuración a nivel de canal. Las claves que cambian son principalmente de transporte (servidor REST frente a CLI local). Las claves de comportamiento (dmPolicy, groupPolicy, allowFrom, etc.) mantienen el mismo significado.
| BlueBubbles | iMessage incluido | Notas |
|---|---|---|
channels.bluebubbles.enabled |
channels.imessage.enabled |
Misma semántica. |
channels.bluebubbles.serverUrl |
(eliminado) | Sin servidor REST: el plugin inicia imsg rpc sobre stdio. |
channels.bluebubbles.password |
(eliminado) | No se necesita autenticación de Webhook. |
| (implícito) | channels.imessage.cliPath |
Ruta a imsg (predeterminado imsg); usa un script envoltorio para SSH. |
| (implícito) | channels.imessage.dbPath |
Anulación opcional de chat.db de Messages.app; se detecta automáticamente cuando se omite. |
| (implícito) | channels.imessage.remoteHost |
host o user@host: solo necesario cuando cliPath es un envoltorio SSH y quieres obtener adjuntos por SCP. |
channels.bluebubbles.dmPolicy |
channels.imessage.dmPolicy |
Mismos valores (pairing / allowlist / open / disabled). |
channels.bluebubbles.allowFrom |
channels.imessage.allowFrom |
Las aprobaciones de emparejamiento se conservan por handle, no por token. |
channels.bluebubbles.groupPolicy |
channels.imessage.groupPolicy |
Mismos valores (allowlist / open / disabled). |
channels.bluebubbles.groupAllowFrom |
channels.imessage.groupAllowFrom |
Igual. |
channels.bluebubbles.groups |
channels.imessage.groups |
Copia esto literalmente, incluida cualquier entrada comodín groups: { "*": { ... } }. requireMention, tools y toolsBySender por grupo se conservan. Con groupPolicy: "allowlist", un bloque groups vacío o ausente descarta silenciosamente todos los mensajes de grupo; consulta "Riesgo del registro de grupos" abajo. |
channels.bluebubbles.sendReadReceipts |
channels.imessage.sendReadReceipts |
Predeterminado true. Con el plugin incluido, esto solo se ejecuta cuando la sonda de API privada está activa. |
channels.bluebubbles.includeAttachments |
channels.imessage.includeAttachments |
Misma forma, también desactivado de forma predeterminada. Si tenías adjuntos funcionando en BlueBubbles, debes volver a configurar esto explícitamente en el bloque de iMessage: no se conserva implícitamente, y las fotos/medios entrantes se descartarán silenciosamente sin línea de registro Inbound message hasta que lo hagas. |
channels.bluebubbles.attachmentRoots |
channels.imessage.attachmentRoots |
Raíces locales; mismas reglas de comodines. |
| (N/D) | channels.imessage.remoteAttachmentRoots |
Solo se usa cuando remoteHost está configurado para obtenciones por SCP. |
channels.bluebubbles.mediaMaxMb |
channels.imessage.mediaMaxMb |
Predeterminado 16 MB en iMessage (el predeterminado de BlueBubbles era 8 MB). Configúralo explícitamente si quieres mantener el límite inferior. |
channels.bluebubbles.textChunkLimit |
channels.imessage.textChunkLimit |
Predeterminado 4000 en ambos. |
channels.bluebubbles.coalesceSameSenderDms |
channels.imessage.coalesceSameSenderDms |
Misma opción voluntaria. Solo DM: los chats de grupo mantienen el despacho instantáneo por mensaje en ambos canales. Amplía el antirrebote entrante predeterminado a 2500 ms cuando se habilita sin un messages.inbound.byChannel.imessage explícito. Consulta docs de iMessage § Combinar DM de envío dividido. |
channels.bluebubbles.enrichGroupParticipantsFromContacts |
(N/D) | iMessage ya lee los nombres visibles de los remitentes desde chat.db. |
channels.bluebubbles.actions.* |
channels.imessage.actions.* |
Activadores por acción: reactions, edit, unsend, reply, sendWithEffect, renameGroup, setGroupIcon, addParticipant, removeParticipant, leaveGroup, sendAttachment. |
Las configuraciones multicuenta (channels.bluebubbles.accounts.*) se traducen una a una a channels.imessage.accounts.*.
Riesgo del registro de grupos
El plugin de iMessage incluido ejecuta dos compuertas de lista de permitidos de grupo separadas, una tras otra. Ambas deben aprobarse para que un mensaje de grupo llegue al agente:
- Lista de permitidos de remitente / destino de chat (
channels.imessage.groupAllowFrom): verificada porisAllowedIMessageSender. Coincide con mensajes entrantes por handle de remitente,chat_guid,chat_identifierochat_id. Misma forma que BlueBubbles. - Registro de grupos (
channels.imessage.groups): verificado porresolveChannelGroupPolicydesdeinbound-processing.ts:199. CongroupPolicy: "allowlist", esta compuerta requiere:- una entrada comodín
groups: { "*": { ... } }(estableceallowAll = true), o - una entrada explícita por
chat_idengroups.
- una entrada comodín
Si la compuerta 1 aprueba pero la compuerta 2 falla, el mensaje se descarta. El plugin emite dos señales de nivel warn, por lo que esto ya no es silencioso con el nivel de registro predeterminado:
- Un
warnde inicio único por cuenta cuandogroupPolicy: "allowlist"está configurado perochannels.imessage.groupsestá vacío (sin comodín"*", sin entradas porchat_id): se dispara antes de que llegue cualquier mensaje. - Un
warnúnico porchat_idla primera vez que se descarta un grupo específico en tiempo de ejecución, indicando el chat_id y la clave exacta que debes añadir agroupspara permitirlo.
Los DM siguen funcionando porque toman una ruta de código distinta.
Este es el modo de fallo más común en la migración de BlueBubbles a iMessage incluido: los operadores copian groupAllowFrom y groupPolicy, pero omiten el bloque groups, porque groups: { "*": { "requireMention": true } } de BlueBubbles parece una configuración de mención no relacionada. En realidad es esencial para la compuerta del registro.
La configuración mínima para mantener el flujo de mensajes de grupo después de groupPolicy: "allowlist":
{
channels: {
imessage: {
groupPolicy: "allowlist",
groupAllowFrom: ["+15555550123", "chat_guid:any;-;..."],
groups: {
"*": { requireMention: true },
},
},
},
}
requireMention: true bajo * es inocuo cuando no hay patrones de mención configurados: el runtime establece canDetectMention = false y omite anticipadamente el descarte de menciones en inbound-processing.ts:512. Con patrones de mención configurados (agents.list[].groupChat.mentionPatterns), funciona como se espera.
Si los registros del Gateway muestran imessage: dropping group message from chat_id=<id> o la línea de inicio imessage: groupPolicy="allowlist" but channels.imessage.groups is empty, la puerta 2 está descartando mensajes: añade el bloque groups.
Paso a paso
-
Añade un bloque de iMessage junto al bloque existente de BlueBubbles. Mantenlo deshabilitado mientras el Gateway siga enrutando tráfico de BlueBubbles:
{ 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, }, }, }, } -
Prueba antes de que el tráfico importe: detén el Gateway, habilita temporalmente el bloque de iMessage y confirma que iMessage se informa como saludable desde la CLI:
openclaw gateway stop # edit config: channels.imessage.enabled = true openclaw channels status --probe --channel imessage # expect imessage.privateApi.available: truechannels status --probesolo prueba cuentas configuradas y habilitadas. No reinicies el Gateway con BlueBubbles e iMessage habilitados a la vez, salvo que quieras intencionadamente que ambos monitores de canal se ejecuten. Si no vas a hacer la transición de inmediato, vuelve a establecerchannels.imessage.enabledenfalseantes de reiniciar el Gateway. Usa los comandos directos deimsgen Antes de empezar para validar el Mac antes de habilitar el tráfico de OpenClaw. -
Haz la transición. Cuando la cuenta de iMessage habilitada se informe como saludable, elimina la configuración de BlueBubbles y mantén iMessage habilitado:
{ channels: { imessage: { enabled: true /* ... */ }, }, }Reinicia el Gateway. El tráfico entrante de iMessage ahora fluye por el Plugin incluido.
-
Verifica los MD. Envía un mensaje directo al agente; confirma que llega la respuesta.
-
Verifica los grupos por separado. Los MD y los grupos usan rutas de código diferentes: que los MD funcionen no prueba que los grupos estén enrutando. Envía un mensaje al agente en un chat grupal emparejado y confirma que llega la respuesta. Si el grupo queda en silencio (sin respuesta del agente, sin error), revisa el registro del Gateway en busca de
imessage: dropping group message from chat_id=<id>o la línea de inicioimessage: groupPolicy="allowlist" but channels.imessage.groups is empty; ambas se emiten en el nivel de registro predeterminado. Si aparece cualquiera de las dos, tu bloquegroupsfalta o está vacío; consulta “problema del registro de grupos” más arriba. -
Verifica la superficie de acciones: desde un MD emparejado, pídele al agente que reaccione, edite, anule el envío, responda, envíe una foto y (en un grupo) cambie el nombre del grupo / añada o elimine un participante. Cada acción debería llegar de forma nativa a Messages.app. Si alguna arroja "iMessage
<action>requires the imsg private API bridge", ejecutaimsg launchde nuevo y actualizachannels status --probe. -
Elimina el servidor y la configuración de BlueBubbles cuando se hayan verificado los MD, los grupos y las acciones de iMessage. OpenClaw no usará
channels.bluebubbles.
Paridad de acciones de un vistazo
| Acción | BlueBubbles heredado | iMessage incluido |
|---|---|---|
| Enviar texto / respaldo por SMS | ✅ | ✅ |
| Enviar medios (foto, video, archivo, voz) | ✅ | ✅ |
Respuesta en hilo (reply_to_guid) |
✅ | ✅ (cierra #51892) |
Tapback (react) |
✅ | ✅ |
| Editar / anular envío (destinatarios con macOS 13+) | ✅ | ✅ |
| Enviar con efecto de pantalla | ✅ | ✅ (cierra parte de #9394) |
| Texto enriquecido en negrita / cursiva / subrayado / tachado | ✅ | ✅ (formato de tramos tipados mediante attributedBody) |
| Cambiar nombre del grupo / establecer icono de grupo | ✅ | ✅ |
| Añadir / eliminar participante, salir del grupo | ✅ | ✅ |
| Confirmaciones de lectura e indicador de escritura | ✅ | ✅ (controlado por la prueba de API privada) |
| Coalescencia de MD del mismo remitente | ✅ | ✅ (solo MD; activación explícita mediante channels.imessage.coalesceSameSenderDms) |
| Recuperación de mensajes entrantes recibidos mientras el Gateway está caído | ✅ (repetición de Webhook + obtención de historial) | ✅ (activación explícita mediante channels.imessage.catchup.enabled; cierra #78649) |
La recuperación de iMessage ahora está disponible como una función de activación explícita en el Plugin incluido. Al iniciar el Gateway, si channels.imessage.catchup.enabled es true, el Gateway ejecuta una pasada de chats.list + messages.history por chat contra el mismo cliente JSON-RPC usado por imsg watch, vuelve a reproducir cada fila entrante perdida por la ruta de despacho en vivo (listas de permitidos, política de grupos, debouncer, caché de eco) y persiste un cursor por cuenta para que los inicios posteriores continúen desde donde quedaron. Consulta Ponerse al día tras una caída del Gateway para los ajustes.
Emparejamiento, sesiones y enlaces ACP
- Las aprobaciones de emparejamiento se trasladan por identificador. No necesitas volver a aprobar remitentes conocidos:
channels.imessage.allowFromreconoce las mismas cadenas+15555550123/user@example.comque usaba BlueBubbles. - Las sesiones siguen delimitadas por agente + chat. Los MD se colapsan en la sesión principal del agente con el valor predeterminado
session.dmScope=main; las sesiones de grupo siguen aisladas porchat_id. Las claves de sesión difieren (agent:<id>:imessage:group:<chat_id>frente al equivalente de BlueBubbles): el historial de conversaciones antiguo bajo claves de sesión de BlueBubbles no se transfiere a las sesiones de iMessage. - Los enlaces ACP que hagan referencia a
match.channel: "bluebubbles"deben actualizarse a"imessage". Las formas dematch.peer.id(chat_id:,chat_guid:,chat_identifier:, identificador simple) son idénticas.
Sin canal de reversión
No hay un runtime de BlueBubbles compatible al que volver. Si la verificación de iMessage falla, establece channels.imessage.enabled: false, reinicia el Gateway, corrige el bloqueo de imsg y vuelve a intentar la transición.
La caché de respuestas vive en ~/.openclaw/state/imessage/reply-cache.jsonl (modo 0600, directorio padre 0700). Es seguro eliminarla si quieres empezar desde cero.
Relacionado
- Eliminación de BlueBubbles y la ruta iMessage de imsg: anuncio breve y resumen para operadores.
- iMessage: referencia completa del canal iMessage, incluida la configuración de
imsg launchy la detección de capacidades. /channels/bluebubbles: URL heredada que redirige a esta guía de migración.- Emparejamiento: autenticación de MD y flujo de emparejamiento.
- Enrutamiento de canales: cómo el Gateway elige un canal para las respuestas salientes.