不用打开 Xcode,也能构建和发布 Mac / iOS 应用?

不用打开 Xcode,也能构建和发布 Mac / iOS 应用?

XcodeiOSmacOSCLI开发者工具xcodebuild

数据源:HN + web research · HN

2026 年 7 月 11 日,开发者 Scott Willsey 发布了一篇博客《Building and Shipping Mac and iOS Apps Without Ever Opening Xcode》,在 Hacker News 上迅速获得了 489 分和 208 条评论。

Scott Willsey 的 Xcode 替代工作流

文章的核心主张简单直接:Xcode.app 必须安装在 Mac 上,但你完全可以一次都不打开它。

这篇博客之所以引发讨论,部分原因在于它踩中了当前开发者社区的两个热门话题:一是 Apple 生态开发者对 Xcode 长期积累的不满,二是 AI 编程工具(如 Claude Code)正在改变人们与构建工具链的交互方式。Willsey 的立场很有意思:他认同 Xcode 不好用,于是选择绕过它的 GUI 层,用纯命令行完成一切。

核心思路:Xcode 作为运行时,不作为界面

Willsey 的工作流基于一个基本事实:Xcode.app 内部包含了一套完整的命令行工具链——xcodebuildnotarytoolstaplerdevicectl 等。这些工具不需要打开 Xcode 的 GUI 即可独立运行。再加上 XcodeGen(一个用 YAML 文件生成 .xcodeproj 的命令行工具),整个构建、签名、公证、部署流程都可以脚本化。

他的观点是:如果你需要构建一个 Mac 或 iOS 应用,你需要的只是 Xcode 内部打包的工具链,而不是 Xcode 的窗口和按钮。

工具链全景

从这个工作流涉及的 CLI 工具来看,Apple 生态的命令行基础设施比很多人以为的要完整:

  • xcodebuild:Apple 官方的命令行构建工具,支持 build、test、archive、exportArchive 等子命令。它本质上和 Xcode GUI 使用的是同一套构建引擎。
  • XcodeGen:第三方开源工具,通过一个 project.yml 文件定义 targets、configurations、schemes 等,每次构建时重新生成 .xcodeproj。这意味着 .xcodeproj 目录可以从 git 中忽略,只提交 YAML 文件。
  • notarytoolxcrun notarytool):Xcode 13 引入的公证命令行工具,用于将签名后的应用上传到 Apple 公证服务进行恶意软件扫描。相比已被弃用的 altoolnotarytool 支持 --wait 参数自动等待公证完成。
  • staplerxcrun stapler):将公证票据「装订」到应用包中,使 Gatekeeper 可以在离线状态下验证。
  • devicectlxcrun devicectl):用于管理连接的 iOS 设备,支持列出设备 UDID 和通过命令行安装 .app

Willsey 的工作流还依赖 spctl 验证 Gatekeeper 接受状态,以及 codesign 检查签名细节。

一次性设置的摩擦

