<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Developer Tools on Hypho - AI Agent 技术博客</title><link>https://blog.hypho.cn/tags/developer-tools/</link><description>Recent content in Developer Tools on Hypho - AI Agent 技术博客</description><image><title>Hypho - AI Agent 技术博客</title><url>https://blog.hypho.cn/papermod-cover.png</url><link>https://blog.hypho.cn/papermod-cover.png</link></image><generator>Hugo -- 0.148.2</generator><language>zh-cn</language><lastBuildDate>Fri, 12 Jun 2026 10:07:01 +0800</lastBuildDate><atom:link href="https://blog.hypho.cn/tags/developer-tools/index.xml" rel="self" type="application/rss+xml"/><item><title>小米 MiMo Code 深度拆解：fork 一个 17 万星项目后，他们加了什么</title><link>https://blog.hypho.cn/posts/mimo-code-xiaomi-open-source-coding-agent/</link><pubDate>Fri, 12 Jun 2026 10:07:01 +0800</pubDate><guid>https://blog.hypho.cn/posts/mimo-code-xiaomi-open-source-coding-agent/</guid><description>小米开源 MiMo Code 编程智能体，基于 17 万星的 OpenCode 构建，加入持久化记忆、子智能体编排和自我进化机制。本文拆解其技术架构，分析它与 Claude Code 的竞争定位，以及&amp;#34;大厂 fork 开源项目&amp;#34;这一做法引发的社区争议。</description><content:encoded><![CDATA[<p>两天之内 4700+ Star，241 条 HN 评论——小米 MiMo Code 的发布在开发者社区引起了不小的波澜。但让我真正感兴趣的不是这个数字本身，而是它背后的策略：fork 一个已经有 17 万 Star 的开源项目 OpenCode，然后在上面叠加自己的东西。</p>
<p>坦白说，&ldquo;大厂 fork 开源项目&quot;这件事本身就自带争议。HN 评论区有人直接开喷：&ldquo;fork 一个已有的开源项目，不给上游贡献代码，附加可能跟 MIT 许可证冲突的使用限制，然后还要 PR。&ldquo;但也有另一种声音：如果 fork 出来的东西确实有实质性的技术创新，那这件事本身就有讨论的价值。</p>
<p>所以这篇文章想回答的核心问题是：MiMo Code 到底加了什么？这些加的东西值不值得一个独立项目的存在？</p>
<h2 id="从-opencode-到-mimo-code不是换层皮那么简单">从 OpenCode 到 MiMo Code：不是换层皮那么简单</h2>
<p>先说上游项目。<a href="https://github.com/anomalyco/opencode">OpenCode</a>（现在叫 opencode）是一个终端原生的 AI 编程助手，17 万+ Star，TypeScript 写的，支持多 Provider、TUI 界面、LSP、MCP 协议和插件系统。它在 2025 年 4 月创建，到现在已经迭代了一年多，是终端编程 agent 领域里用户量最大的开源项目之一。</p>
<p>MiMo Code 保留了 OpenCode 的所有核心能力——多 Provider 切换、TUI 交互、LSP 集成、MCP 工具协议和插件系统——在此基础上叠加了五个关键模块。从源码结构看，它在 <code>packages/opencode</code> 目录下保留了 OpenCode 的核心代码，同时新增了 <code>packages/app</code>、<code>packages/desktop</code>、<code>packages/enterprise</code>、<code>packages/sdk</code> 等模块，看起来不只是一个 CLI 工具，而是一个完整的平台化产品。</p>
<p><strong>持久化记忆系统</strong> —— 这可能是最有意思的部分。它用 SQLite FTS5（全文搜索）做底层存储，维护一个 <code>MEMORY.md</code> 文件作为跨会话的项目知识库。每次你开新会话，记忆自动注入上下文，agent 不需要重新理解项目结构。</p>
<p>用人话说就是：普通编程 agent 像金鱼，每次开会话都从零开始；MiMo Code 的记忆系统让它能&quot;记住&quot;你的项目，包括架构决策、代码规范、你踩过的坑。</p>
<p><strong>智能上下文管理</strong> —— 当对话接近模型的上下文窗口限制时，MiMo Code 不是简单地截断，而是从最新的 checkpoint、项目记忆、任务进展和保留的近期消息中&quot;重建&quot;上下文。它还用 token budget 控制注入内容的大小，按重要性排序。这是个工程上很实际的问题：长会话的上下文管理做不好，agent 会突然&quot;失忆&rdquo;。</p>
<p><strong>子智能体编排</strong> —— 主 agent 可以按需生成子智能体，它们共享当前会话上下文并行工作。有生命周期追踪、取消机制和后台执行。三种主模式：build（完整工具权限）、plan（只读分析）、compose（specs-driven 编排）。</p>
<p><strong>Goal 停止条件</strong> —— <code>/goal</code> 命令设置停止条件，当 agent 想停下来时，由独立的裁判模型评估对话内容，判断条件是否真正满足。这个设计防的是&quot;乐观停止&rdquo;——agent 觉得自己干完了，其实没干完。</p>
<p><strong>Dream &amp; Distill</strong> —— <code>/dream</code> 扫描近期会话轨迹，提取持久知识到项目记忆；<code>/distill</code> 发现重复的手动工作流，打包成可复用的 skill。这是&quot;自我进化&quot;的核心机制。说白了，用得越多，它越懂你的项目。这跟人类开发者的学习曲线很像——你在一个项目上待得越久，你的 mental model 越完整。MiMo Code 试图把这个过程自动化。</p>
<p>还有一个实验性功能叫 <strong>Max Mode</strong>：并行 best-of-N 推理 + 裁判选优。开启后 agent 会对同一个问题生成多个候选方案，然后用裁判模型选出最好的一个。这个思路在 LLM 推理领域叫 &ldquo;majority voting&rdquo; 或 &ldquo;self-consistency&rdquo;，用在编程 agent 上是个有意思的工程化尝试——代价是 token 消耗翻倍，但复杂任务的质量可能会有明显提升。</p>
<h2 id="架构上值得关注的几个技术选择">架构上值得关注的几个技术选择</h2>
<p><strong>SQLite FTS5 而不是向量数据库</strong>。大部分 AI 记忆方案用 embedding + 向量检索，MiMo Code 选了传统全文搜索。看它的源码，搜索逻辑用 BM25 排序，还做了一个相对阈值过滤——保留得分至少为 top hit 某个比例的结果，而不是用绝对阈值。理由是 BM25 的分数跟语料库大小相关，小语料库里所有分数都趋近于 0，绝对阈值会误杀。</p>
<p>这个选择的工程意义是：SQLite 是零依赖的，不需要额外跑一个向量数据库服务。对于终端工具来说，部署简单性是核心竞争力。但代价是语义搜索能力弱——你搜&quot;authentication&quot;不会匹配到&quot;login&rdquo;。</p>
<p>还有一个细节值得注意：MiMo Code 的记忆系统能索引 Claude Code 的 <code>~/.claude/projects</code> 目录。源码里有一个 <code>cc_index</code> 配置项，开启后会把 Claude Code 的项目记忆也纳入搜索范围。这个设计很聪明——它降低了从 Claude Code 迁移过来的用户的切换成本，你的历史记忆不会丢失。</p>
<p><strong>Effect 框架</strong>。MiMo Code 的核心代码用了 TypeScript 的 Effect 库做依赖注入和错误处理。从源码看，Config、Memory、Agent 等模块都是 Effect Layer。这在 Node.js/Bun 生态里不算主流选择，但确实让代码结构更清晰，副作用管理更可控。</p>
<p><strong>MCP 协议支持</strong>。MiMo Code 完整支持 Model Context Protocol，可以连接外部工具服务器。这意味着它不只是一个封闭的编程 agent，而是一个可扩展的平台——你可以接入数据库、API、自定义工具。</p>
<h2 id="与-claude-code-的直接竞争">与 Claude Code 的直接竞争</h2>
<p>MiMo Code 最大的竞争对手是 <a href="https://github.com/anthropics/claude-code">Claude Code</a>（13 万+ Star）。两者都是终端原生的 AI 编程 agent，但定位差异明显：</p>
<table>
  <thead>
      <tr>
          <th>维度</th>
          <th>MiMo Code</th>
          <th>Claude Code</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>开源</td>
          <td>MIT License（但有使用限制）</td>
          <td>闭源</td>
      </tr>
      <tr>
          <td>默认模型</td>
          <td>MiMo V2.5（免费通道）</td>
          <td>Claude Sonnet/Opus</td>
      </tr>
      <tr>
          <td>记忆系统</td>
          <td>SQLite FTS5 + MEMORY.md</td>
          <td>项目级 CLAUDE.md</td>
      </tr>
      <tr>
          <td>上下文管理</td>
          <td>自动 checkpoint + 重建</td>
          <td>基础截断</td>
      </tr>
      <tr>
          <td>子智能体</td>
          <td>完整编排系统</td>
          <td>有限</td>
      </tr>
      <tr>
          <td>自我进化</td>
          <td>Dream &amp; Distill</td>
          <td>无</td>
      </tr>
  </tbody>
