OpenClaw macOS 컴패니언 (메뉴 바 + 게이트웨이 브로커)

macOS 앱은 OpenClaw의 메뉴 바 컴패니언입니다. 권한을 관리하고, 로컬에서 게이트웨이를 관리/연결하며(launchd 또는 수동), macOS 기능을 에이전트에 노드로 제공합니다.

기능 설명

  • 메뉴 바에 네이티브 알림과 상태를 표시합니다.
  • TCC 프롬프트를 관리합니다 (알림, 접근성, 화면 기록, 마이크, 음성 인식, 자동화/AppleScript).
  • 게이트웨이를 실행하거나 연결합니다 (로컬 또는 원격).
  • macOS 전용 도구를 제공합니다 (Canvas, 카메라, 화면 기록, system.run).
  • 원격 모드에서 로컬 노드 호스트 서비스를 시작하고(launchd), 로컬 모드에서는 중지합니다.
  • 선택적으로 PeekabooBridge를 호스팅하여 UI 자동화를 지원합니다.
  • 요청 시 npm/pnpm을 통해 글로벌 CLI(openclaw)를 설치합니다 (게이트웨이 런타임에는 bun 비권장).

로컬 vs 원격 모드

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

Launchd 제어

앱은 ai.openclaw.gateway (또는 --profile/OPENCLAW_PROFILE 사용 시 ai.openclaw.<profile>; 레거시 com.openclaw.*도 언로드됨) 레이블의 사용자별 LaunchAgent를 관리합니다.

launchctl kickstart -k gui/$UID/ai.openclaw.gateway
launchctl bootout gui/$UID/ai.openclaw.gateway

이름이 있는 프로파일을 실행할 때는 레이블을 ai.openclaw.<profile>로 변경하세요.

LaunchAgent가 설치되어 있지 않으면, 앱에서 활성화하거나 openclaw gateway install을 실행하세요.

노드 기능 (mac)

macOS 앱은 노드로 동작합니다. 주요 명령:

  • Canvas: canvas.present, canvas.navigate, canvas.eval, canvas.snapshot, canvas.a2ui.*
  • 카메라: camera.snap, camera.clip
  • 화면: screen.record
  • 시스템: system.run, system.notify

노드는 permissions 맵을 보고하여 에이전트가 허용된 작업을 판단할 수 있습니다.

노드 서비스 + 앱 IPC:

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

다이어그램 (SCI):

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

실행 승인 (system.run)

system.run은 macOS 앱의 실행 승인(Settings → Exec approvals)으로 제어됩니다. 보안 + 확인 + 허용 목록은 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 패턴입니다.
  • 셸 제어 또는 확장 구문(&&, ||, ;, |, `, $, <, >, (, ))을 포함하는 원시 셸 명령 텍스트는 허용 목록 미스로 처리되며, 명시적 승인(또는 셸 바이너리 허용 목록 등록)이 필요합니다.
  • 프롬프트에서 “Always Allow”를 선택하면 해당 명령이 허용 목록에 추가됩니다.
  • system.run 환경 오버라이드는 필터링되며(PATH, DYLD_*, LD_*, NODE_OPTIONS, PYTHON*, PERL*, RUBYOPT, SHELLOPTS, PS4 제외), 앱의 환경과 병합됩니다.
  • 셸 래퍼(bash|sh|zsh ... -c/-lc)의 경우, 요청 범위 환경 오버라이드는 소규모 명시적 허용 목록(TERM, LANG, LC_*, COLORTERM, NO_COLOR, FORCE_COLOR)으로 축소됩니다.
  • 허용 목록 모드의 항상 허용 결정 시, 알려진 디스패치 래퍼(env, nice, nohup, stdbuf, timeout)는 래퍼 경로 대신 내부 실행 파일 경로를 저장합니다. 언래핑이 안전하지 않으면 허용 목록 항목이 자동으로 저장되지 않습니다.

딥 링크

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

openclaw://agent

게이트웨이 agent 요청을 트리거합니다.

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

쿼리 매개변수:

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

보안:

  • key 없이: 앱이 확인을 요청합니다.
  • key 없이: 앱은 확인 프롬프트에 짧은 메시지 제한을 적용하고, deliver / to / channel을 무시합니다.
  • 유효한 key가 있으면: 무인 실행 (개인 자동화용).

온보딩 흐름 (일반적인 과정)

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

상태 디렉터리 위치 (macOS)

OpenClaw 상태 디렉터리를 iCloud나 다른 클라우드 동기화 폴더에 두지 마세요. 동기화 기반 경로는 세션 및 자격 증명에 대해 지연과 간헐적인 파일 잠금/동기화 경합을 유발할 수 있습니다.

동기화되지 않는 로컬 상태 경로를 권장합니다:

OPENCLAW_STATE_DIR=~/.openclaw

openclaw doctor가 다음 경로에서 상태를 감지하면:

  • ~/Library/Mobile Documents/com~apple~CloudDocs/...
  • ~/Library/CloudStorage/...

경고를 표시하고 로컬 경로로 이동할 것을 권장합니다.

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

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

게이트웨이 연결 디버깅 (macOS CLI)

macOS 앱이 사용하는 것과 동일한 게이트웨이 WebSocket 핸드셰이크 및 디스커버리 로직을 앱 실행 없이 테스트하려면 디버그 CLI를 사용하세요.

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: diff에 적합한 구조화된 출력

디스커버리 옵션:

  • --include-local: “로컬”로 필터링될 게이트웨이 포함
  • --timeout <ms>: 전체 디스커버리 기간 (기본: 2000)
  • --json: diff에 적합한 구조화된 출력

팁: openclaw gateway discover --json과 비교하여 macOS 앱의 디스커버리 파이프라인(NWBrowser + 테일넷 DNS-SD 대안)이 Node CLI의 dns-sd 기반 디스커버리와 차이가 있는지 확인하세요.

원격 연결 구조 (SSH 터널)

macOS 앱이 원격 모드에서 실행되면, SSH 터널을 열어 로컬 UI 컴포넌트가 원격 게이트웨이를 마치 로컬호스트처럼 통신할 수 있게 합니다.

제어 터널 (게이트웨이 WebSocket 포트)

  • 용도: 상태 확인, 상태, Web Chat, 설정 및 기타 제어 플레인 호출.
  • 로컬 포트: 게이트웨이 포트 (기본 18789), 항상 고정.
  • 원격 포트: 원격 호스트의 동일한 게이트웨이 포트.
  • 동작: 무작위 로컬 포트 없음; 앱은 기존의 정상 터널을 재사용하거나 필요 시 재시작합니다.
  • SSH 형식: ssh -N -L <local>:127.0.0.1:<remote> BatchMode + ExitOnForwardFailure + keepalive 옵션 포함.
  • IP 보고: SSH 터널은 루프백을 사용하므로, 게이트웨이는 노드 IP를 127.0.0.1로 인식합니다. 실제 클라이언트 IP가 표시되길 원하면 Direct (ws/wss) 전송을 사용하세요 (macOS 원격 접근 참조).

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

관련 문서