你的AI编程助手不过是个有妄想症的while循环

第一次使用Claude Code重构整个模块时,我几乎产生了宗教般的震撼体验。描述需求后喝了杯咖啡回来,就看见14个文件变更的PR,测试用例全更新,提交信息也像模像样。“这简直是魔法”,我当时这样想。 但根本不是魔法。就是个while循环。 OpenAI的Michael Bolin最近发文拆解了Codex CLI的内部机制。原来这些AI编程助手背后的秘密既不是革命性算法,也不是神秘神经网络,而是一个循环调用LLM、执行工具直到任务完成的简单流程。 让我们来庖丁解牛。 状态机:5阶段循环结构 所有编程助手——Codex、Claude Code、Cursor等都遵循相同的基础模式。Michael Bolin将其描述为5阶段循环: flowchart TD A["1. 提示词组装"] --> B["2. 模型推理"] B --> C{需要工具调用?} C -->|是| D["3. 工具执行"] D --> E["4. 工具结果反馈"] E --> B C -->|否| F["5. 生成最终响应"] F -->|新输入| A 用开发者能懂的话说: 提示词组装:构建包含系统指令、可用工具、读取文件、对话历史等完整上下文的提示词 模型推理:将提示词token化后传给模型,获取思维链/工具调用/文本响应 工具调用:若模型请求工具(读文件/执行命令等),则运行对应操作 工具反馈循环:将工具执行结果作为新增上下文再次传给模型,重复2-4阶段 结果生成:当模型判定任务完成时输出最终响应 就这么简单。没有知识图谱,没有符号规划器,没有复杂架构。本质上就是个封装了LLM的while循环。 优秀助手与平庸助手的差异不在循环结构——它们完全一致——而在于每个阶段的实现细节。 阶段1:提示词工程的艺术 第一阶段是核心所在。在LLM看到任何代码前,助手需要构建包含以下要素的提示词: flowchart LR subgraph 提示词组件["提示词组装"] 方向 TB SP["系统指令\n(角色设定/规则)"] Tools["可用工具\n(读/写/Bash等)"] Ctx["已读取文件/图像"] Inst["CLAUDE.md/AGENTS.md\n(项目规范)"] Env["环境信息\n(OS/git状态等)"] Hist["完整对话历史"] User["用户最新消息"] end SP --> 最终提示 Tools --> 最终提示 Ctx --> 最终提示 Inst --> 最终提示 Env --> 最终提示 Hist --> 最终提示 User --> 最终提示 这里有个关键设计决策:组件顺序至关重要。提示词按稳定性降序排列:系统指令最前(永不变动),工具定义次之(很少变动),最后是动态增长的文件内容和对话历史。 ...

2026年3月11日 · Fernando

你的LLM缓存让你付出双倍成本省钱(并且有道理)

几周前我写了一篇文章,解释了为什么你发给Claude的99%数据已经在缓存里。KV张量、VRAM、本地SSD——所有的内部机制。但我遗漏了最痛的部分:账单。 因为prompt缓存是那种看起来像超值优惠的东西,但一旦仔细看看数字,你就会发现为了节省成本,你竟然被要求付更多的钱。 成本悖论 让我们用一些数字来说明。在Claude Sonnet的定价中: 项目 每百万tokens价格 常规输入 $3.00 缓存写入 $3.75 (1.25倍) 缓存读取 $0.30 (0.10倍) 注意一件事:写入缓存的成本比直接处理输入高25%。你为了让下一次使用更便宜而需要额外付费。 这就像加入Costco那样。年费有点心疼。但如果买得足够多,就会值回票价。 问题是,“足够多”取决于你能在缓存过期前读取它的次数。 什么时候你会亏钱? 假设你用cache_control发了一个100K tokens的prompt。第一次请求: 100,000 tokens × $3.75/M = $0.375 (缓存写入) 如果你没有用缓存发送它: 100,000 tokens × $3.00/M = $0.300 (常规输入) 你额外多付了$0.075,比常规价格高出25%。你亏钱了。 现在第二次请求,同样有100K tokens的前缀: 100,000 tokens × $0.30/M = $0.030 (缓存读取) 对比来看: 100,000 tokens × $3.00/M = $0.300 (常规未缓存输入) 你节省了$0.27。两次请求的总成本不仅回本了之前多支付的$0.075,现在还实现了盈亏平衡。 盈亏平衡点是1.4次读取。 用更直白的话说:如果你计划在接下来的5分钟内至少重复使用该前缀两次,缓存就是值得的。 为什么对Claude Code来说使用缓存是明智选择 在Claude Code的一次会话中,每条消息都会包含system prompt、工具定义以及整个对话历史。每条消息都在重复发送相同的上下文。如果没有缓存,每次发送“把这个按钮换个颜色”,你都需要为相同的150K tokens上下文支付$3.00/M。 没人能负担得起这个。 而有了prompt缓存,你只需为写入缓存支付一次费用,之后每次读取只需要$0.30/M。在包含150K上下文的50条消息会话中,差距很明显: 无缓存: 50 × 150,000 × $3.00/M = $22.50 有缓存: 1 × 150,000 × $3.75/M + 49 × 150,000 × $0.30/M = $2.77 从$22.50降到$2.77。节省了88%。这就是为什么Anthropic默认在Claude Code中启用缓存。如果不这样做,从经济角度看是不可行的。 ...