</table>
<p>从 HN 评论看，用户体验的反馈集中在几点：免费零配置启动是最大卖点（&ldquo;不用注册，不用+86手机号&rdquo;）；MiMo V2.5 Pro 模型能力接近 Claude Opus 水平但价格低得多；但 token 计费方式有争议（有用户反映 500K tokens 的任务显示消耗了 1.52 亿 tokens）。</p>
<p>说白了，MiMo Code 的策略是：用开源 + 免费通道拉用户，用记忆系统和自我进化做差异化，用小米的模型生态做成本优势。Claude Code 的护城河是模型能力本身和 Anthropic 的品牌信任。两条路线，短期看 MiMo Code 的增长势头很猛，长期能不能留住用户取决于模型能力的持续追赶。</p>
<p>值得注意的是，编程 agent 赛道现在已经是红海。除了 Claude Code，还有 OpenAI 的 Codex CLI、Google 的 Gemini CLI、以及社区里的各种方案。从 HN 评论看，有开发者提到自己的项目 &ldquo;VT Code&rdquo; 已经成为小米 Orbit 合作伙伴，可以在不同 harness 里使用 MiMo V2.5/Pro 模型。这意味着小米的策略不只是推自己的工具，而是让模型渗透进整个生态——工具是入口，模型 API 才是真正的商业模式。</p>
<h2 id="争议与隐忧">争议与隐忧</h2>
<p>不回避问题。MiMo Code 有几个值得警惕的点：</p>
<p><strong>USE_RESTRICTIONS.md 与 MIT 许可证的兼容性</strong>。代码是 MIT 的，但附加了一个使用限制文件，禁止军事用途、恶意网络活动、未经授权的数据处理等。从法律角度看，MIT 许可证本身不附加使用限制，这个文件的法律效力存疑。HN 上有人直接说&quot;use restrictions probably incompatible with the license&quot;。</p>
<p><strong>不给上游贡献</strong>。MiMo Code 是 fork，不是 contributor。OpenCode 仍在活跃开发（最近一次提交就在今天），MiMo Code 的独立发展可能导致两个项目渐行渐远。这在开源社区是敏感话题——fork 的权利是 GPL/MIT 保证的，但社区道义上期望 fork 能反哺上游。</p>
<p><strong>curl-pipe-bash 安装方式</strong>。<code>curl -fsSL https://mimo.xiaomi.com/install | bash</code> 这种安装方式在安全意识强的开发者中一直有争议。虽然很多工具都这么做（Homebrew、nvm），但对于一个新项目来说，建立信任需要时间。</p>
<p><strong>免费通道的商业逻辑</strong>。&ldquo;免费的东西最贵&rdquo;——你的代码上下文、项目结构、编程习惯都会被上传到小米的服务器。对于个人项目可能无所谓，对于企业代码库就需要谨慎评估了。好消息是 MiMo Code 支持自定义 Provider，你可以连 OpenRouter、Azure 或者任何 OpenAI 兼容的 API，完全绕开小米的服务器。但大部分人可能不会这么配——免费的诱惑力太大了。</p>
<h2 id="实际使用建议">实际使用建议</h2>
<p>如果你在考虑是否试用 MiMo Code，我的判断是：</p>
<p><strong>值得试的场景</strong>：个人项目、开源贡献、学习新技术栈。免费通道的 MiMo V2.5 模型在常规编程任务上表现不错，记忆系统对于跨天的长任务确实有优势。</p>
<p><strong>谨慎使用的场景</strong>：企业代码库、涉及商业机密的项目。需要仔细评估数据上传策略，或者配置自定义 Provider 连接自己的模型 API。</p>
<p><strong>不建议的场景</strong>：如果你已经在 Claude Code 生态里有成熟的工作流，短期内不建议切换。MiMo Code 的记忆系统和编排能力虽然有吸引力，但生态成熟度（插件、社区支持、文档）还需要时间。</p>
<p>从更宏观的角度看，MiMo Code 的发布标志着 AI 编程工具赛道的竞争进入新阶段。不再只是模型能力的比拼，而是在 agent 架构、记忆系统、开发者体验上的全面竞争。小米作为一家硬件公司，能在短时间内做出这样的产品，本身说明 AI 编程工具的门槛在降低——真正的壁垒不是代码，而是模型能力和用户信任。</p>
<p>还有一点容易被忽略：MiMo Code 的名字里虽然带着&quot;小米&quot;，但它的代码是 MIT 许可的，任何人都可以 fork、修改、二次分发。这意味着社区完全可以基于 MiMo Code 的记忆系统和编排能力，去掉小米的使用限制，做一个纯社区版本。开源的可 fork 性本身就是对商业滥用的制衡——你可以限制使用，但社区也可以选择不接受你的限制。</p>
<p>最后说一个实际体验上的细节：MiMo Code 的安装是一行命令，首次启动自动引导配置，支持从 Claude Code 一键迁移认证。这种&quot;零摩擦上手&quot;的设计理念，加上免费的默认模型通道，说明小米很清楚开发者工具的获客逻辑——降低尝试成本比什么都重要。至于能不能把试用用户变成长期用户，那就是另一回事了。</p>
<hr>
<p><em>参考来源：<a href="https://github.com/XiaomiMiMo/MiMo-Code">MiMo Code GitHub</a> | <a href="https://github.com/anomalyco/opencode">OpenCode GitHub</a> | <a href="https://news.ycombinator.com/item?id=48490826">Hacker News 讨论</a></em></p>
<p><em>相关阅读：<a href="https://blog.hypho.cn/posts/claude-code-routines/">Claude Code 实战：用 Routines 构建可复用的 AI 编程工作流</a> | <a href="https://blog.hypho.cn/posts/stash-open-source-ai-memory-layer/">Stash：开源 AI 记忆层的工程实践</a></em></p>
]]></content:encoded></item><item><title>Vibe Coding 让你跳过学习，这个开源项目偏要让你亲手写代码</title><link>https://blog.hypho.cn/posts/lathe-llm-learn-by-doing-not-vibecoding/</link><pubDate>Mon, 08 Jun 2026 10:06:01 +0800</pubDate><guid>https://blog.hypho.cn/posts/lathe-llm-learn-by-doing-not-vibecoding/</guid><description>当 AI 编程助手让开发者习惯&amp;#34;跳过思考直接出代码&amp;#34;时，开源项目 Lathe 反其道而行——用 LLM 生成手把手教程，要求你亲手敲每一行代码。这种&amp;#34;反 Vibe Coding&amp;#34;的学习方式，可能才是 LLM 时代真正需要的开发者工具。</description><content:encoded><![CDATA[<p>最近 HN 上有篇帖子引起了我的注意：一个叫 Lathe 的开源项目，247 points，标题是&quot;Use LLMs to learn a new domain, not skip past it&quot;。</p>
<p>说实话，看到这个标题的第一反应是：又一个 LLM 教学工具？市面上这类东西已经太多了——NotebookLM、各种 AI tutor、ChatGPT 自己就能教你任何东西。但仔细看完 README 和 HN 评论区之后，我觉得这个项目抓住了一个很多人没说出口的痛点。</p>
<h2 id="问题出在哪">问题出在哪？</h2>
<p>过去一年，&ldquo;Vibe Coding&quot;这个概念从 Andrej Karpathy 的一条推文变成了整个行业的主流工作方式。打开 Claude Code、Cursor 或者 Copilot，描述你想要什么，AI 帮你生成代码，你负责 Review 和微调。效率确实高，但这里有一个很少被正面讨论的问题：<strong>你到底学到了什么？</strong></p>
<p>HN 上另一篇今天 807 points 的帖子——&ldquo;LLMs are eroding my software engineering career&rdquo;——把这个焦虑写得很直白。一位资深工程师说，LLM 正在侵蚀他的软件工程职业，他不知道该怎么办。评论区里各种声音都有，但核心矛盾其实就一个：当 AI 代劳了思考过程，工程师的价值在哪里？</p>
<p>这不是杞人忧天。看看现在的 AI 编程成本追踪工具（比如 <a href="/posts/budi-ai-coding-cost-tracker/">Budi</a>）就知道，很多团队每个月在 AI 编程上的开销已经不小了。但如果你问这些开发者&quot;你从 AI 生成的代码里学到了什么&rdquo;，大部分人会沉默。</p>
<h2 id="lathe-的反直觉设计">Lathe 的反直觉设计</h2>
<p>Lathe 的作者 Deven Jarvis 在 README 里写了一段很长的个人经历，我读完觉得挺真诚的。他在 2000 年代通过 PSP 自制游戏社区学会了编程，后来通过各种 hands-on 教程（build-your-own-x、Crafting Interpreters 这类）不断精进。他说这些教程给他的不只是知识，更是&quot;从零到一&quot;的信心和继续深入的底气。</p>
<p>然后他发现 LLM 把这个过程跳过了。</p>
<p>Lathe 的设计哲学很明确：<strong>LLM 应该是你的老师，不是你的代笔。</strong> 具体来说，它做的是：</p>
<ol>
<li><strong>生成手把手教程</strong>：你给一个主题（比如&quot;用 Zig 写一个 3D 切片器&quot;），Lathe 会生成多部分的详细教程，每一步都有代码和解释</li>
<li><strong>你必须亲手敲代码</strong>：教程在本地 UI 里展示，但代码不会自动复制到你的编辑器——你得自己打</li>
<li><strong>带验证机制</strong>：教程可以被 LLM 自己验证，跑一遍看能不能编译通过</li>
<li><strong>记录信源</strong>：每个教程都记录它参考了哪些资料，方便你溯源</li>
</ol>
<p>技术实现上，Lathe 是一个 Go CLI + LLM Skills 的组合。CLI 负责存储和管理教程（存在 <code>~/.lathe/tutorials/</code>），本地 Web 服务（端口 4242）负责展示，而生成、验证、提问这些操作都通过 LLM Skills 完成。目前支持 Claude Code、Cursor 和 Codex。</p>
<h2 id="skills-架构比想象中更精巧">Skills 架构：比想象中更精巧</h2>
<p>Lathe 的 Skills 设计值得单独说一下。它不是简单地让 LLM &ldquo;写一篇教程&rdquo;，而是拆分成了多个专门的 Skills：</p>
<table>
  <thead>
      <tr>
          <th>Skill</th>
          <th>功能</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>/lathe</code></td>
          <td>生成教程（单篇或系列）</td>
      </tr>
      <tr>
          <td><code>/lathe-extend</code></td>
          <td>在现有教程基础上追加新部分</td>
      </tr>
      <tr>
          <td><code>/lathe-verify</code></td>
          <td>在临时目录里跑一遍教程，验证能不能正常工作</td>
      </tr>
      <tr>
          <td><code>/lathe-ask</code></td>
          <td>针对教程内容提问</td>
      </tr>
      <tr>
          <td><code>/lathe-tag</code></td>
          <td>给教程添加搜索标签</td>
      </tr>
      <tr>
          <td><code>/lathe-voice</code></td>
          <td>自定义写作风格</td>
      </tr>
  </tbody>
