Mainstream messaging
مهاجرت از BlueBubbles
افزونهٔ همراه imessage اکنون با هدایت steipete/imsg از طریق JSON-RPC به همان سطح API خصوصی BlueBubbles (react، edit، unsend، reply، sendWithEffect، مدیریت گروه، پیوستها) دسترسی دارد. اگر از قبل یک Mac با imsg نصبشده اجرا میکنید، میتوانید سرور BlueBubbles را کنار بگذارید و بگذارید افزونه مستقیماً با Messages.app صحبت کند.
پشتیبانی از BlueBubbles حذف شده است. OpenClaw از iMessage فقط از طریق imsg پشتیبانی میکند. این راهنما برای مهاجرت پیکربندیهای قدیمی channels.bluebubbles به channels.imessage است؛ هیچ مسیر مهاجرت پشتیبانیشدهٔ دیگری وجود ندارد.
چکلیست مهاجرت
وقتی پیکربندی قدیمی BlueBubbles خود را از قبل میشناسید و کوتاهترین مسیر امن را میخواهید، از این چکلیست استفاده کنید:
imsgرا مستقیماً روی همان Mac که Messages.app را اجرا میکند تأیید کنید (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، URLهای وبهوک و راهاندازی سرور BlueBubbles. - اگر Gateway روی Mac مربوط به Messages اجرا نمیشود،
channels.imessage.cliPathرا روی یک wrapper مربوط به SSH تنظیم کنید و برای دریافت پیوستهای راهدور،remoteHostرا تنظیم کنید. - در حالی که Gateway متوقف است،
channels.imessageرا فعال کنید، سپسopenclaw channels status --probe --channel imessageرا اجرا کنید. - یک DM، یک گروه مجاز، پیوستها در صورت فعال بودن، و هر اقدام API خصوصیای را که انتظار دارید عامل استفاده کند آزمایش کنید.
- پس از تأیید مسیر iMessage، سرور BlueBubbles و پیکربندی قدیمی
channels.bluebubblesرا حذف کنید.
چه زمانی این مهاجرت منطقی است
- شما از قبل
imsgرا روی همان Mac (یا Macی که از طریق SSH در دسترس است) اجرا میکنید که Messages.app در آن وارد حساب شده است. - یک جزء متحرک کمتر میخواهید — بدون سرور جداگانهٔ BlueBubbles، بدون endpoint مربوط به REST برای احراز هویت، بدون لولهکشی وبهوک. یک باینری CLI واحد بهجای سرور + برنامهٔ کلاینت + ابزار کمکی.
- روی یک macOS / ساخت
imsgپشتیبانیشده هستید که probe مربوط به API خصوصی مقدارavailable: trueرا گزارش میکند.
imsg چه میکند
imsg یک CLI محلی macOS برای Messages است. OpenClaw، imsg rpc را بهعنوان فرایند فرزند شروع میکند و از طریق stdin/stdout با JSON-RPC صحبت میکند. هیچ سرور HTTP، URL وبهوک، daemon پسزمینه، launch agent یا پورتی برای در معرض قرار دادن وجود ندارد.
- خواندنها از
~/Library/Messages/chat.dbبا استفاده از یک handle فقطخواندنی SQLite انجام میشوند. - پیامهای ورودی زنده از
imsg watch/watch.subscribeمیآیند، که رویدادهای فایلسیستمchat.dbرا با fallback مبتنی بر polling دنبال میکند. - ارسالها برای متن عادی و ارسال فایل از خودکارسازی Messages.app استفاده میکنند.
- اقدامات پیشرفته از
imsg launchبرای تزریق ابزار کمکیimsgبه Messages.app استفاده میکنند. همین مورد رسید خواندن، نشانگرهای تایپ، ارسالهای غنی، ویرایش، لغو ارسال، پاسخ رشتهای، tapbackها و مدیریت گروه را فعال میکند. - ساختهای Linux میتوانند یک
chat.dbکپیشده را بررسی کنند، اما نمیتوانند ارسال کنند، پایگاهدادهٔ زندهٔ Mac را watch کنند، یا Messages.app را هدایت کنند. برای OpenClaw iMessage،imsgرا روی Mac واردشده اجرا کنید یا از طریق یک wrapper مربوط به SSH به آن Mac وصل شوید.
پیش از شروع
-
imsgرا روی Macی نصب کنید که Messages.app را اجرا میکند:bash brew install steipete/tap/imsgimsg --versionimsg chats --limit 3اگر
imsg chatsباunable to open database file، خروجی خالی، یاauthorization deniedشکست خورد، دسترسی کامل به دیسک را به ترمینال، ویرایشگر، فرایند Node، سرویس Gateway، یا فرایند والد SSH کهimsgرا اجرا میکند بدهید، سپس آن فرایند والد را دوباره باز کنید. -
پیش از تغییر پیکربندی OpenClaw، سطوح خواندن، watch، ارسال و RPC را تأیید کنید:
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 --help42را با یک شناسهٔ چت واقعی ازimsg chatsجایگزین کنید. ارسال به مجوز Automation برای Messages.app نیاز دارد. اگر OpenClaw از طریق SSH اجرا خواهد شد، این فرمانها را از همان wrapper مربوط به SSH یا زمینهٔ کاربریای اجرا کنید که OpenClaw استفاده خواهد کرد. اگر خواندنها/probeها کار میکنند اما ارسالها با AppleEvents-1743شکست میخورند، بررسی کنید آیا Automation روی/usr/libexec/sshd-keygen-wrapperثبت شده است یا نه؛ ارسالهای wrapper مربوط به SSH با AppleEvents -1743 شکست میخورند را ببینید. -
وقتی به اقدامات پیشرفته نیاز دارید، پل API خصوصی را فعال کنید:
bash imsg launchimsg status --jsonimsg launchنیاز دارد SIP غیرفعال باشد. ارسال پایه، تاریخچه و watch بدونimsg launchکار میکنند؛ اقدامات پیشرفته کار نمیکنند. -
پس از افزودن یک پیکربندی فعال
channels.imessage، پل را از طریق OpenClaw تأیید کنید:bash openclaw channels status --probeمقدار مطلوب شما
imessage.privateApi.available: trueاست. اگرfalseگزارش شد، ابتدا همان را اصلاح کنید — تشخیص قابلیت را ببینید.channels status --probeفقط حسابهای پیکربندیشده و فعال را probe میکند. -
از پیکربندی خود snapshot بگیرید:
bash cp ~/.openclaw/openclaw.json5 ~/.openclaw/openclaw.json5.bak
ترجمهٔ پیکربندی
iMessage و BlueBubbles مقدار زیادی از پیکربندی سطح کانال را به اشتراک میگذارند. کلیدهایی که تغییر میکنند عمدتاً مربوط به انتقال هستند (سرور REST در برابر CLI محلی). کلیدهای رفتاری (dmPolicy، groupPolicy، allowFrom و غیره) همان معنا را حفظ میکنند.
| BlueBubbles | iMessage همراه | یادداشتها |
|---|---|---|
channels.bluebubbles.enabled |
channels.imessage.enabled |
همان معناشناسی. |
channels.bluebubbles.serverUrl |
(حذفشده) | سرور REST وجود ندارد — این Plugin، imsg rpc را از طریق stdio اجرا میکند. |
channels.bluebubbles.password |
(حذفشده) | احراز هویت Webhook لازم نیست. |
| (ضمنی) | channels.imessage.cliPath |
مسیر imsg (پیشفرض imsg)؛ برای SSH از یک اسکریپت wrapper استفاده کنید. |
| (ضمنی) | channels.imessage.dbPath |
بازنویسی اختیاری chat.db مربوط به Messages.app؛ وقتی حذف شود، بهصورت خودکار شناسایی میشود. |
| (ضمنی) | channels.imessage.remoteHost |
host یا user@host — فقط وقتی لازم است که cliPath یک wrapper برای 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 |
این را عیناً کپی کنید، از جمله هر ورودی wildcard به شکل groups: { "*": { ... } }. موارد requireMention، tools و toolsBySender برای هر گروه منتقل میشوند. با groupPolicy: "allowlist"، یک بلوک groups خالی یا حذفشده همه پیامهای گروه را بیسروصدا حذف میکند — پایینتر «دام رجیستری گروه» را ببینید. |
channels.bluebubbles.sendReadReceipts |
channels.imessage.sendReadReceipts |
پیشفرض true. با Plugin همراه، این فقط وقتی فعال میشود که probe مربوط به API خصوصی بالا باشد. |
channels.bluebubbles.includeAttachments |
channels.imessage.includeAttachments |
همان شکل، همان حالت پیشفرض خاموش. اگر پیوستها در BlueBubbles برای شما جریان داشتند، باید این را صراحتاً در بلوک iMessage دوباره تنظیم کنید — این مورد بهصورت ضمنی منتقل نمیشود و عکسها/رسانههای ورودی تا زمانی که این کار را انجام ندهید، بیسروصدا و بدون خط لاگ Inbound message حذف خواهند شد. |
channels.bluebubbles.attachmentRoots |
channels.imessage.attachmentRoots |
ریشههای محلی؛ همان قواعد wildcard. |
| (ناموجود) | 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 |
همان حالت opt-in. فقط برای DM — چتهای گروهی در هر دو کانال ارسال فوری برای هر پیام را حفظ میکنند. وقتی بدون messages.inbound.byChannel.imessage صریح یا messages.inbound.debounceMs سراسری فعال شود، debounce ورودی پیشفرض را به 7000 ms افزایش میدهد. مستندات iMessage § ادغام DMهای split-send را ببینید. |
channels.bluebubbles.enrichGroupParticipantsFromContacts |
(ناموجود) | iMessage از قبل نامهای نمایشی فرستنده را از chat.db میخواند. |
channels.bluebubbles.actions.* |
channels.imessage.actions.* |
toggleهای هر action: reactions، edit، unsend، reply، sendWithEffect، renameGroup، setGroupIcon، addParticipant، removeParticipant، leaveGroup، sendAttachment. |
پیکربندیهای چندحسابی (channels.bluebubbles.accounts.*) بهصورت یکبهیک به channels.imessage.accounts.* ترجمه میشوند.
دام رجیستری گروه
Plugin همراه iMessage دو دروازه allowlist گروه جداگانه را پشتسرهم اجرا میکند. برای اینکه پیام گروه به عامل برسد، هر دو باید عبور کنند:
- allowlist فرستنده / هدف چت (
channels.imessage.groupAllowFrom) — توسطisAllowedIMessageSenderبررسی میشود. پیامهای ورودی را بر اساس handle فرستنده،chat_guid،chat_identifierیاchat_idتطبیق میدهد. همان شکل BlueBubbles. - رجیستری گروه (
channels.imessage.groups) — توسطresolveChannelGroupPolicyازinbound-processing.ts:199بررسی میشود. باgroupPolicy: "allowlist"، این دروازه یکی از این موارد را لازم دارد:- یک ورودی wildcard به شکل
groups: { "*": { ... } }(کهallowAll = trueرا تنظیم میکند)، یا - یک ورودی صریح برای هر
chat_idزیرgroups.
- یک ورودی wildcard به شکل
اگر دروازه 1 عبور کند اما دروازه 2 شکست بخورد، پیام حذف میشود. Plugin دو سیگنال سطح warn منتشر میکند تا این وضعیت دیگر در سطح لاگ پیشفرض بیصدا نباشد:
- یک
warnیکباره در زمان راهاندازی برای هر حساب، وقتیgroupPolicy: "allowlist"تنظیم شده اماchannels.imessage.groupsخالی است (بدون wildcard"*"و بدون ورودیهای هرchat_id) — پیش از رسیدن هر پیام اجرا میشود. - یک
warnیکباره برای هرchat_id، اولین باری که یک گروه مشخص در زمان اجرا حذف میشود، که chat_id و کلید دقیق لازم برای افزودن بهgroupsجهت اجازه دادن به آن را نام میبرد.
DMها همچنان کار میکنند، چون از یک مسیر کد متفاوت عبور میکنند.
این رایجترین حالت شکست مهاجرت BlueBubbles → iMessage همراه است: اپراتورها groupAllowFrom و groupPolicy را کپی میکنند اما بلوک groups را جا میاندازند، چون groups: { "*": { "requireMention": true } } در BlueBubbles شبیه یک تنظیم نامرتبط برای منشن به نظر میرسد. در واقع این بخش برای گیت رجیستری حیاتی است.
حداقل پیکربندی برای ادامه یافتن جریان پیامهای گروهی پس از groupPolicy: "allowlist":
{ channels: { imessage: { groupPolicy: "allowlist", groupAllowFrom: ["+15555550123", "chat_guid:any;-;..."], groups: { "*": { requireMention: true }, }, }, },}requireMention: true زیر * وقتی هیچ الگوی منشنی پیکربندی نشده باشد بیضرر است: runtime مقدار canDetectMention = false را تنظیم میکند و حذف منشن را در inbound-processing.ts:512 کوتاهمسیر میکند. با الگوهای منشن پیکربندیشده (agents.list[].groupChat.mentionPatterns)، طبق انتظار کار میکند.
اگر لاگهای gateway پیام imessage: dropping group message from chat_id=<id> یا خط راهاندازی imessage: groupPolicy="allowlist" but channels.imessage.groups is empty را نشان دهند، گیت ۲ در حال حذف است — بلوک groups را اضافه کنید.
گامبهگام
-
یک بلوک iMessage را کنار بلوک موجود BlueBubbles اضافه کنید. تا وقتی Gateway هنوز ترافیک BlueBubbles را مسیریابی میکند، آن را غیرفعال نگه دارید:
json5 { channels: { bluebubbles: { enabled: true, // ... existing config ... }, imessage: { enabled: false, cliPath: "/opt/homebrew/bin/imsg", dmPolicy: "pairing", allowFrom: ["+15555550123"], // copy from bluebubbles.allowFrom groupPolicy: "allowlist", groupAllowFrom: [], // copy from bluebubbles.groupAllowFrom groups: { "*": { requireMention: true } }, // copy from bluebubbles.groups — silently drops groups if missing, see "Group registry footgun" above actions: { reactions: true, edit: true, unsend: true, reply: true, sendWithEffect: true, sendAttachment: true, }, }, },} -
قبل از مهم شدن ترافیک، Probe کنید — Gateway را متوقف کنید، بلوک iMessage را موقتاً فعال کنید، و از CLI تأیید کنید که iMessage سالم گزارش میشود:
bash openclaw gateway stop# edit config: channels.imessage.enabled = trueopenclaw channels status --probe --channel imessage # expect imessage.privateApi.available: truechannels status --probeفقط حسابهای پیکربندیشده و فعال را Probe میکند. Gateway را در حالی که هم BlueBubbles و هم iMessage فعالاند دوباره راهاندازی نکنید، مگر اینکه عمداً بخواهید هر دو مانیتور کانال اجرا شوند. اگر فوراً در حال cut over نیستید، پیش از راهاندازی دوباره Gateway مقدارchannels.imessage.enabledرا بهfalseبرگردانید. برای اعتبارسنجی Mac پیش از فعال کردن ترافیک OpenClaw، از فرمانهای مستقیمimsgدر پیش از شروع استفاده کنید. -
Cut over کنید. وقتی حساب فعال iMessage سالم گزارش شد، پیکربندی BlueBubbles را حذف کنید و iMessage را فعال نگه دارید:
json5 { channels: { imessage: { enabled: true /* ... */ }, },}gateway را دوباره راهاندازی کنید. ترافیک ورودی iMessage اکنون از Plugin همراه عبور میکند.
-
DMها را تأیید کنید. یک پیام مستقیم به agent بفرستید؛ تأیید کنید پاسخ میرسد.
-
گروهها را جداگانه تأیید کنید. DMها و گروهها از مسیرهای کد متفاوتی عبور میکنند — موفقیت DM ثابت نمیکند گروهها مسیریابی میشوند. در یک چت گروهی pairشده، پیامی به agent بفرستید و تأیید کنید پاسخ میرسد. اگر گروه ساکت شد (نه پاسخی از agent، نه خطا)، لاگ gateway را برای
imessage: dropping group message from chat_id=<id>یا خط راهاندازیimessage: groupPolicy="allowlist" but channels.imessage.groups is emptyبررسی کنید — هر دو در سطح لاگ پیشفرض فعال میشوند. اگر هرکدام ظاهر شد، بلوکgroupsشما وجود ندارد یا خالی است — «دام رجیستری گروه» بالا را ببینید. -
سطح action را تأیید کنید — از یک DM pairشده، از agent بخواهید واکنش نشان دهد، ویرایش کند، ارسال را لغو کند، پاسخ دهد، عکس بفرستد، و (در یک گروه) نام گروه را تغییر دهد / مشارکتکنندهای را اضافه یا حذف کند. هر action باید بهصورت بومی در Messages.app اعمال شود. اگر هرکدام خطای "iMessage
<action>requires the imsg private API bridge" داد، دوبارهimsg launchرا اجرا کنید وchannels status --probeرا تازهسازی کنید. -
پس از تأیید DMها، گروهها، و actionهای iMessage، سرور و پیکربندی BlueBubbles را حذف کنید. OpenClaw از
channels.bluebubblesاستفاده نخواهد کرد.
برابری actionها در یک نگاه
| Action | BlueBubbles قدیمی | iMessage همراه |
|---|---|---|
| ارسال متن / fallback به SMS | ✅ | ✅ |
| ارسال رسانه (عکس، ویدیو، فایل، صدا) | ✅ | ✅ |
پاسخ رشتهای (reply_to_guid) |
✅ | ✅ (#51892 را میبندد) |
Tapback (react) |
✅ | ✅ |
| ویرایش / لغو ارسال (گیرندگان macOS 13+) | ✅ | ✅ |
| ارسال با جلوه صفحه | ✅ | ✅ (بخشی از #9394 را میبندد) |
| متن غنی پررنگ / مورب / زیرخطدار / خطخورده | ✅ | ✅ (قالببندی typed-run از طریق attributedBody) |
| تغییر نام گروه / تنظیم آیکن گروه | ✅ | ✅ |
| افزودن / حذف مشارکتکننده، ترک گروه | ✅ | ✅ |
| رسید خواندهشدن و نشانگر تایپ | ✅ | ✅ (وابسته به private API probe) |
| ادغام DMهای فرستنده یکسان | ✅ | ✅ (فقط DM؛ opt-in از طریق channels.imessage.coalesceSameSenderDms) |
| بازیابی ورودی پس از راهاندازی مجدد | ✅ (بازپخش Webhook + دریافت تاریخچه) | ✅ (خودکار: بازپخش موارد ازدسترفته از طریق since_rowid + dedupe؛ پنجره گستردهتر روی local) |
iMessage پیامهایی را که هنگام خاموش بودن gateway از دست رفتهاند بازیابی میکند: هنگام راهاندازی، از آخرین rowid ارسالشده از طریق imsg watch.subscribe و since_rowid بازپخش میکند و بر اساس GUID dedupe انجام میدهد، در حالی که یک حصار سنی برای backlog کهنه از «انفجار backlog» ناشی از Push-flush جلوگیری میکند. این کار روی اتصال RPC مربوط به imsg اجرا میشود، بنابراین برای setupهای SSH راهدور cliPath هم کار میکند؛ setupهای local پنجره بازیابی گستردهتری دارند چون میتوانند chat.db را بخوانند. بازیابی ورودی پس از راهاندازی مجدد bridge یا gateway را ببینید.
Pairing، نشستها، و bindingهای ACP
- تأییدهای Pairing بر اساس handle منتقل میشوند. نیازی نیست فرستندگان شناختهشده را دوباره تأیید کنید —
channels.imessage.allowFromهمان رشتههای+15555550123/user@example.comرا که BlueBubbles استفاده میکرد میشناسد. - نشستها برای هر agent + چت محدود میمانند. DMها با مقدار پیشفرض
session.dmScope=mainدر نشست اصلی agent ادغام میشوند؛ نشستهای گروهی برای هرchat_idجدا میمانند. کلیدهای نشست متفاوتاند (agent:<id>:imessage:group:<chat_id>در برابر معادل BlueBubbles) — تاریخچه مکالمه قدیمی زیر کلیدهای نشست BlueBubbles به نشستهای iMessage منتقل نمیشود. - bindingهای ACP که به
match.channel: "bluebubbles"اشاره میکنند باید به"imessage"بهروزرسانی شوند. شکلهایmatch.peer.id(chat_id:،chat_guid:،chat_identifier:، handle خام) یکساناند.
بدون کانال rollback
هیچ runtime پشتیبانیشدهای برای BlueBubbles وجود ندارد که بتوانید به آن برگردید. اگر تأیید iMessage شکست خورد، مقدار channels.imessage.enabled: false را تنظیم کنید، Gateway را دوباره راهاندازی کنید، مانع imsg را برطرف کنید، و cutover را دوباره امتحان کنید.
کش پاسخ در وضعیت SQLite Plugin زندگی میکند. openclaw doctor --fix در صورت وجود، sidecar قدیمی imessage/reply-cache.jsonl را import و archive میکند.
مرتبط
- حذف BlueBubbles و مسیر imsg iMessage — اعلامیه کوتاه و خلاصه اپراتور.
- iMessage — مرجع کامل کانال iMessage، شامل setup با
imsg launchو تشخیص قابلیت. /channels/bluebubbles— URL قدیمی که به این راهنمای مهاجرت redirect میشود.- Pairing — احراز هویت DM و جریان pairing.
- مسیریابی کانال — اینکه gateway چگونه یک کانال را برای پاسخهای خروجی انتخاب میکند.