iMessage (imsg)

Status: Externe CLI-Integration. Der Gateway startet imsg rpc (JSON-RPC über stdio).

Schnellstart (Einsteiger)

  1. Stelle sicher, dass Messages auf diesem Mac angemeldet ist.
  2. Installiere imsg:
    • brew install steipete/tap/imsg
  3. Konfiguriere OpenClaw mit channels.imessage.cliPath und channels.imessage.dbPath.
  4. Starte den Gateway und bestätige alle macOS-Berechtigungsabfragen (Automation + Full Disk Access).

Minimale Konfiguration:

{
  channels: {
    imessage: {
      enabled: true,
      cliPath: "/usr/local/bin/imsg",
      dbPath: "/Users/<you>/Library/Messages/chat.db",
    },
  },
}

Was ist das

  • iMessage Channel basierend auf imsg unter macOS.
  • Deterministisches Routing: Antworten gehen immer zurück zu iMessage.
  • DMs teilen sich die Haupt-Session des Agents; Gruppen sind isoliert (agent:<agentId>:imessage:group:<chat_id>).
  • Wenn ein Thread mit mehreren Teilnehmern mit is_group=false ankommt, kannst du ihn trotzdem per chat_id über channels.imessage.groups isolieren (siehe “Gruppenähnliche Threads” weiter unten).

Config-Schreibzugriff

Standardmäßig darf iMessage Config-Updates durchführen, die durch /config set|unset ausgelöst werden (erfordert commands.config: true).

Deaktivieren mit:

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

Voraussetzungen

  • macOS mit angemeldetem Messages.
  • Full Disk Access für OpenClaw + imsg (Zugriff auf Messages-Datenbank).
  • Automation-Berechtigung beim Senden.
  • channels.imessage.cliPath kann auf jeden Befehl zeigen, der stdin/stdout weiterleitet (z. B. ein Wrapper-Script, das per SSH zu einem anderen Mac verbindet und imsg rpc ausführt).

Setup (schneller Weg)

  1. Stelle sicher, dass Messages auf diesem Mac angemeldet ist.
  2. Konfiguriere iMessage und starte den Gateway.

Dedizierter Bot-macOS-Benutzer (für isolierte Identität)

Wenn der Bot von einer separaten iMessage-Identität senden soll (und deine persönlichen Messages sauber bleiben sollen), nutze eine dedizierte Apple ID + einen dedizierten macOS-Benutzer.

  1. Erstelle eine dedizierte Apple ID (Beispiel: [email protected]).
    • Apple kann eine Telefonnummer für Verifizierung / 2FA verlangen.
  2. Erstelle einen macOS-Benutzer (Beispiel: openclawhome) und melde dich dort an.
  3. Öffne Messages in diesem macOS-Benutzer und melde dich mit der Bot-Apple-ID bei iMessage an.
  4. Aktiviere Remote Login (Systemeinstellungen → Allgemein → Freigaben → Remote-Anmeldung).
  5. Installiere imsg:
    • brew install steipete/tap/imsg
  6. Richte SSH so ein, dass ssh <bot-macos-user>@localhost true ohne Passwort funktioniert.
  7. Setze channels.imessage.accounts.bot.cliPath auf einen SSH-Wrapper, der imsg als Bot-Benutzer ausführt.

Hinweis beim ersten Start: Senden/Empfangen kann GUI-Freigaben (Automation + Full Disk Access) im Bot-macOS-Benutzer erfordern. Falls imsg rpc hängt oder abbricht, melde dich bei diesem Benutzer an (Bildschirmfreigabe hilft), führe einmalig imsg chats --limit 1 / imsg send ... aus, bestätige die Abfragen und versuche es erneut.

Beispiel-Wrapper (chmod +x). Ersetze <bot-macos-user> durch deinen tatsächlichen macOS-Benutzernamen:

#!/usr/bin/env bash
set -euo pipefail

# Führe einmal interaktiv SSH aus, um Host-Keys zu akzeptieren:
#   ssh <bot-macos-user>@localhost true
exec /usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=5 -T <bot-macos-user>@localhost \
  "/usr/local/bin/imsg" "$@"

Beispiel-Konfiguration:

{
  channels: {
    imessage: {
      enabled: true,
      accounts: {
        bot: {
          name: "Bot",
          enabled: true,
          cliPath: "/path/to/imsg-bot",
          dbPath: "/Users/<bot-macos-user>/Library/Messages/chat.db",
        },
      },
    },
  },
}