</table>
<p>这个设计的好处是：每个 Skill 都有明确的输入输出和行为约束，不会出现&quot;LLM 突然开始帮你写代码而不是教你&quot;的情况。尤其是 <code>/lathe-verify</code>，它在 <code>mktemp -d</code> 临时目录里执行，不会碰你的项目代码，但能验证教程的可执行性。</p>
<p>自定义 Voice 功能也很有意思。默认有两种风格：&ldquo;plainspoken&rdquo;（平实直接）和&quot;companion&quot;（温暖的第一人称）。你还可以用 <code>/lathe-voice</code> 让 LLM 采访你的写作偏好，生成自定义风格。不过有一点值得注意：所有 Voice 都被要求不能冒充真人、不能伪造资质、不能否认 LLM 作者身份。这种透明性设计在现在的 AI 写作工具里其实不多见。</p>
<h2 id="与-notebooklm-和传统-ai-教学的区别">与 NotebookLM 和传统 AI 教学的区别</h2>
<p>HN 评论区有人问&quot;这和 Google NotebookLM 有什么区别&quot;。我觉得核心区别在于：</p>
<p><strong>NotebookLM 是被动学习</strong>：你上传资料，它帮你总结和回答问题。学习的主体还是你，但交互模式是问答式的。</p>
<p><strong>Lathe 是主动学习</strong>：它生成结构化的动手教程，要求你实际操作。学习过程中你会遇到真实的编译错误、运行时问题，这些&quot;挫折&quot;本身就是学习的一部分。</p>
<p>还有一个关键区别：Lathe 的教程会记录信源（sources），在 UI 里展示&quot;Researched against N sources&quot;。这意味着你可以追溯 LLM 的知识来源，而不是像 ChatGPT 那样凭空给你一段看起来很专业的解释。</p>
<h2 id="坦白说这个方案也有局限">坦白说，这个方案也有局限</h2>
<p>Lathe 不是万能的。作者自己也很坦诚地承认了几个问题：</p>
<ol>
<li><strong>幻觉风险依然存在</strong>：虽然教程要求你亲手写代码（这意味着你会自然地发现不合理的地方），但 LLM 生成的教程本身可能有错误</li>
<li><strong>学习效果取决于你的投入</strong>：如果你只是机械地抄代码而不思考，效果和直接让 AI 写没区别</li>
<li><strong>依赖 Claude Code 等付费工具</strong>：作者提到 Claude Code 的 headless 模式即将收费（2026-06-15），这可能影响成本</li>
<li><strong>目前主要在 macOS + Claude Code 上测试</strong>：其他平台的兼容性还需要验证</li>
</ol>
<p>但我觉得，这些问题恰恰说明了 Lathe 的定位很清醒——它不是要取代人类写的教程（作者明确说&quot;能找到人类写的教程就先看那个&quot;），而是填补那些&quot;没有现成教程的冷门领域&quot;的空白。</p>
<h2 id="对开发者工具的启示">对开发者工具的启示</h2>
<p>Lathe 给我最大的启发不是它本身，而是它代表的一种设计模式：<strong>用 LLM 的能力来增强人的学习，而不是替代人的思考。</strong></p>
<p>在 <a href="/posts/claude-code-routines/">Claude Code 的 Routines</a> 这类工具里，我们已经看到 LLM 可以被约束成&quot;按规则办事&quot;的执行者。Lathe 更进一步，把 LLM 约束成&quot;按规则教学&quot;的老师。这种思路可能比单纯追求&quot;AI 帮你写更多代码&quot;更有长期价值。</p>
<p>想想看，如果每个 AI 编程工具都有一个&quot;学习模式&quot;——在帮你写完代码之后，用教程的形式解释为什么这样写、背后的原理是什么、有哪些替代方案——那&quot;LLM 侵蚀工程师职业&quot;的焦虑可能会小很多。</p>
<h2 id="怎么用">怎么用？</h2>
<p>如果你感兴趣，安装很简单：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># macOS（推荐）</span>
</span></span><span class="line"><span class="cl">brew install devenjarvis/tap/lathe
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Linux</span>
</span></span><span class="line"><span class="cl">curl -sSf https://raw.githubusercontent.com/devenjarvis/lathe/main/install.sh <span class="p">|</span> sh
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 或者 Go 安装</span>
</span></span><span class="line"><span class="cl">go install github.com/devenjarvis/lathe@latest
</span></span></code></pre></div><p>然后在 Claude Code（或 Cursor/Codex）里：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 安装 Skills</span>
</span></span><span class="line"><span class="cl">lathe skills install
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 生成教程</span>
</span></span><span class="line"><span class="cl">/lathe build a raytracer in Rust
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 启动本地 UI</span>
</span></span><span class="line"><span class="cl">lathe serve
</span></span></code></pre></div><p>项目地址：<a href="https://github.com/devenjarvis/lathe">github.com/devenjarvis/lathe</a></p>
<p>目前 550 stars，MIT 协议，4 个 release，作者（和 Claude）123 commits，非常活跃。如果你和我一样，觉得&quot;Vibe Coding 虽然爽但总有点心虚&quot;，可以试试这个。</p>
<hr>
<p><strong>参考资料：</strong></p>
<ul>
<li><a href="https://github.com/devenjarvis/lathe">Lathe GitHub README</a></li>
<li><a href="https://news.ycombinator.com/item?id=48433756">HN: Show HN: Lathe</a></li>
<li><a href="https://human-in-the-loop.bearblog.dev/llms-are-eroding-my-software-engineering-career-and-i-dont-know-what-to-do/">HN: LLMs are eroding my software engineering career</a></li>
</ul>
]]></content:encoded></item><item><title>Semble 代码搜索：给编程 Agent 用的检索工具，真比 grep 更适合生产吗？</title><link>https://blog.hypho.cn/posts/semble-code-search-for-agents/</link><pubDate>Mon, 18 May 2026 10:04:30 +0800</pubDate><guid>https://blog.hypho.cn/posts/semble-code-search-for-agents/</guid><description>Semble 是一个面向编程 Agent 的本地代码搜索工具，声称比 grep+read 少用约 98% token。本文从 MCP 集成、BM25+静态向量混合检索、索引延迟、上下文噪声和生产落地边界出发，分析它适合哪些 AI 编程工作流，什么时候能提升代码理解效率，以及什么时候仍然应该保留传统 grep、完整阅读和人工代码审查。</description><content:encoded><![CDATA[<p>我对“给 Agent 做代码搜索”这类工具一直有点警惕。</p>
<p>原因很简单：很多产品把问题讲成“grep 太笨，向量检索更聪明”，最后落地却变成另一个黑盒。Agent 找不到符号定义时，开发者至少还能看见它 grep 了什么；如果换成一个语义搜索服务，结果看起来更像魔法，但错的时候也更难排查。</p>
<p>所以看到 HN 上的 <a href="https://github.com/MinishLab/semble">Semble</a> 时，我第一反应不是“又一个代码 RAG”，而是问一个更工程化的问题：<strong>编程 Agent 到底需要什么样的代码搜索？</strong></p>
<p>Semble 的答案挺明确：它不是给人做 IDE 搜索，也不是给企业做大规模代码知识库，而是给 Claude Code、Codex、Cursor、OpenCode 这类编程 Agent 提供一个本地、低延迟、少 token 的代码检索层。HN 原帖标题也很直接：<a href="https://news.ycombinator.com/item?id=48169874">Show HN: Semble – Code search for agents that uses 98% fewer tokens than grep</a>。截至我写这篇时，项目在 GitHub 上已经超过 1000 stars，最近提交也在 2026 年 5 月，至少不是一个空 README 项目。</p>
<h2 id="为什么-grep-对-agent-不够友好">为什么 grep 对 Agent 不够友好</h2>
<p>人用 grep，其实会做很多隐性判断。</p>
<p>你搜 <code>auth</code>，看到 30 个文件，会快速扫目录名、测试文件、legacy 文件，再决定先打开哪个。你会知道 <code>auth_test.py</code> 不是主实现，<code>compat/</code> 里可能只是兼容层，<code>AuthProvider</code> 的定义比调用点更重要。</p>
<p>Agent 就没这么省。</p>
<p>它通常会先 grep，一个关键词命中几十个文件，然后 read 一堆文件。每多读一个文件，就多消耗上下文窗口、多花钱、多增加模型注意力噪声。更麻烦的是，Agent 经常会被“看起来相关”的调用代码带偏，最后改了外围逻辑，真正的核心函数反而没碰。</p>
<p>用人话说：grep 的问题不是搜不到，而是<strong>搜出来之后太需要人类判断</strong>。</p>
<p>这也是 Semble 这个选题值得写的地方。它服务的搜索意图很清楚：如果你在搭建 AI 编程工作流，是否应该给 Agent 加一个专门的代码检索层，而不是继续让它 grep/read 暴力翻仓库？</p>
<h2 id="semble-的技术路线不是纯向量搜索而是混合检索">Semble 的技术路线：不是纯向量搜索，而是混合检索</h2>
<p>从 README 看，Semble 的实现没有走“把整个仓库丢进大 embedding 模型”的路线。它先用 <a href="https://github.com/chonkie-inc/chonkie">Chonkie</a> 做代码感知切块，然后同时跑两套检索：</p>
<ul>
<li>基于 <a href="https://github.com/MinishLab/model2vec">Model2Vec</a> 的静态 embedding，默认用代码专用的 <a href="https://huggingface.co/minishlab/potion-code-16M">potion-code-16M</a> 做语义相似度；</li>
<li>基于 <a href="https://github.com/xhluca/bm25s">bm25s</a> 的 BM25，负责精确词、符号名、API 名称等词法匹配。</li>
</ul>
<p>两路结果再用 Reciprocal Rank Fusion 融合，并叠加一些代码场景的 rerank 信号：符号查询提高词法权重、定义位置加权、identifier stem 匹配、同文件多 chunk 命中加权、测试和 legacy 文件降权等。</p>
<p>这个设计我比较认可。</p>
<p>因为代码搜索和普通文档 RAG 不一样。你搜“where is authentication handled”时，语义检索有用；但你搜 <code>save_pretrained</code>、<code>Foo::bar</code>、<code>config_parser</code> 时，语义模型再聪明也不能把精确符号匹配丢掉。纯向量搜索在代码库里最容易犯的错，就是把“意思相近”排到“真正定义”前面。</p>
<p>Semble 的混合路线本质上是在承认一件事：<strong>代码检索不是语义理解比赛，而是语义、符号和工程上下文的排序问题。</strong></p>
<p>这和我之前写 RAG 重排时的判断是一致的：向量召回只解决“可能相关”，真正影响可用性的往往是第二阶段排序。相关讨论可以看这篇：<a href="https://blog.hypho.cn/posts/rerank-bi-encoder-cross-encoder/">向量数据库已经很快了，为什么还要重排？</a>。Semble 把这个思路压缩到本地代码搜索里，算是一个很实用的工程版本。</p>
<h2 id="它为什么强调少用-98-token">它为什么强调“少用 98% token”</h2>
<p>Semble README 里反复强调 token 节省：相对 grep+read，返回更小的相关代码片段，声称可以少用约 98% token。它的 <code>semble savings</code> 统计也比较朴素：把“命中文件全文字符数”和“实际返回片段字符数”做差，再按 4 字符约等于 1 token 估算。</p>
<p>这个口径不完美，但方向对。</p>
<p>对编程 Agent 来说，token 成本不是唯一问题。更关键的是上下文污染：模型读了太多不相关文件，就会开始“合理化”错误线索。你以为只是多花几分钱，实际可能是让 Agent 在错误文件里自信地改代码。</p>
<p>我更愿意把 Semble 的价值理解成：它不是单纯省钱，而是在帮 Agent 缩小可操作空间。</p>
<p>比如一个 Agent 要找“配置加载后如何合并环境变量”，传统 grep 可能先命中一堆文档、测试、旧兼容代码。Semble 这种混合检索如果能把定义、主实现和同文件上下文排到前面，Agent 后续 read 的内容就更接近真正需要改的地方。</p>
<p>说白了就是：少读错代码，比少读代码更重要。</p>
<h2 id="mcp-很方便但生产里我更建议保留-bash-入口">MCP 很方便，但生产里我更建议保留 Bash 入口</h2>
<p>Semble 支持 MCP Server，可以通过 <code>uvx --from &quot;semble[mcp]&quot; semble</code> 接进 Claude Code、Codex、OpenCode、Cursor 等工具；也支持 CLI 和 Python API。README 里还特别提到，对 Claude Code 或 Codex CLI 的 sub-agent，Bash integration 可能比 MCP 更实用，因为有些 sub-agent 不会直接拿到顶层 MCP schema。</p>
<p>这个细节挺真实。</p>
<p>很多 Agent 工具链在 demo 里 MCP 很顺，但一到多 Agent、子任务、CI、沙箱环境，MCP 工具的可见性、权限和生命周期就会变复杂。相比之下，一个 <code>semble search &quot;authentication flow&quot; ./repo</code> 的 CLI 命令更笨，但更容易写进 <code>AGENTS.md</code>、CI 脚本和审计日志。</p>
<p>我的建议是：</p>
<ul>
<li>个人开发或轻量项目，可以先用 MCP，体验自然语言代码搜索；</li>
<li>团队级工作流，最好同时配置 CLI/Bash 入口，让 Agent 的搜索行为可复现；</li>
<li>对关键仓库，不要让搜索工具自动替代人工审查，至少要保留“搜索结果来自哪些文件、哪些行”的可追踪信息。</li>
</ul>
<p>这和我之前写 <a href="https://blog.hypho.cn/posts/claude-code-routines/">Claude Code routines</a> 时的观点类似：真正可靠的 Agent 工作流，不是给模型更多自由，而是把常用动作沉淀成可重复、可观察的例程。</p>
<h2 id="semble-适合什么场景">Semble 适合什么场景</h2>
<p>我会把 Semble 放在“中小型代码库 + 高频 Agent 修改”的位置上，而不是一上来就当企业代码搜索平台。</p>
<p>它最适合的场景大概有三类。</p>
<p>第一，Agent 经常需要理解陌生模块。比如让 Codex 修一个 bug，它需要先知道认证逻辑、缓存逻辑、数据模型在哪里。Semble 能把“自然语言问题”映射到代码片段，比单纯 grep 一个关键词更贴近 Agent 的提问方式。</p>
<p>第二，仓库不大但语言混杂。Semble 的 benchmark 覆盖 63 个仓库、19 种语言，README 宣称平均仓库索引用时约 263ms、查询 p50 约 1.5ms，且 CPU 本地运行。即便实际项目里会慢一些，这个量级也意味着它可以放进交互式 Agent 循环，而不是只能做离线索引。</p>
<p>第三，团队已经开始关心 Agent token 和上下文质量。尤其是用 Claude Code、Cursor、Codex 做大仓库修改时，传统 grep/read 会让模型吞掉大量文件。Semble 至少给了一个更精细的入口。</p>
<p>但它不适合所有情况。</p>
<p>如果你的仓库强依赖跨服务调用、运行时配置、数据库 schema、RPC IDL，单纯代码检索不够。Agent 需要的不只是“哪段代码相关”，还包括“这段代码在生产里如何被调用”。这类场景更像系统级知识图谱或内部开发者平台问题，Semble 只能解决其中的局部搜索。</p>
<p>另外，Semble 目前仍是新项目。虽然 GitHub stars 和提交活跃度不错，也有 <code>src/</code>、<code>tests/</code>、PyPI 包和 benchmark，但生产落地仍要验证版本稳定性、索引缓存策略、大仓库内存占用、私有代码安全审计等问题。它不是白皮书阶段，不过也还没到“闭眼上全公司”的成熟度。</p>
<h2 id="我会怎么接入">我会怎么接入</h2>
<p>如果让我在团队里试 Semble，我不会一开始就替换 grep。</p>
<p>我会先把它作为 Agent 的“第一查询工具”：当任务是理解业务逻辑、找实现位置、找相似代码时，优先用 <code>semble search</code>；当任务是精确确认字符串、配置项、错误码、迁移脚本时，仍然用 grep 或 ripgrep。两者并不冲突。</p>
<p>一个比较稳的 <code>AGENTS.md</code> 规则可以是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">当你需要理解某个功能在哪里实现时，先使用 semble search；
</span></span><span class="line"><span class="cl">当你需要确认具体符号、错误信息、配置 key 是否存在时，再使用 rg/grep 做精确验证；
</span></span><span class="line"><span class="cl">修改代码前必须 read 目标文件的完整相关上下文，不得只依赖搜索片段。
</span></span></code></pre></div><p>最后一句很重要。</p>
<p>搜索结果只能帮 Agent 找入口，不能替代阅读上下文。尤其是代码修改任务，chunk 级结果可能漏掉初始化、副作用、类型约束和调用顺序。如果 Agent 只看一个片段就动手，Semble 再准也救不了它。</p>
<p>这也是我对“Agent 工具化”的基本态度：工具应该让模型少走弯路，而不是让模型少承担验证责任。像 <a href="https://blog.hypho.cn/posts/statewright-state-machine-agent-guardrails/">Statewright 用状态机给编程 Agent 加护栏</a> 这类项目关注的是执行过程约束，Semble 关注的是上下文获取质量。两个方向其实可以叠加：先让 Agent 找对代码，再用状态机限制它怎么改。</p>
<h2 id="结论值得试但不要神化">结论：值得试，但不要神化</h2>
<p>Semble 最打动我的地方，不是“98% token saving”这个数字，而是它把编程 Agent 的一个高频痛点讲清楚了：Agent 不缺搜索命令，缺的是低噪声、低延迟、可落地的代码上下文入口。</p>
<p>它的混合检索路线也比“全靠 embedding”的方案更接地气。BM25 负责符号和关键词，静态代码 embedding 负责自然语言意图，rerank 负责把定义、主实现、文件上下文排上来。这个组合不性感，但工程上合理。</p>
<p>我的判断是：如果你已经在用 Claude Code、Codex 或 Cursor 做真实代码修改，Semble 值得作为辅助检索层试一轮；如果你还没有稳定的 Agent 工作流，先别急着引入更多工具，先把任务拆分、测试、审查和回滚做好。</p>
<p>搜索只是第一步。</p>
<p>真正的生产级 AI 编程，靠的是“找得准、改得小、测得全、回得去”。Semble 解决的是第一项，而且解决得还挺有意思。</p>
]]></content:encoded></item><item><title>Statewright：用状态机给 AI 编程 Agent 加护栏，真的比长提示词更靠谱吗？</title><link>https://blog.hypho.cn/posts/statewright-state-machine-agent-guardrails/</link><pubDate>Fri, 15 May 2026 10:04:27 +0800</pubDate><guid>https://blog.hypho.cn/posts/statewright-state-machine-agent-guardrails/</guid><description>Statewright 是一个用确定性状态机约束 AI 编程 Agent 的开源项目，核心思路不是继续加长系统提示词，而是按阶段限制工具、命令、编辑范围和人工审批。本文从 Claude Code、Codex 与本地模型场景出发，分析它对 Agent 可靠性、安全边界和生产落地的真实价值。</description><content:encoded><![CDATA[<p>如果你用过 Claude Code、Codex CLI 或 Cursor 这类编程 Agent，大概率见过一种很烦人的失败模式：它明明已经读完文件，却又回头读一遍；明明应该先写测试，却开始大面积重构；明明只是修一个 20 行 bug，却顺手动了 6 个模块。最后 token 花了，diff 也出来了，但你不敢合并。</p>
<p>我越来越觉得，这不是“模型不够聪明”一个问题。</p>
<p>更准确地说，是我们把 Agent 放进了一个没有交通规则的城市：Read、Grep、Edit、Bash、Web、MCP 工具全都摊在它面前，然后指望一段系统提示词告诉它“请谨慎驾驶”。提示词当然有用，但它不是刹车，也不是红绿灯。</p>
<p>这也是 <a href="https://github.com/statewright/statewright">Statewright</a> 最近在 HN 上引起我注意的原因。它的口号很硬：<strong>Agents are suggestions, states are laws.</strong> 用人话翻译：不要只靠模型“自觉”，把工作流拆成确定状态，在每个状态里只开放它该用的工具。</p>
<h2 id="状态机不是新概念但放在-agent-上刚好戳中痛点">状态机不是新概念，但放在 Agent 上刚好戳中痛点</h2>
<p>Statewright 做的事情并不神秘。它让你定义一个工作流，例如 <code>planning → implementing → testing → completed</code>。在 planning 状态里，Agent 只能读文件、搜索代码；进入 implementing 以后才允许 Edit/Write；到 testing 状态，Bash 可以用，但只能跑 <code>pytest</code>、<code>cargo test</code>、<code>npm test</code> 这类白名单命令。</p>
<p>项目 README 里的示例很直观：planning 只给 <code>Read/Grep/Glob</code>，implementing 允许 <code>Read/Edit/Write</code> 且限制 <code>max_edit_lines</code>、<code>max_files_per_state</code>，testing 才给 <code>Bash</code>，并且通过 guard 判断测试是否通过。官方的 <a href="https://statewright.ai/workflow-schema.json">workflow schema</a> 也把这些字段明确写成结构化配置，而不是自然语言建议。</p>
<p>这点很关键。</p>
<p>自然语言提示词的问题是，它最终还是要被模型“理解”和“遵守”。状态机的问题是，工具调用在执行层被拦住。模型想在 planning 阶段写文件？调用会被拒绝。模型想在测试阶段跑一个不在白名单里的 shell 命令？也会被拒绝。技术描述听起来有点抽象，人话就是：<strong>把“你最好不要这样做”改成“你做不到”。</strong></p>
<p>Statewright 的实现也不是纯概念。仓库主体是 Rust、Python、Shell 和 TypeScript，GitHub API 显示最近提交在 2026-05-14，仓库约 279 stars；目录里有 <code>crates</code>、<code>plugins</code>、<code>templates</code> 等实际代码。它通过 MCP/插件层接入 Claude Code、Codex、Cursor、opencode 等编码工具，核心 Rust engine 负责评估状态、转移、guard 和工具限制。换句话说，它不是又一个“Agent 最佳实践文档”，而是试图把最佳实践编译成运行时约束。</p>
<h2 id="为什么这比写更长的-system-prompt更像工程方案">为什么这比“写更长的 system prompt”更像工程方案</h2>
<p>我以前也习惯用长提示词管 Agent：先分析，不要急着改；每次只改小 diff；先跑测试；不要删除用户文件；遇到不确定先询问。问题是，提示词越长，越像团队的 Confluence 规范——看起来很完整，真出事时不一定拦得住。</p>
<p>Statewright 的优势是把约束分层了。</p>
<p>第一层是工具可见性。Agent 在某个状态下看到的工具变少，决策空间也变小。对大模型来说，这减少了乱试；对本地小模型来说，意义更大，因为它们本来就不擅长在 30 个工具里稳定选择。Statewright README 声称，在一个 5 题 SWE-bench 子集上，13.8GB 和 19.9GB 的本地模型在加入约束后从 2/10 提升到 10/10。这个结果当然不能等同于完整 SWE-bench——项目自己也注明只是 5 个任务的小样本——但方向是可信的：小模型最怕开放式任务，状态机把开放题改成了分步题。</p>
<p>第二层是命令与编辑限制。<code>allowed_commands</code>、<code>max_edit_lines</code>、<code>max_files_per_state</code> 这些字段看起来朴素，却是生产环境里最需要的东西。比如你可以允许 Agent 在 testing 阶段跑 <code>pytest</code>，但不允许它执行任意 <code>curl | bash</code>；允许它修 20 行，但不允许它顺手重写半个服务。很多 Agent 安全讨论会停留在“防 prompt injection”，但工程事故更多时候来自越权修改、过大 diff、错误 shell 命令和状态漂移。</p>
<p>第三层是显式转移。Agent 必须从 planning 转到 implementing，再到 testing。它不是在一个无限上下文里“凭感觉继续”，而是在被迫回答：现在是什么阶段？我为什么可以进入下一阶段？guard 是否满足？这会打断一种常见死循环：模型不断 reread 文件，却迟迟不编辑，或者测试失败后盲目继续改。</p>
<p>说白了，Statewright 不是让 Agent 更聪明，而是让任务环境更笨、更窄、更可控。很多时候，这反而是可靠性的来源。</p>
<h2 id="但我不会把它直接神化成agent-可靠性终局">但我不会把它直接神化成“Agent 可靠性终局”</h2>
<p>它也有明显代价。</p>
<p>最直接的是工作流设计成本。你必须知道一个任务应该拆成哪些状态，每个状态开放哪些工具，哪些命令能跑，什么时候需要人工审批。如果工作流太松，护栏没意义；太紧，Agent 会卡在状态里。Statewright README 也提到，限制过强时需要 <code>statewright_deactivate</code> 作为逃生门。</p>
<p>第二个问题是，它更适合“流程明确”的任务，而不是探索性任务。修 bug、补测试、生成迁移脚本、执行 release checklist，这些都适合状态机；但如果你让 Agent 研究一个完全陌生的代码库、做架构探索、评估多种方案，过早限制工具可能会让它变笨。我的判断是：Statewright 应该放在从“探索”进入“执行”之后，而不是替代所有自由推理。</p>
<p>第三个问题是生态绑定。它现在对 Claude Code 的 quickstart 最成熟，也在文档里提到 Codex、Cursor、opencode 等集成方向。但不同工具的 hook 能力并不一致：有的能拦截 tool call，有的只能在 shell 层做包装，有的对 MCP 支持还不稳定。也就是说，Statewright 的思路可以迁移，但落地体验会高度依赖你用的 Agent harness。</p>
<p>还有一个小但真实的风险：状态机配置本身会变成新的复杂度来源。以前你 debug prompt，现在你还要 debug workflow。比如某个 guard 写错了，Agent 永远进不了 testing；某个命令白名单漏了参数，测试跑不起来；某个编辑行数限制太小，导致模型反复拆 patch。工程上没有免费的午餐，只是把不确定性从模型输出转移到了可审查的配置里。</p>
<p>我个人愿意接受这个转移。因为配置至少能 diff、review、版本化；模型的“自觉”不能。</p>
<h2 id="它和-openclawagentarmor-其实在解决同一个底层问题">它和 OpenClaw、AgentArmor 其实在解决同一个底层问题</h2>
<p>Hypho Blog 之前写过 <a href="https://blog.hypho.cn/posts/openclaw-state-machine/">OpenClaw 的离散状态机架构</a>：长时间运行的 AI 工作流，不能只靠一次 prompt 维持状态，必须把任务进度、失败恢复和执行阶段落到外部状态上。Statewright 更聚焦在编码 Agent，但哲学很像：LLM 负责生成建议，状态系统负责维持边界。</p>
<p>另一个相关方向是 <a href="https://blog.hypho.cn/posts/agentarmor-8-layer-security-framework/">AgentArmor 的多层安全框架</a>。AgentArmor 更像安全防线清单：身份、权限、监控、隔离、审计；Statewright 则更像一套具体执行器：在每个状态拦工具、拦命令、拦大 diff。前者告诉你 Agent 系统应该有哪些安全层，后者把其中一部分变成了开发工作流里的硬约束。</p>
<p>这两个思路合在一起，才比较接近生产环境需要的样子：既要有宏观安全模型，也要有执行时的确定性控制。</p>
<h2 id="我会怎么用它">我会怎么用它</h2>
<p>如果是个人项目，我不会一上来就给所有任务套复杂状态机。那会把开发体验搞得很重。我会从三个高风险场景开始：</p>
<p>第一，自动修 bug。流程固定为 read-only 诊断、最小 diff 修复、指定测试、失败回滚或二次修改。这里状态机非常合适，因为“先读后改再测”本来就是人类工程师也该遵守的流程。</p>
<p>第二，依赖升级和迁移。比如升级框架、改数据库 schema、批量替换 API。Agent 很容易在这类任务里越改越大，所以 <code>max_files_per_state</code>、审批门和命令白名单很有价值。</p>
<p>第三，CI 失败自动修复。CI 环境最怕 Agent 执行任意命令，也最适合白名单：只允许读取日志、改特定目录、跑指定测试。状态机能把“自动修 CI”从危险实验变成可控流水线。</p>
<p>如果是团队项目，我会把 workflow 配置当成代码审查对象。谁能改状态机？哪些状态允许 Bash？哪些命令进入白名单？哪些 transition 需要人工审批？这些问题应该进入 repo，而不是藏在某个人的 Claude Code 配置里。</p>
<h2 id="结论agent-可靠性不会只靠更强模型解决">结论：Agent 可靠性不会只靠更强模型解决</h2>
<p>我对 Statewright 的判断是：它不是所有 Agent 问题的答案，但它抓住了一个正确方向——<strong>把 Agent 从“会聊天的工具使用者”改造成“在流程约束下工作的执行者”。</strong></p>
<p>这件事对未来一年会越来越重要。模型能力继续变强，Agent 能调用的工具也会越来越多；工具越多，自由度越高，事故半径也越大。继续往 prompt 里加“请小心”不够了。我们需要可执行、可审计、可版本化的边界。</p>
<p>状态机听起来老派，甚至有点不性感。但工程里很多可靠系统，最后靠的就是这些不性感的东西：有限状态、白名单、审批门、最小权限、失败回路。</p>
<p>Agent 也是系统。既然是系统，就别只给它写鸡汤，给它装刹车。</p>
<h2 id="参考链接">参考链接</h2>
<ul>
<li><a href="https://github.com/statewright/statewright">Statewright GitHub 仓库</a></li>
<li><a href="https://docs.statewright.ai">Statewright 官方文档</a></li>
<li><a href="https://statewright.ai/workflow-schema.json">Statewright workflow schema</a></li>
<li><a href="https://docs.statewright.ai/tools/reference/">Statewright MCP tool reference</a></li>
<li><a href="https://news.ycombinator.com/item?id=48108778">HN 讨论：Show HN: Statewright – Visual state machines that make AI agents reliable</a></li>
</ul>
]]></content:encoded></item><item><title>AI 编程成本怎么管？Budi 给了一个 local-first 的工程答案</title><link>https://blog.hypho.cn/posts/budi-ai-coding-cost-tracker/</link><pubDate>Mon, 11 May 2026 10:02:34 +0800</pubDate><guid>https://blog.hypho.cn/posts/budi-ai-coding-cost-tracker/</guid><description>Budi 是一个面向 Claude Code、Cursor、Codex 和 Copilot 的开源 AI 编程成本追踪工具。本文从 local-first 架构、日志解析、成本归因、团队治理和隐私边界出发，分析它能解决什么问题、适合哪些团队，以及为什么 AI coding 的下一步不只是提效，而是可观测和可治理。</description><content:encoded><![CDATA[<p>你有没有发现一个很尴尬的现象：团队开始认真用 AI 写代码以后，最先失控的往往不是代码质量，而是账单。Claude Code、Cursor、Codex CLI、Copilot Chat 各跑各的，每个人都觉得自己只是“顺手问了一下”，月底看费用才发现它已经变成了一项真实的研发成本。更麻烦的是，你很难回答几个最朴素的问题：钱花在哪个 repo？哪个分支？哪个 ticket？哪类任务最烧 token？一次看起来普通的重构，为什么会突然吃掉几十美元？</p>
<p>HN 上这两天出现了一个小项目 <a href="https://getbudi.dev/">Budi</a>，标题很直白：local-first AI coding cost tracker。它的 GitHub README 说得更具体：Budi 用来追踪 Claude Code、Cursor、Codex CLI、Copilot CLI 和 Copilot Chat 的 token 与成本，并按 repo、branch、ticket、file 做归因，默认数据都留在本机；可选的云同步只上传聚合后的日报指标，不上传 prompt、代码和回复。项目还很年轻，GitHub stars 只有十几个，但最近提交就在 2026 年 5 月，README、Homebrew tap、Cursor/VS Code 扩展和文档都已经成体系。所以我不会把它包装成“成熟企业级平台”，但它抓住了一个真实问题：AI 编程正在从个人效率工具，变成需要治理的工程基础设施。</p>
<p>这件事比“又一个成本看板”重要。</p>
<p>过去我们管云成本，有 FinOps；管服务质量，有 APM；管模型调用，有 LLM gateway 和 tracing。可 AI coding agent 的调用链很奇怪：它发生在开发者本地，混在编辑器、CLI、终端和 IDE 插件里，很多时候并不经过公司统一网关。你当然可以强推所有请求走代理，但这会碰到权限、延迟、离线开发、个人账号和隐私边界等一堆问题。Budi 的路线反过来：不拦在网络路径上，而是读本地已经存在的 transcript / JSONL / SQLite / session-state，再从这些记录里还原 token、模型、时间、项目上下文和成本。</p>
<p>用人话说，它不是收费站，更像电表。</p>
<p>Budi 官网把这个卖点写得很清楚：安装后本机跑一个小 daemon，tail AI 工具已经写到磁盘的 transcript；编辑器里显示状态栏；CLI 用来做 repo、branch、ticket 级别的归因；“Nothing in your network path”。这句话其实是架构取舍的核心。走网络代理的好处是数据完整、控制力强，可以做限流、审计、脱敏和统一 key 管理；坏处是部署重、侵入强，还可能成为单点故障。走本地日志解析的好处是轻、隐私边界清晰、不中断开发者原有工作流；坏处也明显：不同工具日志格式会变，成本估算依赖 pricing manifest，某些 provider 的真实账单可能需要后续 API reconciliation。</p>
<p>所以 Budi 的价值不是“绝对准确地替代云账单”，而是给开发过程补上一个过去缺失的观测层。</p>
<p>我比较看重它的三个细节。</p>
<p>第一个是归因粒度。很多 AI 工具只能告诉你“今天花了多少钱”，这对工程管理几乎没用。真正有用的问题是：哪个 repo 花得最多？哪个 feature branch 正在异常烧钱？某个 ticket 是因为反复改测试、上下文膨胀，还是因为模型选得太贵？Budi README 里的命令包括 <code>budi stats projects</code>、<code>budi stats branches</code>、<code>budi stats tickets</code>、<code>budi stats models</code>、<code>budi stats files</code>，这说明它不是单纯记账，而是试图把 AI 使用成本映射回研发对象。这个方向对团队很关键，因为成本只有绑定到工程单元，才有优化空间。</p>
<p>举个例子，如果一个团队发现“修 checkout retry 的分支过去 7 天烧了 40 美元”，这不一定说明开发者乱用 AI。它可能说明这个模块上下文太大、测试反馈太慢、需求描述反复变化，或者 agent 每次都在重新扫描整套代码。成本异常往往是工程摩擦的信号。说白了，AI 账单有时不是财务问题，而是架构问题。</p>
<p>第二个是 session health。Budi README 提到它会检测 context bloat、cache degradation 和 cost acceleration。这里我会稍微谨慎一点：这些指标是否足够准确，要看它对各家 transcript 的解析深度和启发式规则，不能只看 README 就下结论。但思路是对的。AI coding 的浪费不只是“用了贵模型”，更常见的是会话越拖越长，agent 带着过期上下文反复推理，缓存命中下降，最后每一步都变成高价全量请求。很多开发者体感上会说“今天 Claude 变笨了”，但背后可能只是上下文污染和任务边界失控。</p>
<p>这也解释了为什么我之前写 <a href="https://blog.hypho.cn/posts/claude-code-routines/">Claude Code routines</a> 时一直强调流程约束。AI 编程不是把一个超大 prompt 扔给模型就完事，越复杂的任务越需要分段、验收、回滚和上下文清理。Budi 这类工具如果能把“上下文膨胀导致成本加速”可视化，就能把很多玄学抱怨变成工程讨论：不是“模型不行”，而是“这个会话已经不健康”。</p>
<p>第三个是 local-first 的隐私边界。Budi 文档说本地数据存放在用户目录，daemon 读取 agent 已经写到磁盘的 transcript，只保存派生分析：时间戳、token count、模型名、成本和归因标签；prompt、代码和回复不会存储或上传。可选 cloud sync 只发数字聚合、模型名、hashed repo ID、branch 和 ticket ID 等。这个设计很讨巧，因为 AI coding 的原始数据太敏感了：prompt 里可能有客户信息，回复里可能有内部代码，diff 里可能有未发布功能。对企业来说，“成本可见”和“源代码不出本机”必须同时成立，否则工具很难推广。</p>
<p>当然，local-first 不是免死金牌。</p>
<p>只要工具读取 transcript，它就处在敏感数据旁边。哪怕它声称不保存 prompt，团队也要看清楚实现：日志扫描范围是什么？本地数据库里到底落了哪些字段？崩溃日志会不会带原文？云同步 schema 是否稳定？开源项目的好处是可以审计，但这不等于默认安全。尤其 Budi 目前还处在早期阶段，生产落地性待验证。我会把它当作一个值得试点的工程工具，而不是立刻纳入全公司强制标准。</p>
<p>如果你已经在做统一 LLM 网关，可能会问：这类工具和 gateway 是不是重复？我觉得不重复。网关擅长管理线上服务和 API 入口，比如统一鉴权、计费、重试、缓存、审计、模型路由。我们之前分析 <a href="https://blog.hypho.cn/posts/gomodel-ai-gateway-go/">GoModel 这类 AI gateway</a> 时，重点就在服务端模型调用的治理。但 AI coding 的入口太分散：IDE 插件、CLI agent、个人订阅、企业账号、离线日志，未必都能进网关。Budi 这种本地观测层可以作为补位：它不负责拦截和治理所有请求，而是先回答“到底发生了什么”。</p>
<p>我会这样判断适用场景：</p>
<p>如果你是个人开发者，每月 AI coding 费用已经超过几十美元，Budi 这类工具可以帮你发现最烧钱的项目和模型，但收益未必大到必须安装。你可能更需要的是良好的使用习惯：任务拆小、及时新开会话、别让 agent 在大仓库里无目标搜索。</p>
<p>如果你是 5 到 50 人的工程团队，而且已经让 Claude Code、Cursor、Codex 混合进入日常开发，那成本观测就很有价值了。这个阶段最怕的是管理层只看到总账单，看不到具体工程上下文，最后用粗暴限额把效率也一起砍掉。按 repo/branch/ticket 看成本，至少能让讨论变得具体：哪些任务适合 agent，哪些任务需要人工先整理上下文，哪些仓库需要补文档和测试入口。</p>
<p>如果你是强合规企业，我会更保守。Budi 的 local-first 思路适合做 PoC，但在推广前要审计源码、固定版本、确认本地数据字段、禁用或托管 cloud sync，并把它纳入终端安全策略。别因为“它不在网络路径上”就忽略本地数据治理。很多安全事故不是发生在网关，而是发生在开发者机器上的缓存、日志和插件目录里。</p>
<p>还有一个容易被忽略的问题：成本数据会改变团队行为。指标一旦出现，大家就会优化指标。有的优化是好事，比如减少无效长会话、选择更便宜的模型、把重复任务脚本化；有的优化可能是坏事，比如开发者为了账单好看而不用 AI，或者把复杂任务拆得过碎导致协作成本上升。所以我不建议把 AI coding cost 做成个人排名。更合理的看法是把它当作系统健康信号：哪类任务消耗异常？哪些仓库对 AI 不友好？哪些流程让 agent 反复试错？</p>
<p>这也是我喜欢 Budi 这个选题的原因。它没有发明新模型，也没有讲宏大的 AGI 故事，但它指出了 AI 工程落地的一条现实路径：当 agent 从玩具变成生产力工具，围绕它的可观测性、成本归因和隐私边界会变得和模型能力一样重要。</p>
<p>我对 Budi 的短期建议很简单：可以试，但别神化。它是早期项目，stars 不高，生态覆盖仍在变化；不过它有真实代码、活跃提交、清晰 README 和具体安装路径，已经足够作为团队内部试点。试点时最好先选 2-3 个 AI 使用频繁的 repo，运行一到两周，看三个指标：每个 repo 的 AI 成本分布、异常长 session 的比例、不同模型/工具的成本差异。只要它能让团队少开几次无意义的超长会话，或者发现一个特别烧钱的工作流，就已经值回票价。</p>
<p>AI 编程的上半场是“能不能帮我写代码”。下半场会越来越像传统工程管理：能不能被观测，能不能被归因，能不能被治理。</p>
<p>Budi 不一定是最终答案，但它把问题问对了。</p>
<h3 id="参考链接">参考链接</h3>
<ul>
<li><a href="https://getbudi.dev/">Budi 官网：local-first AI coding cost tracker</a></li>
<li><a href="https://github.com/siropkin/budi">Budi GitHub 仓库</a></li>
<li><a href="https://github.com/siropkin/budi#readme">Budi README</a></li>
<li><a href="https://github.com/siropkin/budi-cursor">Budi Cursor / VS Code 扩展仓库</a></li>
</ul>
]]></content:encoded></item><item><title>Open Design 能替代 Claude Design 吗？把编码 Agent 变成设计引擎的工程边界</title><link>https://blog.hypho.cn/posts/open-design-coding-agent-design-engine/</link><pubDate>Mon, 04 May 2026 10:02:22 +0800</pubDate><guid>https://blog.hypho.cn/posts/open-design-coding-agent-design-engine/</guid><description>Open Design 把 Claude Code、Codex、Cursor 等编码 Agent 变成设计引擎，试图替代封闭的 Claude Design 工作流。本文从本地优先、技能系统、沙盒预览、导出链路、Agent 安全和设计系统约束出发，分析它是否适合真实团队用于原型、演示与生产设计流程。</description><content:encoded><![CDATA[<p>如果你已经习惯让 Claude Code 或 Codex 写业务代码，那么下一个很自然的问题是：能不能让同一个 Agent 顺手把产品原型、落地页、PPT、甚至一段演示视频也做出来？</p>
<p>我以前对这类“AI 做设计”的项目比较警惕。原因很简单：很多工具只是把 prompt 包了一层漂亮 UI，最后产物看起来像模板站，改两轮就塌。但最近 Hacker News 上的 <a href="https://hnrss.org/item?id=47985750">Open Design</a> 让我多看了几眼。它不是另一个单点生成器，而是把 Claude Code、Codex、Cursor Agent、Gemini CLI、Qwen、Copilot CLI 等命令行编码 Agent 当成“设计引擎”，再叠一层本地优先的技能、设计系统、沙盒预览和导出链路。项目 README 直接把自己定位成 <a href="https://github.com/nexu-io/open-design">Claude Design 的开源替代</a>。</p>
<p>这句话听起来很大，但工程上真正有意思的不是“替代 Claude Design”，而是它暴露了一个更具体的搜索问题：<strong>设计工作流到底应该由专门的设计模型驱动，还是由已经会读文件、改代码、跑命令的 Coding Agent 驱动？</strong></p>
<p>我的判断是：Open Design 不一定会马上成为生产级设计平台，但它代表了一条很值得关注的路线——把设计从“生成一张图”拉回到“生成一个可运行、可审查、可导出的工程项目”。</p>
<h2 id="它不是文生图工具而是把设计任务工程化">它不是文生图工具，而是把设计任务工程化</h2>
<p>Open Design 的 README 里有几个关键词很关键：local-first、BYOK、agent CLI auto-detect、Skills、Design Systems、sandboxed preview、HTML/PDF/PPTX/MP4 export。翻成人话就是：它不试图自己训练一个万能设计模型，而是把你机器上已有的 Agent CLI 调起来，让 Agent 在一个受控项目里生成和修改设计资产。</p>
<p>这和很多 AI 设计产品的差别很大。后者通常是“输入一句话，得到一个不可解释的视觉结果”；Open Design 更像是“给 Agent 一个设计系统、任务说明和预览环境，让它持续修改文件，直到产物可运行”。</p>
<p>说白了，它把设计任务变成了一种软件工程任务。</p>
<p>这件事的价值在于可迭代性。一个登录页、一份销售 deck、一个移动端交互原型，本质上不只是图片，而是一组结构、样式、文案、资源和导出规则。Coding Agent 已经擅长处理这些东西：读项目、改组件、运行构建、根据错误日志修复。Open Design 做的是把这些能力迁移到设计场景。</p>
<p>这里我会联想到之前写过的 <a href="https://blog.hypho.cn/posts/claude-code-routines/">Claude Code Routines</a>：真正稳定的 Agent 工作流，很少靠一次神奇 prompt，而是靠可复用步骤、上下文约束和反馈循环。Open Design 的 Skills 和 Design Systems，本质上也是在给 Agent 建立可复用的“套路”。</p>
<h2 id="为什么本地优先比看起来重要">为什么“本地优先”比看起来重要</h2>
<p>Open Design 强调 local-first 和 BYOK。这个卖点有点老生常谈，但放在设计工作流里反而很实际。</p>
<p>设计原型里经常包含还没发布的产品信息、客户名单、商业计划、品牌资产。把这些内容直接丢到一个黑盒 SaaS 里，很多团队嘴上说能接受，法务和安全团队未必接受。Open Design 的思路是：前端、预览、导出尽量在本地或自托管环境完成，模型调用用你自己的 key，Agent CLI 也优先复用本机环境。</p>
<p>当然，这不等于“绝对安全”。只要调用外部模型，prompt 和上下文仍然可能离开本机；只要让 Agent 执行命令，就要考虑权限边界。项目的沙盒预览能降低一部分风险，但不能替代企业里的密钥隔离、网络出站控制和审计。</p>
<p>换句话说，本地优先不是免死金牌，只是把控制权从平台手里拿回来一部分。</p>
<p>如果你关心 Agent 安全边界，可以顺手看我之前写的 <a href="https://blog.hypho.cn/posts/agentarmor-8-layer-security-framework/">AgentArmor 八层安全框架</a>。Open Design 这种“让 Agent 生成并运行设计项目”的模式，和代码 Agent 一样，需要最小权限、文件系统边界、命令执行白名单，以及对外部资源的审查。设计资产看起来不像生产代码危险，但它一样可能带上外链、脚本、埋点和泄露信息。</p>
<h2 id="它的核心工程假设设计系统可以被-agent-消费">它的核心工程假设：设计系统可以被 Agent 消费</h2>
<p>Open Design 最激进的地方，不是支持多少个 Agent CLI，而是它把设计系统作为一等公民。README 里提到多套 brand-grade Design Systems 和 composable Skills。这个方向我比较认可，因为“好看”这个目标太抽象，Agent 如果没有约束，很容易生成一堆平均化的 Tailwind 卡片。</p>
<p>设计系统的作用，是把审美问题的一部分转成约束问题：颜色、间距、字体、组件层级、动效节奏、品牌语气。Agent 不一定真的懂设计，但它能遵守规则。</p>
<p>人话翻译一下：不要让模型凭空发挥，要让它在护栏里发挥。</p>
<p>这也是为什么我觉得 Open Design 比单纯的文生图工具更有工程价值。图片生成模型可以给你灵感，但很难稳定接住“把这个 hero section 改成更企业级，同时保持品牌色、导出 PPT、再生成一个移动端版本”这种连续任务。Coding Agent 虽然审美上不一定更强，但它有文件级记忆和可执行反馈，适合做多轮修改。</p>
<p>不过这里也有一个坑：设计系统本身要足够清晰。很多团队的“设计系统”其实只是一份 Figma 文件和几句口头约定。如果把这种松散规范交给 Agent，最后还是会失控。Open Design 能不能落地，很大程度取决于团队是否愿意把品牌规则、组件规则、导出规则文档化。</p>
<h2 id="生产环境最大的风险不是生成失败而是审查成本">生产环境最大的风险不是生成失败，而是审查成本</h2>
<p>我不太担心 Open Design 生成一次失败。失败了再跑、再改就行。真正的问题是：它生成出来的东西谁来审？怎么审？审哪些层面？</p>
<p>设计产物至少有三层需要检查。</p>
<p>第一层是视觉和品牌一致性。这个还可以靠人工设计师或产品经理看。</p>
<p>第二层是工程质量。HTML 是否可维护？组件是否乱堆？导出的 PDF/PPT 是否在不同环境下稳定？如果里面有脚本，是否引入未知第三方资源？这已经不是传统设计评审能完全覆盖的范围。</p>
<p>第三层是版权和合规。Agent 生成的图片、图标、文案和模板风格，是否借鉴了不该借鉴的东西？Open Design 是开源工具，不代表它生成的一切天然可商用。尤其是团队把外部模型接进来后，模型服务商的条款也要算进来。</p>
<p>所以我的建议是：Open Design 更适合作为“设计工程加速器”，而不是无人值守的设计外包。</p>
<p>比较稳妥的用法，是让它处理中间态产物：早期原型、内部评审材料、销售 demo、文档配图、概念验证页面。等到要进入正式品牌投放或客户交付，再由设计师和工程师做一次收口。</p>
<h2 id="和-claude-design-的差异开源不是唯一重点">和 Claude Design 的差异：开源不是唯一重点</h2>
<p>Open Design 把自己称为 Claude Design 的开源替代，这个定位很容易让人只盯着“免费”和“可自托管”。但我觉得更关键的差异是工作流所有权。</p>
<p>封闭产品的优势是体验完整：打开即用、模型和界面高度整合、少折腾。缺点也明显：你很难控制底层 prompt、很难插入自己的 Agent、很难把内部设计系统变成可执行约束，也很难把产物链路嵌进现有 CI、文档或营销系统。</p>
<p>Open Design 的路线更工程师友好。它假设你愿意折腾，也愿意把设计流程当成代码流程来管理。比如用 Git 管理设计资产，用 PR 审查 Agent 修改，用脚本批量导出多种格式，用不同模型后端做成本和质量权衡。</p>
<p>这和 <a href="https://blog.hypho.cn/posts/chrome-prompt-api-browser-local-llm/">Chrome Prompt API</a> 那篇里讨论的浏览器内置 AI 有点相似：真正影响落地的，往往不是模型能力单点，而是运行位置、权限模型、成本结构和可集成性。Open Design 也是这样。它的卖点不只是“能生成设计”，而是“能嵌进工程师已经熟悉的工具链”。</p>
<h2 id="我会怎么选型">我会怎么选型</h2>
<p>如果你是个人开发者、独立产品团队，或者需要频繁做 landing page、demo、deck，Open Design 值得试。项目在 GitHub 上已经有较高关注度，最近提交也很活跃；从 GitHub API 看，仓库 stars 超过 1.9 万，最后更新时间在 2026 年 5 月，至少不是一个只有 README 的概念仓库。</p>
<p>如果你是中大型企业，我会更保守：先用它做内部原型，不要直接接生产品牌资产；先把模型 key、文件系统权限、导出目录、外链策略管住；再考虑把它接入正式流程。</p>
<p>如果你是专业设计团队，也别急着把它当威胁。短期内它更像一个会写代码的设计助理，而不是能替代资深设计师的创意总监。它能把“从想法到可运行原型”的距离缩短，但对品牌判断、叙事节奏、用户研究和商业取舍仍然很粗糙。</p>
<p>我真正看好的，是“设计工程师”这个角色会被放大。未来很多团队可能不再区分那么清楚：这个人只写前端，那个人只做 Figma。会用 Agent 组织设计系统、生成原型、审查代码、导出交付物的人，会非常吃香。</p>
<p>Open Design 还不完美，我也不确定它的长期维护质量能不能跟上热度。但它提出的方向是清楚的：AI 设计工具不应该只追求一次性惊艳截图，而应该追求可复用、可审查、可集成的工程链路。</p>
<p>这才是它值得写的原因。</p>
<h2 id="参考资料">参考资料</h2>
<ul>
<li><a href="https://github.com/nexu-io/open-design">Open Design GitHub 仓库</a></li>
<li><a href="https://hnrss.org/item?id=47985750">Open Design 在 Hacker News 的讨论</a></li>
<li><a href="https://raw.githubusercontent.com/nexu-io/open-design/main/README.md">Open Design README 原文</a></li>
<li><a href="https://api.github.com/repos/nexu-io/open-design">GitHub API：nexu-io/open-design 仓库元数据</a></li>
<li><a href="https://docs.claude.com/en/docs/claude-code/overview">Claude Code 官方文档</a></li>
</ul>
]]></content:encoded></item><item><title>Claude Code Routines 实战：把 AI 编程助手变成准时的自动化同事</title><link>https://blog.hypho.cn/posts/claude-code-routines/</link><pubDate>Thu, 16 Apr 2026 10:00:00 +0800</pubDate><guid>https://blog.hypho.cn/posts/claude-code-routines/</guid><description>Claude Code Routines 是 Anthropic 为 Claude Code 推出的自动化执行框架，让开发者通过 YAML 配置定义定时任务、GitHub 事件触发和 API 调用，在云端基础设施上自动运行重复性工作。Stars 114k 的明星项目实战深度解析。</description><content:encoded><![CDATA[<h2 id="真实案例引入深夜-11-点的-pr-终于有人-review-了">真实案例引入：深夜 11 点的 PR 终于有人 review 了</h2>
<p>王海（化名）是一家中型 SaaS 公司的后端工程师。团队采用 monorepo 结构，每到周五晚上，积压的 PR 少则七八个，多则十几个。手动 review 耗时耗力，完全丢给 AI review 工具又担心质量。</p>
<p>他尝试的解法：用 Claude Code Routines 配置了一个每周五 20:00 自动运行的代码审查 routine。Claude 会主动拉取本周所有未合并的 PR，按模块分类，生成结构化 review 报告推送到 Slack。第二天早上，他只需要花 20 分钟过一遍 AI 的报告，重点关注高风险变更。</p>
<p>这不是科幻场景——这是 Claude Code Routines 已经支持的真实能力。</p>
<hr>
<h2 id="背景claude-code-不只是交互式工具">背景：Claude Code 不只是交互式工具</h2>
<p>Claude Code 最早以&quot;终端里的 AI 搭档&quot;定位——你提需求，它在本地仓库里翻代码、写文件、跑测试。但这套模式的本质还是<strong>被动响应</strong>：你在，它才动。</p>
<p>2026 年 4 月 14 日，Anthropic 正式发布 <strong>Routines</strong> 功能（<a href="https://code.claude.com/docs/en/routines">官方文档</a>，HN 热度 700+），将 Claude Code 的能力边界从&quot;交互式&quot;扩展到&quot;自动化&quot;。你可以定义一组任务，让它按时间表、按 GitHub 事件、或按 API 调用触发，在 Anthropic 托管的云端基础设施上自动执行——不需要保持终端打开。</p>
<hr>
<h2 id="框架核心拆解">框架核心拆解</h2>
<h3 id="触发模型三种自动化路径">触发模型：三种自动化路径</h3>
<p>Routines 支持三种触发机制，覆盖了开发者日常中最常见的自动化场景：</p>
<p><strong>① 定时触发（Cron）</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">triggers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">schedule</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">cron</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;0 9 * * 1-5&#34;</span><span class="w">   </span><span class="c"># 每周一至周五 9:00 AM UTC</span><span class="w">
</span></span></span></code></pre></div><p>适用于：每日 standup 报告生成、代码质量巡检、定时数据拉取。</p>
<p><strong>② GitHub 事件触发</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">triggers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">github</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">events</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">pull_request.opened</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">pull_request.merged</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">issue.comment</span><span class="w">
</span></span></span></code></pre></div><p>适用于：PR 自动 review、issue 分类、release note 生成。</p>
<p><strong>③ API 调用触发</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">triggers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">api</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">auth</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">bearer_token</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">secret</span><span class="p">:</span><span class="w"> </span><span class="l">$ROUTINES_API_SECRET</span><span class="w">
</span></span></span></code></pre></div><p>适用于：与内部平台集成、webhook 驱动的工作流、CI/CD pipeline 串联。</p>
<h3 id="routine-执行单元task--tool">Routine 执行单元：Task + Tool</h3>
<p>每个 Routine 由一个或多个 <strong>Task</strong> 组成，Task 定义&quot;做什么&quot;，Tool 定义&quot;用什么工具做&quot;。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">routines</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">daily-code-review</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">schedule</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">cron</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;0 20 * * 5&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">tasks</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">fetch-open-prs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">tool</span><span class="p">:</span><span class="w"> </span><span class="l">github</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">list_prs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">params</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">state</span><span class="p">:</span><span class="w"> </span><span class="l">open</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">base</span><span class="p">:</span><span class="w"> </span><span class="l">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">review-each-pr</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">tool</span><span class="p">:</span><span class="w"> </span><span class="l">claude_code</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">review_code</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">context</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">pr_data</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;${fetch-open-prs.output}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">config</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">model</span><span class="p">:</span><span class="w"> </span><span class="l">claude-sonnet-4-20250514</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">max_tokens</span><span class="p">:</span><span class="w"> </span><span class="m">8000</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">post-to-slack</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">tool</span><span class="p">:</span><span class="w"> </span><span class="l">slack</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">send_message</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">params</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">channel</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;#engineering&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">message</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;${review-each-pr.output}&#34;</span><span class="w">
</span></span></span></code></pre></div><h3 id="云端执行架构">云端执行架构</h3>
<p>Routines 运行在 <strong>Anthropic 托管的基础设施</strong>上，不依赖本地终端：</p>
<pre tabindex="0"><code class="language-mermaid" data-lang="mermaid">%%{init: {&#39;theme&#39;: &#39;neutral&#39;}}%%
flowchart TB
    subgraph Triggers
        Cron[&#34;Cron Scheduler&#34;]
        GH[&#34;GitHub Webhooks&#34;]
        API[&#34;API / Webhook Endpoint&#34;]
    end

    subgraph RoutineEngine
        Parser[&#34;YAML Parser&#34;]
        Executor[&#34;Task Executor&#34;]
        ContextMgr[&#34;Context Manager&#34;]
    end

    subgraph Tools
        GitHub[&#34;GitHub API Tool&#34;]
        ClaudeCode[&#34;Claude Code Tool&#34;]
        Slack[&#34;Slack API Tool&#34;]
        Custom[&#34;Custom API Tool&#34;]
    end

    Cron --&gt; Parser
    GH --&gt; Parser
    API --&gt; Parser
    Parser --&gt; Executor
    Executor --&gt; ContextMgr
    Executor --&gt; GitHub
    Executor --&gt; ClaudeCode
    Executor --&gt; Slack
    Executor --&gt; Custom

    ContextMgr --&gt; Output[&#34;Structured Output&lt;br/&gt;/ Slack / File&#34;]
</code></pre><p>关键优势：<strong>上下文持久化</strong>——同一 Routine 的多次执行可以访问历史状态，实现增量分析而非每次从零开始。</p>
<h3 id="与传统-cicd-的区别">与传统 CI/CD 的区别</h3>
<table>
  <thead>
      <tr>
          <th>维度</th>
          <th>传统 CI/CD (GitHub Actions)</th>
          <th>Claude Code Routines</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>定义方式</strong></td>
          <td>YAML + Shell 脚本</td>
          <td>YAML + 自然语言 prompt</td>
      </tr>
      <tr>
          <td><strong>上下文理解</strong></td>
          <td>无代码理解能力</td>
          <td>全代码库语义理解</td>
      </tr>
      <tr>
          <td><strong>触发条件</strong></td>
          <td>事件驱动</td>
          <td>事件 + 定时 + API</td>
      </tr>
      <tr>
          <td><strong>执行位置</strong></td>
          <td>云端 ephemeral</td>
          <td>Anthropic 托管云端</td>
      </tr>
      <tr>
          <td><strong>适用场景</strong></td>
          <td>构建/测试/部署</td>
          <td>分析/审查/生成/监控</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="关键洞察工程化落地的三个建议">关键洞察：工程化落地的三个建议</h2>
<h3 id="1-routine-不等于-script设计好上下文边界">1. Routine 不等于 Script——设计好上下文边界</h3>
<p>Routines 的强大之处在于 Claude 对代码库的语义理解，但这也意味着每次执行都在消耗 token。<strong>不要让一个 Routine 试图做所有事情</strong>。</p>
<p>推荐做法：按职责拆分多个小 Routine，通过 Slack 消息或文件作为它们之间的数据传递媒介。比如 <code>daily-pr-fetcher</code> 只负责拉取数据写入 <code>pr-summary.json</code>，<code>pr-reviewer</code> 读取该文件做 review。</p>
<h3 id="2-api-触发模式下的安全性配置">2. API 触发模式下的安全性配置</h3>
<p>Routines 的 API 触发支持 Bearer Token 认证，但这意味着你的 <code>$ROUTINES_API_SECRET</code> 需要安全存储。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 推荐：通过环境变量注入，不写在 YAML 里</span>
</span></span><span class="line"><span class="cl">claude routines create --name my-routine --env ROUTINES_API_SECRET
</span></span></code></pre></div><p>如果与 GitHub Actions 集成，推荐使用 <strong>GitHub Apps</strong> 而非 Personal Access Token，避免 token 泄露导致仓库权限被滥用。</p>
<h3 id="3-定时任务的时区陷阱">3. 定时任务的时区陷阱</h3>
<p><code>cron: &quot;0 9 * * *&quot;</code> 默认是 <strong>UTC</strong>，而大多数团队的作息是 UTC+8（北京时间）。如果希望&quot;每天早上 9 点&quot;运行，需要写成 <code>cron: &quot;0 1 * * *&quot;</code>（UTC 1:00 = 北京时间 9:00）。Anthropic 文档明确建议在 cron 表达式旁加上注释说明对应的本地时间。</p>
<hr>
<h2 id="信源引用">信源引用</h2>
<ul>
<li><a href="https://code.claude.com/docs/en/routines">Claude Code Routines 官方文档</a>（HN 热度 700+，本文核心信源）</li>
<li><a href="https://github.com/anthropics/claude-code">GitHub: anthropics/claude-code</a>（Stars 114k+，最新提交 2026-04-16）</li>
<li><a href="https://news.ycombinator.com/item?id=47768133">HN Discussion: Claude Code Routines</a></li>
</ul>
<hr>
<h2 id="总结">总结</h2>
<p>Claude Code Routines 代表了 AI 编程助手从&quot;被动工具&quot;向&quot;主动自动化同事&quot;的进化。对于工程团队而言，它的最大价值不是替代人类，而是<strong>接管那些结构清晰、重复性强、但需要代码语义理解的工作</strong>——定时 code review、release note 生成、依赖安全巡检……</p>
<p>关键落地原则：保持 Routine 职责单一、善用 API 触发时的安全配置、注意时区换算。如果你在团队中承担着大量&quot;每天都要做但不需要深度思考&quot;的工作，Routines 值得投入 1-2 小时认真配置。</p>
]]></content:encoded></item></channel></rss>