我发布了一款完全由 Claude Code 构建的 macOS 应用

信息来源:indragie

我最近发布了 Context,这是一款用于调试 MCP 服务器的原生 macOS 应用。我的目标是打造一款在平台上如鱼得水的实用开发者工具,基于 Apple 的 SwiftUI 框架。自 2008 年以来,我一直在为 Mac 开发软件,但这一次有所不同:Context 几乎 100%由 Claude Code1 构建。 在帮助 Claude 构建软件的过程中,仍然需要一定的技能和反复迭代,但在这个拥有 2 万行代码的项目中,我估计自己手写的代码不到 1000 行 2

这是一篇长文,讲述了我的经历、我如何选择工具、这些工具目前擅长和不擅长的地方,以及你如何利用它们来最大化生成代码的质量,尤其是当你像我一样在构建原生应用时。

  1. 从 Copilot 到 Claude Code
  2. 又一个副业项目的开始
  3. Claude Code 擅长写代码
  4. Claude Code 对 Swift 还可以,对 SwiftUI 很擅长
  5. 你只需要说“让它更美观”
  6. 上下文工程至关重要
  7. 为智能体设定前提
  8. 智能体无法读心,它们需要规范
  9. “超前思考并制定计划”
  10. 建立反馈循环
  11. Claude Code 不只是写代码
  12. 现在构建高质量自动化几乎是免费的
  13. 未来的集成开发环境将大不相同
  14. 我又能发布副业项目了

1. 从 Copilot 到 Claude Code

ASCII art generated by Claude Code

我第一次接触 AI 编码工具是在 VS Code 中尝试 GitHub Copilot。这是同类中的第一个工具,当时我感到非常惊讶:虽然它只是自动补全,但效果出奇地好——不像普通编辑器只补全符号名或函数签名,它能根据上下文自动补全整个函数实现 。这极大提升了生产力,但你仍然感觉大部分工作还是自己在做。

然后事情开始迅速发展:Cursor 起飞了,他们加入了 Agent Mode,新的竞争者如 Windsurf 也进入了这个领域。所有产品都在倾向于“代理式”开发模式,不再只是用一次性的 LLM 响应来自动补全,而是让 LLM 在循环中调用各种工具,以完成更复杂的任务:收集你的代码库上下文、阅读网页和文档、编译程序、运行测试、对构建/测试失败进行迭代等。

我之前并没有深入尝试过这些新工具,因为那时我并没有在积极进行副业项目,但在 2025 年 2 月,一个有趣的竞争者突然出现:Claude Code 并不像其他工具那样是 VS Code 的一个分支,而是一个完全在终端中使用的 IDE。它没有传统的代码编辑功能,也没有堆满各种功能的复杂界面:它把智能体循环放在了最核心的位置。只有一个用于输入提示的文本框,几乎没有其他内容。它不是增强你的 IDE,而是取代你的 IDE。我并不完全相信这是理想的用户体验,但相比于现有的工具,这个想法足够新颖,让我决定必须试一试。

2. 又一个副业项目的开始

Side projects I never shipped

像许多有高强度本职工作的工程师一样,我有一大堆从未发布的副业项目。做出可用的原型还算容易,但最后的20%需要花费大量时间和精力,以至于我已经有6年没有发布过任何副业项目了。

此时,我开始尝试使用 Claude Code 及其对 MCP(模型上下文协议)服务器的支持。Anthropic 设计了 MCP 作为一种开放标准,使代理能够访问工具和其他上下文,以完成特定任务。例如,Sentry MCP 服务器 提供的工具可以让代理获取包含堆栈跟踪和其他有用调试上下文的问题,甚至可以调用 Sentry 自己的修复 bug 代理。

