OpenClaw macOS 앱 설정: 메뉴바에서 시스템 제어하기
맥에서 AI 에이전트를 돌리다 보면 권한 설정이나 백그라운드 프로세스 관리 때문에 머리가 아플 때가 많죠. 터미널을 계속 열어두기도 번거롭고, 원격 서버에 있는 Gateway와 연결하는 과정도 생각보다 까다로워요.
OpenClaw macOS Companion은 이런 고민을 해결해 주는 메뉴바 앱이에요. 복잡한 설정을 메뉴바에서 직관적으로 관리하고, 맥의 강력한 기능을 에이전트가 바로 사용할 수 있게 도와줍니다.
OpenClaw macOS Companion (menu bar + gateway broker)
섹션 제목: “OpenClaw macOS Companion (menu bar + gateway broker)”이 macOS 앱은 OpenClaw를 위한 메뉴바 컴패니언이에요. 권한을 소유하고, 로컬 Gateway를 관리하거나 연결하며(launchd 또는 수동), macOS의 기능을 에이전트에 node로 노출하는 역할을 해요.
어떤 기능을 하나요?
섹션 제목: “어떤 기능을 하나요?”- 메뉴바에서 네이티브 알림과 상태를 보여줘요.
- TCC 프롬프트(알림, 손쉬운 사용, 화면 기록, 마이크, 음성 인식, 자동화/AppleScript) 권한을 관리해요.
- 로컬 또는 원격 Gateway를 실행하거나 연결해요.
- macOS 전용 도구(Canvas, Camera, Screen Recording,
system.run)를 노출해요. - remote 모드(launchd)에서 로컬 node host service를 시작하고, local 모드에서 이를 중지해요.
- 선택적으로 UI 자동화를 위한 PeekabooBridge를 호스팅해요.
- 요청 시 npm/pnpm을 통해 글로벌 CLI(
openclaw)를 설치해요 (Gateway 런타임으로 bun은 권장하지 않아요).
로컬 vs 원격 모드
섹션 제목: “로컬 vs 원격 모드”- Local (기본값): 앱이 실행 중인 로컬 Gateway가 있다면 그곳에 연결해요. 없다면
openclaw gateway install을 통해 launchd 서비스를 활성화해요. - Remote: 앱이 SSH/Tailscale을 통해 원격 Gateway에 연결하며, 로컬 프로세스를 시작하지 않아요. 원격 Gateway가 이 맥에 접속할 수 있도록 앱이 로컬 node host service를 시작해요. 이때 앱은 Gateway를 자식 프로세스로 생성하지 않아요. Gateway 탐색 시 이제 실제 tailnet IP보다 Tailscale MagicDNS 이름을 우선적으로 사용하므로, tailnet IP가 바뀌어도 맥 앱이 더 안정적으로 복구돼요.
Launchd 제어
섹션 제목: “Launchd 제어”앱은 ai.openclaw.gateway라는 레이블의 사용자별 LaunchAgent를 관리해요 (--profile이나 OPENCLAW_PROFILE을 사용할 때는 ai.openclaw.<profile> 사용, 기존의 com.openclaw.*는 여전히 언로드됨).
launchctl kickstart -k gui/$UID/ai.openclaw.gatewaylaunchctl bootout gui/$UID/ai.openclaw.gateway이름이 지정된 프로필을 실행할 때는 레이블을 ai.openclaw.<profile>로 바꾸면 돼요.
LaunchAgent가 설치되어 있지 않다면, 앱에서 활성화하거나 openclaw gateway install을 실행하세요.
노드 기능 (mac)
섹션 제목: “노드 기능 (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는 에이전트가 허용된 작업을 결정할 수 있도록 permissions 맵을 보고해요.
Node 서비스 + 앱 IPC:
- 헤드리스 node host service가 실행 중일 때(원격 모드), node로서 Gateway WS에 연결해요.
system.run은 로컬 Unix 소켓을 통해 macOS 앱(UI/TCC 컨텍스트)에서 실행되며, 프롬프트와 출력은 앱 내에 유지돼요.
다이어그램 (SCI):
Gateway -> Node Service (WS) | IPC (UDS + token + HMAC + TTL) v Mac App (UI + TCC + system.run)실행 승인 (system.run)
섹션 제목: “실행 승인 (system.run)”system.run은 macOS 앱의 Exec approvals 설정(Settings → Exec approvals)에서 제어돼요. 보안, 확인 요청, allowlist 설정은 맥 로컬의 다음 위치에 저장돼요:
~/.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 누락으로 처리되어 명시적 승인이 필요해요 (또는 쉘 바이너리를 allowlist에 추가해야 해요). - 프롬프트에서 “Always Allow”를 선택하면 해당 명령어가 allowlist에 추가돼요.
system.run환경 변수 오버라이드는 필터링된 후(PATH,DYLD_*,LD_*,NODE_OPTIONS,PYTHON*,PERL*,RUBYOPT,SHELLOPTS,PS4제거) 앱의 환경 변수와 병합돼요.- 쉘 래퍼(
bash|sh|zsh ... -c/-lc)의 경우, 요청 범위의 환경 변수 오버라이드는 작은 명시적 allowlist(TERM,LANG,LC_*,COLORTERM,NO_COLOR,FORCE_COLOR)로 축소돼요. - allowlist 모드에서 “항상 허용”을 결정할 때, 알려진 디스패치 래퍼(
env,nice,nohup,stdbuf,timeout)는 래퍼 경로 대신 내부 실행 파일 경로를 저장해요. 래핑 해제가 안전하지 않으면 allowlist 항목이 자동으로 저장되지 않아요.
딥 링크
섹션 제목: “딥 링크”앱은 로컬 액션을 위해 openclaw:// URL 스킴을 등록해요.
openclaw://agent
섹션 제목: “openclaw://agent”Gateway agent 요청을 트리거해요.
open 'openclaw://agent?message=Hello%20from%20deep%20link'쿼리 파라미터:
message(필수)sessionKey(선택)thinking(선택)deliver/to/channel(선택)timeoutSeconds(선택)key(선택 사항, 무인 모드 키)
안전성:
key가 없으면 앱에서 확인 프롬프트를 띄워요.key가 없으면 확인 프롬프트를 위해 짧은 메시지 제한을 적용하고deliver/to/channel을 무시해요.- 유효한
key가 있으면 무인 모드로 실행돼요 (개인 자동화 용도).
온보딩 흐름 (일반적)
섹션 제목: “온보딩 흐름 (일반적)”- OpenClaw.app을 설치하고 실행하세요.
- 권한 체크리스트(TCC 프롬프트)를 완료하세요.
- Local 모드가 활성화되어 있고 Gateway가 실행 중인지 확인하세요.
- 터미널 접근이 필요하다면 CLI를 설치하세요.
상태 디렉토리 위치 (macOS)
섹션 제목: “상태 디렉토리 위치 (macOS)”OpenClaw 상태 디렉토리를 iCloud나 다른 클라우드 동기화 폴더에 두지 마세요. 동기화 경로를 사용하면 지연 시간이 발생할 수 있고, 세션이나 자격 증명 파일에 대해 파일 잠금/동기화 충돌이 일어날 수 있어요.
다음과 같은 로컬 비동기화 경로를 권장해요:
OPENCLAW_STATE_DIR=~/.openclaw만약 openclaw doctor가 다음 경로 아래에서 상태를 감지하면:
~/Library/Mobile Documents/com~apple~CloudDocs/...~/Library/CloudStorage/...
경고를 표시하고 로컬 경로로 옮길 것을 추천할 거예요.
빌드 및 개발 워크플로우 (네이티브)
섹션 제목: “빌드 및 개발 워크플로우 (네이티브)”cd apps/macos && swift buildswift run OpenClaw(또는 Xcode 사용)- 앱 패키징:
scripts/package-mac-app.sh
Gateway 연결 디버깅 (macOS CLI)
섹션 제목: “Gateway 연결 디버깅 (macOS CLI)”앱을 실행하지 않고도 macOS 앱이 사용하는 것과 동일한 Gateway WebSocket 핸드셰이크 및 탐색 로직을 디버그 CLI로 테스트해 볼 수 있어요.
cd apps/macosswift run openclaw-mac connect --jsonswift run openclaw-mac discover --timeout 3000 --json연결 옵션:
--url <ws://host:port>: 설정 오버라이드--mode <local|remote>: 설정에서 확인 (기본값: 설정 또는 local)--probe: 강제로 새로운 상태 확인(health probe) 수행--timeout <ms>: 요청 타임아웃 (기본값:15000)--json: 비교를 위한 구조화된 출력
탐색 옵션:
--include-local: “local”로 필터링될 Gateway 포함--timeout <ms>: 전체 탐색 시간 (기본값:2000)--json: 비교를 위한 구조화된 출력
팁: openclaw gateway discover --json 결과와 비교해서 macOS 앱의 탐색 파이프라인(NWBrowser + tailnet DNS-SD 폴백)이 Node CLI의 dns-sd 기반 탐색과 어떻게 다른지 확인해 보세요.
원격 연결 구조 (SSH 터널)
섹션 제목: “원격 연결 구조 (SSH 터널)”macOS 앱이 Remote 모드로 실행될 때, 로컬 UI 컴포넌트가 원격 Gateway와 마치 로컬에 있는 것처럼 통신할 수 있도록 SSH 터널을 열어요.
제어 터널 (Gateway WebSocket 포트)
섹션 제목: “제어 터널 (Gateway WebSocket 포트)”- 목적: 상태 확인, 상태 표시, 웹 채팅, 설정 및 기타 제어 평면(control-plane) 호출.
- 로컬 포트: Gateway 포트(기본값
18789), 항상 고정됨. - 원격 포트: 원격 호스트의 동일한 Gateway 포트.
- 동작: 무작위 로컬 포트를 사용하지 않으며, 앱이 기존의 정상적인 터널을 재사용하거나 필요한 경우 다시 시작해요.
- SSH 형태: BatchMode + ExitOnForwardFailure + keepalive 옵션을 포함한
ssh -N -L <local>:127.0.0.1:<remote>. - IP 보고: SSH 터널은 루프백을 사용하므로 Gateway는 node IP를
127.0.0.1로 인식해요. 실제 클라이언트 IP가 나타나게 하려면 Direct (ws/wss) 전송 방식을 사용하세요 (macOS remote access 참고).
설정 단계는 macOS remote access를, 프로토콜 세부 사항은 Gateway protocol을 확인하세요.
관련 문서
섹션 제목: “관련 문서”OpenClaw Expert
아직 막혀 있나요?
이 문서에서 답을 못 찾았다면 OpenClaw Expert에게 바로 물어보세요.