实战抄作业:使用 Claude Code 将 10 万行 TypeScript 代码移植到 Rust

简介: 本文记录作者仅用Claude Code,在一个月内将10万行TypeScript(实为JavaScript)的宝可梦对战引擎Pokemon Showdown完整移植至Rust的全过程。通过巧妙绕过沙箱限制、设计结构化提示、分块处理、自动化交互与端到端测试,最终实现功能完全一致、性能显著提升的Rust版本,提交5000次,零手写代码。(239字)

一个月内使用 Claude Code 将 10 万行 TypeScript 代码移植到 Rust

我读到一篇题为“我们的战略是将人工智能算法结合起来,重写微软最大的代码库(从 C++ 到 Rust)。我们的目标是‘1 名工程师,1 个月,100 万行代码’”的文章,这让我很好奇,这到底有多难?

在观看了很多WolfeyVGC 的视频,并关注了 NeurIPS 的PokéAgent 挑战赛之后,我一直很想开发一个具有竞争力的宝可梦对战 AI。幸运的是,有一个名为“ Pokemon Showdown ”的开源项目实现了所有规则,但它是用 JavaScript 编写的,在训练循环中运行速度相当慢。因此,我的假期项目诞生了:让我们用 Claude 将其转换为 Rust!

逃离沙盒

让AI能够在你的机器上运行任意代码是很危险的,所以设置了很多安全措施。但是……与此同时,这正是我在这种情况下想要做的。那么,让我来逐步介绍一下我是如何逃出各种沙箱的。

git push

Claude 运行在一个沙箱环境中,限制了一些操作,例如 SSH 访问。你需要 SSH 访问权限才能发布到 GitHub。这一点非常重要,因为我希望能够在进行其他活动的同时,通过手机查看 AI 的运行情况。
img
我发现我可以在自己的终端运行代码,但 Claude 无法在它自己的终端中运行。所以我让 Claude 编写一个 Node.js 脚本,该脚本会在本地端口上打开一个 HTTP 服务器,并执行 URL 中的 Git 命令。现在我只需要在我的终端上保持一个标签页打开,并运行这个服务器,然后让 Claude 在 Claude.md 文件中编写指令,使其能够与该服务器交互。

rustc

我的电脑上装了一个杀毒软件,运行未知二进制文件时需要人工干预。但由于每次编译都会生成一个新的未知二进制文件,所以这种方法行不通。

我发现,我可以搭建一个本地 Docker 实例,然后在 Docker 容器内编译并运行代码,这样就不会触发杀毒软件。我再次请 Claude 在 Claude.md 文件中生成正确的操作说明,问题就解决了。

下一个难题是如何让 Claude 在没有任何人为干预的情况下连续工作数小时。

可行

Claude 总是请求执行某些操作的权限。我尝试在允许的命令文件中添加了很多命令,但--allow-dangerously-skip-permissions --dangerously-skip-permissions在我的环境中被禁用了(现在已经解决了)。

我发现我可以在另一个标签页运行一个 AppleScript 脚本,每隔几秒就自动按下回车键。这样一来,Claude提出的每个要求都会被我回答“是”。目前为止,它还没试图入侵我的电脑……

#!/bin/bash

osascript -e \
'tell application "System Events"
    repeat
        delay 5
        key code 36
    end repeat
end tell'

永不放弃

Claude工作一段时间后,似乎总会停下来回顾一下事情。我尝试过阻止他这样做,甚至威胁他,但都无济于事。
img
我尝试使用拉尔夫·维格姆循环(Ralph Wiggum loop),但没能成功,而且显然我不是唯一遇到这个问题的人。

最终奏效的方法是,将我想要执行的任务复制到剪贴板,然后修改上面的脚本,使其在按下回车键后执行“cmd-v”组合键。这样,如果系统询问问题,就会执行“回车”操作;如果没有询问,则会将提示信息排队,以便在 Claude 交还控制权时显示。

自动更新

电脑上有些程序,比如软件更新程序,会抢占终端窗口的焦点,例如显示一个模态窗口。一旦发生这种情况,cmd-v / Enter 指令就不会再发送到终端,程序执行也会停止。
img
我用了以前玩 Minecraft 时 MurGaa 开发的可靠的自动点击器,每隔几秒模拟一次鼠标左键点击。我把终端和鼠标都放在屏幕边缘,这样当窗口中间出现模态框时,终端就能正确地重新获得焦点。

