OpenClaw macOS 컴패니언 (메뉴바 + gateway broker)

macOS 앱은 OpenClaw를 위한 메뉴바 컴패니언입니다. 권한을 소유하고, 로컬에서 Gateway를 관리/연결하며 (launchd 또는 수동), macOS 기능을 node로 agent에 노출합니다.

기능

  • 메뉴바에 네이티브 알림 및 상태 표시.
  • TCC 프롬프트 소유 (알림, 접근성, 화면 녹화, 마이크, 음성 인식, 자동화/AppleScript).
  • Gateway 실행 또는 연결 (로컬 또는 원격).
  • macOS 전용 도구 노출 (Canvas, Camera, Screen Recording, system.run).
  • 원격 모드에서 로컬 node host 서비스 시작 (launchd), 로컬 모드에서 중지.
  • 선택적으로 UI 자동화를 위한 PeekabooBridge 호스팅.
  • 요청 시 npm/pnpm을 통해 전역 CLI(openclaw) 설치 (Gateway 런타임에는 bun 권장하지 않음).

로컬 vs 원격 모드

  • 로컬 (기본값): 앱이 실행 중인 로컬 Gateway에 연결; 없으면 openclaw gateway install을 통해 launchd 서비스를 활성화합니다.
  • 원격: 앱이 SSH/Tailscale을 통해 Gateway에 연결하며 로컬 프로세스를 시작하지 않습니다. 앱은 원격 Gateway가 이 Mac에 도달할 수 있도록 로컬 node host 서비스를 시작합니다. 앱은 Gateway를 자식 프로세스로 생성하지 않습니다.

Launchd 제어

앱은 bot.molt.gateway로 레이블된 사용자별 LaunchAgent를 관리합니다 (--profile/OPENCLAW_PROFILE 사용 시 bot.molt.<profile>; 레거시 com.openclaw.*는 여전히 언로드됨).

launchctl kickstart -k gui/$UID/bot.molt.gateway
launchctl bootout gui/$UID/bot.molt.gateway

명명된 프로필 실행 시 레이블을 bot.molt.<profile>로 바꾸세요.

LaunchAgent가 설치되지 않은 경우, 앱에서 활성화하거나 openclaw gateway install을 실행하세요.

Node 기능 (mac)

macOS 앱은 자신을 node로 표시합니다. 일반적인 명령:

  • Canvas: canvas.present, canvas.navigate, canvas.eval, canvas.snapshot, canvas.a2ui.*
  • Camera: camera.snap, camera.clip
  • Screen: screen.record
  • System: system.run, system.notify

Node는 agent가 허용되는 것을 결정할 수 있도록 permissions 맵을 보고합니다.

Node 서비스 + 앱 IPC:

  • 헤드리스 node host 서비스가 실행 중일 때 (원격 모드), Gateway WS에 node로 연결합니다.
  • system.run은 로컬 Unix 소켓을 통해 macOS 앱(UI/TCC 컨텍스트)에서 실행됩니다; 프롬프트 + 출력은 앱 내에 유지됩니다.

다이어그램 (SCI):

Gateway -> Node Service (WS)
                 |  IPC (UDS + token + HMAC + TTL)
                 v
             Mac App (UI + TCC + system.run)

Exec 승인 (system.run)

system.run은 macOS 앱(설정 → Exec 승인)의 Exec 승인으로 제어됩니다. 보안 + ask + allowlist는 Mac에 로컬로 저장됩니다:

~/.openclaw/exec-approvals.json

예시:

{
  "version": 1,
  "defaults": {
    "security": "deny",
    "ask": "on-miss"
  },
  "agents": {
    "main": {
      "security": "allowlist",
      "ask": "on-miss",
      "allowlist": [
        { "pattern": "/opt/homebrew/bin/rg" }
      ]
    }
  }
}

