引言:从一个空循环开始,造一个 Claude Code
本章目标
说清楚这个项目做什么、为什么值得从零造、造完是什么样,然后五分钟把它跑起来。
从「给建议」到「自己动手」
AI 辅助编程走过三个阶段:代码补全(Copilot)、聊天助手(Cursor Chat)、自主 Agent(Claude Code)。前两个阶段有个共同的天花板——模型只能给建议,不能自己动手。让它改 bug,它给出一段代码,但它跑不了测试、看不到报错、没法根据结果再改一版。
Claude Code 迈过了这道坎。一句「给这个项目加用户注册」,它会自己去搜路由、读数据库模型、建 handler、写测试、跑 npm test、看到失败、改一版、再跑,来回十几轮,直到测试通过。它不是在补全代码,而是在执行一个任务。
能做到这一点,靠的不是什么复杂魔法,而是一个循环:
while (true) {
调模型,拿到它的回复
回复里有工具调用?→ 执行工具,把结果喂回去,继续
回复只是文本?→ 任务结束,退出
}传统程序里,下一步做什么是程序员用 if/else 提前写死的。这个循环反了过来:下一步做什么由模型决定,代码只负责把循环转起来、把工具递过去。这一个反转,就是 coding agent 和普通聊天机器人的全部区别。
为什么从零造,而不是读源码
真实的 Claude Code 把这个循环包在了五十万行 TypeScript 里——66 个工具、一套 React/Ink 终端界面、MCP 协议、OAuth 认证、多代理系统。直接翻这些代码,很容易淹死在边界情况和抽象层里,读完还是说不清那个循环长什么样。
这个项目反过来做:把那个循环单独拎出来,用最小的代码重造一遍,一块一块搭。起点是十几行、只会聊天的循环;每一章补一块能力,每一块都能单独跑起来。搭到最后是一个能读代码、改文件、跑测试、循环着修到通过的 agent,TypeScript 版约 5500 行,Python 版约 5000 行,两者互为镜像。就像用一台卡丁车理解汽车:引擎、方向盘、刹车都在,空调和音响先不装,但每一颗关键的螺丝都拧得清清楚楚。
各章造出什么
这张表是核心构建线。每一行是一章,右边是那一章结束时 agent 新学会的事——从「只会聊天」一路长到「能自己干活」:
| 章节 | 这一章之后,agent 能…… |
|---|---|
| 1. Agent Loop | 调用工具、把结果喂回自己,不再只是聊天 |
| 2. 工具系统 | 读写文件、跑 Shell、搜代码——真正动手改项目 |
| 3. System Prompt | 知道自己在什么系统、什么目录、什么 Git 状态下干活 |
| 4. CLI 与会话 | 有一个能交互的命令行,对话还能存盘、--resume 接着聊 |
| 5. 流式输出 | 一边生成一边显示,还能接 OpenAI 兼容的模型 |
| 6. 权限与安全 | 危险操作先问一句,deny 规则拦得住越界 |
| 7. 上下文管理 | 对话太长会自动压缩,跑几十轮也不撑爆窗口 |
| 8. 记忆系统 | 跨会话记住偏好和项目事实,用得上时自己捞出来 |
| 9. 技能系统 | 把常用操作打包成可复用的技能,随用随调 |
| 10. Plan Mode | 先只读地拿出方案,批准了再动手 |
| 11. 多 Agent | 任务太大就 fork 一个子 Agent 去啃,啃完把结果带回来 |
| 12. MCP 集成 | 接上外部工具服务器,工具集能往外扩 |
| 13. 架构对比 | 和真实 Claude Code 逐项对照,看清最小实现和生产级差在哪 |
这条线之外还有两章:第 14 章用 22 个手动场景验收 agent 是否真跑得通,第 15 章加上「自治」三件套(/goal、/loop、Auto Mode),让 agent 能自己持续推进任务、逐动作裁决权限。
最终的样子
搭到最后,各个部件是这样接在一起的。这里不必看懂每个框,后面每一章会补上其中一块:
graph TB
User[用户输入] --> CLI[cli.ts<br/>CLI 入口 / REPL]
CLI --> Agent[agent.ts<br/>Agent 主循环]
Agent --> Prompt[prompt.ts<br/>System Prompt]
Agent --> API{API 后端}
API -->|Anthropic| AnthropicSDK[Anthropic SDK]
API -->|OpenAI 兼容| OpenAISDK[OpenAI SDK]
Agent --> Tools[tools.ts<br/>工具系统]
Tools --> FS[文件读写]
Tools --> Shell[Shell 命令]
Tools --> Search[搜索工具]
Tools --> SkillTool[skill 工具]
Tools --> WebFetch[web_fetch]
Agent --> SubAgent[subagent.ts<br/>子 Agent]
SubAgent -.->|fork-return| Agent
Agent --> Memory[memory.ts<br/>记忆系统]
Prompt --> Memory
Prompt --> Skills[skills.ts<br/>技能系统]
Agent --> MCP[mcp.ts<br/>MCP 集成]
MCP --> ExtTools[外部工具服务器]
Agent --> Session[session.ts<br/>会话管理]
Agent --> UI[ui.ts<br/>终端 UI]
style Agent fill:#7c5cfc,color:#fff
style Tools fill:#e8e0ff
style CLI fill:#e8e0ff
style Memory fill:#ffe0e0
style Skills fill:#ffe0e0
style SubAgent fill:#e0ffe0
style MCP fill:#e0f0ff主线一句话:用户输入进来,CLI 交给 Agent Loop,模型决定调哪个工具,代码执行完把结果喂回去,循环到模型说「做完了」为止。中间的 agent.ts 是引擎(约 2169 行),组装消息、调 API、编排工具、压缩上下文、控制预算都在这儿;其余文件各管一摊,规模都不大:
| 文件 | 行数 | 管什么 |
|---|---|---|
agent.ts | ~2169 | Agent 主循环:消息构造、API 调用、工具编排、流式执行、子 Agent、4 层压缩、预算、Plan Mode、自治三件套 |
tools.ts | ~884 | 工具定义与执行:12 个常驻工具、6 种权限模式、mtime 防护、延迟加载(/loop dynamic 期间还会临时挂载 schedule_wakeup) |
autonomy.ts | ~464 | 自治三件套:/goal 评估器、/loop 调度、Auto Mode 分类器 |
cli.ts | ~416 | CLI 入口、参数解析、REPL 交互 |
memory.ts | ~392 | 记忆系统:4 类型、文件存储、语义召回、异步预取 |
mcp.ts | ~277 | MCP 客户端:JSON-RPC over stdio、工具发现与转发 |
prompt.ts | ~253 | System Prompt 构造:模板、@include、变量替换、记忆/技能注入 |
ui.ts | ~215 | 终端输出:颜色、格式化 |
subagent.ts | ~199 | 子 Agent 配置:3 内置类型 + 自定义 Agent 发现 |
skills.ts | ~175 | 技能系统:目录发现、frontmatter 解析、inline/fork 双模式 |
session.ts | ~63 | 会话持久化:JSON 文件存储 |
frontmatter.ts | ~41 | YAML frontmatter 解析 |
Python 版是同一套结构的完整镜像,放在 python/mini_claude/ 包里,约 5000 行。
技术栈
依赖少到可以一眼看完,没有框架,也没有构建工具链。
先跑起来
装好、给一个 API key、跑起来,五分钟的事。
启动后是这样:
Mini Claude Code — A minimal coding agent
Type your request, or 'exit' to quit.
Commands: /clear /cost /compact /memory /skills /plan
>试一句 read src/agent.ts and explain the main loop,看它自己读文件、自己讲。
命令行还有这些开关,后面对应的章节会讲各自怎么实现:
mini-claude --yolo "run all tests" # 跳过所有确认
mini-claude --plan "analyze this codebase" # 只分析不修改
mini-claude --accept-edits "refactor" # 自动批准文件编辑
mini-claude --dont-ask "check style" # 需确认的操作自动拒绝
mini-claude --auto "fix the failing test" # Auto Mode:分类器逐动作裁决权限
mini-claude --thinking "analyze this bug" # 启用 Extended Thinking
mini-claude --resume # 恢复上次会话
mini-claude --max-cost 0.50 --max-turns 20 # 预算控制各章去哪找对应源码
每一章讲最小实现怎么造,也会指出真实 Claude Code 里对应的源码位置,方便造完之后回去对照:
| 章节 | mini-claude 文件 | Claude Code 对应源码 |
|---|---|---|
| Phase 1: 构建一个可用的 Coding Agent | ||
| 1. Agent Loop | agent.ts 的 chatAnthropic() | src/query.ts 的 queryLoop |
| 2. 工具系统 | tools.ts | src/Tool.ts + src/tools/ (66+ 工具) |
| 3. System Prompt | prompt.ts | src/constants/prompts.ts |
| 4. CLI 与会话 | cli.ts + session.ts | src/entrypoints/cli.tsx |
| 5. 流式输出 | agent.ts 的两套 stream 方法 | src/services/api/claude.ts |
| 6. 权限与安全 | tools.ts 的 checkPermission() + 规则配置 | src/utils/permissions/ (52KB) |
| 7. 上下文管理 | agent.ts 的 checkAndCompact() | src/services/compact/ |
| Phase 2: 进阶能力 | ||
| 8. 记忆系统 | memory.ts | src/utils/memory.ts |
| 9. 技能系统 | skills.ts | src/utils/skills.ts + src/tools/SkillTool/ |
| 10. Plan Mode | agent.ts + tools.ts + cli.ts | EnterPlanMode / ExitPlanMode |
| 11. 多 Agent | subagent.ts + agent.ts | src/tools/AgentTool/ |
| 12. MCP 集成 | mcp.ts | src/services/mcpClient.ts |
| 13. 架构对比 | 全局对比 | 全局对比 |
| Phase 3: 自主运行 | ||
| 15. 自治与续跑 | autonomy.ts | /goal · /loop · Auto Mode |
下一章:从最笨的循环开始——一个只会聊天的 while,再一步步把它变成能干活的 agent。