我用 TypeScript 从零手写了一个 Claude Code,然后发现它的核心只有 30 行

32 阅读11分钟

我用 TypeScript 从零手写了一个 Claude Code,然后发现它的核心只有 30 行

👇 关注公众号【前端小卒】,获取更多 AI 工程实战内容。

这个系列的文章会同步在公众号首发,包括:Agent 开发从零到一全流程、Node.js 全栈学习路线、Vibe Coding 实战踩坑。不贩卖焦虑,只给能上手的东西。

一、先问你一个问题

你每天都在用 Claude Code、Cursor、各种 AI 编程工具,那你能说清楚,当你打一句"帮我修一下这个 bug",它背后到底发生了什么吗?

大多数人的回答会停在"它调用了大模型"。再往下问:模型是怎么"读文件""跑命令""改代码"的?它怎么知道该先看哪个文件?聊久了为什么会变笨、变贵?它凭什么敢在你的机器上执行 rm?大部分人就答不上来了。

这不怪你。市面上讲 Agent 的内容,要么停在"你好世界"级别的 API 调用演示,要么直接甩给你一个封装好几层的框架,让你以为 Agent 是个高深莫测的黑盒。

我不信这个邪。于是我做了一件笨事:用 TypeScript,不借助任何 Agent 框架,从第一行 while 开始,把 Claude Code 这类工具的核心机制亲手复刻了一遍。写到最后,我手上有了一个几百行、但结构和真实产品高度接近的 Agent。

这就是《手搓 Claude Code》这个系列。这篇文章,我想把其中几个"拆穿黑箱"的瞬间讲给你听。看完你会发现,Agent 没有你想的那么神秘,但也远比"调个 API"深刻。


二、第一个反直觉的事实:Agent 的核心,是一个 while 循环

我第一次用 Claude Code 时,盯着控制台看了很久。一个月 20 美元的订阅,能自己读代码、改文件、跑测试,我默认它背后是一套庞大的系统:任务规划器、代码分析引擎、执行沙箱。结果从行为上看,它做的事情简单得可疑:调一次 API,读几个文件,再调一次 API,再读几个文件。循环往复。

后来我把这个循环自己写了一遍,确认了那个让人有点难以接受的事实:Agent 的核心不是什么新物种,就是一个 while 循环。

去掉所有工程细节,它的骨架是这样的:

async function agent(task: string) {
  const messages = [{ role: "user", content: task }];

  while (true) {
    // 1. 把整段对话历史 + 工具菜单发给模型
    const res = await client.messages.create({ model, messages, tools });
    messages.push({ role: "assistant", content: res.content });

    // 2. 模型说"话说完了",收工
    if (res.stop_reason !== "tool_use") break;

    // 3. 模型想动手,你替它执行,把结果塞回历史,进入下一轮
    const results = runTools(res.content);
    messages.push({ role: "user", content: results });
  }
}

本体不到 30 行。想通这段代码,很多东西会连锁地清晰起来。

关键在于:模型从来没有执行过任何东西。 大模型 API 的本质就是一个函数:输入一段对话历史,输出一段文字。它没有手,碰不到你的文件系统。所谓"AI 调用了工具",严格说是"AI 输出了一段结构化的文字说'我想读 package.json',然后被你的代码批准并代劳了"。

决策和执行是分离的:模型是大脑,你的代码是手脚。 这一条是整个系列的地基。第 1 期我把它总结成一句话:策略在模型里,机制在循环里。 循环是死的,每一轮里"读哪个文件、下一步干嘛"的判断是活的。

顺带一提,那个 messages 数组就是 Agent 的全部状态。没有隐藏会话、没有服务端存档,Agent 此刻知道什么、干到哪一步,全部等于这个数组的内容。想暂停明天接着干?序列化存盘。想回放调试?重放数组。状态即历史。


三、那为什么各家 Agent 的能力天差地别?

同一批模型,接到不同产品里,能力差得惊人。为什么?

因为能力的边界根本不在模型,而在你递给它的那张"工具菜单"。 你给它 read_file,它就能看代码;给它 bash,它就能跑命令;你什么都不给,它就只能陪聊。2026 年那些打得火热的编程 Agent,用的模型高度重合,拼的就是外面这圈工具和提示词。

这里藏着一个很反直觉的工程观念:你写工具,本质是在给一个"模型用户"设计 UI。 工具的 description 不是文档注释,而是模型做决策时唯一的依据。它没法看你的源码,你没写的它就不知道。真实 Claude Code 里单个工具的描述能到几百上千 token,写清楚什么时候用、什么时候别用、常见错误怎么办。那不是文档,是大量真实翻车换来的用户体验设计。

还有一个更颠覆的点:灵魂在系统提示词里。 同一个裸模型,默认是个"热情过头的实习生":好的!我很乐意帮您……(八轮之后)希望这对您有帮助!而 Claude Code 上来就是"跑测试→定位到 date.ts:42 时区处理→要我改吗?"。差别只在一段你看不见的文字。系统提示词的每一条约束,背后都是一次事故。民航条例说每一条都是用血写成的;系统提示词是软件业的温和版本。


四、一个真正有深度的问题:聊久了,AI 为什么会变笨、变贵?

这是我个人觉得整个系列最"有用"的一期。

先说个反直觉的事实:模型是无状态的,它一点记忆都没有。 每次请求都是一次全新的、无记忆的计算。所谓"它记得上文",是因为你把整段历史原样重发了一遍。你熟悉的前端里,HTTP 也是无状态的,"登录态"是 cookie 一次次重放伪造出来的会话感。模型 API 同理,只不过重放的是整个对话史。

