拓冰建站拓冰建站
首页 / 资讯中心 / 正文

OpenClaw macOS 应用开发与签名实战指南:从快速开发到分发打包

OpenClaw macOS 应用开发与签名实战指南从快速开发到分发打包【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw本篇指南以 apps/macos/README.md 为核心系统讲解 OpenClaw 官方 macOS 桌面应用在开发、签名、打包、测试与发布全流程中的工程实践。你将掌握restart-mac.sh快速开发循环、命名 Profile 多实例隔离、原生测试的安全运行方式、开发包与分发产物的构建差异以及代码签名、Team ID 审计、Sparkle 更新库校验等 macOS 特有的踩坑点与绕过方案。快速开发运行restart-mac.sh在仓库根目录执行一个命令即可完成杀掉旧实例 → 重建 → 重新打包 → 重新启动 → 验证存活的完整开发循环scripts/restart-mac.sh从 restart-mac.sh 的源码结构可以看到该脚本依次执行获取进程级互斥锁防止并发重启互相干扰、停止所有已知的 OpenClaw 实例包括dist/OpenClaw.app、/Applications/OpenClaw.app以及 Swift 构建产物打包插件资源pnpm plugins:assets:build在临时目录中完成应用打包与签名验证codesign --verify --deep --strict最后以最小化环境变量启动应用并确认进程存活。常用启动选项选项作用适用场景--no-sign跳过正式代码签名走 ad-hoc 签名最快开发路径但 TCC 权限如辅助功能、屏幕录制不会持久保留--sign强制代码签名需要真实证书时才用没有证书会直接失败--background-only保持服务运行但不弹出任何自动窗口无人值守 / 后台任务场景--attach-only跳过 launchd 安装仅以附加模式启动应用外部进程已托管本地 Gateway 时--wait/-w等待其他正在进行的重启完成而不是直接退出并发触发重启脚本时--target-only只重启当前 checkout 的 dist 应用若其他 OpenClaw 实例活跃则失败需要精确定位本仓库构建产物时几个选项可以组合使用例如scripts/restart-mac.sh --no-sign # 最快的开发路径 scripts/restart-mac.sh --sign # 强制代码签名需要证书 scripts/restart-mac.sh --background-only # 后台运行不弹窗 scripts/restart-mac.sh --attach-only --background-only # 外部托管 Gateway 时的无人值守模式注意--sign与--no-sign不能同时使用脚本会直接报错。无签名模式的内部机制无签名模式--no-sign下脚本做了三件关键的事设置ALLOW_ADHOC_SIGNING1与SIGN_IDENTITY-让打包脚本走 ad-hoc 签名在~/.openclaw/disable-launchagent写入标记文件禁止应用写 launchd 代理通过node openclaw.mjs daemon install --force --runtime node安装并重启 Gateway 守护进程使 Gateway LaunchAgent 指向仓库 CLI随后读取~/.openclaw/openclaw.json中的gateway.port默认 18789并验证端口在监听。无签名恢复命令开发过程中如果进入了无签名状态可以用以下命令恢复node openclaw.mjs daemon install --force --runtime node node openclaw.mjs daemon restart若需要重置无签名的覆盖配置恢复 launchd 代理写入删除标记文件即可rm ~/.openclaw/disable-launchagent自动签名检测默认行为是自动检测签名密钥若系统中存在Developer ID Application、Apple Distribution或Apple Development证书则自动签名否则回退到--no-sign。检测逻辑位于 restart-mac.sh 的check_signing_keys()通过security find-identity -p codesigning -v实现。应用 Profile多实例隔离运行OpenClaw 支持通过环境变量启动一个独立配置的应用实例Profile 名称与 CLI 使用的 profile 同名OPENCLAW_PROFILEwork /Applications/OpenClaw.app/Contents/MacOS/OpenClawProfile 命名规则Profile 名称必须是 1–64 位小写字母、数字、下划线或连字符且必须以字母或数字开头。以下名称有特殊语义default普通应用等价于未设置 Profilegateway、mac、node保留的 LaunchAgent 身份标识不可用作普通 Profile。Profile 隔离了什么从 AppProfile.swift 的实现可以确认命名 Profile 会建立一套完整的隔离边界状态目录~/.openclaw-name应用默认配置域UserDefaultssuiteai.openclaw.name.profile.nameKeychain 服务附加.profile.name后缀单实例锁/tmp/openclaw-uid-app-instances/ai.openclaw.mac.profile.name.lockCLI 管理的 Gateway 服务ai.openclaw.name。稳定的 Profile 端口推导默认网关端口 18789 仅在 default Profile 下使用。命名 Profile 会基于名称哈希推导一个稳定端口20000–59999 区间其哈希算法在 AppProfile.swift 中与src/config/paths.ts的resolveGatewayPort保持字节级一致确保应用与 CLI 能连到同一个 Profile Gateway。当然通过配置或环境变量显式指定端口总是优先的。Profile 模式的限制restart-mac.sh 明确拒绝处理命名 Profilerestart-mac.sh cannot safely target one app profile因为其打包清理是主机全局的请正常构建/打包后用上面的命令直接启动命名 ProfileProfile 模式下禁用应用重定位、Sparkle 更新以及更新后的服务修复更新已安装应用请走默认 Profile 的正常流程Profile 模式不会安装或修改主机全局的 Mac 节点服务或 OpenClaw 登录项运行时子节点仍照常在进程内运行。注意Profile 不是测试沙箱PortGuardian 会在所有应用实例间共享隧道账本与孤儿清理逻辑端口预留也会检查其他 Profile 的 Gateway 服务占用见 ProfileGatewayPortReservation.swift。当验证场景不允许访问或改动操作者状态时请使用干净的测试账户或虚拟机而非命名 Profile。原生测试如何安全地跑通 AppKit / WebKit 套件测试安全性的核心原则OpenClaw 的原生测试涉及偏好设置、Keychain、AppKit 窗口与 WebKit 辅助进程仅靠测试过滤或临时HOME远远不够。官方建议只在一次性的 macOS CI 或虚拟机无操作者凭据、无活动 Gateway中运行完整测试套件本地子集测试同样需要经过验证的 OS 沙箱以及测试专用的资源。CI 中的隔离机制macos-swiftCI 任务通过 scripts/test-macos-native.mts 运行测试完整套件保留默认 Profile 行为命名 Profile 的 AppState 隔离测试单独运行。每个测试进程都获得独立的私有 home 目录与 config/state 路径短时TMPDIR对遵守该变量的工具生效Foundation 则仍使用 Darwin 每用户临时目录TestIsolationfixture 会在其中自建并清理独有目录一个未加锁的一次性 Keychain被设为用户域默认与搜索列表使目录迁移无需弹出创建登录钥匙串的提示该 Keychain 只在测试资源上禁用自动锁定测试进程组退出后即被删除失败的或未经验证的清理会保留资源并导致启动失败fail-closed。注意launcher 本身并不是沙箱本地运行 scripts/prepush-ci.sh 会保留 Swift lint/构建检查但会将原生测试证据标记为不完整并要求提供精确 commit 对应的macos-swiftCI 结果。打包流程开发包与分发产物的区别开发包签名但不公证scripts/package-mac-app.sh该脚本构建并组装dist/OpenClaw.app通过 scripts/codesign-mac-app.sh 签名。从 package-mac-app.sh 可以看到它做了相当多的工作先跑pnpm install --frozen-lockfile与pnpm build校验 JS 构建来源dist/build-info.json的 version/commit/buildAt 必须匹配调用 scripts/build-mac-swift.mts 构建 Swift 二进制随后组装 Info.plist、复制 macOS 控制 CLIopenclaw-mac、MLX TTS 本地语音助手、Sparkle.framework、CUA 驱动、cloudflared、CLI 安装器、原生 Node worker、Control UI 资源与 SwiftPM 资源包等最后签名并校验。开发包不是分发产物。关键的打包环境变量BUNDLE_ID默认ai.openclaw.mac.debugdebug 后缀会清空SUFeedURL并关闭 Sparkle 自动检查BUILD_CONFIG默认debugrelease 强制要求构建元数据并做源代码校验apple-release-source-check.shBUILD_ARCHSrelease 默认all即 arm64 x86_64 通用二进制debug 默认当前机器架构OPENCLAW_SKIP_MLX_TTS1跳过 MLX 语音助手release 构建禁止公证会校验它OPENCLAW_PACKAGE_APP_ROOT指定输出 bundle 根但必须位于dist/下。分发产物ZIP DMG含公证scripts/package-mac-dist.shpackage-mac-dist.sh 在开发包基础上继续产出三类分发产物输出到dist/OpenClaw-version.zipSparkle 更新用 ZIPOpenClaw-version.dmg给用户的磁盘映像OpenClaw-version.dSYM.zip符号文件。该脚本默认 release 配置与发布 Bundle IDai.openclaw.mac通过 scripts/notarize-mac-artifact.sh 走 Apple 公证notarization并回填 staple。它内置了不可中断的恢复检查点若公证中途失败可用--resume-notarization从断点恢复每次新构建前若检测到未完成的检查点会强制要求先恢复或清理。release 构建还会强制校验CFBundleVersion不低于 Sparkle 规范构建号下限防止更新回退。无人值守的 Peekaboo 提权宿主内部工作流对于无人值守的 Peekaboo 提权宿主使用闭源 Foundation 签名 profile 与按源码地址寻址source-addressed的 ZIP 工作流。package是内部发布操作者命令需要 OpenClaw Foundation 签名身份与公证凭据其归档不是通用下载产物scripts/mac-elevation-host.sh package \ --peekaboo-source-commit full-peekaboo-sha cd dist/elevation-host export PREFIXOpenClaw-full-openclaw-sha-Peekaboo-full-peekaboo-sha-stable export INSTALLER_SHA256authenticated-installer-sha256 export RECEIPT_SHA256authenticated-receipt-sha256 [[ $(shasum -a 256 $PREFIX-installer.sh | awk {print $1}) $INSTALLER_SHA256 ]] || exit 1 shasum -a 256 -c $PREFIX.zip.sha256 shasum -a 256 -c $PREFIX-installer.sh.sha256 ./$PREFIX-installer.sh verify \ --archive $PREFIX.zip \ --receipt $PREFIX.json \ --receipt-sha256 $RECEIPT_SHA256 ./$PREFIX-installer.sh migration-plan \ --migrate-launch-agent $HOME/Library/LaunchAgents/ai.openclaw.node.plist ./$PREFIX-installer.sh install \ --archive $PREFIX.zip \ --receipt $PREFIX.json \ --receipt-sha256 $RECEIPT_SHA256 \ --migrate-launch-agent $HOME/Library/LaunchAgents/ai.openclaw.node.plist ./$PREFIX-installer.sh status --state-dir existing-state-dir该提权包的关键特性仅 ZIP、已公证并 staple内容恰好是OpenClaw.app不含 Apple Events entitlement记录不可变 receiptimmutable receipt并校验一份全新解压的副本同一套按源码地址寻址的产物包含从精确 Git commit 拷贝的可移植安装器外加独立的归档与安装器校验和文件目标 Mac 不需要源码 checkout发布操作者必须通过已验证的交接通道交付 receipt SHA-256与单独验证的安装器摘要配合构成内部工作流信任边界的一部分可移植安装器不在应用代码签名覆盖范围内因此这种显式双摘要交接是必要的。安装前提与行为安装要求存在应用可读的远程 Gateway 配置以及在选定状态目录中已配对的 macOS 节点身份修改 CLI 管理的节点 LaunchAgent 前先用migration-plan当前正在后台运行且没有 LaunchAgent 的应用使用显式的--adopt-running-app计划/安装选项安装器不复制任何 token 或密码只保留状态与配置的属主路径并要求同一节点身份以新应用版本和 computer-use 能力重连为openclaw-macos/node后才提交安装会单独拥有ai.openclaw.mac.elevation-host这个 launchd 任务RunAtLoadKeepAlive拒绝替换或抢占常规的登录时ai.openclaw.mac任务recover在切换失败后恢复记录的旧 bundleuninstall只移除提权任务保留应用、状态、Keychain、TCC 与恢复 receipt安装只有在 launchd 托管的进程同时达到 Bridge-ready 并作为期望的 computer-use 节点重连 Gateway 后才算成功缺失 TCC 授权在status中显示为降级状态托管升级使用代际唯一的 plist 与 receipt 备份回滚后status与同产物重装仍然有效。签名行为与身份选择签名身份自动选择顺序codesign-mac-app.sh 的select_identity()按以下优先级自动选择签名身份Developer ID ApplicationApple DistributionApple Development第一个可用的有效签名身份若一个都找不到默认直接报错设置ALLOW_ADHOC_SIGNING1或SIGN_IDENTITY-可回退到 ad-hoc 签名。ad-hoc 签名下脚本会输出醒目警告macOS 将 TCC 权限辅助功能、屏幕录制等绑定到代码签名、Bundle ID 与路径而 ad-hoc 每次构建都会生成新签名导致系统把应用当作新二进制、遗忘已授予的权限需要每次重启后重新授权个别权限甚至要重启 macOS 才重新出现。签名细节非 ad-hoc 签名一律附加--options runtimeHardened Runtime与时间戳CODESIGN_TIMESTAMP支持auto|on|offauto 模式仅在身份是 Developer ID Application 时启用时间戳ad-hoc 强制--timestampnone时间戳服务偶发失败时自动重试CODESIGN_TIMESTAMP_RETRY_ATTEMPTS8、退避延迟CODESIGN_TIMESTAMP_RETRY_DELAY_SECONDS5标准应用 entitlements 包含 Apple Events、音频输入、摄像头、定位com.apple.security.automation.apple-events等而 elevation-host 变体使用空 entitlements 且禁止Apple Events嵌入式 Node worker 中的node与 Claude Agent SDK CLI 使用带 JIT 权限的专属 entitlementscom.apple.security.cs.allow-jit等签名顺序是先内后外控制 CLI、MLX TTS 助手、CUA 驱动、cloudflared、node-worker、Sparkle 框架、其余 framework/dylib最后才签整个 bundle所有原生可执行文件与库必须持有真实 Mach-O 签名通用签名generic signatures会被拒绝。Team ID 审计Sparkle 更新不匹配的守门员签名完成后脚本会读取应用 bundle 的 Team ID并比对 bundle 内每一个 Mach-O的TeamIdentifier。只要有一个内嵌二进制 Team ID 不同签名即失败。这正是 Sparkle 更新机制所要求的更新框架加载的代码必须与宿主应用属于同一团队。跳过审计不推荐用于发布SKIP_TEAM_ID_CHECK1 scripts/package-mac-app.sh注意即使跳过原生格式检查仍然保留。elevation-host 变体禁止跳过 Team ID 检查并且会在签名阶段就验证 Team ID 与 Authority 必须是Developer ID Application: OpenClaw Foundation (FWJYW4S8P8)同时拒绝 bundle 内出现 CUA 驱动从而把身份失败挡在 Apple 公证提交之前。库校验绕过方案仅限开发Sparkle 的 Team ID 不匹配会阻塞框架加载这在 Apple Development 证书而非 Developer ID下尤为常见。开发时可选择加入DISABLE_LIBRARY_VALIDATION1 scripts/package-mac-app.sh该开关会向应用 entitlements 注入com.apple.security.cs.disable-library-validation。只用于本地开发发布构建必须保持关闭elevation-host 变体直接禁止该开关。非开发构建遇到 Team ID 不匹配时正确的做法是重新签名内嵌框架而不是关闭库校验。常用环境变量速查以下环境变量贯穿打包与签名流程按用途分类签名身份与开关SIGN_IDENTITYApple Development: Your Name (TEAMID)显式指定签名身份也支持 40 位证书哈希ALLOW_ADHOC_SIGNING1无身份时回退 ad-hoc 签名TCC 权限不持久见上文警告CODESIGN_TIMESTAMPoff离线调试时关闭时间戳DISABLE_LIBRARY_VALIDATION1开发专用的 Sparkle 库校验绕过SKIP_TEAM_ID_CHECK1绕过 Team ID 一致性审计。打包控制BUILD_CONFIGdebug|release构建配置release 强制来源校验与元数据BUILD_ARCHSall|arm64|x86_64目标架构release 默认通用二进制BUNDLE_IDai.openclaw.mac.debug|ai.openclaw.macBundle ID.debug后缀关闭 Sparkle 更新SKIP_NOTARIZE1、SKIP_DMG1、SKIP_DSYM1跳过公证 / DMG / 符号产物package-mac-dist.shOPENCLAW_SKIP_MLX_TTS1跳过 MLX TTS 助手release 禁止OPENCLAW_PACKAGE_APP_ROOTpath指定打包输出目录须在dist/下。总结OpenClaw 的 macOS 工程链路是一条开发循环 → 实例隔离 → 安全测试 → 打包签名 → 公证分发的完整流水线restart-mac.sh 让开发者一条命令完成重建重载命名 Profile 借助 AppProfile.swift 实现状态、Keychain 与端口的全隔离原生测试通过一次性 Keychain 与私有 home 满足 AppKit/WebKit 测试的隔离要求而 package-mac-app.sh、codesign-mac-app.sh 与 package-mac-dist.sh 则把签名审计、Team ID 一致性检查、Sparkle 兼容与公证恢复全部固化进脚本。理解这套机制后无论是日常开发调试、多实例并行还是准备一次可公证的 macOS 发布都能在正确的路径上少走弯路。【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门