iMessage (imsg)
상태: 외부 CLI 통합. Gateway는 imsg rpc(JSON-RPC over stdio)를 실행합니다.
빠른 설정 (초보자용)
- 이 Mac에서 Messages가 로그인되어 있는지 확인합니다.
- imsg 설치:
- brew install steipete/tap/imsg
- channels.imessage.cliPath 및 channels.imessage.dbPath로 OpenClaw를 구성합니다.
- Gateway를 시작하고 macOS 프롬프트를 승인합니다(Automation + Full Disk Access).
최소 설정:
{
channels: {
imessage: {
enabled: true,
cliPath: "/usr/local/bin/imsg",
dbPath: "/Users/<you>/Library/Messages/chat.db"
}
}
}
개요
- macOS의 imsg를 기반으로 하는 iMessage 채널입니다.
- 결정론적 라우팅: 응답은 항상 iMessage로 돌아갑니다.
- DM은 에이전트의 메인 세션을 공유하며, 그룹은 격리됩니다(agent:<agentId>:imessage:group:<chat_id>).
- is_group=false로 도착한 다중 참가자 스레드는 channels.imessage.groups를 사용하여 chat_id로 격리할 수 있습니다(아래 "그룹형 스레드" 참조).
설정 쓰기
기본적으로 iMessage는 /config set|unset으로 트리거된 설정 업데이트 쓰기가 허용됩니다(commands.config: true 필요).
비활성화:
{
channels: { imessage: { configWrites: false } }
}
요구사항
- Messages가 로그인된 macOS.
- OpenClaw + imsg에 대한 Full Disk Access(Messages DB 접근).
- 전송 시 Automation 권한.
- channels.imessage.cliPath는 stdin/stdout을 프록시하는 모든 명령을 가리킬 수 있습니다(예: 다른 Mac에 SSH로 접속하여 imsg rpc를 실행하는 래퍼 스크립트).
설정 (빠른 경로)
- 이 Mac에서 Messages가 로그인되어 있는지 확인합니다.
- iMessage를 구성하고 Gateway를 시작합니다.
전용 봇 macOS 사용자 (격리된 ID용)
봇이 별도의 iMessage ID로 전송하고 개인 Messages를 깨끗하게 유지하려면, 전용 Apple ID + 전용 macOS 사용자를 사용하세요.
- 전용 Apple ID를 생성합니다(예: [email protected]).
- Apple은 인증/2FA를 위해 전화번호가 필요할 수 있습니다.
- macOS 사용자를 생성하고(예: openclawhome) 로그인합니다.
- 해당 macOS 사용자에서 Messages를 열고 봇 Apple ID로 iMessage에 로그인합니다.
- Remote Login을 활성화합니다(시스템 설정 → 일반 → 공유 → Remote Login).
- imsg 설치:
- brew install steipete/tap/imsg
- ssh <bot-macos-user>@localhost true가 비밀번호 없이 작동하도록 SSH를 설정합니다.
- channels.imessage.accounts.bot.cliPath를 봇 사용자로 imsg를 실행하는 SSH 래퍼로 지정합니다.
첫 실행 참고사항: 전송/수신 시 봇 macOS 사용자에서 GUI 승인(Automation + Full Disk Access)이 필요할 수 있습니다. imsg rpc가 멈추거나 종료되면, 해당 사용자로 로그인하고(화면 공유 도움), 일회성으로 imsg chats --limit 1 / imsg send ...를 실행하고, 프롬프트를 승인한 후 재시도하세요.
래퍼 예시(chmod +x). <bot-macos-user>를 실제 macOS 사용자명으로 교체하세요:
#!/usr/bin/env bash
set -euo pipefail
# 호스트 키 수락을 위해 먼저 대화형 SSH를 한 번 실행:
# ssh <bot-macos-user>@localhost true
exec /usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=5 -T <bot-macos-user>@localhost \
"/usr/local/bin/imsg" "$@"
설정 예시:
{
channels: {
imessage: {
enabled: true,
accounts: {
bot: {
name: "Bot",
enabled: true,
cliPath: "/path/to/imsg-bot",
dbPath: "/Users/<bot-macos-user>/Library/Messages/chat.db"
}
}
}
}
}
단일 계정 설정의 경우, accounts 맵 대신 플랫 옵션(channels.imessage.cliPath, channels.imessage.dbPath)을 사용하세요.
원격/SSH 변형 (선택사항)
다른 Mac에서 iMessage를 사용하려면, channels.imessage.cliPath를 SSH를 통해 원격 macOS 호스트에서 imsg를 실행하는 래퍼로 설정하세요. OpenClaw는 stdio만 필요합니다.
래퍼 예시:
#!/usr/bin/env bash
exec ssh -T gateway-host imsg "$@"
원격 첨부파일: cliPath가 SSH를 통해 원격 호스트를 가리킬 때, Messages 데이터베이스의 첨부파일 경로는 원격 머신의 파일을 참조합니다. OpenClaw는 channels.imessage.remoteHost를 설정하여 SCP를 통해 자동으로 가져올 수 있습니다:
{
channels: {
imessage: {
cliPath: "~/imsg-ssh", // 원격 Mac으로의 SSH 래퍼
remoteHost: "user@gateway-host", // SCP 파일 전송용
includeAttachments: true
}
}
}
remoteHost가 설정되지 않으면, OpenClaw는 래퍼 스크립트의 SSH 명령을 파싱하여 자동 감지를 시도합니다. 안정성을 위해 명시적 구성을 권장합니다.
Tailscale을 통한 원격 Mac (예시)
Gateway가 Linux 호스트/VM에서 실행되지만 iMessage는 Mac에서 실행되어야 하는 경우, Tailscale이 가장 간단한 브리지입니다: Gateway가 tailnet을 통해 Mac과 통신하고, SSH를 통해 imsg를 실행하며, SCP로 첨부파일을 가져옵니다.
아키텍처:
┌──────────────────────────────┐ SSH (imsg rpc) ┌──────────────────────────┐
│ Gateway 호스트 (Linux/VM) │──────────────────────────────────▶│ Messages + imsg가 있는 Mac │
│ - openclaw gateway │ SCP (attachments) │ - Messages 로그인됨 │
│ - channels.imessage.cliPath │◀──────────────────────────────────│ - Remote Login 활성화됨 │
└──────────────────────────────┘ └──────────────────────────┘
▲
│ Tailscale tailnet (hostname 또는 100.x.y.z)
▼
user@gateway-host
구체적인 설정 예시 (Tailscale 호스트명):
{
channels: {
imessage: {
enabled: true,
cliPath: "~/.openclaw/scripts/imsg-ssh",
remoteHost: "[email protected]",
includeAttachments: true,
dbPath: "/Users/bot/Library/Messages/chat.db"
}
}
}
래퍼 예시 (~/.openclaw/scripts/imsg-ssh):
#!/usr/bin/env bash
exec ssh -T [email protected] imsg "$@"
참고사항:
- Mac이 Messages에 로그인되어 있고, Remote Login이 활성화되어 있는지 확인하세요.
- ssh [email protected]가 프롬프트 없이 작동하도록 SSH 키를 사용하세요.
- remoteHost는 SCP가 첨부파일을 가져올 수 있도록 SSH 타겟과 일치해야 합니다.
다중 계정 지원: 계정별 설정 및 선택적 name과 함께 channels.imessage.accounts를 사용하세요. 공유 패턴은 gateway/configuration을 참조하세요. ~/.openclaw/openclaw.json은 커밋하지 마세요(종종 토큰이 포함됨).
접근 제어 (DM + 그룹)
DM:
- 기본값: channels.imessage.dmPolicy = "pairing".
- 알 수 없는 발신자는 페어링 코드를 받으며, 승인될 때까지 메시지가 무시됩니다(코드는 1시간 후 만료).
- 승인 방법:
- openclaw pairing list imessage
- openclaw pairing approve imessage <CODE>
- 페어링은 iMessage DM의 기본 토큰 교환입니다. 자세한 내용: Pairing
그룹:
- channels.imessage.groupPolicy = open | allowlist | disabled.
- channels.imessage.groupAllowFrom은 allowlist가 설정된 경우 그룹에서 누가 트리거할 수 있는지 제어합니다.
- iMessage에는 네이티브 멘션 메타데이터가 없으므로, 멘션 게이팅은 agents.list[].groupChat.mentionPatterns(또는 messages.groupChat.mentionPatterns)를 사용합니다.
- 다중 에이전트 재정의: agents.list[].groupChat.mentionPatterns에 에이전트별 패턴을 설정합니다.
작동 방식 (동작)
- imsg는 메시지 이벤트를 스트리밍하며, Gateway는 이를 공유 채널 envelope로 정규화합니다.
- 응답은 항상 동일한 chat id 또는 핸들로 라우팅됩니다.
그룹형 스레드 (is_group=false)
일부 iMessage 스레드는 여러 참가자를 가질 수 있지만, Messages가 채팅 식별자를 저장하는 방식에 따라 is_group=false로 도착할 수 있습니다.
channels.imessage.groups 아래에 chat_id를 명시적으로 구성하면, OpenClaw는 해당 스레드를 "그룹"으로 처리합니다:
- 세션 격리 (별도의 agent:<agentId>:imessage:group:<chat_id> 세션 키)
- 그룹 허용목록 / 멘션 게이팅 동작
예시:
{
channels: {
imessage: {
groupPolicy: "allowlist",
groupAllowFrom: ["+15555550123"],
groups: {
"42": { "requireMention": false }
}
}
}
}
특정 스레드에 대한 격리된 personality/모델이 필요한 경우 유용합니다(Multi-agent routing 참조). 파일시스템 격리는 Sandboxing을 참조하세요.
미디어 + 제한사항
- channels.imessage.includeAttachments를 통한 선택적 첨부파일 수집.
- channels.imessage.mediaMaxMb를 통한 미디어 제한.
제한사항
- 아웃바운드 텍스트는 channels.imessage.textChunkLimit(기본값 4000)로 청크됩니다.
- 선택적 줄바꿈 청킹: channels.imessage.chunkMode="newline"로 설정하여 길이 청킹 전에 빈 줄(단락 경계)로 분할합니다.
- 미디어 업로드는 channels.imessage.mediaMaxMb(기본값 16)로 제한됩니다.
주소 지정 / 전달 대상
안정적인 라우팅을 위해 chat_id 사용 권장:
- chat_id:123 (권장)
- chat_guid:...
- chat_identifier:...
- 직접 핸들: imessage:+1555 / sms:+1555 / [email protected]
채팅 목록:
imsg chats --limit 20
설정 참조 (iMessage)
전체 설정: Configuration
제공자 옵션:
- channels.imessage.enabled: 채널 시작 활성화/비활성화.
- channels.imessage.cliPath: imsg 경로.
- channels.imessage.dbPath: Messages DB 경로.
- channels.imessage.remoteHost: cliPath가 원격 Mac을 가리킬 때 SCP 첨부파일 전송을 위한 SSH 호스트(예: user@gateway-host). 설정되지 않으면 SSH 래퍼에서 자동 감지됨.
- channels.imessage.service: imessage | sms | auto.
- channels.imessage.region: SMS 지역.
- channels.imessage.dmPolicy: pairing | allowlist | open | disabled (기본값: pairing).
- channels.imessage.allowFrom: DM 허용목록 (핸들, 이메일, E.164 번호 또는 chat_id:*). open은 "*"가 필요합니다. iMessage에는 사용자명이 없으므로 핸들이나 채팅 타겟을 사용합니다.
- channels.imessage.groupPolicy: open | allowlist | disabled (기본값: allowlist).
- channels.imessage.groupAllowFrom: 그룹 발신자 허용목록.
- channels.imessage.historyLimit / channels.imessage.accounts.*.historyLimit: 컨텍스트로 포함할 최대 그룹 메시지 수 (0은 비활성화).
- channels.imessage.dmHistoryLimit: 사용자 턴 단위의 DM 히스토리 제한. 사용자별 재정의: channels.imessage.dms["<handle>"].historyLimit.
- channels.imessage.groups: 그룹별 기본값 + 허용목록 (전역 기본값은 "*" 사용).
- channels.imessage.includeAttachments: 첨부파일을 컨텍스트에 수집.
- channels.imessage.mediaMaxMb: 인바운드/아웃바운드 미디어 제한 (MB).
- channels.imessage.textChunkLimit: 아웃바운드 청크 크기 (문자).
- channels.imessage.chunkMode: length (기본값) 또는 newline으로 길이 청킹 전에 빈 줄(단락 경계)로 분할.
관련 글로벌 옵션:
- agents.list[].groupChat.mentionPatterns (또는 messages.groupChat.mentionPatterns).
- messages.responsePrefix.