Skip to content

本页适用于已运行 BlueBubbles 服务、需要切换到 OpenClaw 内置 iMessage 插件的用户。迁移核心步骤:确认 Mac 上 imsg 可正常工作,复制行为键,删除传输键,配置 group registry 避免群组消息被静默丢弃。验证用 openclaw channels status --probe --channel imessage 检查 privateApi.available: true

OpenClaw: 从 BlueBubbles 迁移到 iMessage 插件

OpenClaw 内置的 imessage 插件已能覆盖 BlueBubbles 的私有 API 功能(反应、编辑、取消发送、回复、特效发送、群组管理、附件)。它直接驱动 steipete/imsg 通过 JSON-RPC 与 Messages.app 通信。如果你已有装有 imsg 的 Mac,可以完全移除 BlueBubbles 服务,让插件直接操作 Messages.app。

BlueBubbles 支持已被移除。 OpenClaw 仅通过 imsg 支持 iMessage。本文档仅面向从旧 channels.bluebubbles 配置迁移到 channels.imessage 的场景,无其他迁移路径。

INFO

简短公告和操作摘要请见 BlueBubbles 移除与 imsg iMessage 路径

迁移检查清单

如果你已经熟悉旧 BlueBubbles 配置,想走最短安全路径,请按此清单操作:

  1. 在运行 Messages.app 的 Mac 上直接验证 imsg(命令:imsg chatsimsg historyimsg sendimsg rpc --help)。
  2. 复制行为键:从 channels.bluebubbles 复制到 channels.imessagedmPolicyallowFromgroupPolicygroupAllowFromgroupsincludeAttachmentsattachmentRootsmediaMaxMbtextChunkLimitcoalesceSameSenderDmsactions
  3. 删除不再存在的传输键:serverUrlpassword、webhook URL 以及 BlueBubbles 服务相关设置。
  4. 如果网关不在 Messages Mac 上运行,需设置 channels.imessage.cliPath 为 SSH 包装脚本,并设置 remoteHost 用于远程附件拉取。
  5. 停止网关,启用 channels.imessage,然后运行 openclaw channels status --probe --channel imessage
  6. 测试一条私信、一个允许群组、附件(如果启用)以及智能体可能使用的每个私有 API 动作。
  7. 确认 iMessage 路径正常后,删除 BlueBubbles 服务和旧的 channels.bluebubbles 配置。

何时适合迁移

  • Message.app 所在的 Mac(或 SSH 可达的 Mac)上已安装 imsg
  • 希望减少一个依赖组件——无需单独的 BlueBubbles 服务、无需 REST 端点认证、无需 webhook 对接。单个 CLI 二进制代替服务+客户端+助手。
  • 运行在 支持的 macOS 版本和 imsg 构建上,私有 API 探测报告 available: true

imsg 是什么

imsg 是一个本地 macOS CLI 工具,与 Messages.app 交互。OpenClaw 将 imsg rpc 作为子进程启动,通过 stdin/stdout 进行 JSON-RPC 通信。没有 HTTP 服务、webhook URL、后台守护进程、启动代理或暴露端口。

  • 读取:通过只读 SQLite 句柄访问 ~/Library/Messages/chat.db
  • 实时入站消息:imsg watch / watch.subscribe 监听 chat.db 文件系统事件,并带有轮询回退。
  • 发送:使用 Messages.app 的自动化能力发送普通文本和文件。
  • 高级动作:使用 imsg launchimsg 助手注入 Messages.app,从而支持已读回执、输入指示、富发送、编辑、取消发送、线程回复、Tapback 和群组管理。
  • Linux 版本可以检查复制的 chat.db,但无法发送、实时监听 Mac 数据库或驱动 Messages.app。OpenClaw iMessage 必须在已登录的 Mac 上运行 imsg,或通过 SSH 包装脚本连接到该 Mac。