它还能防止电脑进入睡眠状态,这样即使我不使用笔记本电脑或晚上它也能运行。

漏洞

长时间运行的可靠性至关重要。总体来说,运行相当顺利,但有几个晚上我遇到了这个特定的错误,导致程序停止运行。我希望他们能查明原因并解决问题,因为我不是唯一一个报告此问题的人!
img
目前的配置远非最佳,但到目前为止还能用。希望将来能得到优化!

移植宝可梦(Pokemon)

一击(One Shot)

一开始,我只是简单地请 Claude 移植代码库,并确保逐行完成。起初,这感觉非常震撼,它生成了数千行可以编译的 Rust 代码。

可惜的是,它只是徒有其表,因为其中走了许多捷径。例如,它在两个不同的文件中分别创建了两种不同的移动结构,以便它们可以独立编译,但集成在一起时却无法正常工作。它对所有函数的移植都非常粗糙,任何稍微复杂一点的功能都不会移植,而是被“简化”了。

我当时还没意识到,我让循环运行起来是为了让它移植越来越多的代码。问题在于它到处创建了错误的抽象,并且不断添加硬编码代码来修复它本应修复的问题。这样做根本行不通。

赋予它结构(Giving it structure)

这时我意识到,我需要更明确地定义我想要的结果。退一步讲,最终目标应该是每个 JavaScript 文件及其中的每个方法都有一个对应的 Rust 代码。

所以我请 Claude 编写一个脚本,该脚本会获取 JavaScript 代码库中的所有文件和方法,并在 Rust 代码库中,在 Rust 方法旁边,添加与 JavaScript 源代码对应的注释。

编写脚本至关重要,因为即使直接复制粘贴代码,它也会错误地转换 JavaScript 代码。确定性大大提高了获得正确结果的概率。
img

小岛(Litte Islands)

下一个挑战是,原始文件有数千行,加上源代码注释,文件长度翻倍,超过一万行。这导致上下文窗口出现大量问题,Claude 直接拒绝打开文件。因此,它开始分块读取文件,但精度很低。此外,上下文增长速度也快了很多,压缩也变得更加频繁。

所以我把 Rust 版本中的每个方法都拆分到了单独的文件中。这显著提升了性能。为了达到最佳效率,我也需要对 JavaScript 代码库进行同样的操作,但我担心这样做会意外地改变代码行为,所以最终决定不做。
img

清理

移植过程分为两个重复阶段。我会给Claude布置一个大任务,让他循环处理一整天,然后我需要花时间清理出错的地方。

清理代码时,我仍然使用 Claude,但给出了更多具体的建议。例如,我注意到,即使明确告诉它不要这样做,如果不加勾选,它也会把动作/技能/物品的行为硬编码到代码的各个角落。所以我手动查找所有这些硬编码,并告诉它把它们移动到正确的位置。

这时工程技能就派上用场了,我所有的软件开发经验让我能够找出问题所在并解决它。好在清理工作不用我亲自做,Claude在指导下就能做得很好。

集成

在测试之前构建所有内容

到目前为止,我只是确保代码能够编译,但从未真正将所有部分整合起来以确保它能够正常运行。Claude真正想要的是一种传统的软件开发策略,即先实现所有组件的“简单”版本,然后随着时间的推移逐步完善。

但就我们而言,宝可梦对战游戏(Pokemon Showdown)的代码库已经迭代了十年之久。试图重新学习所有这些经验教训是适得其反的,而且不太可能得出相同的结果。更好的做法是一次性移植所有内容,然后在最后进行一次集成。

我是在开发编译器 Skip 的过程中学到这种策略的。多年来,所有构建模块都是独立开发的,最后才把它们整合起来,一开始什么都没看到。但一个月后,一切都运行正常了。我当时非常震惊。

端到端测试

大部分代码库移植完成后,我开始将它们整合起来。好消息是,我们可以用 JavaScript 和 Rust 运行和编辑代码,而且输入/输出非常简单且标准化:一个包含宝可梦及其选项(招式、道具、性格、个体值/努力值分配等)的列表,以及每一步的操作列表(招式和切换)。给定相同的随机序列,状态的推进方式也相同。

