|
1 | 1 | --- |
2 | | -summary: "OpenClaw macOS companion app (menu bar + gateway broker)" |
| 2 | +summary: "Install and use the OpenClaw macOS menu bar app" |
3 | 3 | read_when: |
4 | | - - Implementing macOS app features |
5 | | - - Changing gateway lifecycle or node bridging on macOS |
| 4 | + - Installing the macOS app |
| 5 | + - Deciding between local and remote Gateway mode on macOS |
| 6 | + - Looking for macOS app release downloads |
6 | 7 | title: "macOS app" |
7 | 8 | --- |
8 | 9 |
|
9 | | -The macOS app is the **menu-bar companion** for OpenClaw. It owns permissions, |
10 | | -manages/attaches to the Gateway locally (launchd or manual), and exposes macOS |
11 | | -capabilities to the agent as a node. |
| 10 | +The macOS app is the OpenClaw **menu bar companion**. Use it when you want a |
| 11 | +native tray UI, macOS permission prompts, notifications, WebChat, voice input, |
| 12 | +Canvas, or Mac-hosted node tools such as `system.run`. |
12 | 13 |
|
13 | | -## What it does |
| 14 | +If you only need the CLI and Gateway, start with [Getting started](/start/getting-started). |
14 | 15 |
|
15 | | -- Shows native notifications and status in the menu bar. |
16 | | -- Owns TCC prompts (Notifications, Accessibility, Screen Recording, Microphone, |
17 | | - Speech Recognition, Automation/AppleScript). |
18 | | -- Runs or connects to the Gateway (local or remote). |
19 | | -- Exposes macOS-only tools (Canvas, Camera, Screen Recording, `system.run`). |
20 | | -- Starts the local node host service in **remote** mode (launchd), and stops it in **local** mode. |
21 | | -- Optionally hosts **PeekabooBridge** for UI automation. |
22 | | -- Installs the global CLI (`openclaw`) on request via npm, pnpm, or bun (the app prefers npm, then pnpm, then bun; Node remains the recommended Gateway runtime). |
| 16 | +## Download |
23 | 17 |
|
24 | | -## Local vs remote mode |
| 18 | +Download macOS app builds from the |
| 19 | +[OpenClaw GitHub releases](https://github.com/openclaw/openclaw/releases). |
| 20 | +When a release includes macOS app assets, look for: |
25 | 21 |
|
26 | | -- **Local** (default): the app attaches to a running local Gateway if present; |
27 | | - otherwise it enables the launchd service via `openclaw gateway install`. |
28 | | -- **Remote**: the app connects to a Gateway over SSH/Tailscale and never starts |
29 | | - a local process. |
30 | | - The app starts the local **node host service** so the remote Gateway can reach this Mac. |
31 | | - The app does not spawn the Gateway as a child process. |
32 | | - Gateway discovery now prefers Tailscale MagicDNS names over raw tailnet IPs, |
33 | | - so the Mac app recovers more reliably when tailnet IPs change. |
| 22 | +- `OpenClaw-<version>.dmg` (preferred) |
| 23 | +- `OpenClaw-<version>.zip` |
34 | 24 |
|
35 | | -## Launchd control |
| 25 | +Some releases only include CLI, evidence, or Windows assets. If the newest |
| 26 | +release has no macOS app asset, use the newest release that does, or build the |
| 27 | +app from source with [macOS dev setup](/platforms/mac/dev-setup). |
36 | 28 |
|
37 | | -The app manages a per-user LaunchAgent labeled `ai.openclaw.gateway` |
38 | | -(or `ai.openclaw.<profile>` when using `--profile`/`OPENCLAW_PROFILE`; legacy `com.openclaw.*` still unloads). |
39 | | - |
40 | | -```bash |
41 | | -launchctl kickstart -k gui/$UID/ai.openclaw.gateway |
42 | | -launchctl bootout gui/$UID/ai.openclaw.gateway |
43 | | -``` |
44 | | - |
45 | | -Replace the label with `ai.openclaw.<profile>` when running a named profile. |
46 | | - |
47 | | -If the LaunchAgent isn't installed, enable it from the app or run |
48 | | -`openclaw gateway install`. |
49 | | - |
50 | | -If the gateway repeatedly disappears for minutes to hours and only resumes when you touch the Control UI or SSH into the host, see the troubleshooting note for macOS Maintenance Sleep / `ENETDOWN` crashes and launchd's respawn-protection gate in [Gateway troubleshooting](/gateway/troubleshooting#macos-gateway-silently-stops-responding-then-resumes-when-you-touch-the-dashboard). |
51 | | - |
52 | | -## Node capabilities (mac) |
53 | | - |
54 | | -The macOS app presents itself as a node. Common commands: |
55 | | - |
56 | | -- Canvas: `canvas.present`, `canvas.navigate`, `canvas.eval`, `canvas.snapshot`, `canvas.a2ui.*` |
57 | | -- Camera: `camera.snap`, `camera.clip` |
58 | | -- Screen: `screen.snapshot`, `screen.record` |
59 | | -- System: `system.run`, `system.notify` |
60 | | - |
61 | | -The node reports a `permissions` map so agents can decide what's allowed. |
62 | | - |
63 | | -Node service + app IPC: |
64 | | - |
65 | | -- When the headless node host service is running (remote mode), it connects to the Gateway WS as a node. |
66 | | -- `system.run` executes in the macOS app (UI/TCC context) over a local Unix socket; prompts + output stay in-app. |
67 | | - |
68 | | -Diagram (SCI): |
69 | | - |
70 | | -``` |
71 | | -Gateway -> Node Service (WS) |
72 | | - | IPC (UDS + token + HMAC + TTL) |
73 | | - v |
74 | | - Mac App (UI + TCC + system.run) |
75 | | -``` |
76 | | - |
77 | | -## Exec approvals (system.run) |
78 | | - |
79 | | -`system.run` is controlled by **Exec approvals** in the macOS app (Settings → Exec approvals). |
80 | | -Security + ask + allowlist are stored locally on the Mac in: |
81 | | - |
82 | | -``` |
83 | | -~/.openclaw/exec-approvals.json |
84 | | -``` |
85 | | - |
86 | | -Example: |
87 | | - |
88 | | -```json |
89 | | -{ |
90 | | - "version": 1, |
91 | | - "defaults": { |
92 | | - "security": "deny", |
93 | | - "ask": "on-miss" |
94 | | - }, |
95 | | - "agents": { |
96 | | - "main": { |
97 | | - "security": "allowlist", |
98 | | - "ask": "on-miss", |
99 | | - "allowlist": [{ "pattern": "/opt/homebrew/bin/rg" }] |
100 | | - } |
101 | | - } |
102 | | -} |
103 | | -``` |
104 | | - |
105 | | -Notes: |
106 | | - |
107 | | -- `allowlist` entries are glob patterns for resolved binary paths, or bare command names for PATH-invoked commands. |
108 | | -- Raw shell command text that contains shell control or expansion syntax (`&&`, `||`, `;`, `|`, `` ` ``, `$`, `<`, `>`, `(`, `)`) is treated as an allowlist miss and requires explicit approval (or allowlisting the shell binary). |
109 | | -- Choosing "Always Allow" in the prompt adds that command to the allowlist. |
110 | | -- `system.run` environment overrides are filtered (drops `PATH`, `DYLD_*`, `LD_*`, `BASHOPTS`, `FPATH`, `KSH_ENV`, `NODE_OPTIONS`, `NODE_REDIRECT_WARNINGS`, `NODE_REPL_EXTERNAL_MODULE`, `NODE_REPL_HISTORY`, `NODE_V8_COVERAGE`, `PYTHON*`, `PERL*`, `RUBYOPT`, `SHELLOPTS`, `PS4`, `TCLLIBPATH`) and then merged with the app's environment. |
111 | | -- For shell wrappers (`bash|sh|zsh ... -c/-lc`), request-scoped environment overrides are reduced to a small explicit allowlist (`TERM`, `LANG`, `LC_*`, `COLORTERM`, `NO_COLOR`, `FORCE_COLOR`). |
112 | | -- For allow-always decisions in allowlist mode, known dispatch wrappers (`env`, `flock`, `nice`, `nohup`, `stdbuf`, `timeout`) persist inner executable paths instead of wrapper paths. If unwrapping is not safe, no allowlist entry is persisted automatically. |
113 | | - |
114 | | -## Deep links |
115 | | - |
116 | | -The app registers the `openclaw://` URL scheme for local actions. |
117 | | - |
118 | | -### `openclaw://agent` |
119 | | - |
120 | | -Triggers a Gateway `agent` request. |
121 | | - |
122 | | -```bash |
123 | | -open 'openclaw://agent?message=Hello%20from%20deep%20link' |
124 | | -``` |
125 | | - |
126 | | -Query parameters: |
127 | | - |
128 | | -- `message` (required) |
129 | | -- `sessionKey` (optional) |
130 | | -- `thinking` (optional) |
131 | | -- `deliver` / `to` / `channel` (optional) |
132 | | -- `timeoutSeconds` (optional) |
133 | | -- `key` (optional unattended mode key) |
134 | | - |
135 | | -Safety: |
136 | | - |
137 | | -- Without `key`, the app prompts for confirmation. |
138 | | -- Without `key`, the app enforces a short message limit for the confirmation prompt and ignores `deliver` / `to` / `channel`. |
139 | | -- With a valid `key`, the run is unattended (intended for personal automations). |
140 | | - |
141 | | -## Onboarding flow (typical) |
| 29 | +## First run |
142 | 30 |
|
143 | 31 | 1. Install and launch **OpenClaw.app**. |
144 | | -2. Complete the permissions checklist (TCC prompts). |
145 | | -3. Ensure **Local** mode is active and the Gateway is running. |
146 | | -4. Install the CLI if you want terminal access. |
147 | | - |
148 | | -## State dir placement (macOS) |
149 | | - |
150 | | -Avoid putting your OpenClaw state dir in iCloud or other cloud-synced folders. |
151 | | -Sync-backed paths can add latency and occasionally cause file-lock/sync races for |
152 | | -sessions and credentials. |
153 | | - |
154 | | -Prefer a local non-synced state path such as: |
155 | | - |
156 | | -```bash |
157 | | -OPENCLAW_STATE_DIR=~/.openclaw |
158 | | -``` |
159 | | - |
160 | | -If `openclaw doctor` detects state under: |
161 | | - |
162 | | -- `~/Library/Mobile Documents/com~apple~CloudDocs/...` |
163 | | -- `~/Library/CloudStorage/...` |
164 | | - |
165 | | -it will warn and recommend moving back to a local path. |
166 | | - |
167 | | -## Build and dev workflow (native) |
168 | | - |
169 | | -- `cd apps/macos && swift build` |
170 | | -- `swift run OpenClaw` (or Xcode) |
171 | | -- Package app: `scripts/package-mac-app.sh` |
172 | | - |
173 | | -## Debug gateway connectivity (macOS CLI) |
174 | | - |
175 | | -Use the debug CLI to exercise the same Gateway WebSocket handshake and discovery |
176 | | -logic that the macOS app uses, without launching the app. |
177 | | - |
178 | | -```bash |
179 | | -cd apps/macos |
180 | | -swift run openclaw-mac connect --json |
181 | | -swift run openclaw-mac discover --timeout 3000 --json |
182 | | -``` |
183 | | - |
184 | | -Connect options: |
185 | | - |
186 | | -- `--url <ws://host:port>`: override config |
187 | | -- `--mode <local|remote>`: resolve from config (default: config or local) |
188 | | -- `--probe`: force a fresh health probe |
189 | | -- `--timeout <ms>`: request timeout (default: `15000`) |
190 | | -- `--json`: structured output for diffing |
191 | | - |
192 | | -Discovery options: |
193 | | - |
194 | | -- `--include-local`: include gateways that would be filtered as "local" |
195 | | -- `--timeout <ms>`: overall discovery window (default: `2000`) |
196 | | -- `--json`: structured output for diffing |
197 | | - |
198 | | -<Tip> |
199 | | -Compare against `openclaw gateway discover --json` to see whether the macOS app's discovery pipeline (`local.` plus the configured wide-area domain, with wide-area and Tailscale Serve fallbacks) differs from the Node CLI's `dns-sd` based discovery. |
200 | | -</Tip> |
201 | | - |
202 | | -## Remote connection plumbing (SSH tunnels) |
203 | | - |
204 | | -When the macOS app runs in **Remote** mode, it opens an SSH tunnel so local UI |
205 | | -components can talk to a remote Gateway as if it were on localhost. |
206 | | - |
207 | | -### Control tunnel (Gateway WebSocket port) |
208 | | - |
209 | | -- **Purpose:** health checks, status, Web Chat, config, and other control-plane calls. |
210 | | -- **Local port:** the Gateway port (default `18789`), always stable. |
211 | | -- **Remote port:** the same Gateway port on the remote host. |
212 | | -- **Behavior:** no random local port; the app reuses an existing healthy tunnel |
213 | | - or restarts it if needed. |
214 | | -- **SSH shape:** `ssh -N -L <local>:127.0.0.1:<remote>` with BatchMode + |
215 | | - ExitOnForwardFailure + keepalive options. |
216 | | -- **IP reporting:** the SSH tunnel uses loopback, so the gateway will see the node |
217 | | - IP as `127.0.0.1`. Use **Direct (ws/wss)** transport if you want the real client |
218 | | - IP to appear (see [macOS remote access](/platforms/mac/remote)). |
219 | | - |
220 | | -For setup steps, see [macOS remote access](/platforms/mac/remote). For protocol |
221 | | -details, see [Gateway protocol](/gateway/protocol). |
222 | | - |
223 | | -## Related docs |
224 | | - |
225 | | -- [Gateway runbook](/gateway) |
226 | | -- [Gateway (macOS)](/platforms/mac/bundled-gateway) |
227 | | -- [macOS permissions](/platforms/mac/permissions) |
228 | | -- [Canvas](/platforms/mac/canvas) |
| 32 | +2. Complete the macOS permission checklist. |
| 33 | +3. Pick **Local** or **Remote** mode. |
| 34 | +4. Install the `openclaw` CLI if the app asks for it. |
| 35 | +5. Open WebChat from the menu bar and send a test message. |
| 36 | + |
| 37 | +For the CLI/Gateway setup path, use [Getting started](/start/getting-started). |
| 38 | +For permission recovery, use [macOS permissions](/platforms/mac/permissions). |
| 39 | + |
| 40 | +## Choose a Gateway mode |
| 41 | + |
| 42 | +| Mode | Use it when | Detail page | |
| 43 | +| ------ | --------------------------------------------------------------------------------------- | -------------------------------------------------- | |
| 44 | +| Local | This Mac should run the Gateway and keep it alive with launchd. | [Gateway on macOS](/platforms/mac/bundled-gateway) | |
| 45 | +| Remote | Another host runs the Gateway and this Mac should control it over SSH, LAN, or Tailnet. | [Remote control](/platforms/mac/remote) | |
| 46 | + |
| 47 | +Local mode requires an installed `openclaw` CLI. The app can install it, or you |
| 48 | +can follow [Gateway on macOS](/platforms/mac/bundled-gateway). |
| 49 | + |
| 50 | +## What the app owns |
| 51 | + |
| 52 | +- Menu bar status, notifications, health, and WebChat. |
| 53 | +- macOS permission prompts for screen, microphone, speech, automation, and accessibility. |
| 54 | +- Local node tools such as Canvas, camera/screen capture, notifications, and `system.run`. |
| 55 | +- Exec approval prompts for Mac-hosted commands. |
| 56 | +- Remote-mode SSH tunnels or direct Gateway connections. |
| 57 | + |
| 58 | +The app does **not** replace the OpenClaw Gateway or general CLI docs. Core |
| 59 | +Gateway configuration, providers, plugins, channels, tools, and security live in |
| 60 | +their own docs. |
| 61 | + |
| 62 | +## macOS detail pages |
| 63 | + |
| 64 | +| Task | Read | |
| 65 | +| ---------------------------------------- | ------------------------------------------------------------------------------------------- | |
| 66 | +| Install or debug the CLI/Gateway service | [Gateway on macOS](/platforms/mac/bundled-gateway) | |
| 67 | +| Keep state out of cloud-synced folders | [Gateway on macOS](/platforms/mac/bundled-gateway#state-directory-on-macos) | |
| 68 | +| Debug app discovery and connectivity | [Gateway on macOS](/platforms/mac/bundled-gateway#debug-app-connectivity) | |
| 69 | +| Understand launchd behavior | [Gateway lifecycle](/platforms/mac/child-process) | |
| 70 | +| Fix permissions or signing/TCC issues | [macOS permissions](/platforms/mac/permissions) | |
| 71 | +| Connect to a remote Gateway | [Remote control](/platforms/mac/remote) | |
| 72 | +| Read menu bar status and health checks | [Menu bar](/platforms/mac/menu-bar), [Health checks](/platforms/mac/health) | |
| 73 | +| Use the embedded chat UI | [WebChat](/platforms/mac/webchat) | |
| 74 | +| Use voice wake or push-to-talk | [Voice wake](/platforms/mac/voicewake) | |
| 75 | +| Use Canvas and Canvas deep links | [Canvas](/platforms/mac/canvas) | |
| 76 | +| Host PeekabooBridge for UI automation | [Peekaboo bridge](/platforms/mac/peekaboo) | |
| 77 | +| Configure command approvals | [Exec approvals](/tools/exec-approvals), [advanced details](/tools/exec-approvals-advanced) | |
| 78 | +| Inspect Mac node commands and app IPC | [macOS IPC](/platforms/mac/xpc) | |
| 79 | +| Capture logs | [macOS logging](/platforms/mac/logging) | |
| 80 | +| Build from source | [macOS dev setup](/platforms/mac/dev-setup) | |
| 81 | + |
| 82 | +## Related |
| 83 | + |
| 84 | +- [Platforms](/platforms) |
| 85 | +- [Getting started](/start/getting-started) |
| 86 | +- [Gateway](/gateway) |
| 87 | +- [Exec approvals](/tools/exec-approvals) |
0 commit comments