开始之前

  1. 在运行 Messages.app 的 Mac 上安装 imsg

    bash
    brew install steipete/tap/imsg
    imsg --version
    imsg chats --limit 3

    如果 imsg chats 失败,报错 unable to open database file、空输出或 authorization denied,请授予终端、编辑器、Node 进程、网关服务或启动 imsg 的 SSH 父进程“完全磁盘访问权限”,然后重新打开该父进程。

  2. 在修改 OpenClaw 配置前,验证读、监听、发送和 RPC 表面:

    bash
    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 --help

    42 替换为 imsg chats 输出的真实聊天 ID。发送需要授予 Messages.app “自动化”权限。如果 OpenClaw 通过 SSH 运行,请通过相同的 SSH 包装脚本或用户上下文执行这些命令。

  3. 当需要高级动作时,启用私有 API 桥接:

    bash
    imsg launch
    imsg status --json

    imsg launch 需要禁用 SIP。基本发送、历史和监听无需 imsg launch 即可工作;高级动作则需要。

  4. 添加已启用的 channels.imessage 配置后,通过 OpenClaw 验证桥接:

    bash
    openclaw channels status --probe

    期望输出 imessage.privateApi.available: true。如果为 false,请先修复——参见能力检测channels status --probe 仅探测已配置且已启用的账号。

  5. 备份配置:

    bash
    cp ~/.openclaw/openclaw.json5 ~/.openclaw/openclaw.json5.bak

配置键对照

iMessage 和 BlueBubbles 共享很多渠道级配置。变化的键主要是传输部分(REST 服务 vs 本地 CLI)。行为键(dmPolicygroupPolicyallowFrom 等)含义相同。

BlueBubbles内置 iMessage说明
channels.bluebubbles.enabledchannels.imessage.enabled语义相同。
channels.bluebubbles.serverUrl(已移除)无 REST 服务——插件直接通过 stdio 启动 imsg rpc
channels.bluebubbles.password(已移除)无需 webhook 认证。
(隐式)channels.imessage.cliPathimsg 的路径(默认 imsg);可设为用于 SSH 的包装脚本。
(隐式)channels.imessage.dbPath可选的 Messages.app chat.db 覆盖路径;省略时自动检测。
(隐式)channels.imessage.remoteHosthostuser@host——仅当 cliPath 是 SSH 包装脚本且需要 SCP 获取附件时设置。
channels.bluebubbles.dmPolicychannels.imessage.dmPolicy取值相同(pairing / allowlist / open / disabled)。
channels.bluebubbles.allowFromchannels.imessage.allowFrom配对审批按句柄(handle)继承,非 token。
channels.bluebubbles.groupPolicychannels.imessage.groupPolicy取值相同(allowlist / open / disabled)。
channels.bluebubbles.groupAllowFromchannels.imessage.groupAllowFrom相同。
channels.bluebubbles.groupschannels.imessage.groups原样复制,包括 groups: { "*": { ... } } 通配符条目。 每个群组的 requireMentiontoolstoolsBySender 都会保留。当 groupPolicy: "allowlist" 时,空的或缺失的 groups 块会静默丢弃所有群组消息——见下方“Group registry 踩坑”。
channels.bluebubbles.sendReadReceiptschannels.imessage.sendReadReceipts默认 true。使用内置插件时,仅当私有 API 探测成功时才会触发已读回执。
channels.bluebubbles.includeAttachmentschannels.imessage.includeAttachments形状相同,默认关闭。如果 BlueBubbles 中附件正常,则必须显式在 iMessage 块中再次设置——它不会自动继承。否则入站照片/媒体会被静默丢弃,不会产生 Inbound message 日志。
channels.bluebubbles.attachmentRootschannels.imessage.attachmentRoots本地根路径;通配符规则相同。
(N/A)channels.imessage.remoteAttachmentRoots仅当设置了 remoteHost 用于 SCP 拉取时使用。
channels.bluebubbles.mediaMaxMbchannels.imessage.mediaMaxMbiMessage 默认 16 MB(BlueBubbles 默认 8 MB)。如需保持较低上限,请显式设置。
channels.bluebubbles.textChunkLimitchannels.imessage.textChunkLimit两者默认均为 4000。
channels.bluebubbles.coalesceSameSenderDmschannels.imessage.coalesceSameSenderDms同样为可选开启。仅影响私信——群组聊天在两渠道均保持即时消息分发。启用后,在没有显式设置 messages.inbound.byChannel.imessage 的情况下,默认入站防抖宽限变为 2500 ms。参见 iMessage 文档 § 合并分割发送的私信
channels.bluebubbles.enrichGroupParticipantsFromContacts(N/A)iMessage 已从 chat.db 读取发送者显示名。
channels.bluebubbles.actions.*channels.imessage.actions.*每个动作开关:reactionseditunsendreplysendWithEffectrenameGroupsetGroupIconaddParticipantremoveParticipantleaveGroupsendAttachment