现在我可以让Claude生成这个测试框架,并逐一排查所有问题。令人印象深刻的是,它能够找出所有问题并修复它们。
img
在三周的时间里,它平均每20分钟左右就能修复一个问题。它自行修复了数百个问题。我从未干预过,它修复遇到的所有问题只是时间问题。

赋予它结构

一开始,这个过程极其缓慢。每次进行代码压缩时,Claude都会“犯傻”,重新发明轮子,在此过程中编写了大量的 Markdown 文件和测试脚本。或者,Claude会选择走捷径,直接生成大量的测试用例,但从未让它们与 JavaScript 代码匹配。

于是,我开始研究它的优点并将其编码。例如,它在伪随机数生成器 (PRNG) 的各个步骤中添加了大量的调试信息,包括每个步骤发生的具体操作以及所有调试元数据。所以我让它创建一个测试脚本,用于打印单个步骤的这些信息以及堆栈跟踪。然后将指令添加到 Claude.md 文件中。这样,所有审查都能立即展开。

漫长的跋涉

我利用现有的随机数生成器来生成战斗,并且可以输入一个数字作为种子。这使我能够生成规模不断增大且稳定性更高的战斗。

我先修复了前100场战斗,然后是1000场、1万场、10万场,现在我已经快要解决前240万场战斗的所有问题了!我不确定还有多少问题,但好消息是,随着批次大小的增加,问题越来越少。
img

问题类型

修复的问题大致分为两类。第一类问题不出所料,Rust 与 JavaScript 的限制不同,这些限制需要考虑,并且会导致 bug:

  • Rust 有一个“借用检查器”,它规定可变变量不能同时在两个不同的上下文中传递。问题在于“Pokemon”和“Battle”互相引用。因此,有很多变通方法,例如复制、传递索引而不是对象本身、提供以可变对象作为参数的回调函数等等。
  • JavaScript 代码库大量使用了动态特性,某些函数会返回空字符串、undefined、null、0、1、5.2、Pokemon 等值,这些值都对应着不同的处理方式。最初,Rust 移植版本使用 Option<> 来处理其中许多值,但后来改用结构体来处理所有这些变体。
  • Rust 不支持可选参数,因此每个参数都必须逐字逐句地写出来。

但第二个问题完全是他自己的原因……Claude Code就像一个聪明的学生,总是想方设法逃避艰苦的工作,如果他认为可以蒙混过关,就会选择走捷径。

  • 如果修复需要更改一两个以上的文件,这将是一个“重要的基础架构”,除非明确要求,否则 Claude Code 将拒绝执行此操作,并且会采取任何可能的变通方法来使特定测试正常工作。
  • 同样,它也会实现一些“简化版”的功能。对于某些方法,与其尝试修复它之前创建的所有代码,不如直接删除所有内容并让它从头开始移植。
  • JavaScript 注释理应是权威来源。但如果 Claude 认为修改原始代码是解决问题的办法,他也会毫不犹豫地这么做。
  • 如果给定一个任务列表,它会尽量避免执行那些看起来困难的任务,直到迫不得已才会去做。如果不加注意,这种做法效率低下,因为它会不断花费时间进行审查,然后跳过所有“困难”的任务。压缩本质上就是清除它的所有内存。

提示词

在这个项目中,我一行代码都没写。我白天和 Claude 进行互动式的“合作”开发,晚上则创建任务让它运行,两种方式交替进行。本节我将重点介绍夜间运行的任务。

转换(Conversion)

项目第一阶段,我主要使用了这个程序的各种变体。我让它逐个处理所有的大文件,并忠实地执行它们(正如我们后来看到的,它并没有真正按照指令执行……)。

打开 BATTLE_TODO.md 获取 battle*.rs 中所有方法的列表。
仔细检查每一个代码,确保它们是对 JavaScript 文件中代码的直接翻译。如果存在同名方法,JavaScript 定义会写在注释中。
如果没有 JavaScript 定义,请质疑该方法是否应该出现在 Rust 版本中。我们的目标是尽可能贴近 JavaScript 版本,以避免任何翻译错误。如果您发现实现不匹配,请进行必要的重构,使其完全一致。

这将是一个复杂的项目。你需要按顺序逐一完成所有方法。你不能因为某个方法太难或者需要构建新的基础设施就跳过它。我们会用循环调用它,所以你需要花足够的时间来构建合适的基础设施,使其与对应的 JavaScript 代码完全一致。不要放弃。
更新 BATTLE_TODO.md 文件,并在完成每个工作单元后执行 git commit 命令。

