Appearance
本页适用于已运行 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 配置,想走最短安全路径,请按此清单操作:
- 在运行 Messages.app 的 Mac 上直接验证
imsg(命令:imsg chats、imsg history、imsg send、imsg rpc --help)。 - 复制行为键:从
channels.bluebubbles复制到channels.imessage:dmPolicy、allowFrom、groupPolicy、groupAllowFrom、groups、includeAttachments、attachmentRoots、mediaMaxMb、textChunkLimit、coalesceSameSenderDms、actions。 - 删除不再存在的传输键:
serverUrl、password、webhook URL 以及 BlueBubbles 服务相关设置。 - 如果网关不在 Messages Mac 上运行,需设置
channels.imessage.cliPath为 SSH 包装脚本,并设置remoteHost用于远程附件拉取。 - 停止网关,启用
channels.imessage,然后运行openclaw channels status --probe --channel imessage。 - 测试一条私信、一个允许群组、附件(如果启用)以及智能体可能使用的每个私有 API 动作。
- 确认 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 launch将imsg助手注入 Messages.app,从而支持已读回执、输入指示、富发送、编辑、取消发送、线程回复、Tapback 和群组管理。 - Linux 版本可以检查复制的
chat.db,但无法发送、实时监听 Mac 数据库或驱动 Messages.app。OpenClaw iMessage 必须在已登录的 Mac 上运行imsg,或通过 SSH 包装脚本连接到该 Mac。
开始之前
在运行 Messages.app 的 Mac 上安装
imsg:bashbrew install steipete/tap/imsg imsg --version imsg chats --limit 3如果
imsg chats失败,报错unable to open database file、空输出或authorization denied,请授予终端、编辑器、Node 进程、网关服务或启动imsg的 SSH 父进程“完全磁盘访问权限”,然后重新打开该父进程。在修改 OpenClaw 配置前,验证读、监听、发送和 RPC 表面:
bashimsg 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 包装脚本或用户上下文执行这些命令。当需要高级动作时,启用私有 API 桥接:
bashimsg launch imsg status --jsonimsg launch需要禁用 SIP。基本发送、历史和监听无需imsg launch即可工作;高级动作则需要。添加已启用的
channels.imessage配置后,通过 OpenClaw 验证桥接:bashopenclaw channels status --probe期望输出
imessage.privateApi.available: true。如果为false,请先修复——参见能力检测。channels status --probe仅探测已配置且已启用的账号。备份配置:
bashcp ~/.openclaw/openclaw.json5 ~/.openclaw/openclaw.json5.bak
配置键对照
iMessage 和 BlueBubbles 共享很多渠道级配置。变化的键主要是传输部分(REST 服务 vs 本地 CLI)。行为键(dmPolicy、groupPolicy、allowFrom 等)含义相同。
| BlueBubbles | 内置 iMessage | 说明 |
|---|---|---|
channels.bluebubbles.enabled | channels.imessage.enabled | 语义相同。 |
channels.bluebubbles.serverUrl | (已移除) | 无 REST 服务——插件直接通过 stdio 启动 imsg rpc。 |
channels.bluebubbles.password | (已移除) | 无需 webhook 认证。 |
| (隐式) | channels.imessage.cliPath | imsg 的路径(默认 imsg);可设为用于 SSH 的包装脚本。 |
| (隐式) | channels.imessage.dbPath | 可选的 Messages.app chat.db 覆盖路径;省略时自动检测。 |
| (隐式) | channels.imessage.remoteHost | host 或 user@host——仅当 cliPath 是 SSH 包装脚本且需要 SCP 获取附件时设置。 |
channels.bluebubbles.dmPolicy | channels.imessage.dmPolicy | 取值相同(pairing / allowlist / open / disabled)。 |
channels.bluebubbles.allowFrom | channels.imessage.allowFrom | 配对审批按句柄(handle)继承,非 token。 |
channels.bluebubbles.groupPolicy | channels.imessage.groupPolicy | 取值相同(allowlist / open / disabled)。 |
channels.bluebubbles.groupAllowFrom | channels.imessage.groupAllowFrom | 相同。 |
channels.bluebubbles.groups | channels.imessage.groups | 原样复制,包括 groups: { "*": { ... } } 通配符条目。 每个群组的 requireMention、tools、toolsBySender 都会保留。当 groupPolicy: "allowlist" 时,空的或缺失的 groups 块会静默丢弃所有群组消息——见下方“Group registry 踩坑”。 |
channels.bluebubbles.sendReadReceipts | channels.imessage.sendReadReceipts | 默认 true。使用内置插件时,仅当私有 API 探测成功时才会触发已读回执。 |
channels.bluebubbles.includeAttachments | channels.imessage.includeAttachments | 形状相同,默认关闭。如果 BlueBubbles 中附件正常,则必须显式在 iMessage 块中再次设置——它不会自动继承。否则入站照片/媒体会被静默丢弃,不会产生 Inbound message 日志。 |
channels.bluebubbles.attachmentRoots | channels.imessage.attachmentRoots | 本地根路径;通配符规则相同。 |
| (N/A) | channels.imessage.remoteAttachmentRoots | 仅当设置了 remoteHost 用于 SCP 拉取时使用。 |
channels.bluebubbles.mediaMaxMb | channels.imessage.mediaMaxMb | iMessage 默认 16 MB(BlueBubbles 默认 8 MB)。如需保持较低上限,请显式设置。 |
channels.bluebubbles.textChunkLimit | channels.imessage.textChunkLimit | 两者默认均为 4000。 |
channels.bluebubbles.coalesceSameSenderDms | channels.imessage.coalesceSameSenderDms | 同样为可选开启。仅影响私信——群组聊天在两渠道均保持即时消息分发。启用后,在没有显式设置 messages.inbound.byChannel.imessage 的情况下,默认入站防抖宽限变为 2500 ms。参见 iMessage 文档 § 合并分割发送的私信。 |
channels.bluebubbles.enrichGroupParticipantsFromContacts | (N/A) | iMessage 已从 chat.db 读取发送者显示名。 |
channels.bluebubbles.actions.* | channels.imessage.actions.* | 每个动作开关:reactions、edit、unsend、reply、sendWithEffect、renameGroup、setGroupIcon、addParticipant、removeParticipant、leaveGroup、sendAttachment。 |
多账号配置(channels.bluebubbles.accounts.*)一对一迁移到 channels.imessage.accounts.*。
Group registry 踩坑
内置 iMessage 插件会连续运行两个独立的群组允许列表检查。两者都必须通过,群组消息才能到达智能体:
- 发送者/聊天目标允许列表(
channels.imessage.groupAllowFrom)——由isAllowedIMessageSender检查。根据入站消息的发送者句柄、chat_guid、chat_identifier或chat_id匹配。用法与 BlueBubbles 相同。 - Group registry(
channels.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 迁移最常见的故障模式:操作员复制了 groupAllowFrom 和 groupPolicy,但跳过了 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 块。
逐步迁移
在现有 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, }, }, }, }在启用流量前探测——停止网关,临时启用 iMessage 块,从 CLI 确认 iMessage 状态正常:
bashopenclaw gateway stop # 编辑配置: channels.imessage.enabled = true openclaw channels status --probe --channel imessage # 期望 imessage.privateApi.available: truechannels status --probe仅探测已配置且已启用的账号。如果不想立即切换,将channels.imessage.enabled设回false再重启网关。使用开始之前中的直接imsg命令在启用 OpenClaw 流量前验证 Mac 状态。切换。 当启用的 iMessage 账号报告健康后,移除 BlueBubbles 配置并保持 iMessage 启用:
json5{ channels: { imessage: { enabled: true /* ... */ }, }, }重启网关。入站 iMessage 流量现在通过内置插件。
验证私信。 向智能体发送一条直接消息,确认回复正常。
单独验证群组。 私信和群组走不同代码路径——私信成功不代表群组路由正常。在一个已配对的群组中向智能体发送消息,确认回复正常。如果群组静默(无回复,无错误),检查网关日志中是否有
imessage: dropping group message from chat_id=<id>或启动行imessage: groupPolicy="allowlist" but channels.imessage.groups is empty——两者都会在默认日志级别输出。如果出现任一行,说明groups块缺失或为空——见上方"Group registry 踩坑"。验证动作表面——从已配对的私信中,要求智能体执行:反应、编辑、取消发送、回复、发送照片,以及(在群组中)重命名群组/添加或移除成员。每个动作应在 Messages.app 中本地生效。如果某个动作报错 "iMessage
<action>requires the imsg private API bridge",请重新运行imsg launch并刷新channels status --probe。确认 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.enabled 为 true,网关会使用与 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)。如需全新开始,可安全删除。
相关文档
- BlueBubbles 移除与 imsg iMessage 路径 —— 简短公告及操作摘要。
- iMessage 渠道 —— 完整 iMessage 渠道参考,包括
imsg launch设置和能力检测。 /channels/bluebubbles—— 旧 URL 会重定向到此迁移指南。- 配对 —— 私信认证和配对流程。
- 渠道路由 —— 网关如何选择出站回复的渠道。
常见问题
迁移后群组消息收不到怎么办?
最常见原因是 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 远程运行,还需正确配置 remoteHost 和 remoteAttachmentRoots。