技术架构
Rust 重写,11 个 crate 的一个工作区,产出一个二进制:claw。全无 unsafe,权限默认收紧。本页是全书最技术的一页,读完约 13 分钟(03/04/05 技术核心合计约 35–40 分钟)。
三件套怎么连起来
一个工作区,11 个 crate
| crate | 职责 |
|---|---|
rusty-claude-cli | 主二进制 claw:REPL、一次性 prompt、参数解析、25 个子命令 |
runtime | 会话、配置、权限策略、MCP 客户端、系统提示组装、使用量统计(47 个扁平模块) |
tools | 55 个工具 spec + 执行:bash、read/write/edit、glob/grep、web、agent、todo…… |
commands | 120+ 个 slash 命令的定义、解析与渲染 |
api | 各 provider 客户端 + SSE 流式 + 请求前检查 |
claw-analog | 精简安全壳(lib + bin) |
claw-rag-service | axum HTTP 服务 + SQLite + 可选 Qdrant |
| 其余 | plugins、telemetry、mock-anthropic-service、compat-harness |
注意包名与二进制名不一致:crate 叫 rusty-claude-cli,二进制叫 claw。另外工程刻意使用"巨型扁平文件":main.rs 约 2 万行、tools/lib.rs 约 1.1 万行、commands/lib.rs 约 7 千行,按"类型 → spec 表 → 派发 → 处理器 → 测试"的位置化组织。
工具系统:55 个 spec
tools crate 用一张静态 spec 表(mvp_tool_specs())声明 55 个工具,每个工具带"所需权限级别",由权限层统一拦截。大致分六类:
| 类别 | 代表工具 |
|---|---|
| 文件 | read_file、write_file、edit_file、notebook_edit |
| 搜索 | glob_search、grep_search、tool_search |
| 执行 | bash、powershell、repl |
| 网络 | web_fetch、web_search |
| 协作/自主 | agent(子代理)、todo_write、send_user_message、skill |
| 系统 | config、sleep、enter/exit_plan_mode、structured_output |
文件工具带了边界防护:二进制检测(NUL 字节)、读写大小上限、工作区边界校验、symlink 逃逸防护。这些是"agent 自由写文件"时最容易出安全问题的点。
权限系统:显式闸门 vs YOLO 自治
- 三种权限模式:
read-only(只读检查)、workspace-write(默认,允许改当前工作区)、danger-full-access(放开全部,需显式选择)。 - 细粒度工具门:
--allowedTools只放行指定工具;PermissionEnforcer在派发前拦截,check_bash()在只读模式拒绝改动命令、交互模式要求确认。 - 全工作区
unsafe_code = "forbid":语言层面禁止不安全代码——对一个"让 AI 自由写代码"的项目,这是很重的自我约束。
对照 ccleaks:Claude Code 泄露源码里有一个 classifyYoloAction()——让模型自己对工具调用做 LOW/MEDIUM/HIGH 风险分级,低风险免确认直接执行。这是"模型自治"路线。claw-code 则走"显式闸门"路线:人先定好模式与白名单,agent 没有模糊地带。两者各有利弊:YOLO 快但可能误判,显式闸门稳但打断多。这是一道没有标准答案的工程选择题,值得学生思考。
多模型后端与请求翻译
api crate 按模型前缀自动路由:claude-* 走 Anthropic Messages API;openai/ 走 OpenAI Chat Completions(含 OpenRouter、Ollama、本地服务);grok 走 xAI;qwen/、qwen-* 走阿里 DashScope。模型别名 opus/sonnet/haiku 映射到具体版本。
请求翻译里有不少"填坑"细节,很能体现工程严谨度:
- 推理模型参数剥离:
qwen-qwq-*、*-thinking等推理模型会拒绝 temperature/top_p 等采样参数,客户端自动去掉; - kimi 兼容:kimi 系列模型不接受
is_error字段(会 400),有专门的检测与剔除逻辑; - 凭据形状区分:
sk-ant-*走x-api-key,OAuth token 走Authorization: Bearer——放错槽位是常见的 401 来源,工具还会在报错里给提示。
流式输出用 SSE(Server-Sent Events)逐块推送;请求前做上下文窗口预检,避免超长请求直接失败。
会话、记忆与上下文
- 会话持久化:会话存为 JSONL,支持
--resume [latest|id]恢复;init首次运行才创建.claw/sessions/。 - 项目记忆:按优先级加载
CLAUDE.md→CLAW.md→AGENTS.md,作为系统提示的一部分注入;发现范围被限制在当前 git 根目录。 - token/成本统计:
status/cost面提供使用量;--output-format json暴露结构化数据供自动化。 - 压缩:会话过长时做 compaction(对照 ccleaks:Claude Code 的 auto-compact / context collapse 思路同源)。
钩子、插件与 MCP
- Hooks:生命周期钩子(
/hooks+ 配置),在会话/工具等事件点执行外部脚本——可以理解为"给 agent 装事件监听器"。 - 插件:
PluginManager负责 install/enable/disable/uninstall/update,插件清单是.claude-plugin/plugin.json。 - MCP 生命周期:
McpServerManager管理 MCP 服务器进程(JSON-RPC stdio),McpToolRegistry跟踪连接状态、资源/工具列表、认证状态;/mcp与mcp子命令可查看。
这三样东西是"agent 的工具箱可扩展性"的三种形态:钩子是被动监听,插件是打包的能力,MCP 是跨应用的标准协议(类比 USB-C)。
值得注意的工程风格
- 巨型扁平文件是刻意设计:main.rs 约 2 万行、tools/lib.rs 约 1.1 万行——按位置化组织,不强行拆小;对 agent 而言,大文件反而一次能读全。
- 处处双输出:
render_x(给人)+render_x_json(给机器),JSON 错误走 stdout、文本错误走 stderr——为自动化而生。 - 测试内联:主测试写在模块内
#[cfg(test)];集成测试用 mock 服务起子进程跑(mock-anthropic-service + mock_parity_scenarios.json)。 - 对账文化:PARITY.md 与 mock parity harness 保证行为可对照、可复现。
项目知识库 · 工程约定AGENTS.md(机器生成)▶
参考对照 · YOLO 自动授权ccleaks.com/leaks(外部参考)▶
延伸学习资源(选读,不计入 40 分钟)
对照真实的编码 agent 实现,最能检验你对架构的理解:
- 📄 论文 · Dive into Claude Code: The Design Space of Today's and Future AI Agent Systems(arXiv 2604.14228,含 GitHub 中文版)——对 Claude Code 的源码级架构分析:约 1,900 个 TS 文件、512K 行代码,拆出 7 层安全、9 步 turn 流水线、5 层压缩。
arxiv.org/abs/2604.14228 · github.com/VILA-Lab/Dive-into-Claude-Code(中文 README) - 📄 中文解读 · 看看 Claude Code 怎么做 Harness(北京智源)——生产级 agent harness 的工程化难点:为什么"外壳"比模型本身更决定可靠性。
hub.baai.ac.cn/view/53619 - 📄 逆向分析 · ccleaks.com/leaks——Claude Code 泄露源码的整理:8 个未发布功能、26 个隐藏命令、32 个构建标志、120+ 环境变量。
ccleaks.com/leaks - 📄 官方文档 · OpenAI Codex——与 09 页对比配套:Codex CLI 的安装、配置与用法。
developers.openai.com/codex · github.com/openai/codex - 📄 博客 · Simon Willison——长期更新编码 agent 的实测与评测框架。
simonwillison.net
思考题
Q1 · 为什么"无 unsafe"和"三种权限模式"对"AI 自主写代码"尤其重要?请从攻击面角度推理。
提示:AI 可能生成任意命令;如果工具本身不安全,一次幻觉就可能变成一次漏洞。
Q2 · 巨型扁平文件与"每个文件只做一件事"两种风格,各自的取舍是什么?你会怎么选?
提示:导航成本 vs 上下文切换成本;对 agent 而言,大文件是否更容易一次读全?
Q3 · YOLO 自治授权 vs 显式权限闸门:如果让你设计一个"学生作业批改 agent",你会选哪条路线?为什么?
提示:考虑出错后果、使用频率、被打断的代价。