乐于分享
好东西不私藏

不碰一行源码,如何用 Rust 复刻 Claude Code?Claurst 实战 Spec-first Engineering

不碰一行源码,如何用 Rust 复刻 Claude Code?Claurst 实战 Spec-first Engineering

2026 年 3 月 31 日,Claude Code 的 51.2 万行 TypeScript 源码,因为 .npmignore 配置错误被误发到 npm。4 小时内 GitHub fork 超过 4 万次,整个技术圈都炸了。

所有人都在做同一件事——下载、翻看、转发。但有个人想的完全不一样——

如果不照抄源码,只靠观察它的行为,能不能完整复刻出来?

答案是可以,做法就是先写规范,再按规范实现

这个方法叫 Spec-first Engineering(规范优先工程)。Claurst 项目是目前把这件事做得最彻底的一个——用纯 Rust,通过一套严格的两阶段净室实现(clean-room),在不碰 Claude Code 一行源码的前提下,完整复刻了它的全部行为。

本文不是 Claurst 的使用教程。我们想借它说明一件事:在 AI 时代,怎么通过「先写规范」的方式,让 AI 帮你写出正确的东西

一、什么是 Spec-first Engineering

核心定义

Spec-first Engineering(规范优先工程)是一种软件开发方法,核心原则只有三条:

  1. 规范是唯一的真相来源(不是源码)
  2. 规范描述「做什么」,不描述「怎么做」
  3. 代码必须符合规范,而不是规范迁就代码

换句话说,开发流程从:

源码 → 运行 → 修 bug → 上线

变成了这样:

规范文档 → AI 生成代码 → 编译验证 → 上线

其中 AI 生成代码这一步全程不看原始实现,只看规范。规范是唯一的输入,代码是唯一的输出。

为什么这种流程在 AI 时代变得重要

因为 AI 写代码的能力已经过剩了,真正稀缺的是让 AI 写对的东西

一个 AI 能写出 100 种实现,但哪种是对的?这需要一个客观的参照物——那就是规范。没有规范,AI 写出来的代码要么千人千面,要么过度拟合原始代码(侵犯版权),要么缺少边界条件。

Spec-first Engineering 解决的就是这个问题:先让人(或者一个 AI agent)把「要做什么」用结构化的方式写清楚,再让第二个 AI agent 按规范从零实现。两个 agent 完全隔离,第二个 agent 只看规范,不看源码。

三种开发模式的对比

维度
传统开发
看源码重写
Spec-first Engineering
真相来源
源码即规范
源码作为参照
规范文档是唯一蓝本
AI 的角色
辅助写代码
辅助重写代码
规范驱动代码生成
代码一致性
依赖人工 Code Review
容易过度拟合
编译器 + 规范双重验证
可审计性
低(代码即逻辑)
中(有源码对照)
高(规范可公开审查)
版权风险
高(直接看源码)
零(净室实现隔离)
适用范围
所有开发
复刻已有系统
复刻已有系统 + 新项目架构设计

二、Claurst 完整复刻过程:两阶段净室实现

项目简介

Claurst 是用纯 Rust(99.4% Rust)从零构建的终端 AI 编程助手,GitHub ⭐ 9k,定位是 Claude Code 的开源替代品。

作者 Kuberwastaken 在 Claude Code 源码泄露后,没有 fork 或者直接参考代码,而是选了最笨、但也最正确的方式——

先分析行为,再按行为写规范,最后照规范实现。

整个项目分成两个完全隔离的阶段:

第一阶段:分析 Agent    ↓    读取 Claude Code 源码(仅用于分析)    ↓    输出 14 个 .md 规范文件(spec/ 目录)    ↓第二阶段:实现 Agent(完全隔离)    ↓    只读 spec/ 规范,从不看 Claude Code 源码    ↓    输出纯 Rust 代码(src-rust/ 目录)

规范目录结构:14 个文件的完整体系

Claurst 的 spec/ 目录里有 14 个 Markdown 规范文件,覆盖了 Claude Code 的所有核心模块:

spec/├── INDEX.md                          # 规范索引├── 00_overview.md                    # 项目整体架构├── 01_core_entry_query.md            # 核心入口 + 查询系统├── 02_commands.md                    # 87 个斜杠命令├── 03_tools.md                       # 40+ 工具├── 04_components_core_messages.md    # UI 组件 + 消息组件├── 05_components_agents_permissions.md  # 代理 + 权限 + 设计系统├── 06_services_context_state.md      # 服务 + 上下文 + 状态├── 07_hooks.md                       # React 钩子系统├── 08_ink_terminal.md                # Ink 终端渲染引擎├── 09_bridge_cli_remote.md           # CLI 远程桥接├── 10_utils.md                       # 工具函数库├── 11_special_systems.md              # 伙伴系统 + 记忆 + 语音├── 12_constants_types.md             # 常量 + 类型定义└── 13_rust_codebase.md               # Rust 代码库结构规范

这 14 个文件,把 51.2 万行 TypeScript 的庞然大物,拆解成了一套人类可读、可审计、可执行的规范文档

规范文档长什么样:真实样本解析