然而,构建和测试 MCP 服务器的体验相当繁琐:MCP 服务器通过标准输入/输出流与客户端通信,或者通过带有 服务器发送事件(SSE) 的 HTTP 通信,以便服务器能够向客户端流式传输响应。这并不像调用 CLI 或使用 curl 向服务发送请求那样简单。虽然有一个官方工具叫做 MCP Inspector,允许开发者测试服务器功能,但作为一名长期的 macOS 和 iOS 开发者,我想尝试构建一个原生应用来解决这个问题。我认为这将是一次很好的学习体验,可以推动 AI 代理的边界,并希望最终能产出一个有用的产品。

3. Claude Code 擅长编写代码

我想先说一句,Claude Code(搭载最新的 Sonnet 4 和 Opus 4 模型) 确实擅长编写代码。它当然不是顶尖 1%的程序员,但我认为 Claude 的输出明显优于普通开发者。只要你描述清楚要实现的功能,Claude 可以做到:

  • 定位并阅读你项目中与该功能相关的现有源代码
  • 理解代码风格和设计模式
  • 阅读你提供的其他文档或规范
  • 生成实现该功能的代码
  • 生成测试以验证该功能的行为
  • 构建你的程序并运行测试
  • 反复修正编译失败和测试失败,直到构建和测试全部通过
  • 查看截图或控制台日志,找出并修复漏洞(后文会详细介绍)

Claude writing Swift code for my app

真正令人难以置信的是,它完成这一切所需的时间只是人工实现的很小一部分。 想象一下,你让一个对你的项目毫无背景的新员工加入,然后几分钟后他们就交付了一个完整的功能。

4. Claude Code 在 Swift 方面还可以,在 SwiftUI 方面表现良好

我决定使用最新的苹果开发者技术来构建我的应用:在 macOS 15.5 上使用 Swift 6.1 和 SwiftUI。我很好奇 Claude 在编写 Swift 方面的表现,因为与 Python 或 JavaScript 这样更为普及的语言相比,模型的训练数据中包含的 Swift 代码要少得多。

好消息是,Claude 能够胜任大多数 Swift 语言特性的使用,直到 Swift 5.5(引入了 Swift Concurrency)。Swift Concurrency 对语言来说是一次巨大的变革,在我看来,即使是人类也很难正确使用。Claude 在选择现代框架和旧版等价物时也会感到困惑。它经常会在有更现代的 Swift 替代方案时,尝试使用旧版的 Objective-C API,或者用 AppKit/UIKit 替代 SwiftUI。

它生成的 SwiftUI 代码运行得相当不错:通常能够准确(但有些丑陋)地还原 UI,通过进一步迭代可以将其打磨成真正设计良好且易用的界面。

My macOS app, Context

Claude 在生成 UI 代码时经常遇到的一个问题,实际上是 Swift 本身的一个根本性问题:UI 代码的类型表达式通常会变得非常复杂,导致编译器出现令人头疼的 The compiler is unable to type-check this expression in reasonable time 错误。解决方法是将视图主体重构为更小的表达式,所幸的是,Claude 在不破坏实现的前提下,非常擅长完成这项工作——有时候当它在输出中看到编译器错误时,甚至会自动进行这样的重构。

你可以通过创建一个包含使用现代 API 基本说明的 CLAUDE.md 文件,让 Claude 避免常见的陷阱。以下是我 Context 项目的 CLAUDE.md 文件中的一段内容:

* Aim to build all functionality using SwiftUI unless there is a feature that is only supported in AppKit.
* Design UI in a way that is idiomatic for the macOS platform and follows Apple Human Interface Guidelines.
* Use SF Symbols for iconography.
* Use the most modern macOS APIs. Since there is no backward compatibility constraint, this app can target the latest macOS version with the newest APIs.
* Use the most modern Swift language features and conventions. Target Swift 6 and use Swift concurrency (async/await, actors) and Swift macros where applicable.