2026年3月10日 · Fernando

/loop 在 Claude Code 中:一个与终端共存的 cron

几个月来,我一直用自制的 cron 来执行 Claude Code 的任务。一个 Bash 脚本启动一个 headless 会话,给它一个 prompt,等待任务完成后关闭。它能运作,虽然运作得勉强,但能用。如果有需要,我把代码放在 GitHub 供大家参考。 而上周五,Anthropic 发布了 2.1.71 版本,引入了 /loop。一个原生的调度器,就直接内置在 Claude Code 会话中。 我的第一反应是:“我的项目凉了。” 试用之后的第二反应是:“嗯…还没死,但离死不远了。” /loop 的功能 语法相当简洁: /loop 5m check the deploy status 这个命令告诉 Claude Code:“每 5 分钟,执行这个 prompt 一次。” 不需要退出会话,也不需要 cron,也不用脚本。Claude 来解析时间间隔,安排任务,并在会话仍然开启且处于 *空闲* 状态时执行它。 你可以串联多个斜杠命令: /loop 20m /review-pr 1234 /loop 1h make test 2>&1 | tail -5 每个 loop 都有一个“安全网”:三天后它会自动到期。如果你曾经留下一个忘记关闭的 cron,你大概能理解这种设计有多贴心。 ## 我会如何使用它 试用一天后,我已经发现了三个明确的用途: **1. 在开发过程中监控测试。** 现在我正在 Tokamak 上实现一个重要功能(比如冷启动的五个优化阶段)。与其每次修改一点代码就运行 `make test`,不如直接这样做: /loop 10m make test 2>&1 | grep -E “passed|failed” ...

2026年3月9日 · Fernando

Claude Code Remote Control 的结构解析:尚未开放的隐藏 API

2026 年 2 月 25 日,Anthropic 宣布了针对 Claude Code 的 Remote Control 功能。构思是这样的:你在终端启动 Claude Code,然后拿着手机躺在沙发上,通过 claude.ai 继续你的会话。无需 SSH。无需 tmux。也不需要远程终端窗口。 听起来很酷,对吧? 但实际上,当我在终端输入 /rc 激活后,它给了我一个 URL。我打开手机,登录进去… 然后 claude.ai 提示我 “this feature is not active in your organization”(此功能尚未在您的账户中启用)。2026 年 2 月,我订阅的是 Max 5x 账户,每月按时付款。但什么都没用。 于是,我决定做任何理性人都会做的事:反编译 API,弄清楚后台到底发生了什么。 什么是 Remote Control(官方说法) 本质上:它是一个连接本地 CLI 和 claude.ai 网页的桥梁。Claude Code 的 CLI 仍在你的机器上运行(可以访问你的代码、终端和文件),但你可以通过任何浏览器查看它、批准 tool calls,并发送消息。 Anthropic 将它作为一项 “research preview"(研究预览)推出,仅面向 Max 用户。官方的期望是,你可以启动一个长任务(/rc + 提示词),关上笔记本电脑,去健身房,然后通过手机查看任务进度。 然而,正如我们接下来要讨论的,现实要微妙得多。 我们发现的底层真相 当你运行 /rc 时,Claude Code 会在后台做很多事情。而且,这些行动会留下大量的痕迹——在 JSONL 文件中、在 debug logs 里、在 API 响应里。让我们逐一拆解。 ...

2026年2月27日 · Fernando

如何在 Anthropic 断供时估算你的 Claude 配额