Todos

Claude Code在逐个移植方法时,经常会编写一个“简化版”或添加一个“待办事项”以备后用。我也发现,在生成工作任务时,通过TODO注释将说明直接添加到代码库中非常有用,这样我就不必祈祷它能被从上下文中读取出来。

实际上,主 md 文件并没有起到应有的作用,它很快就变得过于庞大而无法使用,而且 Claude 还创建了一大堆文件,导致代码库里到处都是。因此,我提供了一种确定性的方法来遍历这些文件,即在代码库中调用 grep 命令,这样它就知道何时查找它们了。

我们希望修复代码库中的所有待办事项。pokemon-showdown-rs/ 中的TODOsimplif
题目有数百道,所以请认真逐一完成。即使题目很难也不要跳过。我会反复提醒大家注意,所以不用担心在一道题目上花费太多时间。
移植必须完全一一对应。如果基础设施不存在,请自行搭建。请勿自行发明任何内容。
确保每次添加后都能编译通过,然后提交并推送到 git。

不知何时,上下文被破坏了,原本的 JavaScript 代码库中有一个 TODO 语句,它被修改成了其他更合理的内容。但之后所有后续的 TODO 语句也都发生了同样的情况,导致它们变得不合理……幸好我可以撤销所有这些提交。

Fixing

我在 Claude.md 文件中编写了所有调试指令,并编写了一个脚本来运行所有测试,该脚本会输出一个包含进度报告的 txt 文件。这样,Claude 就能持续不断地修复各种问题。

我们需要修复战斗中所有不一致的地方。请查看 500-seeds-results.txt 文件,并逐一修复。唯一的修复方法是确保 JavaScript 和 Rust 之间的差异是由语言差异而非逻辑差异造成的。两行代码之间的每一行都必须完全匹配。如果您修复了某个具体问题,那很可能是一个更大的问题,请花时间找出其他类似问题,并着手进行更全面的基础架构修复。每次添加代码后,请确保代码仍然可以编译,然后提交并推送到 Git。检查代码库中是否存在其他部分也存在此错误。

将这个 txt 文件差异提交到 GitHub 上真的很有用,可以随时了解进度!

结语

Claude Code有用

在开始这个项目之前,我并不知道会是什么结果。通常这类项目都会因为需要投入大量精力才能接近完成而夭折。但这次不一样!

我们已完整实现了宝可梦对战系统,其效果与现有的 JavaScript 代码库*完全相同。这项工作历时 4 周,提交了 5000 次,Rust 代码库约有 10 万行代码。

我希望没有分歧,但目前在前240万个种子中出现了80个分歧,占比0.003%。我需要运行更长时间才能解决这些问题。

它速度快吗?

这个项目的全部意义就在于使其速度比最初的 JavaScript 实现更快。直到项目接近尾声,我们已经成功运行了相当数量的战斗后,我才觉得是时候进行性能比较了。

我请 Claude Code 对这两个实现进行并行化,结果让我松了一口气,Rust 移植版实际上速度快得多,我没有白费这些时间!


我曾尝试让 Claude 进一步优化它,它创建了一个看起来很合理的计划(我这辈子都没接触过 Rust),并且花了一整天的时间构建了许多优化,但最终,这些优化都没有真正改善运行时间,有些甚至让情况变得更糟。

这很好地说明了经验和专业知识对于充分发挥LLM的作用仍然至关重要。

结论

这简直太不可思议了,我竟然在短短两周内,独自一人将一个约 10 万行的 JavaScript 代码库移植到了 Rust,而且 Claude Code 还 24 小时不间断运行了一个月,提交了 5000 次!我之前从未写过一行 Rust 代码。

基于LLM的编码代理对于工程师来说真是个很棒的新工具,如果没有Claude Code,我根本不可能做到。话虽如此,这种工具仍让我感觉需要我具备专业的工程技术知识,并且需要我持续进行监控才能获得这样的效果。

很遗憾我没能完成宝可梦对战AI的开发,而且寒假也结束了,所以如果有人想做的话,请尽情使用代码库吧

Porting 100k lines from TypeScript to Rust using Claude Code in a month

https://blog.vjeux.com/2026/analysis/porting-100k-lines-from-typescript-to-rust-using-claude-code-in-a-month.html

