Skip to content

Sign OpenClaw macOS Debug Builds: Complete Guide

If you have ever spent your afternoon clicking “Allow” on the same macOS permission prompts every time you rebuild your app, you know how frustrating it is. macOS security is great for users, but for developers, it can feel like a wall that resets every time your binary changes.

This guide explains how we handle macOS signing for debug builds in OpenClaw to keep your development flow smooth and your permissions persistent.

The app is usually built using scripts/package-mac-app.sh. This script handles several important tasks for you:

  • It sets a stable debug bundle identifier: ai.openclaw.mac.debug.
  • It writes the Info.plist with that bundle id (you can override this via BUNDLE_ID=...).
  • It calls scripts/codesign-mac-app.sh to sign the main binary and app bundle. This ensures macOS treats each rebuild as the same signed bundle and keeps your TCC permissions (notifications, accessibility, screen recording, mic, speech). For stable permissions, you should use a real signing identity; ad-hoc is opt-in and fragile (see macOS permissions).
  • It uses CODESIGN_TIMESTAMP=auto by default to enable trusted timestamps for Developer ID signatures. You can set CODESIGN_TIMESTAMP=off to skip timestamping for offline debug builds.
  • It injects build metadata into Info.plist: OpenClawBuildTimestamp (UTC) and OpenClawGitCommit (short hash) so the About pane can show build, git, and debug/release channel info.
  • Packaging defaults to Node 24: The script runs TS builds and the Control UI build. Node 22 LTS, currently 22.14+, remains supported for compatibility.
  • It reads SIGN_IDENTITY from your environment. You can add export SIGN_IDENTITY="Apple Development: Your Name (TEAMID)" (or your Developer ID Application cert) to your shell rc to always sign with your cert. Ad-hoc signing requires explicit opt-in via ALLOW_ADHOC_SIGNING=1 or SIGN_IDENTITY="-" (this is not recommended for permission testing).
  • It runs a Team ID audit after signing and fails if any Mach-O inside the app bundle is signed by a different Team ID. You can set SKIP_TEAM_ID_CHECK=1 to bypass this.
Terminal window
# from repo root
scripts/package-mac-app.sh # auto-selects identity; errors if none found
SIGN_IDENTITY="Developer ID Application: Your Name" scripts/package-mac-app.sh # real cert
ALLOW_ADHOC_SIGNING=1 scripts/package-mac-app.sh # ad-hoc (permissions will not stick)
SIGN_IDENTITY="-" scripts/package-mac-app.sh # explicit ad-hoc (same caveat)
DISABLE_LIBRARY_VALIDATION=1 scripts/package-mac-app.sh # dev-only Sparkle Team ID mismatch workaround

When signing with SIGN_IDENTITY="-" (ad-hoc), the script automatically disables the Hardened Runtime (--options runtime). This is necessary to prevent crashes when the app attempts to load embedded frameworks (like Sparkle) that do not share the same Team ID. Ad-hoc signatures also break TCC permission persistence; see macOS permissions for recovery steps.

package-mac-app.sh stamps the bundle with:

  • OpenClawBuildTimestamp: ISO8601 UTC at package time
  • OpenClawGitCommit: short git hash (or unknown if unavailable)

The About tab reads these keys to show version, build date, git commit, and whether it’s a debug build (via #if DEBUG). You should run the packager to refresh these values after making code changes.

TCC permissions are tied to the bundle identifier and the code signature. Unsigned debug builds with changing UUIDs cause macOS to forget grants after each rebuild. By signing the binaries (ad‑hoc by default) and keeping a fixed bundle id and path (dist/OpenClaw.app), the system preserves those grants between builds. This matches the VibeTunnel approach to local development.

Need help setting up your environment? Talk to the AI Setup Assistant.

OpenClaw

OpenClaw Expert

Still stuck?

If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.