我正在构建 Tokamak,一个监控 Claude Max 配额的 macOS 菜单栏应用。几周前,Anthropic 在他们的服务条款中发布了这样的条文: “您不得使用 OAuth 或类似的授权机制来允许第三方应用程序代表用户访问 Claude。” 而我,正在使用浏览器 cookies 调用一个未公开的端点来读取 Claude Max 配额,盯着屏幕想:“现在怎么办?” 今天的工作方式(有用的权宜之计) Tokamak 需要知道你的配额百分比。就是当你在 claude.ai 上用了一段时间后看到的那个 42%。问题是Anthropic 没有公开的配额 API。没有一个带 API key 的文档化的 GET /api/quota。 但确实存在一个 claude.ai 网站自己使用的内部端点: GET /api/organizations/{org_id}/usage 返回类似这样的内容: { "five_hour": { "utilization": 42, "resets_at": "2026-02-22T18:00:00Z" }, "seven_day": { "utilization": 19, "resets_at": "2026-02-28T14:59:59Z" } } 要调用这个端点,你需要已登录用户的会话 cookies。Tokamak 用一个隐藏的 WKWebView 解决这个问题:用户在应用内的 claude.ai 中登录,cookies 保留在 WebView 中,应用每 30 秒使用这些 cookies 进行轮询。 这样做有效。已经运行了好几个月。但这是一个优雅的权宜之计,而不是稳健的解决方案。我们在使用一个内部 API,Anthropic 可以随时更改、破坏或阻止它,而无需预先通知。 法律灰色地带 OAuth 的禁令是明确的。但这适用于 cookies 吗?技术上我们没有使用 OAuth 或"类似的授权机制"。用户直接在标准 WebView 中登录 claude.ai。就像在应用内打开 Safari。 ...

2026年2月22日 · Fernando

为什么你发送给Claude的99%内容都已经被缓存了

我正在构建一个应用来监控我在Claude Code中的token消费。几天前,查看原始数据时,我遇到了这样的情况: cacheReadInputTokens: 4.241.579.174 inputTokens: 1.293.019 从缓存中读取的四十二亿个tokens。一百三十万个"新鲜"tokens。这是**99.97%**的缓存命中率。 我的第一反应是认为出了什么问题。没人能达到99%的缓存率。Redis不行。Cloudflare不行。你妈妈说她已经知道你要吃什么的时候也不行。 但事实证明它没有坏。就是这样工作的。而原因既优雅又反直觉。 缓存的不是文本 这里是大多数解释都不够深入的地方。当你看到"提示词缓存"时,你会想到类似Redis的东西:保存问题,保存答案,如果有人问同样的问题就返回同样的答案。 完全不是这样。 缓存的是KV张量——transformer在预填充阶段计算的Key和Value矩阵。用通俗的话说:当LLM收到你的提示词时,它首先要做的是将所有这些文本转换为内部数字表示(embeddings),然后与权重矩阵相乘,得到注意力机制生成响应所需的"键"(K)和"值"(V)。 这种计算是极其昂贵的。在一个200,000个tokens的提示词中(在Claude Code中很常见,对话历史会累积),我们谈论的是数十亿次矩阵乘法运算。这是最消耗GPU的部分,最耗时的部分,成本最高的部分。 这就是巧妙之处:在你的一条消息和下一条消息之间,99%的提示词不会改变。系统提示词是相同的。之前的对话历史是相同的。它读取的文件是相同的。唯一新的是你的最后一条消息。 为什么要重新计算你30秒前已经计算过的东西呢? 匹配机制的工作原理 仅仅缓存是不够的。你必须知道缓存什么时候有用。这里Anthropic使用了一个优雅的技巧:按前缀的累积哈希。 提示词的每个块(system、tools、消息)生成一个哈希。但不是单独的哈希:是累积哈希。第3块的哈希包括第1、2、3块的内容。如果前面任何块中的任何东西发生变化,后面所有块的哈希也会改变。 当新请求到达时,系统从标记有cache_control的点开始向后搜索,逐块比较哈希,直到找到匹配的最长前缀。所有匹配的→从缓存读取。只有新的→重新计算。 这就像一部你已经看了40遍的电影。你不需要看完整部电影就知道会发生什么。你只需要从与你记忆中不同的点开始看。 注意这个数据:系统只向后检查最多20个块。超过这个范围,它就停止搜索。这是一个实用的决定,避免花在搜索缓存上的时间超过直接计算张量的时间。 为什么Claude Code有99%的缓存命中率 现在你知道匹配是如何工作的了,99%就不再神秘了。看看Claude Code中典型会话发生的情况: 消息1(会话中的第一条): 系统提示词 (8K tokens) + 工具 (2K tokens) + 你的消息 (500 tokens) = 10,500 tokens → 全部计算,全部写入缓存 消息2: 系统提示词 (8K) + 工具 (2K) + 消息1 (500) + 响应1 (3K) + 你的消息2 (500) = 14,000 tokens → 前面的10,500个 → 缓存命中(我们之前已经计算过) → 新的3,500个 → 计算并添加到缓存 缓存命中率:75% 消息10: 系统提示词 + 工具 + 9条消息 + 9个响应 + 你的消息10 = ~150,000 tokens → 前面的~149,500个 → 缓存命中 → 新的~500个 → 计算 缓存命中率:99.7% 看到了吗?对话历史只是增长。每条新消息都是累积总数的微小部分。缓存比率以自然对数的确定性收敛到99%。 ...

