人不在電腦前,但 Claude Code session 正在跑。手機震了一下——不是 LINE,不是 Slack,是 iMessage。你直接在訊息 App 裡打「幫我跑一下測試」,幾秒後 Claude 回你結果。整個過程你連筆電都沒打開。

上次介紹了 Channels 的整體架構,Telegram、Discord、iMessage 三個平台都帶過一輪。但 iMessage 這條路線有太多眉角沒講到——self-chat 的 echo 迴圈、is_from_me 的詭異行為、號碼格式踩坑。這篇專門把 iMessage Channel 從頭到尾拆開來講,包括那些官方文件沒寫清楚的 troubleshooting。


前置需求——四個條件缺一不可

開始之前先確認:

macOS 電腦。iMessage Channel 的原理是直接讀你 Mac 上的 ~/Library/Messages/chat.db,這是 macOS 獨有的 SQLite 資料庫。Windows 和 Linux 沒有這個東西,所以 iMessage Channel 是 macOS 限定。

Claude Code CLI 已安裝。這個不用多說。

iMessage 已登入 Apple ID。確認你的「訊息」App 可以正常收發 iMessage(藍色泡泡,不是綠色的 SMS)。

終端機有完整磁碟取用權限。這是最容易漏掉的一步。不管你用 Terminal、iTerm2、Warp 還是什麼終端機,都要去 系統設定 → 隱私權與安全性 → 完整磁碟取用權限 把它打開。沒開的話 Claude 讀不到 chat.db,什麼事都不會發生。


啟動 iMessage Channel

一行指令:

1
claude --channels 'plugin:imessage@claude-plugins-official' --dangerously-skip-permissions

拆開來看:

參數 做什麼
--channels 指定要啟用的 Channel 外掛
plugin:imessage@claude-plugins-official 官方 iMessage Channel 外掛
--dangerously-skip-permissions 跳過工具權限確認

最後那個 --dangerously-skip-permissions 是關鍵。沒加的話,Claude 每次要回覆 iMessage 都會在終端機跳出確認提示——你人都不在電腦前了,誰來按 yes?加了這個 flag,Claude 才能自動回覆。

名字裡有 “dangerously” 不是嚇你。它的意思是 Claude 在這個 session 裡面可以不經你同意就執行 Bash、Write、Edit。如果你不放心,**不要只靠 CLAUDE.md——它是自然語言指示,Claude 不保證每次遵守。真正能做確定性限制的是 Hooks**。在 .claude/settings.json 設定 PreToolUse hook,就能在工具執行前攔截、允許或拒絕特定操作——是 shell 層級的硬限制,不管 Claude 怎麼想,該擋就擋。想知道怎麼在 bypass 模式下做雙層防護,可以看 Bypass 模式安全防護


存取控制——誰能跟 Claude 說話

啟動之後,Claude 會在 ~/.claude/channels/imessage/access.json 建立一份存取控制設定。預設是空的,誰都進不來。

查看目前狀態

1
/imessage:access

加人

1
/imessage:access allow +886912345678

號碼格式是最常踩的坑。必須用國際格式,不能有橫線或空格+886912345678 是對的,+886-912-345-678 會讓比對直接失敗。不確定的話,跑這段看你的 chat.db 裡面號碼長什麼樣:

1
sqlite3 ~/Library/Messages/chat.db "SELECT DISTINCT chat_identifier FROM chat LIMIT 10;"

access.json 裡的格式要跟查詢結果一模一樣。

移除

1
/imessage:access remove +886912345678

DM 政策模式

模式 說明 什麼時候用
allowlist 只有白名單上的號碼能跟 Claude 對話 推薦,最安全
pairing 任何人傳訊息會收到配對碼,你在終端機確認後才加入 不知道對方號碼的時候
disabled 關閉 DM 功能 暫時不想收

切換:

1
/imessage:access policy allowlist

一個重要的安全設計:存取控制只能在終端機操作。沒有人可以透過 iMessage 傳訊息來修改你的設定。這不是 bug,是防 prompt injection 的設計。


測試——傳訊息給自己

最快的測試方式:打開 iPhone 的「訊息」App,傳一則 iMessage 給你自己的 Apple ID。如果一切正常,Claude 會在幾秒內回覆,訊息結尾帶「Sent by Claude」標記。

聽起來很簡單對吧?然後你就會遇到問題了。


Troubleshooting——那些官方文件沒講清楚的事

傳了訊息但 Claude 沒反應

