Aller au contenu

iMessage

État : intégration native externe CLI. Le Gateway génère imsg rpc et communique via JSON-RPC sur stdio (pas de démon/port distinct). Les actions avancées nécessitent imsg launch et une sonde réussie de l’API privée.

APIActions de l'API privée

Réponses, tapbacks, effets, pièces jointes et gestion de groupe.

Appairage

Les DMs iMessage sont en mode appairage par défaut.

Mac distant

Utilisez un wrapper SSH lorsque le Gateway ne s’exécute pas sur le Mac Messages.

Référence de configuration

Référence complète des champs iMessage.

  1. Installer et vérifier imsg

    Fenêtre de terminal
    brew install steipete/tap/imsg
    imsg rpc --help
    imsg launch
    openclaw channels status --probe
  2. OpenClawConfigurer OpenClaw

    {
    channels: {
    imessage: {
    enabled: true,
    cliPath: "/usr/local/bin/imsg",
    dbPath: "/Users/user/Library/Messages/chat.db",
    },
    },
    }
  3. Démarrer la passerelle

    Fenêtre de terminal
    openclaw gateway
  4. Approuver le premier appairage DM (dmPolicy par défaut)

    Fenêtre de terminal
    openclaw pairing list imessage
    openclaw pairing approve imessage
    Les demandes d'appairage expirent après 1 heure.
  • Vous devez être connecté à Messages sur le Mac exécutant imsg.
  • L’accès complet au disque est requis pour le contexte de processus exécutant OpenClaw/imsg (accès à la base de données Messages).
  • L’autorisation d’automatisation est requise pour envoyer des messages via Messages.app.
  • Pour les actions avancées (réagir / modifier / annuler l’envoi / réponse en fil / effets / opérations de groupe), la protection de l’intégrité du système doit être désactivée — voir Activation de l’imsg private API ci-dessous. L’envoi et la réception basiques de texte et de médias fonctionnent sans cela.

imsg est fourni en deux modes opérationnels :

  • Mode de base (par défaut, aucune modification SIP nécessaire) : texte et média sortants via send, surveillance/historique entrant, liste de discussion. C’est ce que vous obtenez directement après une installation fraîche de brew install steipete/tap/imsg plus les permissions standard macOS ci-dessus.
  • Mode Private API : imsg injecte une dylib d’aide dans Messages.app pour appeler des fonctions internes IMCore. C’est ce qui déverrouille react, edit, unsend, reply (en fil), sendWithEffect, renameGroup, setGroupIcon, addParticipant, removeParticipant, leaveGroup, ainsi que les indicateurs de frappe et les accusés de lecture.

Pour atteindre la surface d’action avancée que cette page de channel documente, vous avez besoin du mode Private API. Le README de imsg est explicite quant à cette exigence :

Les fonctionnalités avancées telles que read, typing, launch, l’envoi enrichi pris en charge par un pont, la mutation de messages et la gestion des discussions sont optionnelles. Elles nécessitent que SIP soit désactivé et qu’une dylib d’aide soit injectée dans Messages.app. imsg launch refuse d’injecter lorsque SIP est activé.