即使是这样一套相对简单的规则,也能产生合理的结果,但你还可以做得更多:例如,Peter Steinberger 的 agent-rules 仓库中包含了一些规则,你可以将这些规则添加到你的 agent 中,既有通用的编码指南,也有更具体的编写更优质 Swift 代码的建议。

如果你有兴趣自己评判代码质量,可以查看这些来自我的项目的示例:

5. 你可以直接说“让它更美观”

如果 Claude 第一次没有生成设计良好的 UI,你可以直接告诉它 “让它更美观/优雅/易用”。我发现只需付出很少的努力,结果却出奇地好。你也可以更有条理地操作,先让它 “提出让这个 UI 更美观的建议”,这样它会生成一份设计优化建议清单,供你选择。

如果你发现了一个 UI bug 或者想要调整某个 UI 元素,你可以截屏后直接拖拽(或使用⌘+V 粘贴)到 Claude Code 中。也许将来会有更好的自动化方式,但目前这种方法已经很好用,并且无论你在开发哪种前端平台都适用。

6. 上下文工程至关重要

随着主流 AI 的兴起,业界很快定义了一个新领域: 提示工程 。提示工程的理念是,你必须精心设计提示词,才能从模型中获得最佳输出。这在当时或许是对的,但根据我的经验,在使用更先进的模型时,提示工程并不是最值得关注的重点。

如今的模型在处理不完美的输入并理解你的意图方面要好得多,这既是因为模型本身更强大,也因为它们引入了思维链(CoT)提示 。你可以用模糊的描述、不完整的句子以及拼写和语法错误来提示模型,它依然能够相当好地理解你的需求,并将问题分解为一系列步骤。

你在使用 Claude Code 或类似工具时将不断面临的限制是上下文窗口 。Anthropic 最新的两款模型(Sonnet 4 和 Opus 4)都拥有 20 万个上下文窗口,这意味着它们一次可以处理 20 万个 token 的文本。每一次提示和回复都会消耗更多的上下文,并且模型在接近上下文窗口末尾时的表现往往会变差 

Claude Code's auto compaction indicator

Claude 甚至会贴心地显示一个指示器,显示你还剩多少上下文可用,之后它会进行“压缩”对话。压缩意味着它会对当前对话进行总结,并用该总结来初始化一个新的上下文窗口,以便你可以继续提问。压缩并不完美——它可能会遗漏之前对话中的重要细节,或者因为之前的错误而用低质量的上下文来初始化新窗口。

在有限的上下文 token 数量下产出最高质量的输出,换句话说, 上下文工程 ,是高效使用编码代理的主要挑战。

7. 预设代理

有一个我称之为“预处理”代理的过程,就是不让代理直接执行任务,而是让它先阅读更多的上下文信息,以提高其输出质量的概率。

默认情况下,它会读取用户范围和项目范围内的 CLAUDE.md 文件,但你也可以通过让它阅读特定的文档或源代码,来引入更多与任务相关的上下文。下面是我最近用来让它阅读一些现有源代码和网络规范的提示词:

Read DXTTransport.swift, DXTManifest.swift, DXTManifestView.swift, DXTConfigurationView.swift, DXTUserConfiguration.swift, AddServerFeature.swift, and AddServerView.swift to learn how adding servers from DXT packages is implemented.

Then read the documentation for the manifest.json format here: https://raw.githubusercontent.com/anthropics/dxt/refs/heads/main/MANIFEST.md

After reading these sources, summarize what you've learned.

Claude 随后会使用 Search 和 Read 工具来查找并阅读源文件,并使用 Fetch 工具从 GitHub 下载 Markdown 文件。让它进行总结可以促使它思考自己从这些来源中理解了什么,而将该总结作为上下文,则能提升后续任务的表现。

当你的代码使用第三方依赖或新 API(这些 API 可能是在模型知识截止日期之后引入的)时,预设尤为重要。像 Context7 和 llm.codes 这样的工具,就是为了解决将文档格式化为模型可读取的纯文本格式这一问题而存在的。