참고사항:

  • allowlist 항목은 해결된 바이너리 경로에 대한 glob 패턴입니다.
  • 프롬프트에서 "항상 허용"을 선택하면 해당 명령이 allowlist에 추가됩니다.
  • system.run 환경 재정의는 필터링(PATH, DYLD_*, LD_*, NODE_OPTIONS, PYTHON*, PERL*, RUBYOPT 삭제)된 후 앱의 환경과 병합됩니다.

딥 링크

앱은 로컬 작업을 위해 openclaw:// URL 스킴을 등록합니다.

openclaw://agent

Gateway agent 요청을 트리거합니다.

open 'openclaw://agent?message=Hello%20from%20deep%20link'

쿼리 매개변수:

  • message (필수)
  • sessionKey (선택사항)
  • thinking (선택사항)
  • deliver / to / channel (선택사항)
  • timeoutSeconds (선택사항)
  • key (선택사항 무인 모드 키)

안전:

  • key 없이는 앱이 확인을 요청합니다.
  • 유효한 key가 있으면, 실행이 무인 모드입니다 (개인 자동화 용도).

온보딩 흐름 (일반적)

  1. OpenClaw.app을 설치하고 실행합니다.
  2. 권한 체크리스트 완료 (TCC 프롬프트).
  3. 로컬 모드가 활성화되어 있고 Gateway가 실행 중인지 확인합니다.
  4. 터미널 접근을 원하면 CLI를 설치합니다.

빌드 & 개발 워크플로우 (네이티브)

  • cd apps/macos && swift build
  • swift run OpenClaw (또는 Xcode)
  • 앱 패키징: scripts/package-mac-app.sh

Gateway 연결 디버그 (macOS CLI)

디버그 CLI를 사용하여 앱을 실행하지 않고 macOS 앱이 사용하는 동일한 Gateway WebSocket 핸드셰이크 및 검색 로직을 실행하세요.

cd apps/macos
swift run openclaw-mac connect --json
swift run openclaw-mac discover --timeout 3000 --json

연결 옵션:

  • --url <ws://host:port>: 구성 재정의
  • --mode <local|remote>: 구성에서 해결 (기본값: 구성 또는 로컬)
  • --probe: 새 헬스 프로브 강제
  • --timeout <ms>: 요청 타임아웃 (기본값: 15000)
  • --json: 비교를 위한 구조화된 출력

검색 옵션:

  • --include-local: "로컬"로 필터링될 gateway 포함
  • --timeout <ms>: 전체 검색 창 (기본값: 2000)
  • --json: 비교를 위한 구조화된 출력

팁: openclaw gateway discover --json과 비교하여 macOS 앱의 검색 파이프라인 (NWBrowser + tailnet DNS‑SD 대체)이 Node CLI의 dns-sd 기반 검색과 다른지 확인하세요.

원격 연결 플러밍 (SSH 터널)

macOS 앱이 원격 모드로 실행될 때, 로컬 UI 구성 요소가 마치 localhost에 있는 것처럼 원격 Gateway와 통신할 수 있도록 SSH 터널을 엽니다.

제어 터널 (Gateway WebSocket 포트)

  • 목적: 헬스 체크, 상태, Web Chat, 구성 및 기타 control-plane 호출.
  • 로컬 포트: Gateway 포트 (기본값 18789), 항상 안정적.
  • 원격 포트: 원격 호스트의 동일한 Gateway 포트.
  • 동작: 무작위 로컬 포트 없음; 앱은 기존의 건강한 터널을 재사용하거나 필요한 경우 재시작합니다.
  • SSH 형태: ssh -N -L <local>:127.0.0.1:<remote> BatchMode + ExitOnForwardFailure + keepalive 옵션 포함.
  • IP 보고: SSH 터널은 loopback을 사용하므로 gateway는 node IP를 127.0.0.1로 봅니다. 실제 클라이언트 IP가 나타나도록 하려면 직접 (ws/wss) 전송을 사용하세요 (macOS 원격 접근 참조).

설정 단계는 macOS 원격 접근을 참조하세요. 프로토콜 세부사항은 Gateway 프로토콜을 참조하세요.

관련 문서