虽然日常使用可以完全无 GUI,但初始配置仍然需要打开 Xcode 一次。这包括:

  1. 接受 Xcode 许可协议(sudo xcodebuild -license accept
  2. 在 Xcode 的 Settings → Accounts 中登录 Apple ID(需要付费的 Apple Developer 账号)
  3. 创建 Developer ID Application 证书(注意:这是分发证书,与用于本地调试的 Apple Development 证书不同)
  4. xcrun notarytool store-credentials 在终端中交互式地存储公证凭据

其中最后一步需要输入 App-Specific Password(在 appleid.apple.com 生成),且每次修改 Apple ID 密码后这些密码会静默失效。Willsey 提到他会把 App-Specific Password 存在 1Password 中,让 Claude Code 可以读取。

此外,还需要配置一个 Local.xcconfig 文件存储 Team ID 和 Bundle Prefix,并将其加入 .gitignore。签名私钥存储在系统钥匙串中,由 xcodebuild 自动查找——秘密不会进入代码仓库。

release.sh:一条命令完成全流程

工作流的核心是一个 scripts/release.sh 脚本,Willsey 让 Claude Code 帮他生成的。脚本的流程是:

  1. 预检:确认 xcodegen 已安装,公证凭据已存储
  2. 重新生成项目xcodegen generate
  3. 归档xcodebuild archive(Release 配置)
  4. 导出xcodebuild -exportArchive(Developer ID 签名,signingStyle: automatic
  5. 公证ditto 打包 zip → notarytool submit --wait
  6. 装订stapler staple
  7. 验证spctl -a -vvv 检查 Gatekeeper
  8. 安装cp -R/Applications

脚本使用了 set -euo pipefail,任何步骤失败立即停止。Willsey 强调这个脚本的初始版本也并不完美——他和 Claude Code 经历了几轮「运行→出错→修复」的循环才得到最终版本。他对此的描述比较务实:「这个循环不是失败模式,它就是过程本身。」

iOS 部署的差异

Mac 应用和 iOS 应用在部署路径上有本质区别。iOS 不需要公证(这是 Mac 分发的概念),但需要 devicectl。构建并安装到 iPhone 的流程是:

xcodebuild archive -destination 'generic/platform=iOS' -allowProvisioningUpdates
xcrun devicectl device install app --device <UDID> path/to/app

设备构建使用 Apple Development 签名身份(非 Developer ID),配合开发 provisioning profile。-allowProvisioningUpdates 会自动从 Apple 获取所需的 profile。

Hacker News 社区讨论的焦点

这篇博客在 HN 上引发的讨论,话题分布比文章本身更广。从 208 条评论来看,几个反复出现的主题是:

安全与 AI Agent 的边界。 多位评论者指出,这种工作流的隐含前提是 AI 编程 Agent(如 Claude Code)在本地 Mac 上以较高权限运行——它可以访问钥匙串中的签名私钥,可以读取 ~/.ssh,可以修改 /Applications。有评论者提到 xAI 曾上传用户整个家目录(包括 SSH 密钥)的事件,认为这种模式在安全实践上存在倒退。一些建议的缓解措施包括:用 Tart 或 VirtualBuddy 在 macOS 虚拟机中隔离开发环境、使用 Secretive 将 SSH 密钥存储在 Secure Enclave 中、以独立用户身份运行 Agent。

Xcode MCP 的价值。 有评论指出,Xcode MCP(Model Context Protocol)工具提供了 xcodebuild 无法替代的能力,比如 SwiftUI Preview 的生成和渲染、模拟器的自动化驱动、崩溃符号化等。在 Xcode 27 中,内置的 Agent 和 MCP 可以驱动模拟器和设备。这意味着完全不打开 Xcode 可能会牺牲一些调试效率。

跨平台编译的尝试。 有开发者分享了自己在 Linux 上编译 iOS 应用的经验:使用 OSXCross 工具链,复制 iPhoneOS.sdk,用 zsign 签名,用 go-ios 安装到设备。虽然这种方案不在 Apple 官方支持范围内,但至少说明技术上可行。

对 Xcode 本身的看法。 一位自称在 Xcode 团队工作过二十年的评论者提供了一个视角:大多数人对 Xcode 的不满,根本原因在于他们想用不同于 Xcode 设计意图的方式工作,然后通过各种 workaround 强行适配,最终把挫败感归咎于工具。这个观点在某种意义上与 Willsey 的方案形成了互补——如果 Xcode 的设计不适合你的工作流,那用命令行绕开它可能比在 GUI 里对抗它更省力。

值得注意的局限性

这个工作流并不适用于所有场景:

  • 初始设置绕不开 GUI。 创建 Developer ID 证书仍需在 Xcode 中操作。Willsey 自己也承认有「一次性摩擦」。
  • 复杂调试仍需 GUI。 xcodebuild 可以提供编译器输出,但 SwiftUI Preview、可视化调试器、Instruments 性能分析、崩溃日志符号化等功能在纯命令行环境下不可用或使用体验大幅下降。
  • AI Agent 的运行环境受限。 如果团队的安全策略禁止 AI Agent 访问本地文件系统或钥匙串,这套流程就需要重新设计(例如通过 CI/CD 管道执行签名和公证)。
  • 依赖 XcodeGen 的 YAML 配置。 对于已经存在的大型 .xcodeproj,迁移到 XcodeGen 需要一次性投入。Wealthfront 团队在 2026 年初的工程博客中也分享了类似的经验。

此外,Scott Willsey 的方法论高度依赖 Claude Code 作为「翻译层」——他把这篇博客作为参考文档提供给 AI,让 AI 来理解和执行复杂的命令行参数组合。对于那些不使用 AI 编程工具的开发者来说,直接记忆和手写这些 xcodebuild 的长参数列表可能会让「不用 Xcode GUI」的好处被命令行本身的复杂性抵消。

对 Apple 生态开发者的启示

Willsey 的博客实际上揭示了一个被很多开发者忽略的事实:Apple 的命令行工具链比 Xcode 的 GUI 更稳定、更可预测。xcodebuild 的接口变化频率远低于 Xcode 的 UI 重构;notarytoolstapler 的行为比 Organizer 中的自动流程更透明;devicectl 提供的设备管理能力也比 Xcode 的 Devices 窗口更易于自动化。

这套方案也反映了 2026 年一个更大的趋势:开发者与工具的关系正在从「学习工具的界面」转向「告诉 AI 你要什么,AI 去调用工具」。在这样的范式下,工具的 CLI 接口可能比 GUI 更有价值——因为 CLI 输出的是结构化文本,AI 可以直接解析和处理;而 GUI 的操作需要屏幕感知、UI 自动化或 MCP 等额外的抽象层。

Willsey 在文章末尾提供了一张对比表,将 GUI 操作与对应的 CLI 命令一一列出:⌘B 对应 xcodebuild build,Product → Archive 对应 xcodebuild archive,Organizer → Distribute 对应 xcodebuild -exportArchive……这张表本身就是一份实用的速查手册。如果你对这个工作流感兴趣,文章中的 release.sh 脚本和 CLAUDE.md 配置可以直接作为起点。

本文的素材来自公开信息和社区讨论。如果你对这个话题有更深入的一手经验,欢迎指出文中的不足。

参考链接

  • Scott Willsey 博客原文:Building and Shipping Mac and iOS Apps Without Ever Opening Xcode
  • Hacker News 讨论(489 分,208 评论)
  • XcodeGen 项目文档
  • Wealthfront 工程博客:XcodeGen 迁移经验
  • Apple 官方文档:xcodebuild、notarytool、devicectl 手册