OpenClaw macOS-Companion (Menüleiste + Gateway-Broker)
Die macOS-App ist der Menüleisten-Companion für OpenClaw. Sie verwaltet Berechtigungen, steuert/verbindet sich mit dem Gateway lokal (launchd oder manuell) und stellt macOS-Funktionen als Node dem Agenten zur Verfügung.
Was sie kann
- Zeigt native Benachrichtigungen und Status in der Menüleiste.
- Verwaltet TCC-Prompts (Benachrichtigungen, Bedienungshilfen, Bildschirmaufnahme, Mikrofon, Spracherkennung, Automation/AppleScript).
- Startet oder verbindet sich mit dem Gateway (lokal oder remote).
- Stellt macOS-spezifische Tools bereit (Canvas, Kamera, Bildschirmaufnahme,
system.run). - Startet den lokalen Node-Host-Service im Remote-Modus (launchd) und stoppt ihn im Lokal-Modus.
- Hostet optional PeekabooBridge für UI-Automatisierung.
- Installiert die globale CLI (
openclaw) via npm/pnpm auf Anfrage (Bun wird für die Gateway-Runtime nicht empfohlen).
Lokal vs. Remote-Modus
- Lokal (Standard): Die App verbindet sich mit einem laufenden lokalen Gateway, falls vorhanden;
andernfalls aktiviert sie den launchd-Service über
openclaw gateway install. - Remote: Die App verbindet sich über SSH/Tailscale mit einem Gateway und startet niemals einen lokalen Prozess. Die App startet den lokalen Node-Host-Service, damit das Remote-Gateway diesen Mac erreichen kann. Die App startet das Gateway nicht als Child-Prozess.
Launchd-Steuerung
Die App verwaltet einen benutzerspezifischen LaunchAgent mit dem Label ai.openclaw.gateway
(oder ai.openclaw.<profile> bei Verwendung von --profile/OPENCLAW_PROFILE; Legacy com.openclaw.* wird weiterhin entladen).
launchctl kickstart -k gui/$UID/ai.openclaw.gateway
launchctl bootout gui/$UID/ai.openclaw.gateway
Ersetze das Label durch ai.openclaw.<profile> bei Verwendung eines benannten Profils.
Falls der LaunchAgent nicht installiert ist, aktiviere ihn über die App oder führe
openclaw gateway install aus.
Node-Funktionen (Mac)
Die macOS-App präsentiert sich als Node. Gängige Befehle:
- Canvas:
canvas.present,canvas.navigate,canvas.eval,canvas.snapshot,canvas.a2ui.* - Kamera:
camera.snap,camera.clip - Bildschirm:
screen.record - System:
system.run,system.notify
Der Node meldet eine permissions-Map, damit Agenten wissen, was erlaubt ist.
Node-Service + App-IPC:
- Wenn der Headless-Node-Host-Service läuft (Remote-Modus), verbindet er sich per Gateway-WS als Node.
system.runwird in der macOS-App (UI/TCC-Kontext) über einen lokalen Unix-Socket ausgeführt; Prompts + Output bleiben in der App.
Diagramm (SCI):
Gateway -> Node Service (WS)
| IPC (UDS + Token + HMAC + TTL)
v
Mac App (UI + TCC + system.run)
Exec-Genehmigungen (system.run)
system.run wird durch Exec-Genehmigungen in der macOS-App gesteuert (Einstellungen → Exec-Genehmigungen).
Sicherheit + Ask + Allowlist werden lokal auf dem Mac gespeichert in:
~/.openclaw/exec-approvals.json
Beispiel:
{
"version": 1,
"defaults": {
"security": "deny",
"ask": "on-miss"
},
"agents": {
"main": {
"security": "allowlist",
"ask": "on-miss",
"allowlist": [{ "pattern": "/opt/homebrew/bin/rg" }]
}
}
}
Hinweise:
allowlist-Einträge sind Glob-Patterns für aufgelöste Binary-Pfade.- Roher Shell-Befehlstext mit Shell-Steuerungs- oder Expansionssyntax (
&&,||,;,|,`,$,<,>,(,)) wird als Allowlist-Miss behandelt und erfordert explizite Genehmigung (oder das Allowlisten der Shell-Binary). - Die Wahl von „Immer erlauben” im Prompt fügt den Befehl zur Allowlist hinzu.
system.run-Umgebungsüberschreibungen werden gefiltert (entferntPATH,DYLD_*,LD_*,NODE_OPTIONS,PYTHON*,PERL*,RUBYOPT,SHELLOPTS,PS4) und dann mit der App-Umgebung zusammengeführt.- Bei Shell-Wrappern (
bash|sh|zsh ... -c/-lc) werden anfragespezifische Umgebungsüberschreibungen auf eine kleine explizite Allowlist reduziert (TERM,LANG,LC_*,COLORTERM,NO_COLOR,FORCE_COLOR). - Bei Always-Allow-Entscheidungen im Allowlist-Modus werden bekannte Dispatch-Wrapper (
env,nice,nohup,stdbuf,timeout) mit inneren ausführbaren Pfaden statt Wrapper-Pfaden persistiert. Wenn das Unwrapping nicht sicher ist, wird kein Allowlist-Eintrag automatisch persistiert.
Deep Links
Die App registriert das openclaw:// URL-Schema für lokale Aktionen.
openclaw://agent
Löst eine Gateway-agent-Anfrage aus.
open 'openclaw://agent?message=Hello%20from%20deep%20link'
Query-Parameter:
message(erforderlich)sessionKey(optional)thinking(optional)deliver/to/channel(optional)timeoutSeconds(optional)key(optionaler Unattended-Mode-Schlüssel)
Sicherheit:
- Ohne
keyfragt die App zur Bestätigung. - Ohne
keyerzwingt die App ein kurzes Nachrichtenlimit für den Bestätigungsprompt und ignoriertdeliver/to/channel. - Mit einem gültigen
keyläuft der Run unbeaufsichtigt (gedacht für persönliche Automatisierungen).
Onboarding-Ablauf (typisch)
- Installiere und starte OpenClaw.app.
- Schließe die Berechtigungs-Checkliste ab (TCC-Prompts).
- Stelle sicher, dass der Lokal-Modus aktiv ist und das Gateway läuft.
- Installiere die CLI, wenn du Terminal-Zugang möchtest.
Platzierung des State-Verzeichnisses (macOS)
Vermeide es, dein OpenClaw-State-Verzeichnis in iCloud oder andere Cloud-synchronisierte Ordner zu legen. Synchronisierte Pfade können Latenz hinzufügen und gelegentlich Dateisperren-/Sync-Konflikte bei Sessions und Zugangsdaten verursachen.
Bevorzuge einen lokalen, nicht synchronisierten State-Pfad wie:
OPENCLAW_STATE_DIR=~/.openclaw
Wenn openclaw doctor State unter einem der folgenden Pfade erkennt:
~/Library/Mobile Documents/com~apple~CloudDocs/...~/Library/CloudStorage/...
wird es warnen und empfehlen, auf einen lokalen Pfad umzuziehen.
Build & Entwicklungsworkflow (nativ)
cd apps/macos && swift buildswift run OpenClaw(oder Xcode)- App paketieren:
scripts/package-mac-app.sh
Gateway-Konnektivität debuggen (macOS CLI)
Verwende die Debug-CLI, um denselben Gateway-WebSocket-Handshake und dieselbe Discovery-Logik auszuführen, die die macOS-App nutzt, ohne die App zu starten.
cd apps/macos
swift run openclaw-mac connect --json
swift run openclaw-mac discover --timeout 3000 --json
Connect-Optionen:
--url <ws://host:port>: Konfiguration überschreiben--mode <local|remote>: aus Konfiguration auflösen (Standard: Konfiguration oder local)--probe: frischen Health-Probe erzwingen--timeout <ms>: Request-Timeout (Standard:15000)--json: strukturierte Ausgabe zum Vergleichen
Discovery-Optionen:
--include-local: Gateways einschließen, die als „lokal” gefiltert würden--timeout <ms>: gesamtes Discovery-Zeitfenster (Standard:2000)--json: strukturierte Ausgabe zum Vergleichen
Tipp: Vergleiche mit openclaw gateway discover --json, um zu sehen, ob die Discovery-Pipeline
der macOS-App (NWBrowser + Tailnet DNS-SD Fallback) sich von der dns-sd-basierten Discovery
der Node-CLI unterscheidet.
Remote-Verbindungs-Plumbing (SSH-Tunnel)
Wenn die macOS-App im Remote-Modus läuft, öffnet sie einen SSH-Tunnel, damit lokale UI-Komponenten mit einem Remote-Gateway kommunizieren können, als wäre es auf localhost.
Control-Tunnel (Gateway-WebSocket-Port)
- Zweck: Health-Checks, Status, Web-Chat, Konfiguration und andere Control-Plane-Aufrufe.
- Lokaler Port: der Gateway-Port (Standard
18789), immer stabil. - Remote-Port: derselbe Gateway-Port auf dem Remote-Host.
- Verhalten: kein zufälliger lokaler Port; die App nutzt einen bestehenden gesunden Tunnel oder startet ihn bei Bedarf neu.
- SSH-Aufbau:
ssh -N -L <local>:127.0.0.1:<remote>mit BatchMode + ExitOnForwardFailure + Keepalive-Optionen. - IP-Meldung: Der SSH-Tunnel nutzt Loopback, daher sieht das Gateway die Node-IP
als
127.0.0.1. Verwende Direct (ws/wss) Transport, wenn die echte Client-IP angezeigt werden soll (siehe macOS-Fernzugriff).
Für Setup-Schritte siehe macOS-Fernzugriff. Für Protokoll-Details siehe Gateway-Protokoll.