AI 工作流程
这个项目是用 Claude Code 构建的。大多数声称”由 AI 构建”的项目止步于一个标签。以下是完整的全貌:AI 知道什么、会话如何运作、提示词在实践中是什么样子,以及人类在哪里划定界限。无论你是自己正在用 AI 构建项目,还是只是好奇它实际上是什么样的,这篇文章都适合你。
AI 知道什么
Section titled “AI 知道什么”Claude Code 拥有一个持久化的记忆文件,可以跨会话传递上下文。它不需要每次对话都重新探索代码库,而是从上次中断的地方继续。以下是其中的内容(已脱敏):
- 应用名称、源代码位置、许可证、应用标识符
- Fork 关系:上游是 Francisco Salgueiro 的 En Croissant,我们独立维护自己的 fork
- Fork 存在的原因:上游维护者拒绝了 TTS 功能,这完全合理——对同一个项目有不同的愿景
- 仅使用 pnpm —— npm 会破坏 vanillaExtract(运行时白屏,没有错误,什么都没有)
- 需要 Node.js 22+(Vite 7 需要
crypto.hash) - 提交前始终执行
pnpm format && pnpm lint:fix - 覆盖二进制文件前关闭应用(“Text file busy”)
- 移动源代码目录后,执行
cargo clean清除过期的路径引用
- 哪些文件负责哪些功能(原子状态在
atoms.ts,棋盘树导航在tree.ts,TTS 引擎在tts.ts) - 为什么所有 TTS 原子都需要
getOnInit: true(在 React 订阅之前通过store.get()进行命令式读取) - 音频缓存的工作原理(
provider:voiceId:lang:text键) - chessground 坐标修复是在 CSS 端,而不是 fork 该库
- 数据布局:什么存储在哪里,什么是符号链接,什么在应用重启后仍然保留
它不知道什么
Section titled “它不知道什么”记忆文件不包含 API 密钥、密码或凭证。它引用了这些内容的存储位置(localStorage 原子名称),但从不包含实际值。AI 生成的代码从设置中读取密钥——它从未见过或处理过实际的密钥。
AI 被告知什么
Section titled “AI 被告知什么”除了记忆文件之外,Claude Code 还遵循内置于其系统中的规则:
- 不要过度工程化。 只做明确要求的更改。修复一个 bug 不需要把周围的代码也清理一遍。三行相似的代码胜过一个过早的抽象。
- 不要猜测 URL。 永远不要编造链接或端点。
- 编辑前先阅读。 永远不要对没有读过的代码提出更改建议。
- 优先编辑而非创建。 除非绝对必要,否则不要创建新文件。
- 不引入安全漏洞。 注意注入、XSS 和 OWASP 十大安全问题。
- 不确定时提问。 如果指令有歧义,问清楚而不是猜测。
- 三思而后行。 破坏性操作(强制推送、reset —hard、删除文件)需要人类明确批准。
一次有用的 AI 交互和一次令人沮丧的交互之间的区别,几乎总是在于提示词。
明确说明你想要什么。 不要说”修复那个 bug”,而要说”TTS 缓存键没有包含提供商名称,所以从 ElevenLabs 切换到 Google 时会播放缓存的 ElevenLabs 音频,而不是生成新的音频。”
提供 AI 不具备的上下文。 AI 可以读你的代码,但它读不了你的心。“用户反映棋盘上的坐标是反的”不如”chessgroundBaseOverride.css 中的 CSS 把行和列搞反了——Francisco 最初的版本就是反的”有用。
说明你的约束条件。 “不要创建新文件”或”使用现有的原子模式”或”这需要在没有 API 密钥的情况下工作”告诉 AI 护栏在哪里。
说明你不想要什么。 “不要为不可能发生的情况添加错误处理”或”不要重构周围的代码”可以防止过度工程化——这是最常见的 AI 失败模式。
这个模式是:意图 + 上下文 + 约束。掌握它,AI 就会变得极其有用。
规划模式:用一个 Claude 来给另一个 Claude 写提示词
Section titled “规划模式:用一个 Claude 来给另一个 Claude 写提示词”Claude Code 有一个”规划模式”,将思考和执行分离。在规划模式下,AI 读取文件、探索代码库并生成计划——但不写任何代码。你审查计划、调整它,然后切换到实现模式,AI 执行计划。
为什么这样做有效?因为任何编码任务中最难的部分不是写代码。而是弄清楚应该写什么代码——修改哪些文件、遵循什么模式、存在哪些边界情况。规划模式在写出任何一行代码之前,将全部注意力集中在这个问题上。
这个项目中的一个例子:当我们重构”帮助”菜单以添加语言选择器时,规划模式的对话探索了 Tauri 菜单的工作方式、已经存在哪些原子、文档查看器如何解析资源路径,以及确认对话框 API 的样子。等到我们切换到实现模式时,AI 已经有了一张完整的更改地图。没有走弯路。
你实际上是在用 AI 的一个实例作为高级架构师,另一个作为开发者。同一个模型,不同的角色。
会话如何运作
Section titled “会话如何运作”一个典型的会话是这样的:
-
人类陈述意图。 “在 KittenTTS 部分添加缓存说明。""移除 PostHog 遥测。""质量评级是错的,应该是这样的。”
-
AI 读取相关文件。 它不会猜测文件的内容。它读取文件,理解当前状态,然后提出更改。当文件之间相互独立时,会并行读取多个文件。
-
AI 进行更改。 对现有文件进行有针对性的编辑。不是重写——而是保留周围一切的精确修改。
-
人类审查。 每次编辑在写入磁盘前都会展示给人类。人类批准、拒绝或重新引导。“不,那太委婉了——说它真的很差。""把那段往上移。""那不是我的意思。”
-
收到指示后才提交。 AI 永远不会自行提交。人类说”提交”或”提交并推送”。提交信息包含
Co-Authored-By: Claude Opus 4.6——始终标注归属,从不隐藏。
上下文窗口和存档点
Section titled “上下文窗口和存档点”每次 AI 对话都有一个上下文窗口——它一次能在内存中保持的文本总量。当对话足够长时,较早的消息会被压缩以腾出空间。
两个策略:保持对话聚焦(每次对话一个任务),以及使用存档点(Claude Code 将对话记录保存为 JSONL 文件,你可以从中恢复完整上下文继续对话)。记忆文件的用途不同——它是一个跨所有对话持久存在的知识库。
AI 提出的内容 vs. 最终发布的内容
Section titled “AI 提出的内容 vs. 最终发布的内容”AI 的第一个建议很少是最终版本。一个典型的交流过程:
- AI 起草一个合理的版本
- 人类说”太商业化了”或”更直接些”或”那是错的,原因是这样的”
- AI 调整
- 人类批准
品味、语调和最终决定权始终在人类手中。AI 负责速度——读取文件、理解上下文、在它能完整保持在内存中的代码库里进行精确的编辑。人类负责判断——构建什么、应该是什么感觉、什么时候停下来。
技能和斜杠命令
Section titled “技能和斜杠命令”Claude Code 支持”技能”——以 markdown 文件形式存储在 .claude/commands/ 目录中的可复用提示词。你通过斜杠命令调用它们,比如 /translate-docs。
本项目使用了一个 /translate-docs 技能来自动将文档翻译成多种语言。技能文件包含完整的指令:翻译哪些文件、使用什么格式、如何处理代码块和链接、保持什么语调。你不需要每次都解释这些,只需输入 /translate-docs,AI 就确切知道该做什么。
技能编码的是流程,而不仅仅是信息。你可以为任何重复性工作流构建技能:运行测试、部署、审查 PR、更新变更日志。
完整的原则文档位于仓库的 .claude/01_UNIVERSAL_PRINCIPLES.md。它最初基于 Robert C. Martin 的 Clean Code(2008)加上针对 AI 时代的补充。然后我们进行了一次坦诚的对话,讨论哪些仍然适用,哪些已经不适用。
经久不变的原则
Section titled “经久不变的原则”- 名称要揭示意图。 始终如此。永远如此。
- 函数只做一件事。 真正的原则是内聚性,不是大小。
- 没有副作用。 仍然是大多数 bug 的根源。
- 注释解释为什么,而不是什么。
- 单一职责。 一个模块应该只有一个变更的理由。
- 面向接口编程,而不是面向实现。
- 不要吞掉错误。 每个错误都是信息。
- 浮现式设计: 通过所有测试、没有重复、表达意图、最小化复杂度。按这个顺序。
需要因地制宜的原则
Section titled “需要因地制宜的原则”这些原则本身是正确的,但具体规则反映的是前 AI 时代或特定语言的世界。我们遵循精神,而非字面:
- DRY。 会逐渐分化的重复是危险的。但将每个重复的模式都提取为抽象会产生间接层,这可能更糟。有时候,就在这里的三行可读代码比另一个文件里的过早抽象要好。
- 严格的 TDD 仪式。 原则——发布经过测试的代码,确保它能正常工作——是不可妥协的。仪式——测试必须先于代码存在——是为人类打字很慢的工作流设计的。写测试。确保它们通过。测试和代码谁先写不如两者都存在来得重要。
- 童子军原则。 “离开时比来时更干净”——是的。但童子军清理的是营地,不是整片森林。修复你接触到的部分。不要因为改了一行代码就重构整个文件的结构。
AI 时代的新增原则
Section titled “AI 时代的新增原则”- 基于原则的指导比基于规则的指导更具扩展性。 原则允许判断;规则是脆弱的。
- 如果是 AI 代理构建的,AI 代理就能维护它。 保留对话上下文和产出物。记录构建过程,而不仅仅是结果。
- 清晰优于巧妙。 构建这个系统的工具需要能够重建推理过程并正确地修改它。显式的结构胜过精巧的小抽象。
- 这能否成为基础设施? 工具为你解决问题。基础设施使他人能够在此之上构建。据此进行设计。
人类在哪里划定界限
Section titled “人类在哪里划定界限”AI 是一个工具。一个非常出色的工具。但有些事情它不做:
- 产品决策。 构建什么功能、砍掉什么、应用应该给人什么感觉。“系统 TTS 的质量评级应该写’勉强能用’,因为它确实很差”——这是基于实际听过之后的人类判断。
- 品味。 AI 可以写出干净的文字,但项目的声音、对质量直言不讳的决定、选择显著地标注 Francisco 的贡献——这些都是人类的选择。
- 伦理。 移除 PostHog 不是一个重构任务。而是”设置页面说我们不收集遥测数据,但代码里有一个活跃的 PostHog API 密钥。这是谎言。修复它。” AI 执行了。人类发现了问题并且在乎这件事。
- 国际象棋。 棋盘不关心你用什么工具。
为什么分享这些
Section titled “为什么分享这些”因为”由 AI 构建”已经变得毫无意义。每个人都这么说。没有人展示出来。有趣的问题不是 AI 是否参与了——而是它如何参与的,以及人类实际贡献了什么。
这就是答案。人类带来愿景、品味、判断和责任。AI 带来速度、记忆,以及凌晨两点仍不知疲倦地阅读 Rust 错误信息的意愿。
两者都无法单独构建这个项目。两者都获得署名。这就是约定。
En Parlant~ 是 Francisco Salgueiro 的 En Croissant 的 fork,使用 Anthropic 的 Claude Code 构建。