跳转至

Lab 0:改出你的 Claude Code

第一步先改一个看得见的东西。
代码变了,终端里的小动物也跟着变,这就是最直接的反馈。

实验目的

  1. 搭建 Node.js + TypeScript 开发环境
  2. 运行完整的 Claude Code TUI,体验最终效果
  3. 通过填写 *-lab0 骨架文件定制自己的品牌与小动物
  4. 理解本项目的核心学习方式:写代码、重新构建、看到真实 TUI 变化

开始前先知道:什么是 Harness,什么是 Claude Code?

为什么 Lab 0 要先讲这几个词

Lab 0 表面上是在改品牌文字和小动物,但它真正承担的任务是:先帮你建立一张正确的地图。后面你会不断看到这些词:模型、工具、Harness、Agent Loop、Claude Code。如果一开始这些概念就混在一起,后面读源码、看测试、补 TODO 时会一直有一种"每个词都好像懂,但连不成一张图"的感觉。

所以在真正动手之前,你先只带走三个最重要的结论:

  • 模型负责判断:它理解需求、阅读上下文、决定下一步做什么。
  • Harness 负责闭环:它把模型的判断变成真实动作,再把结果送回模型。
  • Claude Code 是完整产品:它不是单独的模型,也不是单独的 Harness,而是两者再加上终端界面、权限、上下文管理、会话机制组成的系统。

只要这三句话先站稳,后面的 Lab 就会顺很多。

先分清"模型"和"产品"

第一次接触 coding agent,最容易混淆的是"模型会不会想"和"产品能不能做事"。

大模型像大脑,负责理解你的目标、读懂你给的上下文、判断下一步应该搜索什么、修改什么、验证什么。它当然很重要,因为没有它,系统就不知道该往哪走。

但光有模型还不够。因为对真实世界来说,模型本身并不会直接去读你硬盘上的文件、修改仓库里的代码、执行终端命令、或者判断某个危险操作是不是应该先征得你的同意。模型能做的,首先只是输出文本,或者输出一种结构化的"我想调用这个工具"的意图。

举个最简单的例子:你对一个裸 LLM 说"帮我修一下这个 TypeScript 报错",它也许能给你一段看起来很像修复方案的代码,但它并不知道你的项目目录长什么样,也不知道真正的报错出在哪个文件,更不可能自动跑 npm test 看改完有没有坏掉。也就是说,它能建议,但还不能行动

这也是为什么一个好用的 coding agent,绝对不只是"更聪明的模型",而是"模型外面还有一层能让行动真正发生的系统"。

什么是 Harness

这层让行动发生的系统,通常就叫 Harness。如果直译,它有点像"马具"或"驾驭装置";放在这里,你可以把它理解成:让模型在真实环境里看得见、动得了、并且动得有边界的一层运行机制。

四个先记住的词

  • 模型:负责理解任务、做判断、决定下一步。
  • Harness:负责把判断变成真实动作,并管理边界。
  • Tool:Harness 提供给模型使用的具体能力,比如读文件、改文件、跑命令。
  • Agent Loop:模型判断 -> 调工具 -> 读取结果 -> 再判断 的循环。

你可以把 Harness 想成模型和真实工作环境之间的桥。模型在桥的一头做决策,仓库、终端、测试、网络、权限机制在桥的另一头。Harness 的工作,就是把这两头接起来,而且接得稳定、清晰、可控。

一个面向编程场景的 Harness,通常至少要负责这些事:

  • 提供工具:例如读文件、搜索代码、编辑文件、执行 Shell 命令。
  • 组织上下文:把项目文件、历史消息、系统规则、用户目标整理给模型。
  • 处理权限:决定哪些动作可以直接做,哪些动作必须先征得用户确认。
  • 维护记忆:把规则、偏好、任务状态、会话信息在多轮交互里保留下来。
  • 连接执行环境:让命令在正确的目录里运行,让结果再回到对话里。

所以,如果把模型比作司机,Harness 更像整辆车、仪表盘、方向盘和交通规则。司机决定方向,但是否能转弯、能不能刹车、有没有拿到路况反馈,不是司机一个人说了算。

Claude Code 到底是什么

理解了模型和 Harness 的分工之后,再来看 Claude Code 就清楚很多了。

Claude Code 不是"输入一句话,吐一段建议"的补全工具,也不是一个只会回答问题的聊天框。更准确地说,它是一个运行在终端里的 agentic coding system。这里的重点不在"终端"三个字,而在"system"这个词:Claude Code 不是某一个点功能,而是一整套持续工作的机制。

在这套机制里:

  • 模型负责思考和决策;
  • Harness 负责提供工具、组织上下文、控制权限、执行动作;
  • TUI/CLI 负责把整个过程以可见、可交互的方式呈现给你。

