把一門編程語言整套換掉,這種事放在過去,基本等於給公司立一個兩年起步的軍令狀。工程師們談之色變,預算委員會聞風喪膽,代碼庫卻年復一年卡在原地動彈不得。Anthropic在7月16日甩出一篇文章,直接把這筆舊賬翻了篇:過去一個月裏,他們內部的開發者用Claude Fable5、Opus4.8和動態工作流,把10個代碼包、每個數萬到數十萬行的規模,乾淨利落地搬到了新語言上。這不再是將來時態的設想,而是已經發生在他們自己身上的事實。
最刺眼的兩個案例像兩顆釘子,把想象釘成了現實。Bun的聯合創始人Jarred Sumner,用Claude Code把整個Bun從Zig遷移到了Rust,不到兩週產出一百萬行代碼,合併進主幹前整條CI測試鏈100%通過,合併後浮出19個迴歸,如今已全部修掉,Rust版本6月就已經隨Claude Code發佈。另一邊,Anthropic Labs的聯合負責人Mike Krieger,一個週末就把一套Python代碼庫搬成了16.5萬行TypeScript,裏面塞了數百個代理、8道階段閘門、3輪對抗審查,最後還用一套奇偶校驗,把每條命令的輸出和Python原版逐字比對。

Anthropic把這整套打法提煉成一句話,也是全文最鋒利的那把刀:你修的不是代碼,而是生產代碼的那個流程(循環)本身。一旦想通這一點,那些被無限期擱置的遷移項目,就不再是不可觸碰的禁區。
先說清楚什麼時候該動、爲什麼動,因爲這件事的前提早就變了。團隊啓動遷移,通常是因爲項目誕生時的技術地形,和今天已經對不上號:要麼當初那個心知肚明的權衡終於卡住了脖子,要麼出現了更好的路,要麼原來的生態正在萎縮。Jarred當初選Zig,圖的是C級別的性能加上極致的簡單,特別適合一個創始人在奧克蘭狹小的公寓裏、大模型還沒出現的年代,用一年時間把Bun寫出來。那份簡單是有代價的,他後來專門寫過文章坦白。
快進到2026年,Bun的命令行工具月下載量已經突破一千萬,在Claude Code內部也被大規模使用。就在上季度,這些代價還不足以讓人凍結路線圖、押上幾個季度的資源去做一件大事。遷移語言確實能換來更小、更快、更安全的系統,可沒人有動力去付這筆賬。工程師們還得掂量其中的職業風險:你可能並行維護兩套代碼好幾年,最後只換來90%的等價,那比一開始就別動還頭疼。
現在不一樣了。最壞的結果無非是刪掉那條分支,重頭再來。當然,商業賬還是要算的。一百萬行級別的遷移,雖然不必再像四年項目那樣燒掉三四百萬美元的工程師資源,但落地依舊要花數萬到數十萬美元往上。Bun那次遷移吞掉了59億個未緩存的輸入token和6.9億個輸出token,按API定價約合16.5萬美元;Mike主遷移那塊也燒了2700萬token。真正讓Mike下決心動手的,是編譯這道坎。他團隊的內部工具以單個二進制文件交付用戶,用Python工具鏈爲每個平臺編譯要花大約八分鐘,整個構建矩陣一輪下來得等三十分鐘。搬完之後,同樣的編譯只要兩秒,二進制啓動速度快了6倍,還順手淘汰了一條獨立的部署管線。
爲什麼AI能把這道舊賬算平?因爲大規模代碼遷移恰好是這些高級模型的天選場景。活兒是天然並行的,文件、crate這種成百上千的獨立單元,可以讓代理同時開幹,誰也不用等誰。上下文既清晰又完整,舊代碼本身就是給模型最好的規格說明書,也是翻譯代理照着走的指南藍本。更妙的是自帶裁判,大型代碼庫裏往往躺着一套測試套件,代理能用它來給自己打分,當驗證足夠客觀,模型可以盯着真相死磕好幾天,不需要人坐在旁邊判質量。隊列還會自己寫:編譯器或測試一掛,下一個要修的活兒就自動排上了。流程本身讓偏差無處藏身,審查員每一條發現都要引用背後的規則,於是一次違規變成一個待辦項,而不是悄悄分叉;某個代理撞上邊緣情況,修法就成了之後所有代理都要遵守的規則。下面兩個案例裏,Mike和Jarred都在關鍵步驟用上了Fable,尤其是一種顧問模式,讓多個不同檔位的模型分工,把token消耗壓到最低。
真正能複用的,是他們總結出的六步法,從這兩場遷移裏熬出來,又做了泛化,能套到多種語言和場景上。
開工前得先備好一個鐵面無私的裁判,否則你既不知道何時收工,也沒法衡量成敗。這個裁判必須能站在同一標準上同時評判原代碼和目標代碼。用原語言寫的測試套件,往往依賴目標代碼里根本不存在的內部函數。要把它造出來,先用Claude把現有測試分個類,哪些是能用外部調用表達的,哪些依賴搬不過去的內部實現;再把面向外部的測試改寫成能同時跑在原始代碼和移植版上的斷言,並派對抗代理去驗證改寫沒有削弱斷言力度;最後拿原始代碼跑一遍確認它能過,再拿故意改壞的代碼跑一遍確認它會掛,一個抓不出破損的裁判,算不上裁判。Mike那次Python轉TypeScript,就造了一個覆蓋7個真實場景的奇偶校驗臺,任何行爲變動都算要修的bug。
第一步是立規矩、畫依賴圖、列缺口清單,給整場遷移打下地基。順序有講究:規則手冊必須排在缺口清單前面,因爲缺口正是由規則手冊的默認項覆蓋不到的地方定義的,兩者還要在聯合審計裏一起接受檢驗。規則手冊長什麼樣,取決於你一開始做的核心架構決定:新代碼是沿用老結構,還是徹底重做。沿用結構(Jarred那路),手冊主要就是一張張把類型和慣用法在兩種語言間翻譯的查表,遇到難翻的組件再指向缺口清單;徹底重做(Mike那路),手冊就是一份設計文檔。Jarred是跟Claude聊出來的,給每個含糊地帶立一條政策,還專門派了8個子代理,各盯一類他自己憑直覺列出的常見失敗模式。依賴圖要摸清文件間的依賴,才能把活兒有效地切成並行流,知道哪些先搬、哪些要打包在一起。有些語言和代碼庫自帶清單文件,這事不難,但面對C/C++、Python這類老代碼,依賴得自己探出來、畫出來,Claude Code能派出代理跑一個確定性腳本把圖生成。缺口清單記的是新舊語言之間的硬差距:Zig轉Rust,差在手動內存管理,一個忘了釋放的緩衝區,編譯能過,漏不漏只有運行時才知道;Python轉TypeScript,差在接口和契約,Python不要求聲明對象長什麼樣,TypeScript卻要白紙黑字寫下來才肯編譯。Jarred和Mike都把這些隱性知識記進了缺口清單文件,Jarred是前期就盤清楚,Mike是先翻再補,你可能兩頭都得做。
第二步壓一壓規則,來一場迷你遷移當試航。Jarred派了一個代理照手冊翻三個文件,一個代理像資深Rust工程師那樣翻三個,再一個代理拿着兩份差異去提煉新規則。就在這個階段,他逮住了兩個致命問題,要是等攤到全部1448個文件上再爆,麻煩就大了。這套壓力測試只對結構保持型遷移有效,因爲同一份文件的兩版翻譯能逐行比。要是你的手冊是重設計,像Mike那樣,等價做法是直接拿對抗審查員去炮轟設計文檔,再用一次可丟棄的端到端跑通來驗證。無論如何,翻出來的文件全部扔掉,這一步的目的只是把規則磨利,不是攢進度。
第三步翻譯一切,剩下的步驟都跑同一套多代理循環:實現、審查、修復。實現這種苦力活能甩給小模型,審查留給大塊頭,Mike鋪開12個子代理時用的就是Claude Sonnet。任務隊列要機械到無聊:一個批處理腳本看翻譯後的文件在不在磁盤上,來決定哪些算完工,再把待辦切片丟給實現代理;因爲隊列每次都從磁盤重建,遷移天生就能斷點續跑。代理有時候會過於謹慎、幹得太少,解法就是一條幹脆利落、帶着上下文的指令,提醒它下一步編譯器會替它抓錯。翻譯器沒把握的活兒,標上一行// TODO(port): 原因,留給第四步。從這兒往後,待辦清單自己會寫:編譯器數出錯,冒煙測試逮住崩潰,測試套件報出失敗。兩個對抗審查員用各自的上下文給實現者的活兒打分,兩者意見相左就交給第三個代理。當一個審查員在多個文件裏反覆抓到同一種錯,修法不是逐文件打補丁,而是在規則手冊里加一句話,把受影響的批次重新生成。這一步裏手冊不斷變厚,代碼卻從不被手工對着它改。還有一個關鍵設計決定是編譯器放在哪:Mike把TypeScript編譯器塞進了每一個循環,因爲它幾秒就能查一個單元;Jarred則把編譯器徹底擋在循環外、推遲到下一步,因爲cargo要跑好幾分鐘。
第四、五、六步合在一起說,因爲它們共用同一套循環,且越往後越不需要人的判斷。第四步編譯,取決於語言和規模,它常常融進第三步。Jarred用一個編排腳本在整個工作區調一次編譯器,修復代理再並行掃着錯誤清單幹,對抗審查同步進行,構建重跑,如此往復。翻錯誤清單能幫你抓出系統性的毛病,比如Jarred修完Zig寬鬆編譯所容忍的循環依賴後,冒出幾千個Rust模塊錯誤,他給循環加了一段邏輯來分類該刪、該挪、還是該重構邊界,纔算壓住。第五步和編譯器錯誤清單一樣有機械真相來源:冒煙測試吐出的崩潰,修法依舊是按根因歸類、交給對抗子代理審。第六步,也就是故事的尾聲,是拿兩套代碼庫的行爲逐項比對。文件翻譯完、編譯完、冒煙完,就把它切碎,把預備階段那份測試套件套上去跑,失敗的交給修復代理對着兩套代碼審,對抗審查員再查它們的修法。循環再往後是一道構建守護進程,它是唯一被允許重建二進制的角色,修復代理只寫補丁,守護進程把它們攢批、重建一次、重跑受影響的測試、再把結果喂回來,把最貴的操作串行化,免得一羣代理各自觸發。當同一個失敗在大量測試裏反覆出現,修法要往上游走:改掉生出這個bug的規則,只重新生成它碰過的文件。Mike這招尤其值得記:很多開發者手頭沒有現成或移植好的測試套件,他讓Claude寫了個小腳本,拿7個真實場景同時跑新移植版和Python原版,比輸出差異,每個掛掉的場景配一個修復代理,循環跑到7個全過。他還更進一步,讓Claude自己設計了端到端測試套件,通宵自主運行,哪裏崩就修哪裏,連跑四個晚上,逮住了任何場景清單都預測不到的那些細小的傷。
這套打法跑下來,有幾條實踐在每個項目上都站得住,但Anthropic也提醒,別盲信這份指南,每場遷移都不一樣,把它當起點,先跟Claude把你那場的具體方案聊清楚再動手。別盯着單點失敗,那是循環的活兒,修復代理會替你把它們磨平,你的注意力該放在規律上。讓審查保持對抗、讓驗證保持機械,對抗審查能撐起更長的任務,多花的那點token往往值;讓編譯器、差異比對、測試套件這些腳本去當裁判。別什麼事都上最大模型,token開銷集中在你的循環裏,要刻意設計,小模型扛得住高吞吐的實現鋪開,把最大的模型留給審查員,以及任何寫規則手冊、要被其他代理照着走的人。把人的工時前置,規則手冊和壓力測試最耗時間,之後基本就是隊列在燒。讓任務隊列機械且可續跑,完工的定義就是輸出文件已經躺在磁盤上。
回到結果本身,而不是代碼細節。Jarred的Bun遷移已經上線生產,當然任何遷移都有取捨,大約4%的Rust代碼待在unsafe塊裏,主要是C/C++邊界上那些單行指針操作。但新代碼庫是肉眼可見地更好:團隊工具能偵測到的內存泄漏全修乾淨了,一個重複構建2000次的基準測試,內存佔用從6745兆字節掉到609兆;二進制在Linux和Windows上小了19%;跨語言優化讓它在HTTP服務和next build、tsc這類真實負載上快了2%到5%。
那些你一直忍着沒動、將就着用的代碼庫,也許是時候重新算算這筆賬了。挑出那個你容忍最久的傢伙,問問Claude,爲它做一場遷移到底長什麼樣。