Bei Single-Account-Setups nutze die flachen Optionen (channels.imessage.cliPath, channels.imessage.dbPath) statt der accounts-Map.

Remote/SSH-Variante (optional)

Wenn du iMessage auf einem anderen Mac nutzen willst, setze channels.imessage.cliPath auf einen Wrapper, der imsg auf dem Remote-macOS-Host über SSH ausführt. OpenClaw braucht nur stdio.

Beispiel-Wrapper:

#!/usr/bin/env bash
exec ssh -T gateway-host imsg "$@"

Remote-Anhänge: Wenn cliPath über SSH auf einen Remote-Host zeigt, verweisen Anhangspfade in der Messages-Datenbank auf Dateien auf der Remote-Maschine. OpenClaw kann diese automatisch per SCP holen, wenn du channels.imessage.remoteHost setzt:

{
  channels: {
    imessage: {
      cliPath: "~/imsg-ssh", // SSH-Wrapper zum Remote-Mac
      remoteHost: "user@gateway-host", // für SCP-Dateitransfer
      includeAttachments: true,
    },
  },
}

Falls remoteHost nicht gesetzt ist, versucht OpenClaw es automatisch zu erkennen, indem es den SSH-Befehl in deinem Wrapper-Script parst. Explizite Konfiguration wird für Zuverlässigkeit empfohlen.

Remote-Mac via Tailscale (Beispiel)

Wenn der Gateway auf einem Linux-Host/VM läuft, aber iMessage auf einem Mac laufen muss, ist Tailscale die einfachste Brücke: Der Gateway kommuniziert mit dem Mac über das Tailnet, führt imsg via SSH aus und holt Anhänge per SCP zurück.

Architektur:

┌──────────────────────────────┐          SSH (imsg rpc)          ┌──────────────────────────┐
│ Gateway host (Linux/VM)      │──────────────────────────────────▶│ Mac with Messages + imsg │
│ - openclaw gateway           │          SCP (attachments)        │ - Messages signed in     │
│ - channels.imessage.cliPath  │◀──────────────────────────────────│ - Remote Login enabled   │
└──────────────────────────────┘                                   └──────────────────────────┘

              │ Tailscale tailnet (hostname or 100.x.y.z)

        user@gateway-host

Konkretes Konfigurations-Beispiel (Tailscale-Hostname):

{
  channels: {
    imessage: {
      enabled: true,
      cliPath: "~/.openclaw/scripts/imsg-ssh",
      remoteHost: "[email protected]",
      includeAttachments: true,
      dbPath: "/Users/bot/Library/Messages/chat.db",
    },
  },
}

Beispiel-Wrapper (~/.openclaw/scripts/imsg-ssh):

#!/usr/bin/env bash
exec ssh -T [email protected] imsg "$@"

Hinweise:

  • Stelle sicher, dass der Mac bei Messages angemeldet ist und Remote Login aktiviert ist.
  • Nutze SSH-Keys, damit ssh [email protected] ohne Abfragen funktioniert.
  • remoteHost sollte zum SSH-Ziel passen, damit SCP Anhänge holen kann.

Multi-Account-Unterstützung: Nutze channels.imessage.accounts mit Account-spezifischer Config und optionalem name. Siehe gateway/configuration für das gemeinsame Pattern. Committe nicht ~/.openclaw/openclaw.json (enthält oft Tokens).

Zugriffskontrolle (DMs + Gruppen)

DMs:

  • Standard: channels.imessage.dmPolicy = "pairing".
  • Unbekannte Absender erhalten einen Pairing-Code; Nachrichten werden ignoriert, bis sie freigegeben sind (Codes laufen nach 1 Stunde ab).
  • Freigabe via:
    • openclaw pairing list imessage
    • openclaw pairing approve imessage <CODE>
  • Pairing ist der Standard-Token-Austausch für iMessage-DMs. Details: Pairing

Gruppen:

  • channels.imessage.groupPolicy = open | allowlist | disabled.
  • channels.imessage.groupAllowFrom steuert, wer in Gruppen triggern kann, wenn allowlist gesetzt ist.
  • Mention-Gating nutzt agents.list[].groupChat.mentionPatterns (oder messages.groupChat.mentionPatterns), weil iMessage keine nativen Mention-Metadaten hat.
  • Multi-Agent-Override: Setze Agent-spezifische Patterns auf agents.list[].groupChat.mentionPatterns.

