Files
openclaw/docs/platforms/mac/dev-setup.md
T
Peter Steinberger f87580ceb8 build(macos): add OPENCLAW_SKIP_MLX_TTS to unblock beta-toolchain builds (#123698)
The openclaw-mlx-tts voice helper pulls in the full mlx-swift Metal shader
stack, which some beta Xcode toolchains (e.g. Xcode 27 / macOS 27 SDK) cannot
compile: the metal compiler dies non-deterministically (a different .metal file
each run, 'Could not read serialized diagnostics file'). The main app builds
fine, so an unrelated dev/proof build should not be blocked by the helper.

Add OPENCLAW_SKIP_MLX_TTS=1 (matching the sibling SKIP_TSC/SKIP_UI_BUILD
toggles) to package the app without the voice helper, gating both the per-arch
build and the bundle copy. Refuse the flag for release builds, which must ship
the helper (notarization verifies it), so a skipped build can never become a
silently incomplete release.
2026-08-14 08:28:43 -07:00

3.9 KiB

summary, read_when, title
summary read_when title
Setup guide for developers working on the OpenClaw macOS app
Setting up the macOS development environment
macOS dev setup

macOS developer setup

Build and run the OpenClaw macOS application from source.

Prerequisites

  • Xcode 26.2+ (Swift 6.2 toolchain), on the latest macOS available in Software Update.
  • Node.js 24.15+ & pnpm for the gateway, CLI, and packaging scripts. Node 22.22.3+ also works.

1. Install dependencies

pnpm install

2. Build and package the app

./scripts/package-mac-app.sh

Outputs dist/OpenClaw.app. Without an Apple Developer ID certificate, the script falls back to ad-hoc signing.

Set OPENCLAW_SKIP_MLX_TTS=1 to package a dev/proof build without the local MLX voice helper. This skips the openclaw-mlx-tts binary and its large mlx-swift Metal shader stack, which some beta Xcode toolchains cannot compile. The resulting app has no on-device MLX voice; it is rejected for release builds, which must ship the helper.

For dev run modes, signing flags, and Team ID troubleshooting, see apps/macos/README.md. Fast dev loop from repo root: scripts/restart-mac.sh (add --no-sign for ad-hoc signing; TCC permissions do not stick with --no-sign).

Ad-hoc signed apps may trigger security prompts. If the app crashes immediately with "Abort trap 6", see [Troubleshooting](#troubleshooting).

3. Install the CLI and Gateway

The packaged app embeds the canonical scripts/install-cli.sh installer. On a fresh profile, choose This Mac during onboarding; the app installs the matching user-space CLI and runtime before starting the Gateway wizard.

For manual development recovery, install the matching CLI yourself:

npm install -g openclaw@<version>

pnpm add -g openclaw@<version> and bun add -g openclaw@<version> also work. Node remains the recommended runtime for the Gateway itself.

Troubleshooting

Build fails: toolchain or SDK mismatch

The macOS app build expects the latest macOS SDK and the Swift 6.2 toolchain (Xcode 26.2+).

xcodebuild -version
xcrun swift --version

If versions don't match, update macOS/Xcode and re-run the build.

Build fails: MLX voice helper Metal shaders

On a beta-only Xcode toolchain (for example Xcode 27 with the macOS 27 SDK), only the openclaw-mlx-tts helper may fail while the main app builds fine. The mlx-swift Metal compilation errors non-deterministically (a different .metal file each run, Could not read serialized diagnostics file then a nonzero metal exit), because the beta metal compiler and its separately downloaded Metal Toolchain are still unstable. This is an upstream toolchain issue, not an OpenClaw one.

If you do not need on-device MLX voice, skip the helper:

OPENCLAW_SKIP_MLX_TTS=1 ./scripts/package-mac-app.sh

Otherwise, install the Metal Toolchain (xcodebuild -downloadComponent MetalToolchain) and build from a stable Xcode release.

App crashes on permission grant

If the app crashes when you try to allow Speech Recognition or Microphone access, it may be a corrupted TCC cache or signature mismatch.

  1. Reset TCC permissions for the debug bundle id:

    tccutil reset All ai.openclaw.mac.debug
    
  2. If that fails, temporarily change BUNDLE_ID in scripts/package-mac-app.sh to force a clean slate from macOS.

Gateway "Starting..." indefinitely

Check whether a zombie process holds the port:

openclaw gateway status
openclaw gateway stop

# If you're not using a LaunchAgent (dev mode / manual runs), find the listener:
lsof -nP -iTCP:18789 -sTCP:LISTEN

If a manual run holds the port, stop it (Ctrl+C), or kill the PID found above as a last resort.