8. 智能体无法读心,他们需要规范

在让 Claude 构建一个功能时,详细的规格说明对于引导模型至关重要。如果你不投入精力,Claude 无法构建任何非简单的功能。AI 产品演示通常会突出只用一句话提示就能“创建完整应用”,但如果你想要的不只是原型,你就需要一份真正的规格说明。

规格说明不需要写得很正式。你甚至可以用语音输入随意说(我还是更喜欢打字,但其实都可以)。以下是我给 Claude 写的一个用于在我的应用中构建新功能的规格说明示例:

A spec I gave Claude to implement support for Anthropic's DXT package format

这看起来很多,但我打字写下这些内容的速度远比我自己实现这个功能要快得多。

9. “超前思考并制定计划”

Claude 往往会在没有足够背景信息的情况下直接进入实现阶段,这会导致结果质量较差。为激发代理的另一种策略是让 Claude 使用其扩展思维模式,并先制定一个计划。扩展思维可通过以下这组魔法关键词激活: "think" < "think hard" < "think harder" < "ultrathink." 这些不仅仅是对模型的建议——它们是激活不同层级扩展思维的特定短语。Ultrathink 会消耗最多的 tokens,但会带来最佳的结果。如果你想对计划进行多次迭代,建议在提示中明确加入指令,要求在用户接受计划之前不要进行实现。

总的来说,我强烈建议阅读 Anthropic 的 Claude Code: Best practices for agentic coding 一文。我在这里讨论的许多技巧都在文章中有所涵盖,对于想要充分发挥 Claude Code 或任何编码代理的能力来说,这篇文章应被视为必读内容。

10. 建立反馈循环

当 Claude 能够独立推动反馈循环,使其能够进行更改、测试更改,并收集失败的上下文以尝试下一次迭代时,它才最有用。关键的循环包括:

  • 构建 。Claude 应该知道如何编译你的应用。Claude 知道如何通过 swift build 编译 Swift 包,但对于我的 macOS 应用目标,它经常无法正确找到 xcodebuild 的调用方式。XcodeBuildMCP 通过为模型提供一套简化的构建和运行应用工具,解决了这个问题。
  • 测试 。Claude 应该能够构建并运行你的测试,并查看测试输出。同样,Claude 能够直接通过 swift test 对 Swift 包进行测试。我还没有测试它是否能运行应用/UI 测试,但我怀疑这也可能需要 XcodeBuildMCP。
  • 修复漏洞 。Claude 已经知道如何通过添加调试日志来调试问题。问题在于它无法像用户那样与应用程序交互,从而让应用进入能够输出正确日志的状态。你需要手动与应用交互,并将控制台中的日志复制粘贴到 Claude。这种方式可以正常工作,但意味着除非你事先编写了封装相关行为的单元测试或 UI 测试,否则无法让它完全自主地修复问题。对于浏览器应用,有像 playwright-mcp 这样的自动化解决方案,但我还不知道原生开发领域有经过充分测试的类似工具。
  • 修复用户体验问题 。我之前提到过,你可以将截图粘贴到 Claude,让它对 UI 进行迭代。你也许可以使用像 Peekaboo 这样的工具来自动截取屏幕,但你仍然会遇到需要手动与应用交互以先让其进入正确状态的问题。

11. Claude Code 能做的不止是写代码

由于 Claude Code 是一个封装了通用模型的代理,因此在你迭代应用程序本身时,仍然可以用它来协助完成非编程任务。例如,编辑文案,或者通过向模型询问如何改进应用功能的建议来规划功能版本。

我发现一个很有用的小功能,就是在还没有办法将真实数据导入应用时,可以生成模拟数据。在开发 Context 的过程中,我已经部分完成了一个 Swift MCP 客户端库的实现,但我想转换思路,做一些 UI 原型设计。通常,生成逼真的模拟数据过程会非常繁琐,以至于我根本不会去尝试,但 Claude 在几秒钟内就生成了很棒的模拟数据。我在调整 UI 时与朋友们分享的应用最初的截图,背后用的都是模拟数据,但看起来足够真实,让人能够很好地感受到应用在渲染真实 MCP 服务器数据时的样子 

