← 返回目錄
第 1 章

全局視角:不只是 CLI 工具

從 4756 個檔案看 Claude Code 的整體架構:多入口設計、fast-path 分發、101 個命令的背後邏輯

先從數字開始

Claude Code 的程式碼庫有 4756 個檔案。一個「CLI 工具」通常不需要這個體量。

拆開看才明白它在做什麼:CLI 只是最薄的那一層。底下是一套完整的 Agent 執行引擎——帶工具系統、多 Agent 調度、安全層、Plugin 生態,外加一套把所有這些暴露給第三方的 SDK。

把它叫做 CLI 工具,就像把 VSCode 叫做「能開檔案的軟體」。技術上沒錯,但完全沒說到重點。

四個入口,四種使用方式

程式碼庫的頂層有四個入口點,每個面向不同的呼叫者。

終端使用者走 cli.tsxclaude 指令從這裡進來,初始化 TTY、載入設定、啟動 React/Ink 互動介面。CI/CD 或腳本呼叫走 init.ts,不需要介面,靜默把環境設置好就行。mcp.ts 則把整個工具系統以 MCP 伺服器的形式暴露出去,讓其他 Agent 能接入。最後是 sdk/——第三方應用直接 import,繞過所有 CLI 層,直達核心執行邏輯。

四個入口共用同一套引擎,能力層和呈現層分離,同一套工具系統能在不同場景下複用。這是刻意的。

Fast-path 分發

cli.tsx 啟動後的第一件事不是直接進入對話迴圈,而是做 fast-path 分發。

判斷邏輯大致是:有沒有明確的子指令?是不是 --print 模式(非互動單次執行)?是不是 pipe 進來的輸入?

根據這些條件,請求被分流到不同的執行路徑:

  • 有子指令(claude configclaude doctor 等)→ 直接執行對應指令,不啟動 Agent 引擎
  • --print 或 pipe 輸入 → 進入無 UI 的執行路徑,輸出到 stdout 後退出
  • 互動模式 → 初始化完整的 React/Ink UI,進入主迴圈

這個分發層的存在讓 101 個指令能在同一個二進位檔案裡共存,同時不讓「查個設定」這種輕量操作也跑一遍完整的 Agent 初始化流程。

101 個命令的組織方式

101 個內建命令不是平鋪在一個大檔案裡的。它們按功能分組,每個命令是一個獨立模組,符合一個標準介面:

interface Command {
  name: string
  description: string
  handler: (args: string[], context: CommandContext) => Promise<void>
}

命令在啟動時動態載入,按需執行。使用者看到的 /help 列表是執行時掃描所有已載入命令後生成的,不是硬編碼的字串。

這個設計的副作用是 Plugin 也能用同樣的機制注入自訂命令。Plugin 系統不需要特殊的「命令注入 API」,因為命令本身就是資料,是可以動態添加的。

為什麼要這麼複雜

簡單的 CLI 工具只需要:接受輸入 → 呼叫 API → 印出結果。三步走,幾百行搞定。

Claude Code 的複雜度來自它要解決的問題不同。

對話歷史、專案上下文、使用者偏好得在多輪之間保持一致——這是持久狀態問題。模型說「執行這個指令」時,不能直接執行,要先問能不能執行、怎麼執行、失敗了誰負責——這是工具治理問題。再往上,多 Agent 協作意味著拆任務、並行、整合結果,主迴圈必須是個調度器,不只是個對話框。最後一點最難量化:沒人能預測所有使用場景,所以生態擴展得是一等公民,而不是事後補丁。

四個問題,四層架構。4756 個檔案是這些問題累積出來的,不是過度工程。

架構全圖

粗略的層次結構是這樣的:

入口層 (cli.tsx / init.ts / mcp.ts / sdk/)

Fast-path 分發

主迴圈引擎 (query.ts)

工具系統 (42 個工具 + 治理 Pipeline)

多 Agent 調度 (AgentTool.tsx + 6 種 Agent)

安全層 (權限系統 + Hook + Classifier)

生態層 (Skill / Plugin / MCP)

後面七章每章對應一層。從引擎開始,一層一層拆開來看。


參考來源: 本文內容參考 Xiao Tan(@tvytlx)的《Claude Code 源碼架構深度解析 V2.0》,基於原報告的分析框架和研究成果整理。