2026年2月19日 · Fernando

Claude Code 原生构建:100MB 的二进制文件取代 Node

一个 100MB 的 CLI 二进制文件 Anthropic 刚刚宣布,Claude Code 已经可以作为 原生构建 使用了。翻译一下:这意味着你可以直接下载一个可执行的二进制文件(通过 curl 安装),不需要再依赖 Node.js。 听起来是不是很棒?一个命令,没有额外依赖,后台还能自动更新。简直就是每个 CLI 工具的梦想。 但是有一个问题:这个二进制文件竟然有 100MB 的大小。 作为对比,git 的二进制文件大约只有 3MB,而 curl 则不到 1MB。就算以生成较大二进制文件著称的 Go,它的文件一般也很少超过 15-20MB。 那么,这 100MB 到底装了些什么? 不是 Rust,而是披了可执行文件外衣的 Bun 当我看到这个公告时,第一反应是:“一定是用 Rust 重写了。” 毕竟,要实现快速的原生二进制文件,而且不依赖运行时,Rust 是明显的选择。 但事实并非如此。 Claude Code 仍然是 TypeScript。Anthropic 使用了 bun build --compile 命令,将其打包成了可执行文件。 bun build --compile 的工作原理 神奇的命令是这样的: bun build ./src/index.ts --compile --outfile claude 这个命令到底做了什么?分为三步来解释: 1. 打包 首先,Bun 作为一个打包工具,处理你的入口文件(比如 index.ts),解析所有的 import,并生成一个包含所有代码的单一 JavaScript 文件。在这个过程中,还会自动引入 node_modules 里的依赖,进行 tree-shaking 删除无用代码,并对结果进行压缩优化。 ...

2026年1月27日 · Fernando

10 GB 的虚拟机支持聊天机器人:Claude 在你的 Mac 上到底在做什么

10 GB 的惊喜 你在 Mac 上安装了 Claude Desktop。最初一切正常,这个应用看似占用空间很小。但某天,当你检查磁盘时,发现了这个文件: ~/Library/Application Support/Claude/vm_bundles/claudevm.bundle 10.8 GB。 是的:一个名为 claudevm.bundle 的文件,隐藏在 Claude 的 vm_bundles 文件夹中,竟占用了将近 11 GB 的存储空间。一个聊天机器人居然需要 10 GB?它里面装了什么,魔戒三部曲加长版视频? 其实不是。claudevm.bundle 包含了一个 Ubuntu 系统。 Claude 的三大产品类别 在解释“是什么”之前,先来聊聊“为什么”。Anthropic 提供了三种方式让你使用 Claude: 产品 执行环境 目标用户 claude.ai Anthropic 云服务器 所有人 Claude Desktop + Cowork 你的 Mac 上的虚拟机 专业人士 Claude Code 在你的系统上直接运行 开发者 网页版是最安全的选项:所有操作都在 Anthropic 的云端完成,你的电脑完全不受影响。但如果你希望 Claude 不仅仅用于聊天,还能在你的电脑上“真正做事情”——比如创建文档、执行代码、处理文件等,那你需要更多功能。 这时,Cowork 和 Claude Code 应运而生,两者代表了完全不同的理念。 Cowork:人人都能用的 Claude Code Cowork 是 Anthropic 在 2026 年 1 月 12 日推出的智能助手产品。它的官方口号是: ...

2026年1月25日 · Fernando