多账号配置(channels.bluebubbles.accounts.*)一对一迁移到 channels.imessage.accounts.*

Group registry 踩坑

内置 iMessage 插件会连续运行两个独立的群组允许列表检查。两者都必须通过,群组消息才能到达智能体:

  1. 发送者/聊天目标允许列表channels.imessage.groupAllowFrom)——由 isAllowedIMessageSender 检查。根据入站消息的发送者句柄、chat_guidchat_identifierchat_id 匹配。用法与 BlueBubbles 相同。
  2. Group registrychannels.imessage.groups)——由 inbound-processing.ts:199 中的 resolveChannelGroupPolicy 检查。当 groupPolicy: "allowlist" 时,此检查要求:
    • groups 中存在 "*": { ... } 通配符条目(设置 allowAll = true),
    • groups 中存在针对该 chat_id 的显式条目。

如果第一条通过但第二条失败,消息被丢弃。插件会发出两条 warn 级别的信号(默认日志级别即可看到,不再静默):

  • 启动时,每个账号一条一次性 warn,当 groupPolicy: "allowlist"channels.imessage.groups 为空(没有 "*" 通配符,也没有显式 chat_id 条目)时触发——在任何消息到达前就会打印。
  • 运行时,每个 chat_id 第一次被丢弃时触发一条一次性 warn,说明该 chat_id 以及应添加到 groups 中的键名。

私信不受影响,因为它们走不同的代码路径。

这是 BlueBubbles → 内置 iMessage 迁移最常见的故障模式:操作员复制了 groupAllowFromgroupPolicy,但跳过了 groups 块,因为 BlueBubbles 中的 groups: { "*": { "requireMention": true } } 看起来像不相关的提及设置。实际上它对 registry 检查至关重要。

groupPolicy: "allowlist" 下保持群组消息流动的最小配置:

json5
{
  channels: {
    imessage: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["+15555550123", "chat_guid:any;-;..."],
      groups: {
        "*": { requireMention: true },
      },
    },
  },
}

requireMention: true* 下是安全的,如果未配置提及模式:运行时会将 canDetectMention 设为 false,并在 inbound-processing.ts:512 处短路提及丢弃逻辑。如果配置了提及模式(agents.list[].groupChat.mentionPatterns),则正常工作。

如果网关日志中出现 imessage: dropping group message from chat_id=<id> 或启动行 imessage: groupPolicy="allowlist" but channels.imessage.groups is empty,说明第二条检查失败——请添加 groups 块。

逐步迁移

  1. 在现有 BlueBubbles 块旁边添加一个 iMessage 块,暂不启用:

    json5
    {
      channels: {
        bluebubbles: {
          enabled: true,
          // ... 现有配置 ...
        },
        imessage: {
          enabled: false,
          cliPath: "/opt/homebrew/bin/imsg",
          dmPolicy: "pairing",
          allowFrom: ["+15555550123"], // 从 bluebubbles.allowFrom 复制
          groupPolicy: "allowlist",
          groupAllowFrom: [], // 从 bluebubbles.groupAllowFrom 复制
          groups: { "*": { requireMention: true } }, // 从 bluebubbles.groups 复制——缺失则静默丢弃群组消息,见上方"Group registry 踩坑"
          actions: {
            reactions: true,
            edit: true,
            unsend: true,
            reply: true,
            sendWithEffect: true,
            sendAttachment: true,
          },
        },
      },
    }
  2. 在启用流量前探测——停止网关,临时启用 iMessage 块,从 CLI 确认 iMessage 状态正常:

    bash
    openclaw gateway stop
    # 编辑配置: channels.imessage.enabled = true
    openclaw channels status --probe --channel imessage   # 期望 imessage.privateApi.available: true

    channels status --probe 仅探测已配置且已启用的账号。如果不想立即切换,将 channels.imessage.enabled 设回 false 再重启网关。使用开始之前中的直接 imsg 命令在启用 OpenClaw 流量前验证 Mac 状态。

  3. 切换。 当启用的 iMessage 账号报告健康后,移除 BlueBubbles 配置并保持 iMessage 启用:

    json5
    {
      channels: {
        imessage: { enabled: true /* ... */ },
      },
    }

    重启网关。入站 iMessage 流量现在通过内置插件。

  4. 验证私信。 向智能体发送一条直接消息,确认回复正常。

  5. 单独验证群组。 私信和群组走不同代码路径——私信成功不代表群组路由正常。在一个已配对的群组中向智能体发送消息,确认回复正常。如果群组静默(无回复,无错误),检查网关日志中是否有 imessage: dropping group message from chat_id=<id> 或启动行 imessage: groupPolicy="allowlist" but channels.imessage.groups is empty——两者都会在默认日志级别输出。如果出现任一行,说明 groups 块缺失或为空——见上方"Group registry 踩坑"。

  6. 验证动作表面——从已配对的私信中,要求智能体执行:反应、编辑、取消发送、回复、发送照片,以及(在群组中)重命名群组/添加或移除成员。每个动作应在 Messages.app 中本地生效。如果某个动作报错 "iMessage <action> requires the imsg private API bridge",请重新运行 imsg launch 并刷新 channels status --probe

  7. 确认 iMessage 私信、群组和动作都正常后,删除 BlueBubbles 服务和配置。 OpenClaw 不再使用 channels.bluebubbles

