Prism:AI辅助开发的SwiftUI菜单栏工具,统一管理Claude API配置
1. 项目概述与核心价值
如果你和我一样,日常开发、写作或者处理信息时,Claude 已经成了离不开的助手,那你肯定也遇到过这个痛点:手头有好几个不同的 AI 服务提供商,有的是官方的 Claude API,有的是国内大厂提供的 Claude 兼容服务,还有的是一些第三方网关。每次想切换,都得手动去修改那个藏在~/.claude/settings.json里的配置,复制粘贴 API Key,改来改去,不仅麻烦,还容易出错。更别提有时候想临时换个模型试试效果,或者对比不同服务的响应速度了。
Prism 就是为了解决这个“甜蜜的烦恼”而生的。它是一个纯粹的 macOS 菜单栏(Menu Bar)小工具,用 SwiftUI 写成,核心功能就一个:帮你集中、便捷地管理所有兼容 Claude API 的服务配置。你可以把它想象成 Claude 生态的一个“快捷开关面板”。它不运行模型,不处理你的对话,只做配置管理这一件事,但做得极其专注和优雅。
这个项目的诞生本身就很有意思。它最初是一个实验,目的是验证当前的大语言模型(比如 GLM 4.6)是否真的有能力产出可用的、能“发货”的 macOS 实用工具。结果你猜怎么着?项目的大部分代码确实是由 AI 智能体生成的,人类开发者只做了架构审核、路径验证和界面打磨这些“收尾”工作。这个原型最终不仅跑通了,而且确实好用,于是作者决定将其开源。所以,你看到的既是一个实用的工具,也是一个关于“AI 辅助开发”可行性的鲜活案例。
对于开发者而言,Prism 的价值是多维度的:
- 对于终端用户:它极大地简化了在多 AI 服务间切换的流程,一键激活,安全备份,体验流畅。
- 对于 Swift/macOS 开发者:它提供了一个非常干净的、现代 SwiftUI + Swift 6 的菜单栏应用范本,代码结构清晰,值得学习借鉴。
- 对于对 AI 编程感兴趣的人:它的整个代码库就是一个研究 AI 生成代码风格、边界和需要人工干预环节的绝佳样本。
接下来,我会带你深入这个项目,从设计思路、代码结构到实操细节,完整拆解这个“AI 制造”的精致工具。
1.1 核心需求与设计哲学
Prism 要解决的核心问题非常明确:统一管理分散的、异构的 Claude 兼容 API 配置,并提供零摩擦的切换体验。围绕这个核心,其设计哲学体现在以下几个关键决策上:
1. 非侵入式集成(Zero-Intrusion Integration)Prism 没有选择自己发明一套配置格式,或者要求用户将密钥存入它的私有数据库。它直接读写 Claude 官方工具链(如 Claude Desktop, Claude Code)使用的标准配置文件——~/.claude/settings.json。这样做的好处是:
- 兼容性最大化:任何遵循 Claude 配置规范的工具都能立即识别 Prism 的修改。
- 用户无迁移成本:用户原有的配置和手动设置的 API Key 会被完整保留。
- 职责单一:Prism 只负责“写入”正确的配置片段,不负责存储密钥,降低了安全设计的复杂性。
2. 配置即模板(Configuration as Templates)不同服务商的 API 配置,差异往往体现在几个环境变量上,比如ANTHROPIC_API_KEY、ANTHROPIC_API_URL、ANTHROPIC_VERSION等。Prism 将这些差异抽象为“Provider Profile”(供应商模板)。每个模板预定义了该服务所需的环境变量键值对和元数据(如名称、图标)。
- 开箱即用:内置了智谱AI(Zhipu)、月之暗面(Moonshot)、深度求索(DeepSeek)、MiniMax 等热门服务的模板。
- 高度可扩展:用户可以通过“Custom”模板自定义任何兼容的网关地址和变量。
- 类型安全:模板中的环境变量在代码层面有明确的类型定义,减少了运行时错误。
3. 菜单栏优先(Menu-Bar-First UX)作为一个需要频繁调用、随时待命的工具,菜单栏是最佳载体。Prism 的 UI 设计完全围绕“快速、精准、不打扰”展开:
- 极简交互:点击菜单栏图标,弹出面板,选择服务,点击激活。整个过程通常不超过 3 秒。
- 键盘友好:支持键盘导航和快捷键,对于效率控来说,可以完全不用鼠标。
- 状态可视:当前激活的服务名称或图标可以显示在菜单栏上,一目了然。
4. 安全与鲁棒性(Safety & Robustness)操作系统级配置文件是有风险的。Prism 通过两个机制来保障:
- 自动备份:在每次写入新配置前,都会将现有
settings.json复制一份为settings.json.backup。误操作可以一键回滚。 - 敏感信息脱敏:所有涉及
AUTH_TOKEN、API_KEY的字段在 debug 日志中都会被自动掩码(显示为***),避免开发调试时意外泄露。
这个设计思路决定了 Prism 的代码结构必然是模块化、数据驱动且易于测试的。
2. 项目架构与代码深度解析
打开 Prism 的 Xcode 工程,你会发现它的目录结构非常清晰,遵循了现代 SwiftUI 应用的最佳实践,同时为菜单栏应用的特殊性做了适配。我们来逐一拆解核心模块。
2.1 应用入口与生命周期管理 (Prism/App/)
这是应用的起点。对于菜单栏应用,App协议的实现是关键。
import SwiftUI import Sparkle @main struct PrismApp: App { @State private var viewModel: AppViewModel private let updaterController: SPUStandardUpdaterController init() { // 初始化 ViewModel 和 Sparkle 更新控制器 self._viewModel = State(initialValue: AppViewModel()) self.updaterController = SPUStandardUpdaterController( startingUpdater: true, updaterDelegate: nil, userDriverDelegate: nil ) } var body: some Scene { MenuBarExtra("Prism", systemImage: "prism") { ContentView(viewModel: viewModel) .environment(updaterController.updater) // 注入更新器 } .menuBarExtraStyle(.window) // 使用窗口式弹出面板,而非纯菜单 } }关键点解析:
@main与App协议:这是 SwiftUI 应用的现代入口。PrismApp结构体定义了应用的根。MenuBarExtra:这是 SwiftUI 中用于创建菜单栏项的核心组件。在 macOS 13 (Ventura) 及以上版本中,它替代了旧的NSStatusItem方式,与 SwiftUI 的生命周期管理集成得更好。.menuBarExtraStyle(.window):这是一个重要的样式选择。它让弹出的内容以一个独立的、可交互的 SwiftUI 窗口形式呈现,而不是简单的Menu。这给了我们更大的 UI 设计自由度,可以放置按钮、列表等复杂控件。- Sparkle 集成:
SPUStandardUpdaterController是 Sparkle 框架的控制器,负责在后台检查应用更新。将其注入到Environment中,方便子视图触发更新检查或显示更新状态。Prism 选择 Sparkle 是因为它是 macOS 开源生态中事实标准的自动更新方案,成熟稳定。
注意:
MenuBarExtra在 macOS 13 及以上才完全稳定。如果你的应用需要支持更早的系统,可能需要回退到 AppKit 的NSStatusItem方案,这会显著增加代码复杂度。Prism 选择 macOS 14+ 作为最低要求,是一个在体验和开发成本之间的合理权衡。
2.2 视图模型:状态管理的核心 (ViewModels/)
Prism 采用了@Observable宏(Swift 5.9 引入,在 Swift 6 中成为主流)来构建响应式视图模型。这是 SwiftUI 数据流管理的现代方式。
AppViewModel通常是整个应用的全局状态管理器。在 Prism 中,它可能负责:
- 持有和管理所有供应商模板的列表。
- 管理当前选中的供应商。
- 触发配置的写入和备份操作。
- 处理 UI 的状态,比如弹出框的显示隐藏。
ProviderViewModel则可能代表一个具体的供应商模板,包含其配置数据(名称、图标、环境变量字典等)以及是否被激活的状态。
import SwiftUI import Observation @Observable final class AppViewModel { var providers: [Provider] = [] var selectedProvider: Provider? var isShowingAlert = false var alertMessage = "" private let configService: ConfigurationService init(configService: ConfigurationService = .shared) { self.configService = configService self.loadProviders() } func loadProviders() { // 从本地或内置资源加载模板 self.providers = Bundle.main.decode([Provider].self, from: "providers.json") ?? [] // 尝试从当前 settings.json 中恢复选中的 provider self.selectedProvider = configService.detectActiveProvider(from: providers) } func activateProvider(_ provider: Provider) { do { try configService.writeConfiguration(for: provider) self.selectedProvider = provider // 显示成功提示... } catch { self.alertMessage = "激活失败: \(error.localizedDescription)" self.isShowingAlert = true } } }为什么用@Observable而不是@StateObject或@ObservedObject?@Observable宏是 Swift 并发模型演进的一部分。它通过编译时生成代码,实现了更精细、更高效的属性观察。当AppViewModel中的某个属性(如selectedProvider)变化时,只有依赖这个属性的视图部分会更新,而不是整个视图刷新。这对于性能敏感的菜单栏应用来说是个利好。
2.3 数据模型与服务层 (Models/&Services/)
Models/目录下定义了应用的核心数据结构。
Provider:供应商模板模型。它可能包含id(UUID)、name(显示名称)、icon(SF Symbols 名称或自定义图片)、environmentVariables([String: String] 字典) 等属性。Configuration:可能对应settings.json的整个结构或 Claude 配置的特定部分。EnvironmentKey:一个枚举或结构体,用来定义所有可能的环境变量键,确保类型安全,避免拼写错误。
Services/目录包含了业务逻辑。
ConfigurationService:这是最核心的服务。它负责所有与~/.claude/settings.json文件相关的 IO 操作。class ConfigurationService { static let shared = ConfigurationService() private let fileManager = FileManager.default private let settingsURL: URL private init() { let home = fileManager.homeDirectoryForCurrentUser settingsURL = home.appendingPathComponent(".claude/settings.json") } func readCurrentSettings() throws -> [String: Any] { guard let data = try? Data(contentsOf: settingsURL) else { return [:] // 文件不存在则返回空字典 } let json = try JSONSerialization.jsonObject(with: data) return json as? [String: Any] ?? [:] } func writeConfiguration(for provider: Provider) throws { // 1. 创建备份 try createBackup() // 2. 读取现有配置 var currentSettings = try readCurrentSettings() // 3. 合并或替换环境变量部分 // 假设 Claude 配置在 `anthropic` 键下 var anthropicConfig = (currentSettings["anthropic"] as? [String: Any]) ?? [:] anthropicConfig.merge(provider.environmentVariables) { (_, new) in new } currentSettings["anthropic"] = anthropicConfig // 4. 写回文件 let newData = try JSONSerialization.data(withJSONObject: currentSettings, options: [.prettyPrinted]) try newData.write(to: settingsURL) } private func createBackup() throws { let backupURL = settingsURL.appendingPathExtension("backup") if fileManager.fileExists(atPath: settingsURL.path) { try fileManager.copyItem(at: settingsURL, to: backupURL) } } }- 路径处理:使用
FileManager.homeDirectoryForCurrentUser是获取用户主目录的安全、清晰的方式。 - 合并策略:
merge(_:uniquingKeysWith:)方法确保了用户可能在settings.json中手动设置的其他值(比如自定义的模型偏好)不会被覆盖,Prism 只更新它管理的环境变量部分。这是“非侵入式”设计的具体实现。 - 错误处理:所有文件操作都应使用
try-catch,并将有意义的错误抛给上层 ViewModel 以显示给用户。
- 路径处理:使用
ProviderService:负责加载和管理供应商模板列表,可能从内置的 JSON 资源文件、用户自定义的 plist 或甚至一个远程端点加载。
2.4 视图层:构建菜单栏界面 (Views/)
Prism 的 UI 极其简洁,主要视图可能包括:
ContentView:主弹出窗口的根视图。ProviderListView:显示所有可用供应商模板的列表,通常是一个List或ForEach循环。ProviderRowView:列表中的每一行,显示供应商图标、名称和激活状态。CustomProviderView:用于编辑自定义供应商配置的视图。
SwiftUI 的声明式语法在这里大放异彩。例如,ProviderRowView可能长这样:
struct ProviderRowView: View { let provider: Provider let isActive: Bool let action: () -> Void var body: some View { Button(action: action) { HStack { // 图标 Image(systemName: provider.icon) .foregroundStyle(.secondary) .frame(width: 20) // 名称 Text(provider.name) .font(.body) Spacer() // 激活状态指示器 if isActive { Image(systemName: "checkmark.circle.fill") .foregroundStyle(.blue) } } .contentShape(Rectangle()) // 扩大点击区域 } .buttonStyle(.plain) // 使用无样式按钮,获得更自然的列表交互 .padding(.vertical, 4) } }UI/UX 细节考量:
.buttonStyle(.plain):在List或ScrollView中使用这个样式,可以避免按钮默认的悬停和点击高亮与列表行样式冲突,让交互更自然。.contentShape(Rectangle()):这行代码将整个HStack的矩形区域都设置为可点击,而不仅仅是文字和图标部分,提升了点击命中率,这是提升菜单栏应用体验的一个小技巧。- 键盘导航:在
ContentView中,可以添加.focusable()和.onKeyPress修饰符,或者利用List自带的键盘选择能力,来实现上下箭头选择、回车键激活的功能。
3. 从零开始:编译、运行与配置实战
理论说得再多,不如亲手跑起来。我们走一遍从克隆代码到成功使用的完整流程,并解释每一个步骤背后的原因。
3.1 环境准备与项目初始化
第一步:确保开发环境Prism 要求Xcode 16.0 或更高版本,因为它的 Swift Package Manager 依赖和 Swift 6 语言特性需要新版工具链的支持。你可以在终端用xcode-select -p检查当前命令行工具路径,并通过 Mac App Store 更新 Xcode。
第二步:克隆代码库
git clone https://github.com/okooo5km/Prism.git cd Prism使用git clone是最直接的方式。如果网络不畅,也可以考虑在 GitHub 页面直接下载 ZIP 包并解压。
第三步:打开并编译项目
open Prism.xcodeproj在 Xcode 中打开项目后,首先检查签名与能力(Signing & Capabilities)。由于 Prism 需要访问~/.claude/目录进行文件读写,它不能启用沙盒(App Sandbox)。你会在项目设置中看到 “App Sandbox” 是关闭的。这是此类需要访问特定用户配置文件的工具类应用的常见设置。
重要提示:关闭沙盒的安全考量:沙盒是 macOS 保护用户安全的重要机制。关闭它意味着应用获得了与用户相同的文件系统访问权限(仅限于用户目录)。Prism 之所以敢这么做,是因为它的功能极其单一(只读写一个已知路径的 JSON 文件),代码开源可审计,且不涉及网络通信(除了 Sparkle 更新)。对于用户来说,这意味着你需要从可信来源(如官方 GitHub)获取和编译 Prism。切勿运行来历不明的已编译二进制文件。
在 Xcode 顶部的 Scheme 选择器中,确保选中“Prism”和“My Mac”作为运行目标。然后按下Cmd + B进行编译。首次编译会解析 Swift Package 依赖(主要是 Sparkle),可能需要一点时间。
3.2 处理依赖与编译问题
如果编译失败,最常见的问题集中在 Sparkle 框架上。
证书问题:Sparkle 使用了代码签名来确保更新包的安全。Xcode 可能会报错 “No certificate found” 或签名验证失败。解决方案是:
- 在 Xcode 中,进入项目设置 -> “Signing & Capabilities”。
- 在 “Prism” target 下,取消勾选 “Automatically manage signing”。
- 在 “Team” 下拉菜单中,选择 “None”。
- 重新编译。这将以“未签名(ad-hoc)”的方式编译应用,对于自用完全没问题。
依赖解析失败:如果网络问题导致 Swift Package Manager 无法下载 Sparkle,可以尝试:
- 在 Xcode 中,点击菜单栏的
File->Packages->Reset Package Caches。 - 或者,更彻底地,删除项目根目录下的
DerivedData文件夹(路径通常是~/Library/Developer/Xcode/DerivedData/Prism-xxxxx),然后重新打开项目。
- 在 Xcode 中,点击菜单栏的
编译成功后的关键一步:首次运行前,你需要确保目标配置文件存在。打开终端,执行:
mkdir -p ~/.claude touch ~/.claude/settings.json echo '{}' > ~/.claude/settings.json # 确保它是一个有效的空 JSON 对象这创建了 Claude 配置目录和空配置文件。Prism 需要这个文件存在且可写。
3.3 核心配置流程详解
现在,点击 Xcode 中的Cmd + R运行应用。你会看到菜单栏右侧出现了一个棱镜图标。点击它,弹出主界面。
界面解读与操作:
- 服务商列表:这里展示了所有预置的模板,如 “Zhipu AI”, “Moonshot”, “DeepSeek” 等,以及一个 “Custom…” 选项。
- 激活服务:点击列表中的任意一项,Prism 会执行以下动作:
- 读取:读取你现有的
~/.claude/settings.json。 - 合并:将所选服务商对应的环境变量(如
ANTHROPIC_API_KEY: “你的智谱API密钥”、ANTHROPIC_API_URL: “https://open.bigmodel.cn/api/paas/v4/”)合并到配置文件的适当位置。 - 备份:将操作前的配置文件复制为
settings.json.backup。 - 写入:将合并后的完整配置写回
settings.json。 - 反馈:UI 上该服务商旁边会显示一个蓝色的勾选标记,表示已激活。
- 读取:读取你现有的
如何获取并配置 API Key?Prism不存储你的 API Key。Key 是存储在settings.json文件中的。你需要手动将 Key 添加到对应的环境变量值中。有两种方式:
- 方式一:直接编辑 JSON 文件(不推荐给新手):用文本编辑器打开
~/.claude/settings.json,找到 Prism 写入的anthropic或对应字段,修改ANTHROPIC_API_KEY的值。 - 方式二:使用 Claude Desktop 或其他工具(推荐):许多 Claude 客户端提供了图形界面来输入 API Key。你可以在那些工具里输入一次,Prism 就能读取到。
自定义(Custom)模板的使用: 这是 Prism 最强大的功能之一。点击 “Custom…”,通常会弹出一个表单让你输入:
- Profile Name: 自定义名称,如 “我的私有网关”。
- API Endpoint: Claude 兼容 API 的完整 URL,例如
https://your-gateway.com/v1。 - API Key: 该网关所需的认证密钥。
- Additional Env Vars: 其他必要的环境变量,比如
ANTHROPIC_VERSION。
填写后保存,这个自定义模板就会出现在主列表中,和内置模板一样使用。这对于使用企业内部分流网关或小众兼容服务的用户来说非常方便。
3.4 构建发布版本与自动更新
在 Xcode 中,将编译模式从 “Debug” 切换到 “Release”,然后再次按下Cmd + B,会生成一个优化过的版本。你可以在 Products 目录下找到生成的Prism.app,将其拖拽到 “应用程序” 文件夹即可安装。
关于 Sparkle 自动更新: Sparkle 框架配置在Prism/App/目录下。为了让自动更新生效,开发者需要:
- 生成一个 EdDSA 密钥对用于签名更新包。
- 配置一个应用服务器来托管更新元数据 (
appcast.xml) 和压缩的更新包。 由于 Prism 是开源项目,这部分可能由项目维护者配置。对于你自己编译的版本,自动更新可能无法工作,你需要手动关注 GitHub 上的 Releases 来获取新版本。
4. 常见问题、排查技巧与进阶思考
即使设计得再完善,在实际使用和开发中还是会遇到各种问题。下面是我在探索 Prism 过程中总结的一些典型场景和解决方案。
4.1 使用问题排查速查表
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 点击 Prism 菜单栏图标无反应 | 1. 应用崩溃。 2. 菜单栏图标被系统隐藏。 | 1. 打开“控制台”应用,筛选Prism进程,查看崩溃日志。2. 按住 Cmd键拖拽菜单栏其他图标,看是否能将 Prism 图标拖出隐藏区。或重启应用。 |
| 激活服务后,Claude 客户端仍报错“无效 API Key” | 1.settings.json文件权限错误。2. API Key 未正确写入或格式错误。 3. Claude 客户端未读取新配置。 | 1. 终端执行ls -la ~/.claude/settings.json,确保当前用户有读写权限 (-rw-r--r--)。2. 用 cat ~/.claude/settings.json检查文件内容,确认api_key字段值正确且被引号包裹。3.完全退出并重启 Claude 客户端,许多客户端只在启动时加载配置。 |
| Prism 列表为空或缺少某个服务商 | 1. 内置的providers.json资源文件损坏或丢失。2. 该服务商模板尚未被 Prism 支持。 | 1. 重新克隆项目或检查Prism/Resources/providers.json文件是否存在。2. 使用 “Custom…” 功能手动添加。你需要知道该服务的 API 端点 URL 和所需的环境变量。 |
编译错误:Cannot find ‘Sparkle’ in scope | Sparkle 依赖未正确加载或链接。 | 1. 在 Xcode 中,点击项目导航器顶部的蓝色项目图标,选择 “Prism” Target,查看 “General” -> “Frameworks, Libraries, and Embedded Content”,确认 Sparkle.framework 已存在。 2. 尝试 File->Packages->Reset Package Caches。 |
运行时报错:The file “settings.json” doesn’t exist. | Claude 配置目录或文件未创建。 | 在终端执行:mkdir -p ~/.claude && echo '{}' > ~/.claude/settings.json |
4.2 开发与调试心得
1. 文件路径的坑在 macOS 开发中,获取标准目录路径应优先使用FileManager的 API(如.homeDirectoryForCurrentUser),而不是手动拼接字符串“/Users/username”。后者在系统语言、用户名包含特殊字符或通过sudo运行时极易出错。Prism 的代码在这方面做得很好。
2. JSON 序列化的稳健性ConfigurationService中读写 JSON 的代码必须非常健壮。readCurrentSettings方法在文件不存在时返回空字典,这是一个很好的降级处理。在writeConfiguration时,使用JSONSerialization.data(withJSONObject:options: [.prettyPrinted])的.prettyPrinted选项虽然增加了文件大小,但让生成的 JSON 对人类可读,方便用户手动调试,这是一个用户体验的细节。
3. 菜单栏应用的内存管理菜单栏应用通常长期驻留。要避免内存泄漏,需注意:
- 在
AppViewModel中使用weak或unowned打破可能的循环引用,尤其是在闭包中引用self时。 - 观察
NSStatusItem(或MenuBarExtra的底层实现)的生命周期,确保在应用退出时正确清理资源。SwiftUI 的MenuBarExtra在这方面帮我们管理了大部分生命周期,但自定义的观察者或计时器仍需手动清理。
4. 关于 AI 生成代码的审查Prism 作为 AI 生成代码的案例,在审查时会发现一些有趣的特点:
- 结构规整:AI 倾向于生成符合 Swift API 设计指南和常见模式的代码,目录结构清晰。
- 注释风格统一但可能冗余:生成的注释往往很全面,但有时会解释一些显而易见的代码。
- 边界情况处理可能不足:AI 可能无法覆盖所有边缘情况,比如网络异常、磁盘已满、文件被其他进程锁定等。这就是需要人类开发者介入“抛光”的地方——添加更细致的错误处理、重试逻辑和用户提示。
4.3 扩展思路:Prism 还能做什么?
Prism 的核心设计非常巧妙,它开辟了一个小而美的赛道。基于这个基础,我们可以想象很多有趣的扩展方向:
1. 配置快照与一键切换除了切换服务商,用户可能还有不同的“场景配置”,比如“工作-使用 GPT-4”、“个人-使用 Claude Haiku”、“实验-使用本地模型”。可以扩展Provider模型,使其支持保存一组完整的环境变量(包括模型名称、温度等),实现“配置场景”的一键切换。
2. 集成更多 AI 生态目前 Prism 专注于 Claude。理论上,同样的模式可以复制到 OpenAI 兼容的 API(管理OPENAI_API_KEY和OPENAI_BASE_URL),甚至同时管理多个 AI 生态的配置。菜单栏可以变成一个真正的“AI 服务控制中心”。
3. 增加简单的健康检查在切换服务商时,Prism 可以尝试向该服务的 API 端点发送一个极简的、不消耗额度的请求(如GET /models),验证 API Key 和端点的有效性,并在 UI 上给出“连接成功”或“验证失败”的即时反馈,体验会更上一层楼。
4. 可视化配置编辑对于高级用户,可以提供一个更友好的界面来直接编辑settings.json中的其他非环境变量配置,比如默认模型、上下文长度、温度等,让 Prism 成为一个功能更全面的 Claude 配置管理器。
Prism 项目像一个精心打磨的瑞士军刀,它证明了在明确的边界内,AI 已经能生成出不仅能用,而且代码质量相当不错的实用工具。对于开发者来说,它的价值不仅在于工具本身,更在于它展示了一种新的、人机协作的软件开发范式:人类负责定义问题、审核架构和打磨体验,AI 负责生成大量的基础实现代码。这种模式正在悄然改变独立开发和小型工具创作的生态。如果你正在寻找一个 SwiftUI 菜单栏应用的参考,或者对 AI 辅助编程感到好奇,那么深入阅读和尝试修改 Prism 的代码,会是一个非常有价值的旅程。