Wie es funktioniert (Verhalten)

  • imsg streamt Message-Events; der Gateway normalisiert sie in das gemeinsame Channel-Envelope.
  • Antworten werden immer zurück zur selben Chat-ID oder zum selben Handle geroutet.

Gruppenähnliche Threads (is_group=false)

Manche iMessage-Threads können mehrere Teilnehmer haben, kommen aber trotzdem mit is_group=false an, je nachdem wie Messages die Chat-ID speichert.

Wenn du explizit eine chat_id unter channels.imessage.groups konfigurierst, behandelt OpenClaw diesen Thread als “Gruppe” für:

  • Session-Isolation (separater agent:<agentId>:imessage:group:<chat_id> Session-Key)
  • Gruppen-Allowlisting / Mention-Gating-Verhalten

Beispiel:

{
  channels: {
    imessage: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["+15555550123"],
      groups: {
        "42": { requireMention: false },
      },
    },
  },
}

Das ist nützlich, wenn du eine isolierte Persönlichkeit/Modell für einen bestimmten Thread willst (siehe Multi-Agent Routing). Für Dateisystem-Isolation siehe Sandboxing.

Medien + Limits

  • Optionale Anhang-Verarbeitung via channels.imessage.includeAttachments.
  • Medien-Cap via channels.imessage.mediaMaxMb.

Limits

  • Ausgehender Text wird in Chunks von channels.imessage.textChunkLimit aufgeteilt (Standard 4000).
  • Optionales Newline-Chunking: Setze channels.imessage.chunkMode="newline", um bei Leerzeilen (Absatzgrenzen) zu splitten, bevor nach Länge gechunkt wird.
  • Medien-Uploads sind durch channels.imessage.mediaMaxMb begrenzt (Standard 16).

Adressierung / Zustellziele

Bevorzuge chat_id für stabiles Routing:

  • chat_id:123 (bevorzugt)
  • chat_guid:...
  • chat_identifier:...
  • Direkte Handles: imessage:+1555 / sms:+1555 / [email protected]

Chats auflisten:

imsg chats --limit 20

Konfigurationsreferenz (iMessage)

Vollständige Konfiguration: Configuration

Provider-Optionen:

  • channels.imessage.enabled: Channel-Start aktivieren/deaktivieren.
  • channels.imessage.cliPath: Pfad zu imsg.
  • channels.imessage.dbPath: Messages-DB-Pfad.
  • channels.imessage.remoteHost: SSH-Host für SCP-Anhang-Transfer, wenn cliPath auf einen Remote-Mac zeigt (z. B. user@gateway-host). Wird aus SSH-Wrapper automatisch erkannt, falls nicht gesetzt.
  • channels.imessage.service: imessage | sms | auto.
  • channels.imessage.region: SMS-Region.
  • channels.imessage.dmPolicy: pairing | allowlist | open | disabled (Standard: pairing).
  • channels.imessage.allowFrom: DM-Allowlist (Handles, E-Mails, E.164-Nummern oder chat_id:*). open erfordert "*". iMessage hat keine Benutzernamen; nutze Handles oder Chat-Ziele.
  • channels.imessage.groupPolicy: open | allowlist | disabled (Standard: allowlist).
  • channels.imessage.groupAllowFrom: Gruppen-Absender-Allowlist.
  • channels.imessage.historyLimit / channels.imessage.accounts.*.historyLimit: Max. Gruppennachrichten als Context (0 deaktiviert).
  • channels.imessage.dmHistoryLimit: DM-History-Limit in User-Turns. Pro-User-Overrides: channels.imessage.dms["<handle>"].historyLimit.
  • channels.imessage.groups: Pro-Gruppen-Defaults + Allowlist (nutze "*" für globale Defaults).
  • channels.imessage.includeAttachments: Anhänge in Context aufnehmen.
  • channels.imessage.mediaMaxMb: Inbound/Outbound-Medien-Cap (MB).
  • channels.imessage.textChunkLimit: Outbound-Chunk-Größe (Zeichen).
  • channels.imessage.chunkMode: length (Standard) oder newline, um bei Leerzeilen (Absatzgrenzen) zu splitten, bevor nach Länge gechunkt wird.

Verwandte globale Optionen:

  • agents.list[].groupChat.mentionPatterns (oder messages.groupChat.mentionPatterns).
  • messages.responsePrefix.