那么代价来了。设每轮平均新增 k 个 token,第 n 轮要把全部历史重发,input 大约是 n×k。n 轮下来累计付费大约是 k · n(n+1)/2,也就是 n 的平方级增长。对话轮数翻一倍,总账单翻四倍。这就是为什么 Agent 跑一个大任务,成本比聊天贵一个数量级:不是它话多,是历史在滚雪球,每一层还被反复计费。

更隐蔽的是它真的会变笨。长上下文研究里有个反复复现的结论叫 lost in the middle:模型对开头结尾召回率高,对中间显著下降。你干到第 30 轮时,第 8 轮定下的关键决定正好沉在"中间",于是它忘了,甚至做出矛盾的决定。

所以这一期我最想留下的一句话是:上下文不是仓库,是工作台。 仓库求大求全,工作台只摆当前工序需要的东西。桌面越乱,手越慢。至于怎么收拾桌子(prompt caching 为什么能把账单打到一折、又反过来绑架你的架构;compact 怎么让模型给自己写交接摘要),我在视频里用真实的账单曲线一点点算给你看。


五、几个"原来如此"的瞬间

篇幅有限,剩下几期我只挑最颠覆认知的一句话,勾一下:

  • 精确编辑(EP06):让模型改一个 2000 行文件里的错别字,它会把整个文件重写一遍,又贵又慢,还会"顺手优化"你没让它碰的代码。业界最后收敛到的方案是让模型给出 old_string/new_string 做精确替换。为什么这个看起来最笨的方案胜出?因为 old_string 是一段引用,而引用即校验:模型要是记错了文件内容,替换会在碰你磁盘之前就失败。匹配失败不是缺点,是安全机制。

  • 权限系统(EP07):想拦住危险命令,第一反应都是搞个黑名单。写两行你就发现这是场必输的军备竞赛,因为 危险根本不是命令的属性,是上下文的属性rm -rf node_modules 稀松平常,rm -rf ~/项目 是灾难,两条命令长得几乎一样。正确的维度不是"危险程度",而是可逆性:可逆的放手,不可逆的把关。安全问题从"预测危险"变成了"匹配后悔成本"。

  • 记忆(EP08):怎么让 Agent 跨会话记住"我们项目用 pnpm"?工程师的第一反应是微调模型、上向量数据库,越靠前的越贵越复杂,越靠后的越对。正确答案朴素到欺负人:写一个 Markdown 文件,每次开工时读进系统提示词。 AI 的记忆不在模型里,在文件里。背后是 2026 年最值钱的一个认知:在应用层,上下文工程 > 模型训练

  • 子 Agent(EP09):一说"多 Agent"大家都以为是并行提速。其实它的核心价值是上下文隔离:把翻几十个文件的脏活丢给一个用完即弃的分身,只让它带一句结论回主线,主线的工作台始终干净。而它的实现会让你会心一笑:所谓"派一个分身",就是在一个工具函数里,再调用一次第 1 期那个 agent() 循环。 递归。绕了九期,我们回到了起点。


六、这个系列到底是什么

《手搓 Claude Code》,10 期,用 TypeScript 从零写一个 Agent,不用任何框架。代码按 ep01~ep10 打了 tag,每一期都能独立跑通、都留一个钩子。

主题一句话
EP01Agent 循环核心就是一个 30 行的 while 循环
EP02工具系统能力边界,是你写的那几行工具代码
EP03系统提示词同一个模型,换个壳就换了人格
EP04上下文经济学聊久了为什么会变笨、变贵
EP05流式与打断字是一个个蹦出来的,但那不是动画
EP06精确编辑改一个错别字,为什么不该重写整个文件
EP07权限系统别让它 rm -rf:信任是设计出来的
EP08文件记忆AI 的记忆不在模型里,在文件里
EP09子 Agent分身的秘密,是第 1 期那个循环
EP10终章架构全景 + 和真实 Claude Code 的差距

它和市面上大多数教程不太一样的地方:

  1. 不用框架,从第一行 while 写起。 你学到的是原理,不是某个 API 的用法。框架会过时,这些本质认知不会。
  2. 每期都能真的跑起来。 不是 PPT 讲概念,是一个持续生长、你能改能扩的完整代码库。
  3. 诚实讲差距。 终章我没有吹"手写的能吊打 Claude Code",而是把它和真产品摆在一起,把剩下那道鸿沟拆成四层讲清楚:工程细节、提示词打磨、产品生态、模型本身。任何一个 Agent 产品,说白了都是「模型 × 工程 × 产品生态」的乘积。看懂这个乘法,市面上再没有哪个 AI 编程工具能唬住你。

七、谁适合看

  • 会一点 JS/TS,想搞懂 AI Agent 到底怎么转的前端 / 全栈;
  • 天天用 Cursor、Claude Code,但受够了把它当黑箱的人;
  • 想做 AI 应用,却发现"调框架"和"理解原理"之间差着一层窗户纸的人。

不需要任何机器学习背景。我们不训练模型,只把模型当成一个会说话、会点菜的零件来用。


八、来看完整版

这篇文章只是把几个认知点摊开给你看,真正的干货——完整代码、逐行讲解、真实账单演示、故意"弄坏"再修好的实验——都在视频和仓库里。

2026 年,会调 Agent 框架的人越来越多,但真正理解它怎么转的人依然稀缺。跟着写完这十期,你就是后者。

如果这篇文章帮你捅破了一层窗户纸,点个赞、关注一下,别错过后面的深度内容。我们视频里见。