相关文章
|
5天前
|
人工智能 API 开发者
Claude Code 国内保姆级使用指南:实测 GLM-4.7 与 Claude Opus 4.5 全方案解
Claude Code是Anthropic推出的编程AI代理工具。2026年国内开发者可通过配置`ANTHROPIC_BASE_URL`实现本地化接入:①极速平替——用Qwen Code v0.5.0或GLM-4.7,毫秒响应,适合日常编码;②满血原版——经灵芽API中转调用Claude Opus 4.5,胜任复杂架构与深度推理。
|
9天前
|
JSON API 数据格式
OpenCode入门使用教程
本教程介绍如何通过安装OpenCode并配置Canopy Wave API来使用开源模型。首先全局安装OpenCode,然后设置API密钥并创建配置文件,最后在控制台中连接模型并开始交互。
4138 8
|
15天前
|
人工智能 JavaScript Linux
【Claude Code 全攻略】终端AI编程助手从入门到进阶(2026最新版)
Claude Code是Anthropic推出的终端原生AI编程助手,支持40+语言、200k超长上下文,无需切换IDE即可实现代码生成、调试、项目导航与自动化任务。本文详解其安装配置、四大核心功能及进阶技巧,助你全面提升开发效率,搭配GitHub Copilot使用更佳。
|
16天前
|
存储 人工智能 自然语言处理
OpenSpec技术规范+实例应用
OpenSpec 是面向 AI 智能体的轻量级规范驱动开发框架,通过“提案-审查-实施-归档”工作流,解决 AI 编程中的需求偏移与不可预测性问题。它以机器可读的规范为“单一真相源”,将模糊提示转化为可落地的工程实践,助力开发者高效构建稳定、可审计的生产级系统,实现从“凭感觉聊天”到“按规范开发”的跃迁。
2484 18
|
1天前
|
人工智能 自然语言处理 Cloud Native
大模型应用落地实战:从Clawdbot到实在Agent,如何构建企业级自动化闭环?
2026年初,开源AI Agent Clawdbot爆火,以“自由意志”打破被动交互,寄生社交软件主动服务。它解决“听与说”,却缺“手与脚”:硅谷Manus走API原生路线,云端自主执行;中国实在Agent则用屏幕语义理解,在封闭系统中精准操作。三者协同,正构建AI真正干活的三位一体生态。
1958 6
|
9天前
|
人工智能 前端开发 Docker
Huobao Drama 开源短剧生成平台:从剧本到视频
Huobao Drama 是一个基于 Go + Vue3 的开源 AI 短剧自动化生成平台,支持剧本解析、角色与分镜生成、图生视频及剪辑合成,覆盖短剧生产全链路。内置角色管理、分镜设计、视频合成、任务追踪等功能,支持本地部署与多模型接入(如 OpenAI、Ollama、火山等),搭配 FFmpeg 实现高效视频处理,适用于短剧工作流验证与自建 AI 创作后台。
1292 5
|
1天前
|
人工智能 自然语言处理 Shell
🦞 如何在 Moltbot 配置阿里云百炼 API
本教程指导用户在开源AI助手Clawdbot中集成阿里云百炼API,涵盖安装Clawdbot、获取百炼API Key、配置环境变量与模型参数、验证调用等完整流程,支持Qwen3-max thinking (Qwen3-Max-2026-01-23)/Qwen - Plus等主流模型,助力本地化智能自动化。
🦞 如何在 Moltbot 配置阿里云百炼 API
|
2天前
|
人工智能 数据可视化 Serverless
国产之光:Dify何以成为国内Workflow Agent开发者的首选工具
随着 LLM 技术发展,将LLM从概念验证推向生产时面临诸多挑战,如复杂Prompt工程、长上下文管理、缺乏生产级运维工具及快速迭代难等。Dify旨在通过融合后端即服务(BaaS)和LLMOps理念,为开发者提供一站式、可视化、生产就绪的解决方案。
424 2
|
7天前
|
人工智能 运维 前端开发
Claude Code 30k+ star官方插件,小白也能写专业级代码
Superpowers是Claude Code官方插件,由核心开发者Jesse打造,上线3个月获3万star。它集成brainstorming、TDD、系统化调试等专业开发流程,让AI写代码更规范高效。开源免费,安装简单,实测显著提升开发质量与效率,值得开发者尝试。