所以当你给 Claude Code 一个目标时,它往往不会像普通聊天机器人那样立刻吐一段话然后结束,而是会进入一个持续迭代的工作过程:先理解问题,再读仓库、搜代码、改文件、跑测试、看结果、继续调整,直到它判断"现在可以交付了"。

你可以先把这个过程记成一句极简总图:

1
用户目标 -> 模型判断 -> harness 调工具 -> 结果回流 -> 再判断

这张图很短,但后面几乎所有概念都能往里面放:

  • 工具系统,属于"harness 调工具"这一步;
  • Agent Loop,描述的是这几步如何不断循环;
  • 规划、子 Agent、上下文压缩,本质上是在让这个循环跑得更稳、更长、更复杂;
  • 权限和执行环境,是为了保证这套循环在真实机器上依然可控。

也就是说,Claude Code 和普通聊天机器人的差别,不是"回答得更像工程师",而是"它真的在工程环境里持续行动,并根据结果继续行动"。

Agent Loop 为什么是核心

到这里,你会发现还有一个词反复出现:Agent Loop。它之所以重要,是因为它描述了 coding agent 最核心的工作方式。

普通聊天系统常常是一问一答:用户发一句,模型回一句,结束。Agent 系统不一样。Agent 系统的关键不是一次回答多精彩,而是能不能在多轮行动里保持目标不丢、信息不断、结果能回流。

一个最小的 Agent Loop,通常就是这样:

  1. 用户给出目标。
  2. 模型判断下一步需要做什么。
  3. 如果需要工具,Harness 去执行工具。
  4. 工具结果回到上下文里。
  5. 模型基于新结果继续判断下一步。
  6. 当模型认为任务完成时,才真正结束。

你可以把它理解成一个"边做边看、边看边改"的循环。没有这个循环,模型只能停留在"我建议你这样做";有了这个循环,系统才真正进入"我先做一部分,再根据结果继续做"的状态。

这也是为什么后面的 Lab 里,最核心的是 Lab 3。因为一旦 Agent Loop 立住了,聊天机器人和真正 coding agent 之间的分界线就出现了。

这门课真正需要的前置知识地图

现在可以把前面这些概念排成一张更完整的学习地图。它不是"学完所有理论再动手"的意思,而是告诉你:后面每个 Lab 不是孤立技巧,而是在补这张图里的某一层。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
工程地基
Terminal / Git / Node.js / TypeScript
        |
        v
模型通信
Messages API:把一次对话表示成 request / response
        |
        v
行动接口
Tool Calling:模型提出工具请求,Harness 执行并返回结果
        |
        v
循环机制
Agent Loop:工具结果回流,模型继续判断下一步
        |
        v
产品系统
Claude Code:TUI、权限、上下文、会话、构建和真实开发环境

这张图从上到下,是一个 coding agent 从工程地基到完整产品的能力叠加过程。Lab 0 先让你站在最完整的产品层观察整体,确认"我的代码能影响 Claude Code";Lab 1-3 再逐步拆出通信、工具和循环;Lab 4-5 继续补规划、子 Agent 和上下文管理。

这里的 TypeScript 也不是无关的背景知识。Claude Code 本身是 TypeScript/Node.js 项目,本课程的骨架代码、测试和 AsyncGenerator 流式输出也都围绕 TypeScript 展开。你不需要先成为 TypeScript 专家,但至少要知道类型、联合类型、async/awaitfor await 这些概念,因为它们会直接出现在后面的 Agent Loop 代码里。API Key、Base URL、模型名称这些配置也不是"杂事",它们决定 Claude Code 能不能真的连上模型,只是 Lab 0 的 UI 反馈阶段暂时不强依赖它们。

先读哪些 Guide,取决于你卡在哪里

你不需要在 Lab 0 之前把所有参考资料都读完。更好的方式是:先动手,遇到概念卡点时再回来看对应 guide。

如果你卡在... 先读这篇 它会帮你理解
不知道 Claude Code 怎么连模型 配置第三方 API(必读) API Key、Base URL、模型配置怎么影响运行
看不懂 TypeScript 类型、asyncyield TypeScript 基础 后面 skeleton 为什么这样写
不知道一次模型调用长什么样 Anthropic Messages API Lab 1 的输入、输出和消息结构
不理解模型为什么能"用工具" Tool Calling 原理 Lab 2 的工具定义、tool_usetool_result
不知道 Agent 如何连续行动 Agent Loop 详解 Lab 3 的核心 while 循环
想知道真实 Claude Code 为什么这么大 Claude Code 架构分析 本课程为什么只抽核心 Harness 来学

这张表也解释了为什么优秀的 Claude Code 入门材料通常不会一开始就讲源码细节:它们会先让你理解终端、项目目录、工具权限、上下文和循环,再逐步进入实现。源码是答案的一部分,但不是读者第一眼最需要抓住的东西。

为什么 Lab 0 不先讲 query.ts

看到这里,很多人会自然冒出一个问题:既然 Agent Loop 这么重要,为什么 Lab 0 不直接从 query.ts 开始?