Context app backed by mock data generated by Claude

对于 MCP 来说,模拟数据就更加重要了,因为当时大多数 MCP 服务器除了工具之外,并没有使用规范中的大部分功能,但我仍然需要一种方法来验证这些功能的 UI。

12. 构建高质量自动化现在(几乎)是免费的

发布过程中最痛苦的最后 20%之一,就是自动化应用的发布流程,尤其是在 macOS 上,你必须应对代码签名、公证和打包等复杂流程。在之前的项目中,这通常是我开始折腾,试图正确配置 fastlane,然后围绕它构建一些简单的 Python 自动化脚本的时候。但这次不是这样。

经过几个小时的迭代,我让 Claude 为我编写了一个发布脚本,能够完成以下任务:

  • 检查环境是否已正确设置并安装了所需工具
  • 从 git 提交中生成变更日志条目,将其与手写的变更日志条目合并,并生成 HTML 格式的发布说明
  • 构建应用程序,对其进行代码签名、公证,并打包成 DMG 文件
  • 生成一个 Sparkle appcast,以便为现有用户提供自动更新
  • 为发布版本打标签并将其发布到 GitHub
  • 将调试符号上传到 Sentry 以便崩溃报告符号化

在脚本完全可用后,我只用了一行简单的提示美化了 CLI 输出,最终得到了这个:

Running my build & release automation script generated by Claude

这是一份包含 2,000 行的 Python 代码,即使是我自己手动编写,我也只会自动化最关键的步骤,绝不会花精力让输出看起来如此美观。这个脚本将在我每次发布新版本时,为我节省数十分钟的手动工作,而我所做的只是写了几段自然语言的需求说明,并让 Claude 调试和修复了我在运行脚本时发现的一些问题。

13. 未来的 IDE 将会大不相同

在这个项目中,我意识到我只用了两种工具:Claude Code 和 GitHub Desktop(用于查看差异)。绝大多数时间里,我并不需要任何典型的编辑器功能:文件树、源代码编辑器、扩展等。我偶尔会用 Xcode 手动进行一些编辑,但这种情况很少见,而且我依然没有用到大多数 Xcode 特有的功能(如 SwiftUI 预览、视图调试器等)。既然现在的编码代理已经是最差的状态了,我不得不想象,未来的 IDE 将会和今天完全不同。

Cursor、Windsurf 和 Copilot 都是以 VS Code 为起点,并在不同方向上进行了改进,但它们本质上都是在一个诞生于 AI 之前的编辑器上强行加装 AI。归根结底,VS Code 与 20 年前的 JetBrains IDE 并没有太大区别。我也看到像 Warp 这样的项目,试图从现代化终端模拟器转型为具备代理能力的开发环境,但我并不认为终端一定是理想的用户体验,尽管我非常喜欢 Claude Code。

我相信未来的集成开发环境(IDE)将专注于让开发者能够为智能体设定上下文,并建立反馈循环,这对于帮助智能体完成任务至关重要。 这种用户体验将会非常不同——我无法准确预测会是什么样子,但我认为源代码编辑器不会再是核心。

14. 我又能发布副业项目了

对我来说,这段旅程中最令人兴奋的并不是我构建的应用,而是我现在又能满足自己的编程欲望,并且能够再次发布打磨好的副业项目。这就像我每天多出了5个小时,而我每月只需花200美元。

Notes

1.I have no affiliation with Anthropic and this is not sponsored content in any way, I just really like the tool 
2.In contrast, 0% of this blog post was written by AI 

了解 RecodeX 的更多信息

立即订阅以继续阅读并访问完整档案。

继续阅读