ClaudeCode 你想知道的所有秘密,程式碼深度研究報告

最近 Claude Code 洩露了 map 文件,導致洩露了程式碼文件,於是我下載了 npm 包裡的 cli.js.map,從裡面提取出 4756 個程式碼文件,沿著入口、提示詞、工具、權限、Agent 調度、plugin、Hook 一路拆下去,我發現其實 Claude Code 的system prompt 只是冰山露出水面的一小塊。
這篇文章會把冰山下面的部分攤開。你不需要是做 Agent 產品的工程師,也能從裡面看到一套通用的系統設計思路。看完之後,你再去看市面上任何一個 AI Agent 產品,會比之前多一層判斷力。
一、大多數人對 Claude Code 的理解停在了表面
現在網路上流傳的 Claude Code 分析,大部分聚焦在兩件事:system prompt 寫了什麼,以及它呼叫了哪些工具。
這兩件事確實重要,但它們只是這個系統的皮膚。你拿到同樣的 prompt,接上同樣的工具,照著寫一遍,出來的東西和 Claude Code 的體驗差距會非常大。
差在哪?差在 prompt 背後有一整套編排機制,工具背後有一整條治理流水線,Agent 背後有一套分工和調度系統,生態擴展背後有一套讓模型"知道自己能幹什麼"的感知通道。
這些東西加在一起,才構成了你用 Claude Code 時感受到的那個"穩"。這個穩不是來自某段神奇文案,是來自工程。
二、程式碼結構第一眼:這不是 CLI 工具,這是一個執行平台
從 src/ 目錄的頂層看,Claude Code 至少有這些模組:入口層 entrypoints,常數與提示詞 constants,工具定義 tools,執行時服務 services,命令系統 commands,UI 元件 components,協調器 coordinator,記憶系統 memdir,plugin plugins,Hook 系統 hooks,狀態初始化 bootstrap,任務系統 tasks。
光看這個目錄結構就能感覺到,這不是一個"把 LLM 接到終端裡"的專案。
入口層更能說明問題。它有四個入口:CLI、初始化流程、MCP 模式、SDK。同一個 agent 執行時,可以服務四種不同的互動介面。這是平台化設計的標誌。
命令系統也不是點綴。它註冊了 /mcp、/memory、/permissions、/hooks、/plugin、/skills、/tasks、/plan、/review、/agents 等十幾個系統級命令。而且命令系統不只載入內建命令,還統一載入 plugin commands、skill commands、bundled skills、動態 skills。所以命令系統本身就是生態的入口。
你回頭想想,大部分開源 coding agent 的目錄長什麼樣。通常是一個 main 文件,一個 prompt 文件,幾個 tool 文件,一個 utils。Claude Code 的目錄結構跟它們完全不在一個量級。這個量級差異不是為了好看,是因為它要解決的問題本身就更多。
三、Prompt 不是一段話,是一台組裝機器
這可能是整個程式碼裡最反直覺的部分。
大多數人以為 system prompt 是一大段固定文本,啟動時塞進去就完了。Claude Code 完全不是這樣。它的 system prompt 是由一個叫 getSystemPrompt() 的函數動態拼裝出來的。
這個函數做的事,更像一個編排器。它先拼一組靜態模組,再根據當前會話狀態拼一組動態模組。
靜態部分包括:身份定位(getSimpleIntroSection)、系統規範(getSimpleSystemSection)、做任務的哲學(getSimpleDoingTasksSection)、風險動作規範(getActionsSection)、工具使用規範(getUsingYourToolsSection)、語氣風格(getSimpleToneAndStyleSection)、輸出效率(getOutputEfficiencySection)。
動態部分包括:session guidance、memory、環境資訊、語言設定、輸出風格、MCP instructions、scratchpad、function result clearing、summarize tool results、token budget、brief mode。
你可以這樣理解:靜態部分是這個 Agent 的"憲法",不管什麼會話都一樣。動態部分是"當期政策",根據你這次用的工具、連了哪些 MCP、用的什麼語言、開沒開 brief 模式來調整。
這裡面有一個設計特別精巧。程式碼裡有一個叫 SYSTEM_PROMPT_DYNAMIC_BOUNDARY 的標記,註釋裡寫得很清楚:邊界之前的文件盡量保持 cache 友好,邊界之後是使用者和會話特定的文件,不能亂改,否則會破壞快取。
這是什麼意思?這意味著 Anthropic 在管理 system prompt 的時候,已經在考慮 token 經濟學了。邊界之前的文件因為穩定,可以被 API 層快取,不用每次都重新計算。邊界之後的文件因為會變,所以放在後面,不影響前面的快取命中。
大部分人寫 prompt,根本不會想到這一層。但當你的產品每天要處理海量請求,每個 token 都有成本的時候,這種設計直接影響營運成本。
四、行為規範:Anthropic 怎麼訓一個 AI 工程師不亂來
Claude Code 有一個叫 getSimpleDoingTasksSection() 的模組,這個模組可能是整個系統裡最不起眼但最有用的部分。
它做的事很簡單:告訴模型什麼該做,什麼不該做。但它列得非常具體。
不要加使用者沒要求的功能。不要過度抽象。不要瞎重構。不要亂加註釋和文件字串。不要做不必要的錯誤處理和兜底邏輯。不要設計一堆面向未來的抽象。先讀程式碼再改程式碼。不要輕易建立新文件。不要給時間估計。方法失敗時先診斷原因再換策略。刪除確認沒用的東西,不搞相容性垃圾。結果要如實彙報,不能假裝自己測試過了。
如果你用過其他 coding agent,你一定遇到過這些問題:你讓它改一個 bug,它順手給你重構了半個文件。你讓它加一個功能,它給你加了三層抽象和五個你沒要的錯誤處理。你讓它測一下,它說"測試透過了",但其實它根本沒跑。
這些問題的根源不是模型笨,是模型的行為沒有被約束。Claude Code 解決這個問題的方式,不是靠更聰明的模型,是靠把行為規範寫成制度。
風險動作規範也是同樣的思路。getActionsSection() 定義了什麼叫"需要確認的風險動作":破壞性操作、難以回滾的操作、修改共享狀態、對外可見的動作、上傳到第三方工具。它還特別強調:不要用破壞性操作當捷徑,遇到陌生狀態先調查,merge conflict 和 lock file 不要粗暴刪除。
這種設計的思路是把 blast radius 意識編進系統。你不能指望一個 AI 在每次做決定時都自己想到"這個操作的爆炸半徑是多大"。但你可以在系統層面告訴它哪些操作需要停下來確認。
工具使用規範更具體。讀文件用 FileRead,不要用 cat/head/tail。改文件用 FileEdit,不要用 sed/awk。新建文件用 FileWrite,不要用 echo 重定向。搜尋文件用 Glob,搜尋內容用 Grep。Bash 只留給真正需要 shell 的場景。沒有依賴關係的工具呼叫要並行。
這不是在說"你有這些工具"。這是說"你必須用正確的方式使用這些工具"。Claude Code 用起來穩,和這套 tool usage grammar 關係很大。很多 agent 的不穩定,恰恰來自模型用錯了工具,比如用 bash sed 去改程式碼,一個正規表達式寫錯就崩了。
五、多 Agent 分工:為什麼一個人做不好所有事
程式碼裡確認了至少六個內建 Agent:General Purpose Agent、Explore Agent、Plan Agent、Verification Agent、Claude Code Guide Agent、Statusline Setup Agent。
這個設計選擇不是為了炫技。它背後有一個很清晰的判斷:讓一個 Agent 同時做研究、規劃、實現、驗證,最後每件事都做不扎實。
Explore Agent 被設計成純只讀模式。不能建立文件,不能修改文件,不能刪除文件,不能移動文件,不能寫臨時文件,不能用重定向寫文件,不能執行任何改變系統狀態的命令。它能用的工具只有 Glob、Grep、FileRead,Bash 也只允許 ls、git status、git log、git diff 這類讀操作。它被故意裁剪成了一個 read-only specialist。
為什麼要這麼做?因為探索階段如果不小心改了什麼東西,後面的實現階段就會出問題。把探索和實現的權限徹底隔離,是一種很樸素但很有效的安全設計。
Plan Agent 也是只讀。它的職責是理解需求、探索程式庫的模式和架構、輸出逐步實現計畫、列出關鍵實現文件。它被定義成 architect,不是 executor。規劃和實現分開的好處是,規劃階段可以專心想清楚怎麼做,不會因為急著寫程式碼而跳過思考。
六、Verification Agent:整個系統裡最值錢的設計
Verification Agent 的 prompt 在整個程式碼裡可能是寫得最狠的一個。
它的核心方向不是"確認實現看起來沒問題"。它的方向是 try to break it,想辦法搞壞它。
prompt 開頭就點出了兩類常見的驗證失敗模式。第一種叫 verification avoidance:只看程式碼不跑檢查,寫個 PASS 就走了。第二種叫被前 80% 迷惑:UI 看起來還行,測試也過了,就忽略剩下 20% 的問題。
然後 prompt 強制要求一系列驗證動作:跑 build,跑測試套件,跑 linter 和類型檢查。根據變更類型還有專項驗證。前端改動要跑瀏覽器自動化或驗證頁面子資源。後端改動要用 curl 或 fetch 實測回應。CLI 改動要看 stdout、stderr 和 exit code。資料庫遷移要測 up 和 down,還要測已有資料。重構也要測 public API surface 有沒有變化。
更狠的是,它要求做 adversarial probes,主動去找邊界情況和破綻。每個檢查必須帶實際執行的命令和觀察到的輸出。最後必須給出 VERDICT: PASS、FAIL 或 PARTIAL。
這個設計解決了 LLM 驗證工作中最常見的問題:"差不多就算了"。人類工程師做 code review 的時候也會犯這個毛病,但至少人有經驗累積和職業壓力。LLM 沒有這些,你不在 prompt 裡把驗證標準寫死,它真的會隨便看兩眼就說 PASS。
Claude Code 的做法是用 prompt 反制這種傾向。而且因為 Verification Agent 是獨立角色,它和"寫程式碼的那個 Agent"沒有利益關聯。寫程式碼的 Agent 可能會傾向於覺得自己寫得沒問題,但驗證 Agent 沒有這個偏見,它的工作就是找問題。
這種"實現者和驗證者分離"的思路,在傳統軟體工程裡是常識,但在 AI Agent 系統裡,大部分產品還沒做到這一步。
七、Agent 調度鏈:14 步 pipeline 不是過度設計
一個子 Agent 從被觸發到執行完成,在 Claude Code 裡要經過一條完整的 pipeline:
主模型決定呼叫 Agent 工具。AgentTool.call() 解析輸入。系統判斷這是 teammate、fork、built-in、background 還是 remote。選擇對應的 agent definition。建構 prompt messages。建構或繼承 system prompt。組裝工具池。建立 agent 專屬的 ToolUseContext。註冊 hooks、skills、MCP servers。呼叫 runAgent()。runAgent 內部再呼叫 query() 進入主循環。query 產出訊息流。runAgent 記錄 transcript,處理生命週期,清理資源。AgentTool 彙總結果或走非同步通知。
這 14 步看起來多,但每一步都在解決一個具體問題。
其中 fork 和 normal path 的區分很有意思。當你 fork 一個子任務時,它會繼承主執行緒的 system prompt 和完整對話上下文,工具集也盡量保持一致。為什麼?為了讓 API 請求的前綴保持位元組級一致,從而複用主執行緒的 prompt cache。
這個細節很容易被忽略,但它反映了一種思維方式的差異。普通人做子 Agent 調度,想的是"子任務能跑起來就行"。Claude Code 想的是"子任務能跑起來,而且盡量複用主執行緒的快取,不白燒 token"。
runAgent() 本身也不是簡單的 wrapper。它要初始化 agent 專屬的 MCP servers,過濾和克隆上下文訊息,處理文件狀態快取,對只讀 Agent 做內容瘦身,建構權限模式,組裝工具,註冊 frontmatter hooks,預載入 skills,建立中斷控制器,執行 SubagentStart hooks。執行完之後還要記錄 transcript,清理 MCP 連接、hooks、效能追蹤、todo、bash tasks 等資源。
這就是為什麼文章開頭說 Claude Code 更像一個執行平台。一個子 Agent 的啟動和關閉,涉及的狀態管理工作量,已經接近一個小型服務的生命週期管理了。
八、工具執行不是一步到位,是一條治理流水線
當模型決定呼叫一個工具時,Claude Code 不是直接執行對應的函數。實際鏈路是這樣的:
先找到對應的 tool definition。解析 MCP metadata。用 Zod schema 做輸入驗證。跑 tool 自己的 validateInput。如果是 Bash 命令,還要跑一個 speculative classifier check 來預判風險。然後執行 PreToolUse hooks。解析 hook 返回的權限結果。走正式的 permission 決策流程。根據 permission 決策可能再次修正輸入。到這裡才真正執行 tool.call()。執行完之後記錄 analytics、tracing 和 OTel。然後執行 PostToolUse hooks。處理結構化輸出。如果失敗了,還有 PostToolUseFailure hooks。
這條鏈路裡最有意思的是 Hook 系統。PreToolUse Hook 不只能記日誌,它能返回 message、blockingError、updatedInput、permissionBehavior、preventContinuation、stopReason、additionalContexts。也就是說 Hook 能改寫輸入,能直接放行或拒絕,能阻止後續流程,能補充上下文資訊。
但 Hook 的權力也不是無限的。resolveHookPermissionDecision() 這個函數定義了一個關鍵規則:Hook 說 allow,不一定能繞過系統設定裡的 deny/ask 規則。如果工具本身要求使用者互動,而 Hook 沒有提供替代輸入,仍然要走統一的權限流程。Hook 說 deny 則直接生效。
這個設計很成熟。Hook 有足夠的表達力來做執行時策略,但它不能繞開核心安全模型。強大但受控,這是工程成熟度的體現。
PostToolUse Hook 也不只是收尾工作。工具成功執行後,Hook 還能追加訊息、注入額外上下文、阻斷後續流程、更新 MCP 工具輸出。工具執行失敗後,Hook 能補充失敗上下文、發阻斷說明、給使用者恢復線索。
整條鏈路的設計哲學是一樣的:預設假設事情會出問題。模型可能亂傳參數(所以有輸入驗證),操作可能有風險(所以有 speculative classifier 和權限決策),執行可能失敗(所以有失敗 hook),成功了也可能需要額外處理(所以有 post hook)。
你提前把這些"可能出問題"的地方都考慮到了,系統才會抗打。你假設一切正常,線上就會教你做人。
九、Skill、Plugin、MCP:生態的關鍵是模型"知道"
Claude Code 有三套擴展機制:Skill、Plugin、MCP。
Skill 不是文件,是 workflow package。它的形態是帶 frontmatter metadata 的 markdown prompt bundle,可以宣告 allowed-tools,可以按需注入當前上下文,可以把重複的工作流壓縮成可複用的能力包。系統要求模型在任務匹配到某個 skill 時,必須呼叫 Skill tool 執行,不能只是提到這個 skill 而不執行。
Plugin 比 Skill 更重。它可以提供 markdown commands、SKILL.md 目錄、commandsMetadata、userConfig、shell frontmatter、allowed-tools、model 和 effort hints、user-invocable 標記、disable-model-invocation 標記,還支援執行時變數替換。Plugin 不是普通的 CLI plugin,它是模型行為層面的擴展單元。
MCP 不只是工具橋。從 prompts.ts 裡可以看到,當 MCP server 連接上來的時候,如果 server 提供了 instructions,這些 instructions 會被拼進 system prompt。也就是說 MCP 能同時給模型兩樣東西:新工具,以及怎麼用這些工具的說明。
這三套機制有一個共同點:它們都不只是"掛載到系統上"。它們會透過 skills 列表、agent 列表、MCP instructions、session-specific guidance、command integration 這些通道,讓模型感知到自己當前有哪些擴展能力、什麼時候該用、怎麼用。
很多平台也有 plugin 系統,也有工具市場,但模型本身不知道這些東西存在。這就像你給一個人配了一整套專業工具箱,但他不知道箱子裡有什麼,也不知道什麼時候該打開。Claude Code 的做法是把工具箱的清單和使用說明都放到模型看得見的地方。這才是生態真正能發揮作用的前提。
十、"怎麼寫給子 Agent 的 prompt"這一節很容易被忽略,但很有用
AgentTool/prompt.ts 裡有一節專門教模型怎麼給子 Agent 寫 prompt。
它說:fresh agent 沒有上下文,你要像給新來的同事做 briefing 一樣寫 prompt。說明目標和原因。說明你已經排除了什麼。提供足夠的背景讓它能做判斷。如果你只要一個短答案,明確說。不要把理解任務的工作外包給子 agent。不要寫"基於你的發現再去修 bug"這種偷懶 prompt。應該給到具體的 file path、行號、具體改動要求。
這段規則在做什麼?在限制"懶 delegation"。
多 Agent 系統裡最常見的失敗模式就是:主 Agent 把一個模糊的任務丟給子 Agent,子 Agent 理解偏了,做出來的東西不對,主 Agent 拿到結果也不知道問題出在哪。
Claude Code 透過 prompt 強制要求主 Agent 承擔 synthesis 責任。你不能偷懶,你得把任務想清楚了再派出去。這種約束看起來增加了主 Agent 的負擔,但實際上大幅減少了子 Agent 返工的機率。
十一、上下文經濟學:它怎麼把 token 當錢花
整個程式碼裡有大量設計圍繞一個主題:上下文是稀缺資源,不是免費空氣。
system prompt 的靜態/動態邊界,前面說過了,是為了快取。fork path 的 cache-identical prefix 設計,也說過了,是為了複用主執行緒快取。
還有一些更細的設計。Skill 是按需注入的,不是一開始就全部塞進去。MCP instructions 是根據當前連接狀態注入的,沒連上的 server 的說明不會佔上下文空間。有 function result clearing 機制,有 summarize tool results 機制,有 compact 和 transcript 機制,有 resume 機制。
這些機制加起來在做一件事:在有限的上下文視窗裡,盡量裝最有用的資訊,盡量減少重複和冗餘,盡量讓快取命中。
對於做 Demo 的人來說,上下文管理不是問題,因為 Demo 跑幾次就結束了。但對於做產品的人來說,上下文經濟學直接關係到成本和體驗。你的系統每天處理幾萬次請求,每次請求的 system prompt 有幾千個 token,快取命中率提高 10%,一個月下來省的錢可能夠你多雇一個人。
十二、產品化的最後一公里:生命週期管理
runAgent() 裡有很多不起眼但很說明問題的程式碼:recordSidechainTranscript()、writeAgentMetadata()、registerPerfettoAgent()、cleanupAgentTracking()、killShellTasksForAgent()、清理 session hooks、清理克隆的文件狀態、清理 todos entry。
後台 Agent 有獨立的 abort controller,可以在後台持續執行,完成後透過 notification 回到主執行緒,支援自動 summarization。前台 Agent 可以在執行過程中被轉成後台執行,有 progress tracking。
這些功能單獨看都不驚豔。但它們加在一起,說明 Anthropic 不是只管"讓 Agent 跑起來",而是把 transcript 記錄、效能追蹤、資源清理、會話恢復、前台/後台切換全都當成了執行時生命週期的正式組成部分。
大部分 Agent 系統在第一天跑得挺好。問題出在第二天,第三天,第一百天。任務中斷了怎麼續?髒狀態怎麼清?子 Agent 的 shell 程式沒殺掉怎麼辦?MCP 連接洩漏了怎麼辦?這些問題不解決,產品就只能是 Demo。
Claude Code 對這些問題都有明確的處理路徑。這就是為什麼它用起來更像一個正式產品,而不是一個很聰明的 prototype。
你能從這裡面學到什麼
把這些拆完之後,回頭看,Claude Code 在做的事其實可以概括成幾條設計原則。
第一條,不要信任模型的自覺性。好行為要寫成制度,不要依賴模型臨場發揮。你希望模型先讀程式碼再改程式碼,就把這條規則寫進 prompt。你希望模型不要亂加功能,就把這條規則寫進 prompt。你希望模型遇到風險操作停下來確認,就在 runtime 層加權限檢查。
第二條,把角色拆開。至少把"做事的人"和"驗收的人"分開。哪怕現在條件有限,只用同一個模型,把職責拆開也會有明顯改善。因為同一個 Agent 既實現又驗證,天然會傾向於覺得自己做得沒問題。
第三條,工具呼叫要有治理。不是模型說呼叫就呼叫,中間要有輸入驗證、權限檢查、風險預判。執行完也不是結束,要有 post-processing 和失敗處理。這層治理決定了系統在異常情況下的表現。
第四條,上下文是預算。每個 token 都有成本,每條資訊都佔空間。能快取的要快取,能按需載入的不要一開始就塞進去,能壓縮的要壓縮。做 Demo 可以不在乎這些,做產品必須在乎。
第五條,生態的關鍵是模型感知。你給系統接了十個 plugin,但模型不知道什麼時候該用哪個,那這十個 plugin 就等於不存在。擴展機制的最後一步,是讓模型看到自己的能力清單,知道什麼場景用什麼能力。
這五條原則不只適用於 coding agent,也適用於幾乎所有需要 LLM 做複雜任務的系統。Claude Code 的價值不在於某個具體實現,而是在於它用工程實踐驗證了這些原則確實有效。
你不需要復刻它的全部。從最薄弱的環節開始補,每補一層,系統的"手感"就會好一個台階。
一句話摘要:拆了 Claude Code 4756 個程式碼文件後發現,它的秘密不在 prompt 裡,在一整套把行為制度、工具治理、Agent 分工、上下文經濟學和生命週期管理連成閉環的工程系統裡。