答案很简单:因为课程设计讲究顺序。对第一次接触这类系统的人来说,最先需要建立的不是源码细节,而是反馈感整体感

如果你一上来就钻进 query.ts、消息协议、工具路由和状态分支,脑子里很容易只剩下一堆局部实现:这里是 stop reason,那里是 tool result,这里为什么又 continue 了。但你还没有真正感受到"我写的代码,会进入一个真实产品,并改变那个产品的行为"。

Lab 0 故意先不碰最难的部分,而是先让你去填写 *-lab0 骨架文件,修改最直观、最容易观察到的那层外观。你会经历一次非常完整的闭环:

1
改代码 -> 构建 -> 启动真实 Claude Code -> 亲眼看到变化

这个闭环对教学非常重要。它会把后面所有更抽象的知识都钉在一个具体事实上:我们不是在空讲 Agent,我们是在逐步接管一个真实运行中的 Claude Code。

所以 Lab 0 先碰产品外壳,不是因为外壳最重要,而是因为它最适合作为"进入系统"的第一步。

后续 Labs 学什么

从 Lab 1 开始,你会一层层往 Harness 里面走。

Lab 1 先让模型真正"说起来",你会开始理解最基础的调用和返回;Lab 2 给模型接上工具,让系统第一次从"会回答"变成"会动手";Lab 3 实现最核心的 Agent Loop,让模型能根据工具结果继续行动;Lab 4 再往上加规划和子 Agent,让系统学会把复杂任务拆开处理;Lab 5 最后处理上下文压缩和长任务稳定性,让这套循环不只会跑,而且能跑得久。

换句话说,后面的 Labs 并不是一堆分散的技巧,而是在逐层搭出一个完整的 coding agent Harness。

更准确地说,后面的 Labs 是从一张图里依次拆层:先补工程地基,再理解模型通信,再让模型接工具,再把工具结果接回循环,最后才讨论真实产品里必不可少的权限、记忆、上下文压缩和任务分解。

为什么 Lab 0 要改 UI?

后面的 Lab 会逐步实现 Agent Harness:消息协议、工具系统、Agent Loop、规划和上下文管理。这些能力很重要,但第一次接触时不一定马上能"看见"。

Lab 0 先让你改一个非常直观的地方:

  • 打开 Clawd-lab0.tsx 等骨架文件
  • 先改品牌文字,再补小动物像素图
  • 运行 node build.mjs --lab=0
  • 再启动 node cli.js,直接看到终端界面变化

这一步不要求你理解 React、Ink、Claude Code 的完整架构,甚至不要求你一开始就把像素图全部画完。你只需要先完成一小段可见改动,感受"改代码 -> 构建 -> 看到真实产品变化"的闭环。

这次 Lab 真正在改什么?

先把两个仓库分开:

  • build-your-own-claude-code / byocc 仓库:负责平台、文档和 Lab 页面
  • claude-code-diy 仓库:负责真实可运行的 Claude Code 源码

Lab 0 的学习者任务发生在 claude-code-diy 工作区 里,但左侧教程文档写在 byocc 仓库里。你这次不是去改原始 Clawd.tsx,而是去填已经为 Lab 0 准备好的 *-lab0.* 骨架文件。

构建时运行:

1
node build.mjs --lab=0

build.mjs 会自动扫描 -lab0 / -lab-0 / -lab00 / -lab-00 这些后缀的文件,把它们编译后的结果覆盖到对应原始文件的产物上。也就是说:

1
2
Clawd-lab0.tsx   -> 编译后覆盖 dist/.../Clawd.js
WelcomeV2-lab0.tsx -> 编译后覆盖 dist/.../WelcomeV2.js

所以对学习者来说,最重要的心智模型只有一句话:

1
填写 *-lab0 文件里的 TODO -> node build.mjs --lab=0 -> node cli.js -> 看到真实 TUI 变化

Lab 0 要填哪些文件?

Lab 0 对应 6 个可见区域,通常会在 claude-code-diy 里预先提供这 6 个骨架文件:

文件 学习者改什么 最终影响哪里
src/components/LogoV2/Clawd-lab0.tsx 像素画主体、颜色、眼睛 左侧主 Logo 小动物
src/components/LogoV2/WelcomeV2-lab0.tsx 欢迎语 首屏欢迎文字
src/components/LogoV2/CondensedLogo-lab0.tsx 品牌短名 紧凑 Logo 文本
src/components/LogoV2/LogoV2-lab0.tsx 边框标题 Logo 外框标题
src/entrypoints/cli-lab0.tsx 版本字符串 node cli.js --version 输出
src/main-lab0.tsx 程序名 / description / version CLI 描述与版本信息

其中最核心的是 Clawd-lab0.tsx。它决定你的小动物长什么样;其余 5 个文件更多是在把品牌文字统一起来。

实验任务

详见 实验任务