这是 Claurst spec/01_core_entry_query.md 里的真实规范文本,看看它是怎么写的。

示例一:模块 Purpose 描述

## main.tsx — Full CLI Entry Point### PurposeThe main CLI module. Loaded only after `entrypoints/cli.tsx`determines no fast-path matches. Defines the Commander.js command tree,handles all CLI flags, orchestrates startup (migrations, trust dialog,MCP config, tool loading), and launches either the interactive REPLor the headless/print (`-p`) path.

描述这个模块做什么,不写一行代码。人和 AI 都能看懂。

示例二:Key Flow(核心流程图)

### Key Flowprocess.argv parsing  ├── --version / -v → print MACRO.VERSION, exit (zero imports)  ├── --dump-system-prompt → dump rendered system prompt  ├── remote-control|rc|remote → bridgeMain()  └── (default) → startCapturingEarlyInput()                 → import main.tsx → cliMain()

用自然语言和树状结构描述执行路径,比代码更清晰,比注释更结构化。

示例三:类型定义

exporttype QueryEngineConfig = {  cwd: string  tools: Tools  mcpClients: MCPServerConnection[]  canUseTool: CanUseToolFn  maxTurns?: number  maxBudgetUsd?: number}

规范里保留原始 TypeScript 类型定义,作为 Rust 实现的参照。

两阶段隔离的关键工程

这是 Claurst 与其他看代码重写项目的本质区别:

第一阶段的分析 Agent

  • 可以读取 Claude Code 的 TypeScript 源码
  • 任务是输出规范文档(spec/)
  • 输出物里不含任何源码片段,只有行为描述

第二阶段的实现 Agent

  • 完全隔离,不看任何 Claude Code 源码
  • 只能读取 spec/ 目录下的规范文件
  • 输出纯 Rust 代码

两个阶段的隔离通过工程约束来保证:第二个 agent 的 prompt 里根本不包含源码路径。

项目文档直接引用了版权法先例——Phoenix Technologies v. IBM (1984),证明净室实现工程在法律上是有效的。

三、从规范到 Rust:对齐约定,而不是逐字段翻译

查询配置:QueryEngineConfig 与 QueryConfig

规范里的 QueryEngineConfig 是 TypeScript 侧查询引擎配置的大结构体。

Rust 里承担单次查询循环配置的是 QueryConfig,字段命名和分工已按 Rust 项目结构重组。

下面是 QueryOutcome 与 QueryConfig 的代码片段

// src-rust/crates/query/src/lib.rs(节选)pubenumQueryOutcome {    EndTurn { message: Message, usage: UsageInfo },    MaxTokens { partial_message: Message, usage: UsageInfo },    Cancelled,    Error(ClaudeError),    BudgetExceeded { cost_usd: f64, limit_usd: f64 },}#[derive(Clone)]pubstructQueryConfig {pub model: String,pub max_tokens: u32,pub max_turns: u32,pub system_prompt: Option<String>,pub working_directory: Option<String>,pub max_budget_usd: Option<f64>,pub fallback_model: Option<String>,// … 另有 tool_result_budget、command_queue、provider_registry 等}

要点:Spec-first 的价值在于,让一次 query 要关心哪些配置项在规范里先讲清楚;Rust 再用强类型把这些项钉在 struct 上,减少实现漂移。

工具系统:Tool trait 与 FileReadTool

spec/03_tools.md 描述的是原版工具框架(含大量 UI / 权限上下文细节)。Claurst 在 claurst-tools 里用更贴近 API 调用的 Tool trait 落地,例如:

// src-rust/crates/tools/src/lib.rs(节选)#[async_trait]pubtraitToolSend + Sync {fnname(&self) -> &str;fndescription(&self) -> &str;fnpermission_level(&self) -> PermissionLevel;fninput_schema(&self) -> Value;asyncfnexecute(&self, input: Value, ctx: &ToolContext) -> ToolResult;}

读文件能力由 FileReadTool 实现,下面是仓库里与 schema 一致的核心字段:

// src-rust/crates/tools/src/file_read.rs(节选)pubstructFileReadTool;#[derive(Debug, Deserialize)]structFileReadInput {    file_path: String,#[serde(default)]    offset: Option<usize>,#[serde(default)]    limit: Option<usize>,}

对外工具名仍可与规范里的命名对齐(规范中 FileRead 对应名称为 Read);实现文件名和内部 struct 名则按 Rust 惯例命名

查询循环:run_query_loop 与 QueryEvent

规范里用伪代码描述「多轮对话 + 工具调用 + 停止条件」。Rust 中入口为 run_query_loop

// src-rust/crates/query/src/lib.rs(节选)pubenumQueryEvent {    Stream(AnthropicStreamEvent),    ToolStart { tool_name: String, tool_id: String, input_json: String },    ToolEnd { tool_name: String, tool_id: String, result: String, is_error: bool },    TurnComplete { turn: u32, stop_reason: String, usage: Option<UsageInfo> },    Status(String),    Error(String),    TokenWarning { state: TokenWarningState, pct_used: f64 },}

循环骨架里轮次上限、取消、pending 消息、命令队列等与规范叙述对应的工程细节:

// src-rust/crates/query/src/lib.rs(节选)pubasyncfnrun_query_loop(    client: &claurst_api::AnthropicClient,    messages: &mutVec<Message>,    tools: &[Box<dyn Tool>],    tool_ctx: &ToolContext,    config: &QueryConfig,    cost_tracker: Arc<CostTracker>,    event_tx: Option<mpsc::UnboundedSender<QueryEvent>>,    cancel_token: tokio_util::sync::CancellationToken,mut pending_messages: Option<&mutVec<String>>,) -> QueryOutcome {letmut turn = 0u32;// …loop {        turn += 1;if turn > effective_max_turns { /* … */ }if cancel_token.is_cancelled() {return QueryOutcome::Cancelled;        }ifletSome(queue) = pending_messages.as_deref_mut() {for text in queue.drain(..) {                messages.push(Message::user(text));            }        }// … 构建请求、流式处理、工具执行、预算与 compact 等    }}

四、为什么 Rust 是 Spec-first Engineering 的最佳拍档

类型系统的验证

规范里的 TypeScript 类型定义(interface/schema),在 Rust 里可以直接映射成 struct + trait bound。这不是简单的语法转换——Rust 的编译器会在编译期强制验证规范与实现的偏差

TypeScript 里你可以在任何地方绕过类型约束;但 Rust 的 struct 必须严格满足定义,字段类型不匹配、缺少必需字段、没处理 Option,编译器会直接报错。

自动化的规范验证器

在传统开发里,代码是否符合规范需要人工 Code Review 来验证。

在 Rust + Spec-first 的工作流里,这条验证链路被压缩成了:

规范文档(定义约束)    ↓AI 生成 Rust 代码(遵循约束)    ↓cargo build(编译验证约束的遵守情况)    ↓编译器报错(如果有偏差,直接中断)

Rust 的 cargo build 等于「规范检查 + 编译 + 测试」三合一。没有 C++ 的 undefined behavior,没有 Python 的运行时类型错误。

所有权模型保证行为一致性

规范里描述了「模块 X 不能访问模块 Y 的内部状态」这样的约束——在 TypeScript/JavaScript 里,这是靠约定和 lint 规则来维护的。

在 Rust 里,这条约束由**借用检查器(Borrow Checker)**在编译期强制执行:

// 规范:Config 模块的状态不能被外部直接修改mod config {pubstructConfig {        inner: ConfigInner,  // private,外部无法直接访问    }impl Config {// 规范:外部只能通过这个方法更新配置pubfnupdate(&mutself, patch: ConfigPatch) -> Result<(), ConfigError> {// 具体的更新逻辑        }    }}// 规范外的代码无法绕过 Config 的接口直接修改 inner 字段// 编译器会报错:field `inner` is private

编译即审计:Rust 的独特价值

验证维度
TypeScript
Rust
类型检查
运行时或弱检查
编译期强制
并发安全
依赖人工
编译器强制
空指针安全
依赖 ?. 操作符
Option<T>

 编译期强制
内存安全
GC 运行时开销
所有权模型,编译期保证
规范与实现一致性
人工 Code Review
编译器 + 类型系统双重验证

Rust 的编译器天然承担了「规范验证者」的角色。

五、Claurst 的实际成果

经过两阶段净室实现工程,Claurst 最终交出了这样的答卷:

指标
数据
编程语言
Rust 99.4%
GitHub Stars
9k
规范文件
14 个 Markdown(完全公开,可审计)
Rust Crate 数量
12 个(core、api、tools、query、tui、commands、mcp、bridge、 …)
工具数量
33 个(规范中列出的 40+ 工具的 Rust 实现)
支持的 AI 提供商
30+(Anthropic、OpenAI、Google、Groq、Ollama、DeepSeek 等)
最新版本
v0.0.9(持续迭代中)
插件系统
托管代理(实验性)
✅ Manager-Executor 架构
无遥测/无跟踪

spec/ 目录在 GitHub 上完全公开——任何人都能下载 Claude Code 的规范文档(行为描述),验证 Claurst 的 Rust 实现是否符合规范。

这是 Spec-first Engineering 最美好的地方:规范即合约,可执行,可审计,可争议。

最后

Claude Code 源码泄露之后,大多数人的反应是赶紧下载。Claurst 的作者选了另一条路——

不碰一行源码,先制定规范

这一行为,后来变成了 14 个 Markdown 规范文件,再后来变成了 9k Star 的纯 Rust 代码。

这不是一个关于复刻 Claude Code 的故事。

这是一个关于工程化思维如何在 AI 时代重新定义开发流程的故事。

Spec-first Engineering 的本质是:让 AI 动手之前,先让人(或者一个专门的 AI agent)把要做什么想清楚、写清楚。 规范文档是人与 AI 之间的契约,而 Rust 的类型系统和编译器,天然承担了契约验证者的角色。

参考链接

  • Claurst 项目:https://github.com/Kuberwastaken/claurst
  • 规范目录(spec/):https://github.com/Kuberwastaken/claurst/tree/main/spec
  • Claurst 文档:https://claurst.kuber.studio/docs