La technique d’injection d’assistant utilise la propre dylib de imsg pour accéder aux API privées de Messages. Il n’y a aucun serveur tiers ou runtime BlueBubbles dans le chemin iMessage OpenClaw iMessage.

  1. Installez (ou mettez à jour) imsg sur le Mac qui exécute Messages.app :

    Fenêtre de terminal
    brew install steipete/tap/imsg
    imsg --version
    imsg status --json

    La sortie de imsg status --json rapporte bridge_version, rpc_methods et selectors par méthode, afin que vous puissiez voir ce que la version actuelle prend en charge avant de commencer.

  2. Désactivez la protection de l’intégrité du système (System Integrity Protection). Ceci est spécifique à la version de macOS car la condition sous-jacente d’Apple dépend du système d’exploitation et du matériel :

    • macOS 10.13–10.15 (Sierra–Catalina) : désactivez la validation de la bibliothèque via le Terminal, redémarrez en mode récupération, exécutez csrutil disable, redémarrez.
    • macOS 11+ (Big Sur et versions ultérieures), Intel : mode récupération (ou récupération Internet), csrutil disable, redémarrez.
    • macOS 11+, Apple Silicon : séquence de démarrage via le bouton d’alimentation pour entrer en récupération ; sur les versions récentes de macOS, maintenez la touche Maj gauche lorsque vous cliquez sur Continuer, puis csrutil disable. Les configurations de machine virtuelle suivent un flux distinct — prenez d’abord un instantané de la VM.
    • macOS 26 / Tahoe : les stratégies de validation de bibliothèque et les vérifications d’autorisations privées imagent ont encore durci ; imsg peut avoir besoin d’une version mise à jour pour suivre. Si l’injection imsg launch ou des selectors spécifiques commencent à renvoyer false après une mise à niveau majeure de macOS, consultez les notes de version de imsg avant de supposer que l’étape SIP a réussi.

    Suivez le flux en mode récupération d’Apple pour votre Mac afin de désactiver SIP avant d’exécuter imsg launch.

  3. Injectez l’assistant. Avec SIP désactivé et Messages.app connecté :

    Fenêtre de terminal
    imsg launch

    imsg launch refuse d’injecter lorsque SIP est toujours activé, ce qui fait également office de confirmation que l’étape 2 a été effectuée.

  4. Vérifiez le pont depuis OpenClaw :

    Fenêtre de terminal
    openclaw channels status --probe

    L’entrée iMessage doit signaler iMessageworks, et imsg status --json | jq '.selectors' doit afficher retractMessagePart: truemacOSOpenClaw ainsi que les sélecteurs d’édition / de frappe / de lecture que votre version macOS expose. Le filtrage par méthode du plugin OpenClaw dans actions.ts n’annonce que les actions dont le sélecteur sous-jacent est true, donc la surface d’action que vous voyez dans la liste d’outils de l’agent reflète ce que le bridge peut réellement faire sur cet hôte.

Si openclaw channels status --probe signale le canal comme worksiMessage mais que des actions spécifiques génèrent l’erreur « iMessage `

API nécessite le bridge de l'API privée imsg » lors de l'envoi, exécutez imsg launchà nouveau — l'assistant peut se désactiver (redémarrage de Messages.app, mise à jour du système d'exploitation, etc.) et le statutavailable: true` mis en cache continuera d’annoncer des actions jusqu’à ce que la prochaine sonde rafraîchisse les informations.

Si la désactivation de SIP n’est pas acceptable pour votre modèle de menace :

  • imsg revient au mode de base — texte + média + réception uniquement.
  • Le plugin OpenClaw annonce toujours l’envoi de texte/médias et la surveillance entrante ; il masque simplement OpenClawreact, edit, unsend, reply, sendWithEffect et les opérations de groupe de la surface d’action (conformément à la porte de capacité par méthode).
  • Vous pouvez faire fonctionner un Mac distinct non-Apple-Silicon (ou un Mac bot dédié) avec SIP désactivé pour la charge de travail iMessage, tout en gardant SIP activé sur vos appareils principaux. Voir Utilisateur macOS de bot dédié (identité iMessage distincte) ci-dessous.

channels.imessage.dmPolicy contrôle les messages directs :

  • pairing (par défaut)
  • allowlist
  • open (nécessite que allowFrom inclue "*")
  • disabled

Champ de liste d’autorisation : channels.imessage.allowFrom.

