Claude Code 源码带读:基础组 00~05 全解析
Claude Code 不是 LLM + 工具 + 聊天界面那么简单。
它更像一个终端原生智能体运行时(Terminal-native Agent Runtime)。
这篇文章用「带读」的方式,带你从 00 到 05,一次性吃透 Claude Code 的基础架构。后面的 Hook、MCP、Agent、Bridge 等进阶模块,都建立在这组概念之上。
建议先收藏,慢慢看!
📚 阅读前必看:核心词典
在开始之前,先把最容易混的几个词理清,后面就不会迷路了:
- Tool(工具)
:模型可以调用的能力,比如读文件、跑命令。 - Command(命令)
:用户主动输入的指令,比如 /compact。 - Message(消息)
:系统里一条有结构的内容,不只是字符串。 - Content Block(内容块)
:消息里的最小单元,如文本块、工具调用块。 - Transcript(会话流水)
:完整的历史对话记录。 - Memory(记忆)
:从历史里提炼出来、方便以后继续复用的信息。 - Compaction(压缩)
:为了节省上下文将历史缩短,同时保留关键语义。 - Query Loop(查询循环)
:一轮提问在内部反复推进的主循环。
00 总体能力地图(Overall Capability Map)
🤔 核心问题: Claude Code 到底由哪些大模块组成?该按什么顺序读?
💡 关键认知:
Claude Code 是一整套会跑起来的系统。它包含了从入口、初始化、主循环,到工具、权限、会话、记忆和扩展系统等 13 个核心层级。
大白话主流程:
用户输入 ➔ 系统初始化 ➔ 进入主循环 ➔ 模型产出文本或调用工具 ➔ 工具执行前过权限检查 ➔ 结果回写到消息系统 ➔ 最后投影成你看到的终端界面。
🌟 记住: 00 篇是全景地图,不讲细节。没有这张地图,后面每篇你都会觉得“怎么又冒出来一个新模块”。
01 消息模型与渲染(Message Model and Rendering)
🤔 核心问题: 为什么它的输出像个成熟产品,而不是一坨原始文本?
💡 关键认知:
系统内部处理的不是“一整段字符串”,而是 Message(消息) 里面装着多个 Content Block(内容块)。
比如一条助手回复,内部其实是:
-
1个工具调用块(如读文件) -
1个文本块(如“我已经读完这个文件了”) -
1个思考块
它的核心处理链路是:
类型化内容块 ➔ 归一化 ➔ 重排 ➔ 关系配对(工具调用与结果挂钩) ➔ 专用渲染器。
🌟 记住: 这是“乐高积木”模式,不是“作文改写器”模式。输出效果好靠的是结构化消息,而非统一润色。
01b 块渲染器(Message Rendering Block Renderers)
🤔 核心问题: 这些“积木”最后是谁画出来的?
💡 关键认知:
系统里没有一个总的「统一润色器」。
不同块走不同的显示路径,并且工具自带渲染器。
-
text 块 ➔ 走文本渲染器 -
tool_use 块 ➔ 走工具调用渲染器 -
thinking 块 ➔ 走思考渲染器
比如系统内部数据其实是 { "file_path": "app.ts", "limit": 80 },但前端呈现给用户看到的是:Read app.ts · Read 80 lines。
🌟 记住: 界面友好不是因为“模型会说漂亮话”,而是每种块、每个工具都有自己的「显示契约」。
02 结构化 IO 与传输(Structured IO and Transport)
🤔 核心问题: StructuredIO 是“把内容变好看”的层吗?
💡 关键认知:
不是。它更像系统的协议层和控制平面,就像一个“总机”。
它关心的不是“这段话好不好看”,而是:
-
这是不是一个合法的控制请求? -
这条响应对应的是哪个请求? -
有没有重复响应?要不要取消?
🌟 记住: 01 和 01b 是“显示系统”,02 是“通信与控制系统”,职责完全分开。
03 工具运行时与权限(Tool Runtime and Permissions)
🤔 核心问题: 工具是不是模型调一下函数就完了?
💡 关键认知:
不是。工具在 Claude Code 里不是“裸函数”,而是一个能力对象(Capability Object)。
它包含了:执行、自我描述、输入模式、并发安全、只读判断、权限检查等一整套协议。
这里有两个极其关键的设计:
- 可见性 ≠ 执行权限
:有些工具模型根本看不见;看得见的也不一定允许执行。 - 权限是分层裁决的
:不是简单的通过/拒绝,而是细分为:拒绝 (deny)、询问用户 (ask)、允许执行 (allow)。
🌟 记住: 工具系统不是“能跑就跑”,而是“先定义契约 ➔ 再管权限 ➔ 再进流水线”。
04 查询循环与生命周期(Query Loop and Turn Lifecycle)
🤔 核心问题: 用户发一句话后,系统内部先经过谁?
💡 关键认知:
这里有个关键区分:
- QueryEngine(查询引擎)
:管“整个会话”,消息、缓存、文件状态是持续存在的。 - queryLoop(查询循环)
:管“这一轮具体怎么跑”。
此外,用户消息会先写入 Transcript(会话流水),再进入主循环。这样如果系统半路崩溃,恢复时才知道用户发过这句话。
🌟 记住: Claude Code 不是“问一次,答一次”的同步程序,而是一个带状态机的多步循环系统。它的流式输出是架构原生的。
05 会话记忆与压缩(Session Memory and Compaction)
🤔 核心问题: 对话这么长,为什么不会很快把上下文撑爆?
💡 关键认知:
Memory(记忆) ≠ Compaction(压缩)。而且压缩分很多层:
- Transcript(转录)
:像完整录像 - Micro Compact(微压缩)
:像先把太长的附件折叠掉 - Session Memory Compact
:像轻量级会议笔记 - Full Compact(完整压缩)
:像把旧聊天做成一段摘要 - Memdir(记忆目录)
:像长期的档案柜
长期记忆不是“全塞回来”,而是先做相关性选择,判断当前哪些记忆真的有用,再注入上下文。
🌟 记住: 这就是成熟系统的「上下文预算管理」——不求全记住,只保留当前真正值钱的信息。
🎯 总结:必须吃透的 5 句话
如果把基础组(00-05)浓缩成 5 句话,那就是:
-
Claude Code 是 Runtime(运行时),不是聊天框。 -
内部核心单位是 Message Block(消息块),不是纯文本。 -
StructuredIO 是 协议层,不是润色层。 -
Tool 是 能力对象,不是普通函数。 -
长会话靠 Memory + Compaction 分层治理。
吃透了这 5 句话,后面再看各种高级扩展设计,就是顺水推舟了!
夜雨聆风