[{"data":1,"prerenderedAt":1050},["ShallowReactive",2],{"post-porting-mihomo-to-rust-with-claude":3},{"id":4,"title":5,"body":6,"cover":1041,"date":1042,"description":1043,"extension":1044,"meta":1045,"navigation":340,"path":1046,"seo":1047,"stem":1048,"__hash__":1049},"posts/posts/porting-mihomo-to-rust-with-claude.md","用 Claude Code 将三万行 Go 项目移植到 Rust：Agent Team 实践与 Harness 效率优化",{"type":7,"value":8,"toc":1012},"minimark",[9,13,24,33,36,43,47,50,132,136,139,142,145,148,154,164,171,174,177,209,212,218,222,225,228,271,274,280,284,287,290,418,422,428,434,440,444,451,454,458,464,471,475,481,488,492,498,501,505,508,511,525,531,534,618,621,628,632,635,638,670,673,680,686,690,694,697,708,712,719,722,742,746,749,752,770,774,777,783,786,806,809,813,828,831,834,837,955,958,962,965,991,994,1005,1008],[10,11,12],"h2",{"id":12},"背景",[14,15,16,23],"p",{},[17,18,22],"a",{"href":19,"rel":20},"https://github.com/MetaCubeX/mihomo",[21],"nofollow","mihomo","（Clash Meta）是一个用 Go 编写的规则代理内核，支持 Shadowsocks、Trojan、VLESS 等多种协议，被广泛部署在路由器和 VPS 上。我决定用 Rust 重写它——不是为了 \"用 Rust 重写一切\" 的执念，而是出于实际需求：更小的二进制体积、更低的内存占用、以及 Rust 类型系统在网络协议实现中带来的安全保障。",[14,25,26,27,32],{},"最终产物 ",[17,28,31],{"href":29,"rel":30},"https://github.com/madeye/mihomo-rust",[21],"mihomo-rust"," 包含 11 个 workspace crate、31,000+ 行 Rust 代码、40 份技术规格文档、2 份架构决策记录（ADR），以及覆盖单元测试、集成测试、端到端 TProxy 测试的完整 CI 管线。从第一个 commit 到 M1 里程碑基本完成，整个过程高度依赖 Claude Code 的 Agent Team 机制。",[14,34,35],{},"这篇文章不是一篇 \"AI 好厉害\" 的宣传稿。它是一份工程实践记录——哪些做法有效，哪些踩了坑，以及如何通过调优 harness 配置让 Claude Code 在大型项目中真正可用。",[14,37,38],{},[39,40],"img",{"alt":41,"src":42},"mihomo-rust crate 架构：31,178 行代码分布在 11 个 crate 中","/assets/2026/chart-mihomo-crate-breakdown.svg",[10,44,46],{"id":45},"agent-team四个角色的分工","Agent Team：四个角色的分工",[14,48,49],{},"Claude Code 的 Agent Team 允许你在一个会话中运行多个专业化 agent，各自承担不同职责。在 mihomo-rust 项目中，我使用了四个角色：",[51,52,53,69],"table",{},[54,55,56],"thead",{},[57,58,59,63,66],"tr",{},[60,61,62],"th",{},"角色",[60,64,65],{},"模型",[60,67,68],{},"职责",[70,71,72,92,106,119],"tbody",{},[57,73,74,82,85],{},[75,76,77,81],"td",{},[78,79,80],"strong",{},"PM","（项目经理）",[75,83,84],{},"Sonnet",[75,86,87,88],{},"拥有路线图、排列优先级、撰写里程碑退出标准、维护 ",[89,90,91],"code",{},"roadmap.md",[57,93,94,100,103],{},[75,95,96,99],{},[78,97,98],{},"Architect","（架构师）",[75,101,102],{},"Opus",[75,104,105],{},"编写差距分析报告、ADR、做架构决策、审查技术方案",[57,107,108,114,116],{},[75,109,110,113],{},[78,111,112],{},"Engineer","（工程师）",[75,115,84],{},[75,117,118],{},"实现代码、编写测试、处理 CI 修复",[57,120,121,126,129],{},[75,122,123],{},[78,124,125],{},"QA",[75,127,128],{},"Haiku",[75,130,131],{},"编写测试计划、审查测试覆盖率、维护 CI 状态报告",[133,134,135],"h3",{"id":135},"为什么这样分配模型",[14,137,138],{},"这不是随意选择。Opus 放在 Architect 角色上，是因为架构决策需要最强的推理能力——比如决定 gRPC transport 是手写 \"gun\" 帧还是引入 tonic（最终选择了手写，因为上游 Go 代码本身就没有 protobuf schema，引入 tonic 会增加约 30 个依赖和 2MB 二进制体积）。",[14,140,141],{},"Sonnet 用于 PM 和 Engineer，因为这两个角色的工作更偏向结构化执行：PM 按固定模板填充路线图表格，Engineer 按 spec 实现代码。Haiku 用于 QA——测试计划是高度模板化的工作，用最快最便宜的模型即可。",[133,143,144],{"id":144},"角色之间的信息流",[14,146,147],{},"四个 agent 并不是各自为战。它们通过文件系统共享状态：",[14,149,150],{},[39,151],{"alt":152,"src":153},"Agent Team 四角色协作模式与信息流向","/assets/2026/chart-mihomo-agent-team.svg",[155,156,161],"pre",{"className":157,"code":159,"language":160},[158],"language-text","docs/vision.md          ← PM 拥有，定义目标和非目标\ndocs/gap-analysis.md    ← Architect 产出，PM 消费\ndocs/roadmap.md         ← PM 拥有，引用 Architect 的分析\ndocs/adr/*.md           ← Architect 拥有，不可协商的架构决策\ndocs/specs/*.md         ← PM 拥有格式，Architect 审查技术内容\ndocs/specs/*-test-plan.md ← QA 产出\ndocs/ci-status.md       ← QA 拥有\n","text",[89,162,159],{"__ignoreMap":163},"",[14,165,166,167,170],{},"关键原则：",[78,168,169],{},"ADR 决定架构（不可协商），spec 填充细节（可讨论），测试计划验证 spec","。这种分层避免了 agent 之间的决策循环。",[10,172,173],{"id":173},"里程碑驱动的开发节奏",[14,175,176],{},"项目分为四个里程碑：",[178,179,180,191,197,203],"ul",{},[181,182,183,186,187,190],"li",{},[78,184,185],{},"M0（正确性修复）","：10 个小项，修复安全漏洞、接线遗漏、CI 缺口——比如 REST API 的 Bearer 认证一直是 ",[89,188,189],{},"#[allow(dead_code)]","，GEOIP 规则解析直接返回错误",[181,192,193,196],{},[78,194,195],{},"M1（用户可用）","：协议、传输层、规则、DNS、API 的全面补齐",[181,198,199,202],{},[78,200,201],{},"M2（性能优化）","：基准测试、分配器审计、feature flag 精简",[181,204,205,208],{},[78,206,207],{},"M3（运维成熟）","：热重载、OpenTelemetry、配置校验",[14,210,211],{},"M0 和 M1 并行推进——M0 的项都是小范围修复，Engineer 可以在等待 M1 spec 评审时穿插完成。",[14,213,214],{},[39,215],{"alt":216,"src":217},"开发速度：Agent Team 全面介入后 commit 密度显著提升","/assets/2026/chart-mihomo-dev-velocity.svg",[133,219,221],{"id":220},"一个具体的例子transport-layer-的开发过程","一个具体的例子：Transport Layer 的开发过程",[14,223,224],{},"Transport Layer（M1.A）是 M1 的前置依赖——VLESS 协议需要可复用的 TLS/WebSocket/gRPC 传输层，否则每个新协议都要复制粘贴 TLS 握手代码。",[14,226,227],{},"开发过程如下：",[229,230,231,248,253,258],"ol",{},[181,232,233,235,236,239,240,243,244,247],{},[78,234,98],{}," 编写 ADR-0001，确定 ",[89,237,238],{},"mihomo-transport"," 作为独立 leaf crate，定义 ",[89,241,242],{},"Transport"," trait 接口，决定用 ",[89,245,246],{},"Box\u003Cdyn Stream>"," trait object 而非泛型（因为运行时需要根据 YAML 配置动态组合传输层链）",[181,249,250,252],{},[78,251,80],{}," 将 ADR 翻译为路线图中的四个有序任务（A-1 到 A-4），标注依赖关系——\"VMess 在 A-2 完成后解锁\"",[181,254,255,257],{},[78,256,112],{}," 按序实现：先建 crate 骨架和 TLS 层，迁移 Trojan；然后 WebSocket 层，迁移 v2ray-plugin；然后手写 gRPC gun 帧；最后 HTTP/2 和 HTTPUpgrade",[181,259,260,262,263,266,267,270],{},[78,261,125],{}," 在每一步验证集成测试仍然通过：",[89,264,265],{},"trojan_integration"," 和 ",[89,268,269],{},"v2ray_plugin_integration"," 不能因迁移而中断",[14,272,273],{},"这个流程看起来很重——四个角色处理一个 crate 的创建。但正是这种结构化保证了几件事：gRPC 没有引入不必要的依赖（Architect 决策）、构建顺序没有被打乱（PM 管控）、迁移过程中测试一直是绿的（QA 验证）。",[14,275,276],{},[39,277],{"alt":278,"src":279},"Spec 驱动开发流水线：以 Transport Layer 为例","/assets/2026/chart-mihomo-spec-workflow.svg",[10,281,283],{"id":282},"claudemdharness-效率的核心杠杆","CLAUDE.md：Harness 效率的核心杠杆",[14,285,286],{},"CLAUDE.md 是 Claude Code 在每次会话开始时自动加载的指导文件。它是提高 harness 效率最重要的手段——写得好，agent 不需要每次都重新探索项目结构。",[14,288,289],{},"mihomo-rust 的 CLAUDE.md 只有 101 行，但信息密度很高：",[155,291,295],{"className":292,"code":293,"language":294,"meta":163,"style":163},"language-markdown shiki shiki-themes github-light github-dark","## Build Commands\ncargo build --release\ncargo test --lib\ncargo test --test rules_test           # 78 rule matching tests\ncargo test --test trojan_integration   # embedded mock server\ncargo test --test shadowsocks_integration  # requires ssserver\n\n## Architecture\nListeners → Tunnel (routing) ←→ DNS Resolver\n                |\n          Rule Matching\n                |\n          Proxy Adapters / Groups → Remote Server\n          \nREST API (Axum) → Runtime control\n\n## Key Patterns\n- ProxyAdapter trait — all protocols implement this\n- Rule trait — all rule types implement this  \n- Tunnel — Arc-shared routing engine\n","markdown",[89,296,297,305,311,317,323,329,335,342,348,354,360,366,371,377,383,389,394,400,406,412],{"__ignoreMap":163},[298,299,302],"span",{"class":300,"line":301},"line",1,[298,303,304],{},"## Build Commands\n",[298,306,308],{"class":300,"line":307},2,[298,309,310],{},"cargo build --release\n",[298,312,314],{"class":300,"line":313},3,[298,315,316],{},"cargo test --lib\n",[298,318,320],{"class":300,"line":319},4,[298,321,322],{},"cargo test --test rules_test           # 78 rule matching tests\n",[298,324,326],{"class":300,"line":325},5,[298,327,328],{},"cargo test --test trojan_integration   # embedded mock server\n",[298,330,332],{"class":300,"line":331},6,[298,333,334],{},"cargo test --test shadowsocks_integration  # requires ssserver\n",[298,336,338],{"class":300,"line":337},7,[298,339,341],{"emptyLinePlaceholder":340},true,"\n",[298,343,345],{"class":300,"line":344},8,[298,346,347],{},"## Architecture\n",[298,349,351],{"class":300,"line":350},9,[298,352,353],{},"Listeners → Tunnel (routing) ←→ DNS Resolver\n",[298,355,357],{"class":300,"line":356},10,[298,358,359],{},"                |\n",[298,361,363],{"class":300,"line":362},11,[298,364,365],{},"          Rule Matching\n",[298,367,369],{"class":300,"line":368},12,[298,370,359],{},[298,372,374],{"class":300,"line":373},13,[298,375,376],{},"          Proxy Adapters / Groups → Remote Server\n",[298,378,380],{"class":300,"line":379},14,[298,381,382],{},"          \n",[298,384,386],{"class":300,"line":385},15,[298,387,388],{},"REST API (Axum) → Runtime control\n",[298,390,392],{"class":300,"line":391},16,[298,393,341],{"emptyLinePlaceholder":340},[298,395,397],{"class":300,"line":396},17,[298,398,399],{},"## Key Patterns\n",[298,401,403],{"class":300,"line":402},18,[298,404,405],{},"- ProxyAdapter trait — all protocols implement this\n",[298,407,409],{"class":300,"line":408},19,[298,410,411],{},"- Rule trait — all rule types implement this  \n",[298,413,415],{"class":300,"line":414},20,[298,416,417],{},"- Tunnel — Arc-shared routing engine\n",[133,419,421],{"id":420},"写好-claudemd-的几个原则","写好 CLAUDE.md 的几个原则",[14,423,424,427],{},[78,425,426],{},"只写不能从代码推断的信息。"," 不要列出每个文件的路径——agent 可以用 Glob 找到。要写的是：哪些 trait 是架构骨架、哪些测试需要外部依赖（ssserver）、构建命令有什么特殊参数。",[14,429,430,433],{},[78,431,432],{},"写清楚扩展点。"," \"如何添加新协议\" 和 \"如何添加新规则类型\" 各三行，告诉 agent 需要改哪三个文件。这比写一整段架构描述更有效——agent 需要的是 actionable 的指令。",[14,435,436,439],{},[78,437,438],{},"不要写过时的信息。"," CLAUDE.md 不是变更日志。如果某个决策已经落实到代码里（比如 fake-ip 已经被移除），就不需要在 CLAUDE.md 里再解释为什么移除。",[10,441,443],{"id":442},"memory-系统跨会话的经验积累","Memory 系统：跨会话的经验积累",[14,445,446,447,450],{},"Claude Code 的 Memory 系统允许在会话之间持久化信息。mihomo-rust 项目积累了 7 条 memory，全部是 ",[89,448,449],{},"feedback"," 类型——即对 agent 行为的纠正或确认。",[14,452,453],{},"几条有代表性的：",[133,455,457],{"id":456},"不要在-router-上加-catchpanic","\"不要在 router 上加 CatchPanic\"",[155,459,462],{"className":460,"code":461,"language":160},[158],"prohibits adding CatchPanic or panic-absorbing middleware to axum router.\nTask #26 requires panics in spawned tokio tasks to abort the process\nso failures are detectable.\n",[89,463,461],{"__ignoreMap":163},[14,465,466,467,470],{},"这条 memory 源于一次具体事件：Engineer agent 试图在 Axum router 上加 ",[89,468,469],{},"tower::catch_panic"," 来 \"提高健壮性\"。但 QA 的测试计划要求 panic 必须导致进程终止，以便在 soak test 中被检测到。保存这条 memory 后，后续会话中 Engineer 不再犯同样的错误。",[133,472,474],{"id":473},"tokiotimepause-不虚拟化系统调用","\"tokio::time::pause() 不虚拟化系统调用\"",[155,476,479],{"className":477,"code":478,"language":160},[158],"tokio::time::pause()/advance() only affects sleep/Instant futures,\nnot kernel syscalls like TcpStream::peek(), read(), recv().\n",[89,480,478],{"__ignoreMap":163},[14,482,483,484,487],{},"这条是 Engineer 在写 sniffer 测试时踩的坑。",[89,485,486],{},"tokio::time::pause()"," 看起来可以用来加速超时测试，但它只影响 tokio 自己的定时器，不影响实际的 socket IO。这个知识点保存后，在后续编写 boring-tls 测试时直接规避了同样的陷阱。",[133,489,491],{"id":490},"里程碑完成时必须重启所有-teammate","\"里程碑完成时必须重启所有 teammate\"",[155,493,496],{"className":494,"code":495,"language":160},[158],"Mandatory shutdown and respawn all four teammates at milestone completion.\nRespawn with model assignment: architect=opus, pm/engineer=sonnet, qa=haiku.\nDo not clear mid-milestone or if any state isn't saved.\n",[89,497,495],{"__ignoreMap":163},[14,499,500],{},"这是最重要的一条操作规范。Agent Team 的上下文窗口是有限的——经历一整个里程碑的讨论后，上下文中充满了过时的中间状态。在里程碑边界处 \"重启\" 所有 agent，让它们从干净的状态重新读取文件系统中的文档，比带着旧上下文继续工作更高效。",[10,502,504],{"id":503},"上游分歧策略adr-0002-的实践价值","上游分歧策略：ADR-0002 的实践价值",[14,506,507],{},"移植项目最棘手的问题之一是：上游的 bug 要不要复制？",[14,509,510],{},"ADR-0002 定义了一个简单的二分类法：",[178,512,513,519],{},[181,514,515,518],{},[78,516,517],{},"Class A（安全/隐私/路由意图）","：硬错误，拒绝加载。用户读配置文件时会误以为自己得到了 X，实际上得到的 Y 更不安全",[181,520,521,524],{},[78,522,523],{},"Class B（性能/兼容性）","：警告一次，继续运行。流量到达正确目的地，只是走了更慢的路径",[14,526,527],{},[39,528],{"alt":529,"src":530},"上游分歧策略：二分类决策框架","/assets/2026/chart-mihomo-divergence.svg",[14,532,533],{},"具体案例：",[51,535,536,551],{},[54,537,538],{},[57,539,540,543,546,548],{},[60,541,542],{},"场景",[60,544,545],{},"上游行为",[60,547,31],{},[60,549,550],{},"分类",[70,552,553,570,586,599],{},[57,554,555,561,564,567],{},[75,556,557,558],{},"VMess ",[89,559,560],{},"cipher: zero",[75,562,563],{},"接受，明文传输",[75,565,566],{},"解析时报错",[75,568,569],{},"A",[57,571,572,577,580,583],{},[75,573,574],{},[89,575,576],{},"alterId > 0",[75,578,579],{},"运行废弃的 MD5 密钥推导",[75,581,582],{},"警告并强制为 0",[75,584,585],{},"B",[57,587,588,591,594,597],{},[75,589,590],{},"sniffer peek IO 错误",[75,592,593],{},"静默跳过",[75,595,596],{},"记日志，保留原始 metadata",[75,598,569],{},[57,600,601,610,613,616],{},[75,602,603,606,607],{},[89,604,605],{},"default-nameserver"," 包含 ",[89,608,609],{},"tls://",[75,611,612],{},"接受，运行时 bootstrap 死循环",[75,614,615],{},"加载时报错",[75,617,569],{},[14,619,620],{},"这个分类法的价值在于：它让 Engineer agent 在实现过程中遇到 spec 未预见的边界情况时，有一个明确的默认规则——\"不确定时选 Class A（硬错误），在 PR 描述中标注\"。这比每次都暂停来请求 Architect 决策高效得多。",[14,622,623,624,627],{},"对 QA 来说，测试用例中引用分歧分类（",[89,625,626],{},"Class A per ADR-0002: upstream accepts, we reject","）让审查者一眼就能判断测试的意图。",[10,629,631],{"id":630},"spec-驱动开发40-份文档不是官僚主义","Spec 驱动开发：40 份文档不是官僚主义",[14,633,634],{},"项目产出了 40 份 spec 文档和对应的测试计划。这看起来像是过度工程，但在 agent team 的协作模式下，spec 是协调四个 agent 的关键工具。",[14,636,637],{},"每份 spec 的固定结构：",[229,639,640,646,652,658,664],{},[181,641,642,645],{},[78,643,644],{},"YAML schema","：配置文件中的字段定义",[181,647,648,651],{},[78,649,650],{},"Struct shapes","：Rust 结构体的字段和类型",[181,653,654,657],{},[78,655,656],{},"Error types","：所有错误情况的枚举",[181,659,660,663],{},[78,661,662],{},"Divergences table","：与上游的分歧，引用 ADR-0002 分类",[181,665,666,669],{},[78,667,668],{},"Test plan","：测试矩阵（独立文件）",[14,671,672],{},"为什么 spec 比直接告诉 Engineer \"去实现 VLESS\" 更高效？",[14,674,675,676,679],{},"因为 ",[78,677,678],{},"spec 是 agent 之间的接口协议","。Architect 在 spec 的 struct shapes 部分定义类型签名，Engineer 实现它们，QA 根据 spec 的 error types 生成测试用例。没有 spec，每个 agent 都需要自己去读上游 Go 代码来理解应该怎么做，这会导致三个 agent 对同一个问题产生三种理解。",[14,681,682,683,685],{},"一个具体的数字：transport-layer.md 这份 spec 覆盖了 M1.A 的全部四个子任务，因为 ADR-0001 已经确定了架构。spec 只需要填充 YAML schema、struct shapes 和 per-layer 测试——大约 200 行。而 Engineer 根据这 200 行 spec 产出了整个 ",[89,684,238],{}," crate 的代码。",[10,687,689],{"id":688},"效率优化踩过的坑和学到的经验","效率优化：踩过的坑和学到的经验",[133,691,693],{"id":692},"_1-上下文窗口是最稀缺的资源","1. 上下文窗口是最稀缺的资源",[14,695,696],{},"Agent team 中每个 agent 都有独立的上下文窗口。长时间运行的会话会导致上下文被早期的探索、失败尝试和中间状态填满。解决方案：",[178,698,699,702,705],{},[181,700,701],{},"在 CLAUDE.md 中写清楚关键信息，让 agent 不需要每次都重新探索",[181,703,704],{},"里程碑边界处重启所有 agent",[181,706,707],{},"用文件系统（docs/、specs/）而不是上下文窗口来传递状态",[133,709,711],{"id":710},"_2-文档是给-agent-写的不只是给人写的","2. 文档是给 Agent 写的，不只是给人写的",[14,713,714,715,718],{},"传统软件项目中，文档是写给下一个读代码的人看的。在 agent team 模式下，文档同时也是 agent 的 \"system prompt\"——它们通过读取 ",[89,716,717],{},"docs/"," 来理解项目状态和决策历史。",[14,720,721],{},"这意味着文档的写法需要调整：",[178,723,724,730,736],{},[181,725,726,729],{},[78,727,728],{},"用表格代替散文。"," Agent 解析表格比理解段落高效",[181,731,732,735],{},[78,733,734],{},"引用要精确。"," \"参见 ADR-0001\" 比 \"参见之前的架构讨论\" 好，因为 agent 可以直接定位文件",[181,737,738,741],{},[78,739,740],{},"状态要明确。"," 每个工作项标注 \"completed / in-progress / blocked\"，而不是 \"我们之前讨论过这个\"",[133,743,745],{"id":744},"_3-memory-要精简且可操作","3. Memory 要精简且可操作",[14,747,748],{},"Memory 系统的陷阱是存太多信息。mihomo-rust 只保存了 7 条 memory，全部是 feedback 类型——即 \"不要做 X\" 或 \"做 Y 时注意 Z\" 的规则。",[14,750,751],{},"不保存的东西：",[178,753,754,757,764,767],{},[181,755,756],{},"代码模式和约定（从代码本身可以推断）",[181,758,759,760,763],{},"Git 历史（",[89,761,762],{},"git log"," 更权威）",[181,765,766],{},"调试方案（修复已经在代码里了）",[181,768,769],{},"临时任务状态（用 task 系统而非 memory）",[133,771,773],{"id":772},"_4-测试是验证-agent-工作质量的唯一可靠手段","4. 测试是验证 Agent 工作质量的唯一可靠手段",[14,775,776],{},"Agent 生成的代码看起来可能是正确的，但 \"看起来正确\" 不等于 \"运行正确\"。",[14,778,779],{},[39,780],{"alt":781,"src":782},"测试基础设施：619 个测试函数覆盖 5 个层次","/assets/2026/chart-mihomo-test-coverage.svg",[14,784,785],{},"mihomo-rust 的 CI 管线包含：",[178,787,788,791,794,797,800,803],{},[181,789,790],{},"100+ 单元测试",[181,792,793],{},"82 个 API 集成测试",[181,795,796],{},"78 个规则匹配测试",[181,798,799],{},"5 个协议级集成测试（Trojan、Shadowsocks、v2ray-plugin、VLESS、boring-tls）",[181,801,802],{},"Docker 化的 TProxy 端到端测试",[181,804,805],{},"MSRV 校验（确保声称的最低 Rust 版本是真的）",[14,807,808],{},"每次 Engineer agent 提交代码后，跑完整测试套件是不可跳过的步骤。在 ECH/uTLS 的开发中，31 个测试用例（包括 C13-C15 的真实 BoringSSL 服务器端到端握手）是判断 \"这个 feature 可以合并\" 的唯一标准。",[133,810,812],{"id":811},"_5-让-agent-管理自己的状态文档","5. 让 Agent 管理自己的状态文档",[14,814,815,816,819,820,823,824,827],{},"ECH/uTLS feature 的开发展示了一种有效模式：PM agent 维护一份 ",[89,817,818],{},"ech-utls-status.md","，记录 16 个 task 的状态、每个 task 的 owner、完成的 commit hash、以及关键决策（为什么选择 boring 而不是 rustls 做 ECH backend、为什么 ",[89,821,822],{},"random"," profile 在 ",[89,825,826],{},"TlsLayer::new"," 时解析而不是每次连接时）。",[14,829,830],{},"这份状态文档既是 agent 团队的协作界面，也是人类审查时的速查表。",[10,832,833],{"id":833},"数字与成本",[14,835,836],{},"一些客观数据：",[51,838,839,849],{},[54,840,841],{},[57,842,843,846],{},[60,844,845],{},"指标",[60,847,848],{},"数值",[70,850,851,859,867,875,883,891,899,907,915,923,931,939,947],{},[57,852,853,856],{},[75,854,855],{},"总 Rust 代码量",[75,857,858],{},"31,178 行（117 个源文件）",[57,860,861,864],{},[75,862,863],{},"Workspace crate 数",[75,865,866],{},"11",[57,868,869,872],{},[75,870,871],{},"最大 crate",[75,873,874],{},"mihomo-proxy（9,797 行，27 文件）",[57,876,877,880],{},[75,878,879],{},"Git commits",[75,881,882],{},"106",[57,884,885,888],{},[75,886,887],{},"Claude 直接 commit",[75,889,890],{},"10",[57,892,893,896],{},[75,894,895],{},"Spec 文档",[75,897,898],{},"40 份（最大 695 行）",[57,900,901,904],{},[75,902,903],{},"ADR",[75,905,906],{},"2 份",[57,908,909,912],{},[75,910,911],{},"测试函数",[75,913,914],{},"619 个（408 同步 + 211 异步）",[57,916,917,920],{},[75,918,919],{},"集成测试套件",[75,921,922],{},"24 个",[57,924,925,928],{},[75,926,927],{},"CI jobs",[75,929,930],{},"5（lint、test、tproxy、msrv、macos）",[57,932,933,936],{},[75,934,935],{},"Cargo 依赖",[75,937,938],{},"375 个",[57,940,941,944],{},[75,942,943],{},"开发跨度",[75,945,946],{},"~4 周（2026-02-21 至 2026-04-12）",[57,948,949,952],{},[75,950,951],{},"单日最高 commit",[75,953,954],{},"27（2026-04-08，M0 sweep + 6 specs）",[14,956,957],{},"Claude 直接 commit 只有 10 个（主要是 CI 修复和 simple-obfs 插件），并不意味着 Claude 只贡献了 10 个 commit 的工作量。大部分 commit 的作者是我，但代码是在 Claude Code 会话中协作完成的——我审查、修改、然后以自己的名义提交。Claude 的贡献更多体现在：编写 spec、生成代码初稿、执行重构、维护文档。",[10,959,961],{"id":960},"总结什么时候值得用-agent-team","总结：什么时候值得用 Agent Team",[14,963,964],{},"Agent Team 不是银弹。以下场景值得使用：",[178,966,967,973,979,985],{},[181,968,969,972],{},[78,970,971],{},"项目规模大到一个上下文窗口装不下。"," mihomo-rust 有 11 个 crate、31K 行代码、40 份文档。单个 agent 无法同时 hold 住全局架构和局部实现细节",[181,974,975,978],{},[78,976,977],{},"需要不同层次的决策。"," 架构决策（用不用 tonic）、项目管理决策（M1 先做什么）、实现决策（这个 struct 的字段类型）需要不同的思维模式",[181,980,981,984],{},[78,982,983],{},"有明确的文档驱动流程。"," Agent team 的协作基于文件系统——如果你的团队没有写 spec 的习惯，agent team 的效率会大打折扣",[181,986,987,990],{},[78,988,989],{},"需要在里程碑之间保持一致性。"," Memory 系统和文档保证了跨会话的知识不丢失",[14,992,993],{},"不值得使用的场景：",[178,995,996,999,1002],{},[181,997,998],{},"小型项目（\u003C 5K 行），单个 agent 足够",[181,1000,1001],{},"探索性原型开发，结构化流程是负担",[181,1003,1004],{},"没有测试基础设施的项目——你无法验证 agent 产出的质量",[14,1006,1007],{},"Claude Code 改变的不是 \"AI 能不能写代码\" 这个问题，而是 \"AI 写的代码能不能被工程化地验证和集成\"。Agent Team + CLAUDE.md + Memory + Spec 驱动开发构成了一个完整的 harness，让 AI 辅助从 \"试试看能不能跑\" 变成了一个可重复、可审查、可扩展的工程流程。",[1009,1010,1011],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":163,"searchDepth":307,"depth":307,"links":1013},[1014,1015,1019,1022,1025,1030,1031,1032,1039,1040],{"id":12,"depth":307,"text":12},{"id":45,"depth":307,"text":46,"children":1016},[1017,1018],{"id":135,"depth":313,"text":135},{"id":144,"depth":313,"text":144},{"id":173,"depth":307,"text":173,"children":1020},[1021],{"id":220,"depth":313,"text":221},{"id":282,"depth":307,"text":283,"children":1023},[1024],{"id":420,"depth":313,"text":421},{"id":442,"depth":307,"text":443,"children":1026},[1027,1028,1029],{"id":456,"depth":313,"text":457},{"id":473,"depth":313,"text":474},{"id":490,"depth":313,"text":491},{"id":503,"depth":307,"text":504},{"id":630,"depth":307,"text":631},{"id":688,"depth":307,"text":689,"children":1033},[1034,1035,1036,1037,1038],{"id":692,"depth":313,"text":693},{"id":710,"depth":313,"text":711},{"id":744,"depth":313,"text":745},{"id":772,"depth":313,"text":773},{"id":811,"depth":313,"text":812},{"id":833,"depth":307,"text":833},{"id":960,"depth":307,"text":961},null,"2026-04-12T00:00:00.000Z","以 mihomo（Clash Meta）代理内核的 Rust 移植为案例，分享使用 Claude Code Agent Team 进行大型项目移植的完整实践——从角色分工、里程碑规划到 CLAUDE.md 与 Memory 系统的效率调优。","md",{},"/posts/porting-mihomo-to-rust-with-claude",{"title":5,"description":1043},"posts/porting-mihomo-to-rust-with-claude","cFAnZlD_-H0HXqOKHnZIOZ-jyi0J4OUEs7Lr7Jrm8H0",1775989669346]