Les entrées de la liste d’autorisation doivent identifier les expéditeurs : identifiants ou groupes d’accès d’expéditeurs statiques (`accessGroup:

). Utilisez channels.imessage.groupAllowFrompour les cibles de conversation telles quechat_id:, chat_guid:ouchat_identifier:*; utilisezchannels.imessage.groupspour les clés de registre numériqueschat_id`.

Les discussions iMessage héritées peuvent également être liées aux sessions ACP.

Flux rapide pour l’opérateur :

  • Exécutez /acp spawn codex --bind here à l’intérieur du DM ou du chat de groupe autorisé.
  • Les futurs messages de cette même conversation iMessage sont acheminés vers la session ACP générée.
  • /new et /reset réinitialisent la même session ACP liée en place.
  • /acp close ferme la session ACP et supprime la liaison.

Les liaisons persistantes configurées sont prises en charge via les entrées bindings[] de niveau supérieur avec type: "acp" et match.channel: "imessage".

match.peer.id peut utiliser :

` (recommandé pour les liaisons de groupe stables)

  • `chat_guid:

`

  • `chat_identifier:

`

Exemple :

{
agents: {
list: [
{
id: "codex",
runtime: {
type: "acp",
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
},
},
],
},
bindings: [
{
type: "acp",
agentId: "codex",
match: {
channel: "imessage",
accountId: "default",
peer: { kind: "group", id: "chat_id:123" },
},
acp: { label: "codex-group" },
},
],
}

Voir ACP Agents pour le comportement de liaison ACP partagée.

macOSiMessageUtilisateur macOS dédié au bot (identité iMessage distincte)

Utilisez un Apple ID et un utilisateur macOS dédiés afin que le trafic du bot soit isolé de votre profil personnel Messages.

Flux type :

  1. Créez/connectez-vous en tant qu’utilisateur macOS dédié.
  2. Connectez-vous à Messages avec l’Apple ID du bot dans cet utilisateur.
  3. Installez imsgOpenClaw dans cet utilisateur.
  4. Créez un wrapper SSH pour qu’OpenClaw puisse exécuter imsg dans le contexte de cet utilisateur.
  5. Pointez `channels.imessage.accounts.

.cliPathet.dbPath` vers ce profil utilisateur.

Le premier lancement peut nécessiter des approbations de l'interface graphique (Automatisation + Accès complet au disque) dans la session de cet utilisateur bot.
TailscaleMac distant via Tailscale (exemple)

Topologie courante :

  • la passerelle (gateway) s’exécute sur Linux/VM
  • iMessage + imsg s’exécute sur un Mac dans votre tailnet
  • le wrapper cliPath utilise SSH pour exécuter imsg
  • remoteHost active la récupération des pièces jointes SCP

Exemple :

{
channels: {
imessage: {
enabled: true,
cliPath: "~/.openclaw/scripts/imsg-ssh",
remoteHost: "[email protected]",
includeAttachments: true,
dbPath: "/Users/bot/Library/Messages/chat.db",
},
},
}
#!/usr/bin/env bash
exec ssh -T [email protected] imsg "$@"

Utilisez des clés SSH pour que SSH et SCP soient non-interactifs. Assurez-vous que la clé de l’hôte est approuvée au préalable (par exemple ssh [email protected]) pour que known_hosts soit renseigné.

Modèle multi-compte

iMessage prend en charge la configuration par compte sous channels.imessage.accounts.

Chaque compte peut remplacer des champs tels que cliPath, dbPath, allowFrom, groupPolicy, mediaMaxMb, les paramètres d’historique et les listes d’autorisation racines des pièces jointes.

Pièces jointes et médias
  • l’ingestion des pièces jointes entrantes est désactivée par défaut — définissez channels.imessage.includeAttachments: true pour transférer les photos, mémos vocaux, vidéos et autres pièces jointes à l’agent. Si elle est désactivée, les iMessages contenant uniquement des pièces jointes sont supprimés avant d’atteindre l’agent et peuvent ne produire aucune ligne de journal Inbound message.
  • les chemins distants des pièces jointes peuvent être récupérés via SCP lorsque remoteHost est défini
  • les chemins des pièces jointes doivent correspondre aux racines autorisées :
    • channels.imessage.attachmentRoots (local)
    • channels.imessage.remoteAttachmentRoots (mode SCP distant)
    • modèle de racine par défaut : /Users/*/Library/Messages/Attachments
  • SCP utilise une vérification stricte de la clé de l’hôte (StrictHostKeyChecking=yes)
  • la taille des médias sortants utilise channels.imessage.mediaMaxMb (par défaut 16 Mo)
Découpage sortant
  • limite de découpage de texte : channels.imessage.textChunkLimit (par défaut 4000)
  • mode de découpage : channels.imessage.chunkMode
    • length (par défaut)
    • newline (découpage par priorité de paragraphe)
Formats d'adressage

Cibles explicites préférées :

  • chat_id:123 (recommandé pour un routage stable)
  • chat_guid:...
  • chat_identifier:...

Les cibles de gestion (handle) sont également prises en charge :

Fenêtre de terminal
imsg chats --limit 20

Lorsque imsg launch est en cours d’exécution et que openclaw channels status --probe signale privateApi.available: trueiMessage, l’outil de message peut utiliser des actions natives iMessage en plus des envois de texte normaux.

{
channels: {
imessage: {
actions: {
reactions: true,
edit: true,
unsend: true,
reply: true,
sendWithEffect: true,
sendAttachment: true,
renameGroup: true,
setGroupIcon: true,
addParticipant: true,
removeParticipant: true,
leaveGroup: true,
},
},
},
}
Available actions
  • react : Ajouter/supprimer des tapbacks iMessage (messageId, emoji, remove). Les tapbacks pris en charge correspondent à love, like, dislike, laugh, emphasize et question.
  • reply : Envoyer une réponse en fil à un message existant (messageId, text ou message, plus chatGuid, chatId, chatIdentifier, ou toiMessage).
  • sendWithEffect : Envoyer du texte avec un effet iMessage (text ou message, effect ou effectIdmacOSAPI).
  • edit : Modifier un message envoyé sur les versions macOS/API privée prises en charge (messageId, text ou newTextmacOSAPI).
  • unsend : Rétracter un message envoyé sur les versions macOS/API privée prises en charge (messageId).
  • upload-file : Envoyer des médias/fichiers (buffer en base64 ou un media/path/filePath hydraté, filename, asVoice facultatif). Ancien alias : sendAttachment.
  • renameGroup, setGroupIcon, addParticipant, removeParticipant, leaveGroup : Gérer les discussions de groupe lorsque la cible actuelle est une conversation de groupe.
Message IDs

Le contexte iMessage entrant inclut à la fois des valeurs MessageSid courtes et des GUID de message complets lorsque disponibles. Les ID courts sont limités au cache de récentes réponses en mémoire et sont vérifiés par rapport à la discussion actuelle avant utilisation. Si un ID court a expiré ou appartient à une autre discussion, réessayez avec le MessageSidFull complet.

<Accordion title=“Détection des fonctionnalités”OpenClawAPI> OpenClaw masque les actions de l’API privée uniquement lorsque l’état de la sonde en cache indique que le pont est indisponible. Si l’état est inconnu, les actions restent visibles et envoient des sondes de manière différée afin que la première action puisse réussir après imsg launch sans actualisation manuelle séparée de l’état.

<Accordion title=“Accusés de réception et saisie”API> Lorsque le pont de l’API privée est actif, les conversations entrantes acceptées sont marquées comme lues avant l’expédition et une bulle de saisie est affichée à l’expéditeur pendant que l’agent génère. Désactivez le marquage comme lu avec :

```json5
{
channels: {
imessage: {
sendReadReceipts: false,
},
},
}
```
Les versions plus anciennes de `imsg`OpenClaw qui précèdent la liste des fonctionnalités par méthode bloqueront silencieusement la saisie/la lecture ; OpenClaw enregistre un avertissement unique par redémarrage afin que l'accusé de réception manquant soit attribuable.

<Accordion title=“Tapbacks entrants”OpenClawiMessage> OpenClaw s’abonne aux tapbacks iMessage et route les réactions acceptées en tant qu’événements système au lieu de texte de message normal, afin qu’un tapback utilisateur ne déclenche pas une boucle de réponse ordinaire.

Le mode de notification est contrôlé par `channels.imessage.reactionNotifications` :
- `"own"` (par défaut) : notifier uniquement lorsque les utilisateurs réagissent aux messages créés par le bot.
- `"all"` : notifier pour tous les tapbacks entrants des expéditeurs autorisés.
- `"off"` : ignorer les tapbacks entrants.
Les substitutions par compte utilisent `channels.imessage.accounts.<id>.reactionNotifications`.

iMessage permet les écritures de configuration initiées par le canal par défaut (pour iMessage/config set|unset lorsque commands.config: true).

Désactiver :

{
channels: {
imessage: {
configWrites: false,
},
},
}

Fusion des envois fractionnés de DMs (commande + URL dans une seule composition)

Section intitulée « Fusion des envois fractionnés de DMs (commande + URL dans une seule composition) »

Lorsqu’un utilisateur tape une commande et une URL ensemble — par exemple Dump https://example.com/article — l’application Messages d’Apple divise l’envoi en deux lignes chat.db distinctes :

  1. Un message texte ("Dump").
  2. Un ballon d’aperçu d’URL ("https://...") avec des images d’aperçu OG en pièces jointes.

Les deux lignes arrivent à OpenClaw environ 0,8 à 2,0 s d’intervalle sur la plupart des configurations. Sans fusion, l’agent reçoit la commande seul au tour 1, répond (souvent « envoyez-moi l’URL »), et ne voit l’URL qu’au tour 2 — moment auquel le contexte de la commande est déjà perdu. C’est le pipeline d’envoi d’Apple, et non quelque chose introduit par OpenClaw ou imsg.

channels.imessage.coalesceSameSenderDms permet à un DM de fusionner les lignes consécutives du même expéditeur en un seul tour d’agent. Les discussions de groupe continuent d’expédier par message afin de préserver la structure des tours multi-utilisateurs.

Activer lorsque :

  • Vous fournissez des compétences qui s’attendent à command + payload en un seul message (dump, paste, save, queue, etc.).
  • Vos utilisateurs collent des URL, des images ou du contenu long à côté des commandes.
  • Vous pouvez accepter la latence ajoutée aux tours de DM (voir ci-dessous).

Laisser désactivé lorsque :

  • Vous avez besoin d’une latence de commande minimale pour les déclencheurs de DM à un seul mot.
  • Tous vos flux sont des commandes ponctuelles sans suivi de payload.
Utilisateur composechat.db produitIndicateur désactivé (par défaut)Indicateur activé + fenêtre de 2500 ms
Dump https://example.com (un envoi)2 lignes à ~1 s d’intervalleDeux tours d’agent : “Dump” seul, puis l’URLUn tour : texte fusionné Dump https://example.com
Save this 📎image.jpg caption (pièce jointe + texte)2 lignesDeux tours (pièce jointe supprimée lors de la fusion)Un tour : texte + image conservés
/status (commande autonome)1 ligneEnvoi instantanéAttendre jusqu’à la fenêtre, puis envoyer
URL collée seule1 ligneEnvoi instantanéEnvoi instantané (une seule entrée dans le bucket)
Texte + URL envoyés comme deux messages distincts délibérés, à quelques minutes d’intervalle2 lignes hors fenêtreDeux toursDeux tours (la fenêtre expire entre eux)
Déluge rapide (>10 petits DM dans la fenêtre)N lignesN toursUn tour, sortie limitée (premier + dernier, plafonds texte/pièce jointe appliqués)
Deux personnes qui écrivent dans une discussion de groupeN lignes de M expéditeursM+ tours (un par bucket d’expéditeur)M+ tours — les discussions de groupe ne sont pas fusionnées

Rattrapage après une interruption de la passerelle

Section intitulée « Rattrapage après une interruption de la passerelle »

Lorsque la passerelle est hors ligne (plantage, redémarrage, mise en veille du Mac, machine éteinte), imsg watch reprend à partir de l’état actuel chat.db une fois la passerelle de retour en ligne — tout ce qui est arrivé pendant l’interruption est, par défaut, jamais vu. Le rattrapage rejoue ces messages au prochain démarrage pour que l’agent ne manque pas silencieusement le trafic entrant.

Le rattrapage est désactivé par défaut. Activez-le par canal :

channels: {
imessage: {
catchup: {
enabled: true, // master switch (default: false)
maxAgeMinutes: 120, // skip rows older than now - 2h (default: 120, clamp 1..720)
perRunLimit: 50, // max rows replayed per startup (default: 50, clamp 1..500)
firstRunLookbackMinutes: 30, // first run with no cursor: look back 30 min (default: 30)
maxFailureRetries: 10, // give up on a wedged guid after 10 dispatch failures (default: 10)
},
},
}

Une passe par démarrage de monitorIMessageProvider, séquencée comme imsg launch prêt → watch.subscribeperformIMessageCatchup → boucle d’expédition en direct. Le rattrapage utilise lui-même chats.list + messages.history par chat sur le même client JSON-RPC utilisé par imsg watch. Tout ce qui arrive pendant la passe de rattrapage circule normalement via l’expédition en direct ; le cache de déduplication entrant existant absorbe tout chevauchement avec les lignes rejouées.

Chaque ligne rejouée passe par le chemin de diffusion en direct (evaluateIMessageInbound + dispatchInboundMessage), de sorte que les listes d’autorisation, la stratégie de groupe, le débouncer, le cache d’écho et les accusés de réception se comportent de manière identique pour les messages rejoués et les messages en direct.

La rattrapage conserve un curseur par compte à <openclawStateDir>/imessage/catchup/<account>__<hash>.json (le répertoire d’état OpenClaw est ~/.openclaw par défaut, remplaçable par OPENCLAW_STATE_DIR) :

{
"lastSeenMs": 1717900800000,
"lastSeenRowid": 482910,
"updatedAt": 1717900801234,
"failureRetries": { "<guid>": 1 }
}
  • Le curseur avance à chaque dispatch réussi et est maintenu lorsque le dispatch d’une ligne échoue — le prochain démarrage réessaie la même ligne à partir du curseur maintenu.
  • Après maxFailureRetries lancers consécutifs contre le même guid, le rattrapage enregistre un warn et force l’avancement du curseur au-delà du message bloqué afin que les démarrages suivants puissent progresser.
  • Les guids déjà abandonnés sont ignorés à vue (aucune tentative de diffusion) lors des exécutions ultérieures et comptabilisés sous skippedGivenUp dans le résumé de l’exécution.
imessage catchup: replayed=N skippedFromMe=… skippedGivenUp=… failed=… givenUp=… fetchedCount=…
imessage catchup: giving up on guid=<guid> after <N> failures; advancing cursor past it
imessage catchup: fetched <X> rows across chats, capped to perRunLimit=<Y>

Une ligne WARN ... capped to perRunLimit signifie qu’un seul démarrage n’a pas vidé toute l’arriéré. Augmentez perRunLimit (max 500) si vos lacunes dépassent régulièrement le passage par défaut de 50 lignes.

  • Le Gateway fonctionne en continu avec un redémarrage automatique par watchdog et les interruptions sont toujours < quelques secondes — la valeur par défaut désactivée convient.
  • Le volume de DM est faible et les messages manqués ne modifieraient pas le comportement de l’agent — la fenêtre initiale firstRunLookbackMinutes peut diffuser un ancien contexte surprenant lors de la première activation.

Lorsque vous activez le rattrapage, le premier démarrage sans curseur ne remonte que firstRunLookbackMinutes (30 min par défaut), et non la fenêtre complète maxAgeMinutes — cela évite de rejouer une longue historique de messages pré-activation.

imsg introuvable ou RPC non pris en charge

Validez le binaire et la prise en charge du RPC :

Fenêtre de terminal
imsg rpc --help
imsg status --json
openclaw channels status --probe

Si la sonde signale que le RPC n’est pas pris en charge, mettez à jour imsg. Si les actions de l’API privée ne sont pas disponibles, exécutez imsg launch dans la session utilisateur macOS connecté et sondez à nouveau. Si le Gateway ne tourne pas sur macOS, utilisez la configuration Mac distant via SSH ci-dessus au lieu du chemin local imsg par défaut.

Le Gateway ne fonctionne pas sous macOS
Le `cliPath: "imsg"` par défaut doit fonctionner sur le Mac connecté à Messages. Sous Linux ou Windows, définissez `channels.imessage.cliPath` sur un script wrapper qui se connecte par SSH à ce Mac et exécute `imsg "$@"`.
#!/usr/bin/env bash
exec ssh -T messages-mac imsg "$@"
Exécutez ensuite :
Fenêtre de terminal
openclaw channels status --probe --channel imessage
Les sont ignorés

Vérifiez :

  • channels.imessage.dmPolicy
  • channels.imessage.allowFrom
  • les approbations d’appariement (openclaw pairing list imessage)
Les messages de groupe sont ignorés

Vérifiez :

  • channels.imessage.groupPolicy
  • channels.imessage.groupAllowFrom
  • le comportement de la liste d’autorisation channels.imessage.groups
  • la configuration du modèle de mention (agents.list[].groupChat.mentionPatterns)
Échec des pièces jointes distantes

Vérifiez :

  • channels.imessage.remoteHost
  • channels.imessage.remoteAttachmentRoots
  • l’authentification par clé SSH/SCP depuis l’hôte de la passerelle
  • la clé de l’hôte existe dans ~/.ssh/known_hosts sur l’hôte de la passerelle
  • la lisibilité du chemin distant sur le Mac exécutant Messages
Les demandes d'autorisation macOS ont été manquées

Réexécutez dans un terminal GUI interactif dans le même contexte utilisateur/session et approuvez les invites :

Fenêtre de terminal
imsg chats --limit 1
imsg send

“test”

Confirmez que l'accès complet au disque + l'automatisation sont accordés pour le contexte de processus qui exécute OpenClaw/`imsg`.