先排除最基本的:終端機的完整磁碟取用權限有沒有開?access.json 裡有沒有你的號碼?格式對不對?

如果以上都確認了,問題可能出在 is_from_me。Self-chat(自己傳給自己)的訊息,macOS 有時候會標記成 is_from_me=1。iMessage Channel 的套件預設會過濾掉所有 is_from_me=1 的訊息——因為正常情況下,「自己發的」不應該觸發回覆。

但 self-chat 是特例。你傳給自己的訊息到底算「自己發的」還是「收到的」?Apple 的路由邏輯會根據裝置、網路狀態、iMessage 同步方式給出不同答案。同一則訊息有時候 is_from_me=0(能被收到),有時候只有 is_from_me=1(被過濾掉)。

解法是改 server.ts,讓 self-chat 的 is_from_me=1 訊息也能通過,但要搭配 echo 去重機制,避免 Claude 自己的回覆又被當成新訊息。

Claude 的回覆又被收到一次(Echo 迴圈)

Self-chat 的經典問題。Claude 送出回覆 → 回覆出現在 chat.db 裡 → 套件把它當成新訊息 → Claude 又回覆 → 無限迴圈。

套件有內建的 echo 去重機制,但它需要知道「你是誰」。它從 chat.dbmessage.account 欄位建立一個 SELF 集合,問題是這個欄位通常只存 Apple ID(email),不存電話號碼。所以你用電話號碼傳訊息的時候,套件不認為那是「自己」,echo 過濾就失效了。

解法:在 server.ts 裡面補一段邏輯,從 handle 表偵測 self-chat 的電話號碼。判斷標準是——一個 handle 如果同時有 is_from_me=1is_from_me=0 的訊息,而且對應的 chat.chat_identifier 等於 handle ID 本身,那它就是 self-chat handle,應該加進 SELF 集合。

同一則訊息出現兩次(跨 chat_guid 重複)

這個更隱晦。Self-chat 的訊息可能同時出現在兩個對話裡——一個是電話號碼的對話,一個是 Apple ID 的對話。兩筆 chat_guid 不同,但內容一模一樣。

需要在 handleInbound 裡面加跨 chat_guid 的去重,用訊息內容和時間戳做 key,只接受第一筆。


講點實際的——self-chat 只是測試用

上面的 troubleshooting 看起來很複雜,但有一個好消息:這些問題幾乎都是 self-chat 獨有的

正式使用場景是別人透過 iMessage 傳訊息給你,或者你從 iPhone 傳給你 Mac 上的 Claude。在這種情況下,is_from_me 永遠是 0,echo 問題不存在,一切正常運作。

Self-chat 主要是拿來測試設定有沒有通,確認完之後用正常的使用方式就好。


指令速查表

操作 指令
啟動頻道 claude --channels 'plugin:imessage@claude-plugins-official' --dangerously-skip-permissions
查看存取狀態 /imessage:access
加入號碼 /imessage:access allow +886912345678
移除號碼 /imessage:access remove +886912345678
切換政策 /imessage:access policy allowlist
配對確認 /imessage:access pair <配對碼>
查看頻道設定 /imessage:configure

你可以拿它來幹嘛

設定完成後,你在 iMessage 裡面打的每一句話都會進到 Claude Code 的 session。Claude 能做的事,你都能用 iMessage 觸發:

問程式碼問題——「這個 function 是做什麼的?」Claude 會去讀你 session 裡的檔案然後回答。

查專案狀態——「Jira 上還有什麼沒做的?」如果你的 session 有接 Jira MCP,Claude 會直接去查。

下指令——「幫我跑測試」「deploy 到 staging」。搭配 --dangerously-skip-permissions,Claude 可以直接執行。

重點是 Claude 帶著整個 session 的 context 在回你,不是一個空白的聊天機器人。你早上在終端機裡面做的事,下午在手機上問它,它都記得。


iMessage Channel 的核心價值是把 Claude Code 從「必須坐在電腦前用」變成「隨時隨地用」。Session 開著就行,iPhone 就是你的遙控器。上次的 Channels 總覽 講了 Telegram 和 Discord 的設定,但如果你本來就在 Apple 生態系裡——Mac + iPhone,iMessage 是阻力最小的選項。不用建 Bot、不用 token、不用額外裝 App,你已經有的東西就夠了。

原文來源:Push events into a running session with channels - Claude Code Docs
原文來源:Channels reference - Claude Code Docs
參考來源:Claude Code in Action - Anthropic Academy