Mainstream messaging
Migration depuis BlueBubbles
La prise en charge de BlueBubbles a été supprimée. OpenClaw prend en charge iMessage uniquement au moyen du Plugin imessage inclus, qui pilote steipete/imsg via JSON-RPC et accède à la même surface d’API privée que BlueBubbles (react, edit, unsend, reply, sendWithEffect, sondages natifs, gestion des groupes, pièces jointes). Un seul exécutable CLI remplace le serveur BlueBubbles, l’application cliente et l’infrastructure Webhook : aucun point de terminaison REST ni aucune authentification de Webhook.
Ce guide explique comment migrer les anciennes configurations channels.bluebubbles vers channels.imessage. Il n’existe aucun autre chemin de migration pris en charge. Dans la version actuelle d’OpenClaw, tout bloc channels.bluebubbles restant est inerte : aucun composant d’exécution ne le lit.
Liste de contrôle de la migration
Voici le chemin sûr le plus court si vous connaissez déjà votre ancienne configuration BlueBubbles :
- Vérifiez directement
imsgsur le Mac qui exécute Messages.app (imsg chats,imsg history,imsg send,imsg rpc --help). - Copiez les clés de comportement de
channels.bluebubblesverschannels.imessage:dmPolicy,allowFrom,groupPolicy,groupAllowFrom,groups,includeAttachments,attachmentRoots,mediaMaxMb,textChunkLimit,coalesceSameSenderDmsetactions. - Supprimez les clés de transport qui n’existent plus :
serverUrl,password, les URL de Webhook et la configuration du serveur BlueBubbles. - Si le Gateway ne s’exécute pas sur le Mac hébergeant Messages, définissez
channels.imessage.cliPathsur un script enveloppe SSH et définissezremoteHostpour la récupération distante des pièces jointes. - Activez
channels.imessage, redémarrez le Gateway, puis exécutezopenclaw channels status --probe --channel imessage. - Testez un message privé, un groupe autorisé, les pièces jointes si elles sont activées et chaque action d’API privée que l’agent est censé utiliser.
- Supprimez le serveur BlueBubbles et l’ancienne configuration
channels.bluebubblesaprès avoir vérifié le parcours iMessage.
Fonctionnement d’imsg
imsg est une CLI macOS locale pour Messages. OpenClaw démarre imsg rpc en tant que processus enfant et communique avec lui par JSON-RPC via l’entrée et la sortie standard. Il n’y a aucun serveur HTTP, aucune URL de Webhook, aucun démon en arrière-plan, aucun agent de lancement ni aucun port à exposer.
- Les lectures sont effectuées dans
~/Library/Messages/chat.dbau moyen d’un accès SQLite en lecture seule. - Les messages entrants en temps réel proviennent de
imsg watch/watch.subscribe, qui suit les événements du système de fichiers dechat.dbavec un mécanisme de repli par interrogation périodique. - Les envois utilisent l’automatisation de Messages.app pour les textes et fichiers ordinaires.
- Les actions avancées utilisent
imsg launchpour injecter l’assistantimsgdans Messages.app. Cela permet d’utiliser les confirmations de lecture, les indicateurs de saisie, les envois enrichis, la modification, l’annulation d’envoi, les réponses dans un fil, les réactions, les sondages et la gestion des groupes. - Les versions Linux peuvent examiner une copie de
chat.db, mais ne peuvent ni envoyer de messages, ni surveiller la base de données active du Mac, ni piloter Messages.app. Pour utiliser iMessage avec OpenClaw, exécutezimsgsur le Mac connecté ou par l’intermédiaire d’un script enveloppe SSH vers ce Mac.
Avant de commencer
-
Installez
imsgsur le Mac qui exécute Messages.app :bash brew install steipete/tap/imsgbrew update && brew upgrade imsgimsg --versionimsg chats --limit 3Pour la configuration locale habituelle, l’assistant de configuration d’OpenClaw peut proposer une installation ou une mise à jour de
imsgavec Homebrew, après confirmation de l’utilisateur, sur le Mac connecté à Messages. Les configurations manuelles et les topologies reposant sur un script enveloppe SSH restent gérées par l’opérateur : répétez la mise à jour Homebrew dans le même contexte utilisateur local ou distant que celui qui exécuteraimsg. Siimsg chatséchoue avecunable to open database file, ne produit aucune sortie ou afficheauthorization denied, accordez l’accès complet au disque au terminal, à l’éditeur, au processus Node, au service Gateway ou au processus parent SSH qui lanceimsg, puis rouvrez ce processus parent. -
Vérifiez les fonctions de lecture, de surveillance, d’envoi et RPC avant de modifier la configuration d’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 --helpRemplacez
42par un identifiant de discussion réel obtenu avecimsg chats. L’envoi nécessite l’autorisation d’automatisation pour Messages.app. Si OpenClaw doit s’exécuter via SSH, exécutez ces commandes au moyen du même script enveloppe SSH ou dans le même contexte utilisateur qu’OpenClaw. Si les lectures fonctionnent, mais que les envois échouent avec l’erreur AppleEvents-1743, vérifiez si l’autorisation d’automatisation a été attribuée à/usr/libexec/sshd-keygen-wrapper; voir Échec des envois via le script enveloppe SSH avec AppleEvents -1743. -
Activez la passerelle vers l’API privée. Elle est fortement recommandée pour iMessage avec OpenClaw, car les réponses, les réactions, les effets, les sondages, les réponses aux pièces jointes et les actions de groupe en dépendent :
bash imsg launchimsg status --jsonimsg launchnécessite que SIP soit désactivé (et, sur les versions modernes de macOS, que la validation des bibliothèques soit assouplie — voir Activation de l’API privée d’imsg). L’envoi de base, l’historique et la surveillance fonctionnent sansimsg launch, mais pas l’ensemble complet des actions iMessage d’OpenClaw. -
Après avoir activé
channels.imessageet démarré le Gateway, vérifiez la passerelle au moyen d’OpenClaw :bash openclaw channels status --probeLe compte iMessage doit indiquer
works; avec--json, la charge utile de la sonde comprendprivateApi.available: true. Si elle indiquefalse, corrigez d’abord ce problème — voir Détection des capacités. La détection nécessite un Gateway accessible (sinon, la CLI se rabat sur une sortie fondée uniquement sur la configuration) et ne vérifie que les comptes configurés et activés. -
Créez un instantané de votre configuration :
bash cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak
Transposition de la configuration
iMessage et BlueBubbles partagent la plupart des clés de comportement au niveau du canal. Les différences concernent le transport (serveur REST ou CLI locale) et le format des clés du registre des groupes.
| BlueBubbles | iMessage intégré | Remarques |
|---|---|---|
channels.bluebubbles.enabled |
channels.imessage.enabled |
Même sémantique (true par défaut dès que le bloc existe). |
channels.bluebubbles.serverUrl |
(supprimé) | Aucun serveur REST — le Plugin lance imsg rpc via l’entrée-sortie standard. |
channels.bluebubbles.password |
(supprimé) | Aucune authentification de Webhook nécessaire. |
| (implicite) | channels.imessage.cliPath |
Chemin vers imsg (imsg par défaut) ; utilisez un script enveloppe pour SSH. |
| (implicite) | channels.imessage.dbPath |
Remplacement facultatif du fichier chat.db de Messages.app ; détecté automatiquement s’il est omis. |
| (implicite) | channels.imessage.remoteHost |
host ou user@host — nécessaire uniquement lorsque cliPath est un script enveloppe SSH et que vous souhaitez récupérer les pièces jointes avec SCP. |
channels.bluebubbles.dmPolicy |
channels.imessage.dmPolicy |
Mêmes valeurs (pairing / allowlist / open / disabled) ; valeur par défaut : pairing. |
channels.bluebubbles.allowFrom |
channels.imessage.allowFrom |
Mêmes formats d’identifiants (+15555550123, user@example.com). Les approbations du magasin d’appairage ne sont pas transférées — voir ci-dessous. |
channels.bluebubbles.groupPolicy |
channels.imessage.groupPolicy |
Mêmes valeurs (allowlist / open / disabled) ; valeur par défaut : allowlist. |
channels.bluebubbles.groupAllowFrom |
channels.imessage.groupAllowFrom |
Identique. Lorsqu’il n’est pas défini, iMessage se rabat sur allowFrom ; un groupAllowFrom: [] explicitement vide bloque tous les groupes lorsque groupPolicy: "allowlist". |
channels.bluebubbles.groups |
channels.imessage.groups |
Copiez à l’identique l’entrée générique "*" ; remplacez les clés des entrées propres à chaque groupe par le chat_id numérique d’iMessage — voir « Piège du registre de groupes ». requireMention, tools, toolsBySender et systemPrompt sont conservés. |
channels.bluebubbles.sendReadReceipts |
channels.imessage.sendReadReceipts |
Valeur par défaut : true. Avec le Plugin intégré, cette option ne s’active que lorsque la sonde de l’API privée est opérationnelle. |
channels.bluebubbles.includeAttachments |
channels.imessage.includeAttachments |
Même structure, également désactivée par défaut. Si les pièces jointes transitaient par BlueBubbles, définissez cette option explicitement — les photos et médias entrants sont ignorés silencieusement (aucune ligne de journal Inbound message) tant que vous ne le faites pas. |
channels.bluebubbles.attachmentRoots |
channels.imessage.attachmentRoots |
Racines locales ; mêmes règles pour les caractères génériques. |
| (S/O) | channels.imessage.remoteAttachmentRoots |
Utilisé uniquement lorsque remoteHost est défini pour les récupérations par SCP. |
channels.bluebubbles.mediaMaxMb |
channels.imessage.mediaMaxMb |
Valeur par défaut de 16 Mo sur iMessage (celle de BlueBubbles était de 8 Mo). Définissez-la explicitement pour conserver la limite inférieure. |
channels.bluebubbles.textChunkLimit |
channels.imessage.textChunkLimit |
Valeur par défaut de 4000 pour les deux. |
channels.bluebubbles.coalesceSameSenderDms |
channels.imessage.coalesceSameSenderDms |
Même option facultative. Messages privés uniquement — les groupes conservent un envoi par message. Étend l’anti-rebond entrant par défaut à 7000 ms, sauf si messages.inbound.byChannel.imessage ou une valeur globale messages.inbound.debounceMs est définie. Voir Regroupement des messages privés envoyés séparément. |
channels.bluebubbles.enrichGroupParticipantsFromContacts |
(S/O) | imsg fournit déjà les noms d’affichage des expéditeurs depuis chat.db. |
channels.bluebubbles.actions.* |
channels.imessage.actions.* |
Mêmes bascules par action (reactions, edit, unsend, reply, sendWithEffect, renameGroup, setGroupIcon, addParticipant, removeParticipant, leaveGroup, sendAttachment), avec la nouvelle action polls. Toutes sont activées par défaut ; les actions de l’API privée nécessitent toujours le pont. |
Les configurations à plusieurs comptes (channels.bluebubbles.accounts.*) correspondent directement à channels.imessage.accounts.*.
Piège du registre de groupes
Le Plugin iMessage intégré applique successivement deux contrôles aux groupes. Un message de groupe doit franchir les deux pour atteindre l’agent :
- Liste d’autorisation des expéditeurs ou des cibles de discussion (
channels.imessage.groupAllowFrom) — correspond à l’identifiant de l’expéditeur ou à la cible de discussion (entréeschat_id:,chat_guid:,chat_identifier:). LorsquegroupAllowFromn’est pas défini, ce contrôle se rabat surallowFrom; ungroupAllowFrom: []explicite désactive ce repli et ignore tous les messages de groupe lorsquegroupPolicy: "allowlist". - Registre de groupes (
channels.imessage.groups) — indexé par lechat_idnumérique d’iMessage :- Aucun bloc
groups(ou bloc vide) : les groupes franchissent ce contrôle tant que le contrôle 1 dispose d’une liste d’autorisation effective et non vide des expéditeurs ; le filtrage des expéditeurs régit l’accès et aucun avertissement de rejet global n’est émis au démarrage. groupscontient des entrées, mais aucune entrée"*": seules les cléschat_idrépertoriées sont acceptées. Le fait de répertorier un groupe transforme le registre en liste d’autorisation, même lorsquegroupPolicy: "open".groups: { "*": { ... } }: tous les groupes franchissent ce contrôle.
- Aucun bloc
Le piège de la migration : BlueBubbles indexait les entrées de groups par GUID ou identifiant de discussion, tandis que le registre iMessage utilise le chat_id numérique. Copier à l’identique les entrées propres à chaque groupe crée un registre non vide dont les clés ne correspondent jamais ; tous les messages de groupe sont donc ignorés lors du contrôle 2. Copiez à l’identique l’entrée générique "*" ; remplacez les clés des entrées de groupes spécifiques par les valeurs chat_id obtenues avec imsg chats.
Les deux motifs de rejet sont visibles au niveau de journalisation par défaut dans des lignes warn :
- Une fois par compte au démarrage, lorsque
groupPolicy: "allowlist"est défini et que la liste d’autorisation effective des expéditeurs de groupe est vide :imessage: groupPolicy="allowlist" for account "<id>" but no group sender allowlist is configured .... DéfinissezgroupAllowFrom(ouallowFrom) pour autoriser des expéditeurs ; ajouter uniquementgroupsne satisfait pas le contrôle des expéditeurs. - Une fois par
chat_idà l’exécution, lorsque le registre rejette un groupe :imessage: dropping group message from chat_id=<id> ... not in channels.imessage.groups allowlist, en indiquant la clé exacte à ajouter.
Les messages privés continuent de fonctionner dans les deux cas — ils empruntent un autre chemin de code ; leur bon fonctionnement ne prouve donc pas que le routage des groupes fonctionne.
Configuration minimale limitée aux expéditeurs avec groupPolicy: "allowlist" :
{ channels: { imessage: { groupPolicy: "allowlist", groupAllowFrom: ["+15555550123", "chat_guid:any;-;..."], }, },}Cette configuration autorise les expéditeurs configurés dans n’importe quel groupe. Ajoutez des entrées groups pour limiter les discussions autorisées ou définir des options propres à chaque discussion, telles que requireMention ; copiez à l’identique l’entrée "*" de BlueBubbles, mais remplacez les clés des entrées spécifiques par les valeurs chat_id numériques d’iMessage.
Étape par étape
-
Traduisez la configuration. Laissez le nouveau bloc désactivé pendant vos modifications ; le bloc
channels.bluebubblesobsolète est ignoré par la version actuelle d’OpenClaw et peut rester à côté comme référence :json5 { channels: { imessage: { enabled: false, // passer à true lorsque vous êtes prêt à effectuer la migration cliPath: "/opt/homebrew/bin/imsg", dmPolicy: "pairing", allowFrom: ["+15555550123"], // copier depuis bluebubbles.allowFrom groupPolicy: "allowlist", groupAllowFrom: [], // copier depuis bluebubbles.groupAllowFrom groups: { "*": { requireMention: true } }, // le caractère générique est copié tel quel ; réindexer les entrées propres à chaque conversation par chat_id // les actions sont activées par défaut ; définir individuellement les options sur false pour les désactiver }, },} -
Effectuez la migration et lancez une vérification. Définissez
channels.imessage.enabled: true, redémarrez le Gateway et vérifiez que le canal est signalé comme opérationnel :bash openclaw gateway restartopenclaw channels status --probe --channel imessage # « works » est attendu ; --json affiche privateApi.available: trueLa vérification nécessite un Gateway accessible et ne teste que les comptes configurés et activés. Utilisez les commandes
imsgdirectes de la section Avant de commencer pour valider le Mac lui-même. -
Vérifiez les messages privés. Envoyez un message direct à l’agent et vérifiez que la réponse arrive.
-
Vérifiez les groupes séparément. Les messages privés et les groupes empruntent des chemins de code différents : le bon fonctionnement des messages privés ne prouve pas que le routage des groupes fonctionne. Envoyez un message dans une conversation de groupe autorisée et vérifiez que la réponse arrive. Si le groupe reste silencieux (aucune réponse de l’agent, aucune erreur), recherchez dans le journal du Gateway les deux lignes
warnde la section « Piège du registre des groupes » ci-dessus. L’avertissement au démarrage signifie que la liste d’expéditeurs effectivement autorisés est vide ; un avertissement propre à unchat_idsignifie qu’un registregroupsnon vide ne contient pas cette conversation. -
Vérifiez l’ensemble des actions. Depuis un message privé appairé, demandez à l’agent d’ajouter une réaction, de modifier et d’annuler l’envoi d’un message, d’y répondre, d’envoyer une photo et, dans un groupe, de renommer le groupe ou d’ajouter ou retirer un participant. Chaque action doit apparaître nativement dans Messages.app. Si une action génère l’erreur
iMessage <action> requires the imsg private API bridge, exécutez à nouveauimsg launch, puis actualisez l’état avecopenclaw channels status --probe. -
Supprimez le serveur BlueBubbles et le bloc
channels.bluebubblesune fois les messages privés, les groupes et les actions iMessage vérifiés. OpenClaw ne lit paschannels.bluebubbles.
Comparaison rapide des actions
| Action | ancien BlueBubbles | iMessage intégré |
|---|---|---|
| Envoyer du texte / repli vers les SMS | ✅ | ✅ |
| Envoyer un média (photo, vidéo, fichier, message vocal) | ✅ | ✅ |
Réponse dans un fil (reply_to_guid) |
✅ | ✅ (résout #51892) |
Tapback (react) |
✅ | ✅ |
| Modifier / annuler l’envoi (destinataires sous macOS 13+) | ✅ | ✅ |
| Envoyer avec un effet d’écran | ✅ | ✅ (résout une partie de #9394) |
| Texte enrichi en gras / italique / souligné / barré | ✅ | ✅ (mise en forme par plages typées via attributedBody) |
| Sondages Messages natifs (création et vote) | ❌ | ✅ (actions.polls ; les destinataires doivent utiliser iOS/macOS 26+ pour l’affichage natif) |
| Renommer le groupe / définir son icône | ✅ | ✅ |
| Ajouter / retirer un participant, quitter le groupe | ✅ | ✅ |
| Accusés de lecture et indicateur de saisie | ✅ | ✅ (conditionné par la vérification de l’API privée) |
| Regroupement des messages privés d’un même expéditeur | ✅ | ✅ (messages privés uniquement ; activation explicite via channels.imessage.coalesceSameSenderDms) |
| Récupération des messages entrants après un redémarrage | ✅ | ✅ (automatique : relecture avec since_rowid + déduplication par GUID ; fenêtre plus large en local) |
iMessage récupère les messages manqués pendant l’arrêt du Gateway : au démarrage, il reprend depuis le dernier identifiant de ligne distribué grâce à since_rowid de imsg watch.subscribe, déduplique les messages par GUID et utilise une limite d’ancienneté des éléments en attente pour neutraliser la « bombe d’arriéré » provoquée par la vidange des notifications Push. Cette opération passe par la connexion RPC d’imsg et fonctionne donc également avec les configurations cliPath utilisant SSH à distance ; les configurations locales bénéficient d’une fenêtre de récupération plus large, car elles peuvent lire chat.db. Consultez Récupération des messages entrants après le redémarrage d’un pont ou du Gateway.
Appairage, sessions et liaisons ACP
- Les listes d’autorisation sont conservées par identifiant.
channels.imessage.allowFromreconnaît les mêmes chaînes+15555550123/user@example.comqu’utilisait BlueBubbles : copiez-les telles quelles. - Les approbations du registre d’appairage ne sont pas transférées. Le registre d’appairage est propre à chaque canal et rien ne migre l’ancien registre BlueBubbles. Les expéditeurs qui avaient uniquement été approuvés par appairage doivent s’appairer une nouvelle fois sous iMessage, sauf si vous ajoutez leurs identifiants à
allowFrom. - Les sessions restent limitées à chaque combinaison d’agent et de conversation. Avec la valeur par défaut
session.dmScope=main, les messages privés sont regroupés dans la session principale de l’agent ; les sessions de groupe restent isolées parchat_id(agent:<agentId>:imessage:group:<chat_id>). L’ancien historique de conversation associé aux clés de session BlueBubbles n’est pas transféré vers les sessions iMessage. - Les liaisons ACP qui font référence à
match.channel: "bluebubbles"doivent utiliser"imessage". Les formats dematch.peer.id(chat_id:,chat_guid:,chat_identifier:, identifiant seul) sont identiques.
Aucun canal de retour arrière
Il n’existe aucun environnement d’exécution BlueBubbles pris en charge vers lequel revenir. Si la vérification d’iMessage échoue, définissez channels.imessage.enabled: false, redémarrez le Gateway, corrigez le problème bloquant d’imsg, puis recommencez la migration.
Le cache des réponses réside dans l’état SQLite du Plugin. Lorsqu’il est présent, openclaw doctor --fix importe et archive l’ancien fichier annexe imessage/reply-cache.jsonl.
Voir aussi
- Suppression de BlueBubbles et migration vers iMessage avec imsg — brève annonce et synthèse à l’intention des opérateurs.
- iMessage — référence complète du canal iMessage, notamment la configuration avec
imsg launchet la détection des fonctionnalités. /channels/bluebubbles— ancienne URL qui redirige vers ce guide de migration.- Appairage — authentification des messages privés et procédure d’appairage.
- Routage des canaux — méthode employée par le Gateway pour choisir le canal des réponses sortantes.