动作功能对比

动作旧 BlueBubbles内置 iMessage
发送文本 / SMS 回退
发送媒体(照片、视频、文件、语音)
线程回复(reply_to_guid✅(解决了 #51892
Tapback(反应)
编辑 / 取消发送(macOS 13+ 接收者)
带屏幕效果发送✅(解决了 #9394 部分内容)
富文本加粗/斜体/下划线/删除线✅(通过 attributedBody 进行富文本格式化)
重命名群组 / 设置群组图标
添加/移除成员,离开群组
已读回执和输入指示✅(依赖私有 API 探测)
同发送者私信合并✅(仅私信;可选开启,通过 channels.imessage.coalesceSameSenderDms
网关离线期间入站消息追回✅(webhook 重放 + 历史拉取)✅(可选开启,通过 channels.imessage.catchup.enabled;解决了 #78649

iMessage 追回功能现已内置并可选启用。网关启动时,如果 channels.imessage.catchup.enabledtrue,网关会使用与 imsg watch 相同的 JSON-RPC 客户端执行一次 chats.list + 每个聊天的 messages.history,将每条未处理的入站记录通过实时分发路径(允许列表、群组策略、防抖器、echo 缓存)重新播放,并持久化每个账号的游标,以便后续启动继续。参见网关停机后追回进行调优。

配对、会话和 ACP 绑定

  • 配对审批按句柄继承。无需重新审批已知发送者——channels.imessage.allowFrom 能识别 BlueBubbles 使用的相同 +15555550123 / user@example.com 字符串。
  • 会话保持按智能体+聊天隔离。默认 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:、纯句柄)与 BlueBubbles 相同。

不可回滚

OpenClaw 已无 BlueBubbles 运行时支持。如果 iMessage 验证失败,将 channels.imessage.enabled 设为 false,重启网关,修复 imsg 问题后重试切换。

回复缓存位于 ~/.openclaw/state/imessage/reply-cache.jsonl(权限 0600,父目录 0700)。如需全新开始,可安全删除。

相关文档

常见问题

迁移后群组消息收不到怎么办?

最常见原因是 groups 配置块缺失或为空,而 groupPolicy: "allowlist"。检查网关日志是否有 imessage: dropping group message from chat_id=<id> 或启动行 imessage: groupPolicy="allowlist" but channels.imessage.groups is empty。解决方案:在 channels.imessage.groups 中添加 "*": { "requireMention": true } 通配符条目,或针对具体群组显式添加。

迁移后私信正常,但私密 API 动作(如编辑、反应)不生效

运行 imsg launch 并确认 imsg status --json 返回正常。然后通过 openclaw channels status --probe --channel imessage 检查 imessage.privateApi.available 是否为 true。如果为 false,需确保 SIP 已禁用,并且 imsg launch 已成功执行。

迁移后附件不显示了

在 BlueBubbles 中附件功能正常,但 iMessage 插件默认不包含附件。请在 channels.imessage 中显式设置 includeAttachments: true 并重启网关。如果通过 SSH 远程运行,还需正确配置 remoteHostremoteAttachmentRoots