BlueBubbles (macOS REST)
상태: 번들 플러그인으로, BlueBubbles macOS 서버와 HTTP로 통신합니다. 레거시 imsg 채널보다 풍부한 API와 간편한 설정 덕분에 iMessage 연동에 권장됩니다.
개요
- BlueBubbles 헬퍼 앱(bluebubbles.app)을 통해 macOS에서 실행됩니다.
- 권장/테스트 환경: macOS Sequoia (15). macOS Tahoe (26)에서도 작동하지만, Tahoe에서는 편집 기능이 현재 작동하지 않으며 그룹 아이콘 업데이트가 성공으로 표시되더라도 동기화되지 않을 수 있습니다.
- OpenClaw는 REST API(
GET /api/v1/ping,POST /message/text,POST /chat/:id/*)를 통해 통신합니다. - 수신 메시지는 웹훅으로 도착하고, 발신 응답, 타이핑 표시기, 읽음 확인, 탭백은 REST 호출입니다.
- 첨부 파일과 스티커는 인바운드 미디어로 수집되며 가능한 경우 에이전트에 표시됩니다.
- 페어링/허용 목록은 다른 채널과 동일하게 작동합니다(
/channels/pairing등).channels.bluebubbles.allowFrom+ 페어링 코드를 사용합니다. - 리액션은 Slack/Telegram과 마찬가지로 시스템 이벤트로 표시되어 에이전트가 응답 전에 “멘션”할 수 있습니다.
- 고급 기능: 편집, 전송 취소, 답장 스레딩, 메시지 이펙트, 그룹 관리.
빠른 시작
-
Mac에 BlueBubbles 서버를 설치합니다(bluebubbles.app/install의 안내를 따르세요).
-
BlueBubbles 설정에서 웹 API를 활성화하고 비밀번호를 설정합니다.
-
openclaw onboard를 실행하고 BlueBubbles를 선택하거나, 수동으로 설정합니다:{ channels: { bluebubbles: { enabled: true, serverUrl: "http://192.168.1.100:1234", password: "example-password", webhookPath: "/bluebubbles-webhook", }, }, } -
BlueBubbles 웹훅을 게이트웨이로 연결합니다(예:
https://your-gateway-host:3000/bluebubbles-webhook?password=<password>). -
게이트웨이를 시작하면 웹훅 핸들러가 등록되고 페어링이 시작됩니다.
보안 참고:
- 항상 웹훅 비밀번호를 설정하세요.
- 웹훅 인증은 항상 필수입니다. OpenClaw는 루프백/프록시 토폴로지와 관계없이,
channels.bluebubbles.password와 일치하는 비밀번호/guid가 포함되지 않은 BlueBubbles 웹훅 요청을 거부합니다(예:?password=<password>또는x-password). - 비밀번호 인증은 전체 웹훅 본문을 읽기/파싱하기 전에 확인됩니다.
Messages.app 활성 유지 (VM / 헤드리스 환경)
일부 macOS VM / 상시 가동 환경에서는 Messages.app이 “유휴” 상태가 될 수 있습니다(앱을 열거나 포그라운드로 가져올 때까지 수신 이벤트가 중단됨). 간단한 해결책은 AppleScript + LaunchAgent를 사용하여 5분마다 Messages를 깨우는 것입니다.
1) AppleScript 저장
다음 위치에 저장하세요:
~/Scripts/poke-messages.scpt
스크립트 예시(비대화형; 포커스를 빼앗지 않음):
try
tell application "Messages"
if not running then
launch
end if
-- Touch the scripting interface to keep the process responsive.
set _chatCount to (count of chats)
end tell
on error
-- Ignore transient failures (first-run prompts, locked session, etc).
end try
2) LaunchAgent 설치
다음 위치에 저장하세요:
~/Library/LaunchAgents/com.user.poke-messages.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.user.poke-messages</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>-lc</string>
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StartInterval</key>
<integer>300</integer>
<key>StandardOutPath</key>
<string>/tmp/poke-messages.log</string>
<key>StandardErrorPath</key>
<string>/tmp/poke-messages.err</string>
</dict>
</plist>
참고:
- 300초마다 그리고 로그인 시 실행됩니다.
- 첫 실행 시 macOS 자동화 프롬프트(
osascript→ Messages)가 표시될 수 있습니다. LaunchAgent를 실행하는 동일한 사용자 세션에서 승인하세요.
로드하려면:
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
온보딩
BlueBubbles는 대화형 설정 마법사에서 사용할 수 있습니다:
openclaw onboard
마법사가 묻는 항목:
- 서버 URL (필수): BlueBubbles 서버 주소(예:
http://192.168.1.100:1234) - 비밀번호 (필수): BlueBubbles 서버 설정의 API 비밀번호
- 웹훅 경로 (선택): 기본값은
/bluebubbles-webhook - DM 정책: pairing, allowlist, open, 또는 disabled
- 허용 목록: 전화번호, 이메일, 또는 채팅 대상
CLI로도 추가할 수 있습니다:
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
접근 제어 (DM + 그룹)
DM:
- 기본값:
channels.bluebubbles.dmPolicy = "pairing". - 알 수 없는 발신자에게 페어링 코드가 전송되며, 승인될 때까지 메시지가 무시됩니다(코드는 1시간 후 만료).
- 승인:
openclaw pairing list bluebubblesopenclaw pairing approve bluebubbles <CODE>
- 페어링은 기본 토큰 교환입니다. 자세한 내용: Pairing
그룹:
channels.bluebubbles.groupPolicy = open | allowlist | disabled(기본값:allowlist).channels.bluebubbles.groupAllowFrom은allowlist가 설정된 경우 그룹에서 트리거할 수 있는 사람을 제어합니다.
멘션 게이팅 (그룹)
BlueBubbles는 iMessage/WhatsApp 동작과 일치하는 그룹 채팅 멘션 게이팅을 지원합니다:
agents.list[].groupChat.mentionPatterns(또는messages.groupChat.mentionPatterns)를 사용하여 멘션을 감지합니다.- 그룹에
requireMention이 활성화되면 에이전트는 멘션될 때만 응답합니다. - 인가된 발신자의 제어 명령은 멘션 게이팅을 우회합니다.
그룹별 설정:
{
channels: {
bluebubbles: {
groupPolicy: "allowlist",
groupAllowFrom: ["+15555550123"],
groups: {
"*": { requireMention: true }, // 모든 그룹의 기본값
"iMessage;-;chat123": { requireMention: false }, // 특정 그룹 재정의
},
},
},
}
명령 게이팅
- 제어 명령(예:
/config,/model)은 인가가 필요합니다. allowFrom과groupAllowFrom을 사용하여 명령 인가를 결정합니다.- 인가된 발신자는 그룹에서 멘션 없이도 제어 명령을 실행할 수 있습니다.
타이핑 + 읽음 확인
- 타이핑 표시기: 응답 생성 전과 생성 중에 자동으로 전송됩니다.
- 읽음 확인:
channels.bluebubbles.sendReadReceipts(기본값:true)로 제어합니다. - 타이핑 표시기: OpenClaw가 타이핑 시작 이벤트를 전송하고, BlueBubbles는 전송 또는 타임아웃 시 자동으로 타이핑을 해제합니다(DELETE를 통한 수동 중지는 불안정함).
{
channels: {
bluebubbles: {
sendReadReceipts: false, // 읽음 확인 비활성화
},
},
}
고급 액션
BlueBubbles는 설정에서 활성화하면 고급 메시지 액션을 지원합니다:
{
channels: {
bluebubbles: {
actions: {
reactions: true, // 탭백 (기본값: true)
edit: true, // 전송된 메시지 편집 (macOS 13+, macOS 26 Tahoe에서 작동 안 함)
unsend: true, // 메시지 전송 취소 (macOS 13+)
reply: true, // 메시지 GUID로 답장 스레딩
sendWithEffect: true, // 메시지 이펙트 (slam, loud 등)
renameGroup: true, // 그룹 채팅 이름 변경
setGroupIcon: true, // 그룹 채팅 아이콘/사진 설정 (macOS 26 Tahoe에서 불안정)
addParticipant: true, // 그룹에 참가자 추가
removeParticipant: true, // 그룹에서 참가자 제거
leaveGroup: true, // 그룹 채팅 나가기
sendAttachment: true, // 첨부 파일/미디어 전송
},
},
},
}
사용 가능한 액션:
- react: 탭백 리액션 추가/제거 (
messageId,emoji,remove) - edit: 전송된 메시지 편집 (
messageId,text) - unsend: 메시지 전송 취소 (
messageId) - reply: 특정 메시지에 답장 (
messageId,text,to) - sendWithEffect: iMessage 이펙트와 함께 전송 (
text,to,effectId) - renameGroup: 그룹 채팅 이름 변경 (
chatGuid,displayName) - setGroupIcon: 그룹 채팅 아이콘/사진 설정 (
chatGuid,media) — macOS 26 Tahoe에서 불안정(API가 성공을 반환하지만 아이콘이 동기화되지 않을 수 있음). - addParticipant: 그룹에 사람 추가 (
chatGuid,address) - removeParticipant: 그룹에서 사람 제거 (
chatGuid,address) - leaveGroup: 그룹 채팅 나가기 (
chatGuid) - sendAttachment: 미디어/파일 전송 (
to,buffer,filename,asVoice)- 음성 메모: MP3 또는 CAF 오디오와 함께
asVoice: true를 설정하면 iMessage 음성 메시지로 전송됩니다. BlueBubbles는 음성 메모 전송 시 MP3를 CAF로 변환합니다.
- 음성 메모: MP3 또는 CAF 오디오와 함께
메시지 ID (짧은 vs 전체)
OpenClaw는 토큰을 절약하기 위해 짧은 메시지 ID(예: 1, 2)를 표시할 수 있습니다.
MessageSid/ReplyToId는 짧은 ID일 수 있습니다.MessageSidFull/ReplyToIdFull에는 제공자의 전체 ID가 포함됩니다.- 짧은 ID는 메모리에 저장되며, 재시작이나 캐시 제거 시 만료될 수 있습니다.
- 액션은 짧은 또는 전체
messageId를 허용하지만, 짧은 ID가 더 이상 사용 불가능하면 오류가 발생합니다.
지속적인 자동화 및 저장에는 전체 ID를 사용하세요:
- 템플릿:
{{MessageSidFull}},{{ReplyToIdFull}} - 컨텍스트: 인바운드 페이로드의
MessageSidFull/ReplyToIdFull
자세한 내용: Configuration의 템플릿 변수.
블록 스트리밍
응답을 단일 메시지로 전송할지 블록 단위로 스트리밍할지 제어합니다:
{
channels: {
bluebubbles: {
blockStreaming: true, // 블록 스트리밍 활성화 (기본적으로 비활성화)
},
},
}
미디어 + 제한
- 인바운드 첨부 파일은 다운로드되어 미디어 캐시에 저장됩니다.
channels.bluebubbles.mediaMaxMb로 인바운드 및 아웃바운드 미디어 상한을 설정합니다(기본값: 8 MB).- 아웃바운드 텍스트는
channels.bluebubbles.textChunkLimit(기본값: 4000자)로 분할됩니다.
설정 레퍼런스
전체 설정: Configuration
제공자 옵션:
channels.bluebubbles.enabled: 채널 활성화/비활성화.channels.bluebubbles.serverUrl: BlueBubbles REST API 기본 URL.channels.bluebubbles.password: API 비밀번호.channels.bluebubbles.webhookPath: 웹훅 엔드포인트 경로 (기본값:/bluebubbles-webhook).channels.bluebubbles.dmPolicy:pairing | allowlist | open | disabled(기본값:pairing).channels.bluebubbles.allowFrom: DM 허용 목록 (핸들, 이메일, E.164 번호,chat_id:*,chat_guid:*).channels.bluebubbles.groupPolicy:open | allowlist | disabled(기본값:allowlist).channels.bluebubbles.groupAllowFrom: 그룹 발신자 허용 목록.channels.bluebubbles.groups: 그룹별 설정 (requireMention등).channels.bluebubbles.sendReadReceipts: 읽음 확인 전송 (기본값:true).channels.bluebubbles.blockStreaming: 블록 스트리밍 활성화 (기본값:false; 스트리밍 응답에 필요).channels.bluebubbles.textChunkLimit: 아웃바운드 청크 크기 (문자 수, 기본값: 4000).channels.bluebubbles.chunkMode:length(기본값)는textChunkLimit초과 시에만 분할;newline은 길이 분할 전에 빈 줄(단락 경계)에서 먼저 분할.channels.bluebubbles.mediaMaxMb: 인바운드/아웃바운드 미디어 상한 (MB, 기본값: 8).channels.bluebubbles.mediaLocalRoots: 아웃바운드 로컬 미디어 경로에 허용되는 절대 디렉토리의 명시적 허용 목록. 이 설정이 없으면 로컬 경로 전송은 기본적으로 거부됩니다. 계정별 재정의:channels.bluebubbles.accounts.<accountId>.mediaLocalRoots.channels.bluebubbles.historyLimit: 그룹 컨텍스트용 최대 메시지 수 (0으로 비활성화).channels.bluebubbles.dmHistoryLimit: DM 히스토리 제한.channels.bluebubbles.actions: 특정 액션 활성화/비활성화.channels.bluebubbles.accounts: 다중 계정 설정.
관련 전역 옵션:
agents.list[].groupChat.mentionPatterns(또는messages.groupChat.mentionPatterns).messages.responsePrefix.
주소 지정 / 전달 대상
안정적인 라우팅을 위해 chat_guid를 사용하세요:
chat_guid:iMessage;-;+15555550123(그룹에 권장)chat_id:123chat_identifier:...- 직접 핸들:
+15555550123,[email protected]- 직접 핸들에 기존 DM 채팅이 없는 경우, OpenClaw가
POST /api/v1/chat/new를 통해 새로 생성합니다. BlueBubbles Private API가 활성화되어 있어야 합니다.
- 직접 핸들에 기존 DM 채팅이 없는 경우, OpenClaw가
보안
- 웹훅 요청은
guid/password쿼리 매개변수 또는 헤더를channels.bluebubbles.password와 비교하여 인증됩니다.localhost에서의 요청도 허용됩니다. - API 비밀번호와 웹훅 엔드포인트를 비밀로 유지하세요(자격 증명처럼 취급).
- 로컬호스트 신뢰는 동일 호스트 리버스 프록시가 의도치 않게 비밀번호를 우회할 수 있음을 의미합니다. 게이트웨이를 프록시하는 경우 프록시에서 인증을 요구하고
gateway.trustedProxies를 설정하세요. 자세한 내용: Gateway security. - BlueBubbles 서버를 LAN 외부에 노출하는 경우 HTTPS + 방화벽 규칙을 활성화하세요.
문제 해결
- 타이핑/읽음 이벤트가 작동을 멈추면, BlueBubbles 웹훅 로그를 확인하고 게이트웨이 경로가
channels.bluebubbles.webhookPath와 일치하는지 확인하세요. - 페어링 코드는 1시간 후 만료됩니다.
openclaw pairing list bluebubbles와openclaw pairing approve bluebubbles <code>를 사용하세요. - 리액션에는 BlueBubbles Private API(
POST /api/v1/message/react)가 필요합니다. 서버 버전이 이를 노출하는지 확인하세요. - 편집/전송 취소에는 macOS 13+ 및 호환 BlueBubbles 서버 버전이 필요합니다. macOS 26(Tahoe)에서는 Private API 변경으로 인해 편집이 현재 작동하지 않습니다.
- 그룹 아이콘 업데이트는 macOS 26(Tahoe)에서 불안정할 수 있습니다: API가 성공을 반환하지만 새 아이콘이 동기화되지 않습니다.
- OpenClaw는 BlueBubbles 서버의 macOS 버전에 따라 알려진 문제가 있는 액션을 자동으로 숨깁니다. macOS 26(Tahoe)에서 편집이 여전히 나타나면
channels.bluebubbles.actions.edit=false로 수동 비활성화하세요. - 상태/상태 정보:
openclaw status --all또는openclaw status --deep.