指令系統:語義入口層

命令層優先處理「使用者要做什麼」;多數命令偏路由層,但部分命令仍包含狀態切換與權限判斷。

90 秒總覽

指令系統是 Claude Code 的語義入口。使用者輸入斜線命令後,系統會在合併後的命令集比對(內建 + skills/plugins/workflows),再交由 availability 與 isEnabled() 決定是否可見。多數命令偏向路由與委派,但也有例外會處理狀態與權限邏輯。

執行路徑(主骨架)

const COMMANDS = memoize((): Command[] => [
  addDir,
  help,
  status,
  ...(feature('VOICE_MODE') ? [voiceCommand] : []),
])

COMMANDS() 會被 memoize,但每次 getCommands() 仍會重新跑 availability 與 isEnabled(),所以可見性不只在初次建表時決定。

建立命令清單(memoize 快取)
依 feature / 條件載入決定附加命令
使用者輸入 /xxx
在命令清單中比對對應 Command 物件
同時檢查 availability 與 isEnabled
委派到工具層或服務層執行
回傳結果給使用者
flowchart TD
  A[使用者輸入 /xxx] --> B[slash command 解析]
  B --> C[命令清單比對]
  C --> D{feature gate 檢查}
  D -->|通過| E[委派到工具/服務]
  D -->|未通過| F[命令不可見,回傳提示]
  E --> G[回傳結果]

路徑判讀重點

  • 命令清單只在首次存取時建立,後續呼叫直接回傳快取結果。
  • 命令是否可見要看三段:註冊來源、availability、isEnabled()
  • 命令匹配不只看 name,也會看 userFacingNamealiases
  • 多數命令偏路由層,但有些命令(如 brief)仍會處理狀態或權限邏輯。
  • 此層未知命令是拋例外(ReferenceError);友善提示通常由上層轉譯。

關鍵決策(為什麼這樣設計)

決策 1:命令清單採 memoize 快取

原因:命令清單在應用程式生命週期內不會改變,每次重建浪費運算資源。透過 memoize 確保只建立一次,後續呼叫直接回傳快取結果,降低重複成本。

代價:如果 feature gate 狀態在執行期間動態改變,快取的清單不會自動更新,可能導致命令可見性與實際狀態不一致。

決策 2:混合式 gating(條件載入 + 執行期過濾)

原因:命令系統同時使用 dead-code-elimination 路徑與執行期過濾,兼顧建置體積與執行彈性。前者控制是否載入模組,後者處理當下可見性。

代價:維護者必須分清楚「載入期決定」與「查詢期決定」兩種 gate,文件也要明確標註。

決策 3:命令以路由為主,但允許少量例外

原因:把大多數命令維持為薄層,可保持邊界清楚;對需要即時模式切換或互動控制的命令,允許在命令層保留必要邏輯。

代價:例外命令若不受控會讓邊界漂移,因此需要明確審查與文件化。

替代方案與取捨

替代方案比較表
方案 優點 缺點 為何未採用/何時可採用
動態註冊(外掛式命令載入) 新命令不需修改核心清單,擴充性高 註冊順序難控制,除錯困難,啟動時需掃描所有外掛 外掛生態成熟後可考慮;目前命令數量有限,靜態清單更直觀可控
命令直接執行(不委派到工具層) 呼叫路徑短,減少間接層級,實作簡單 命令與執行邏輯耦合,無法獨立測試命令解析;職責邊界模糊 極輕量工具可行;目前系統需要清楚的命令/工具/服務分層
編譯時排除(取代 feature gate) 打包產物更小,未啟用的命令完全不存在 切換功能需重新建置與部署,無法在執行期動態調整 對 bundle 大小極度敏感時可考慮;目前彈性與開發速度優先

失敗路徑與防護

Failure 1:使用者輸入未知命令

症狀:使用者輸入 /foobar 等不存在的斜線命令,命令清單比對不到任何 Command 物件,系統沒有回應或拋出未處理的例外。

防護:在命令層保留明確例外(包含可用命令清單);由上層 UI/CLI 統一轉譯為友善提示,避免各處自行包裝而不一致。

Failure 2:feature gate 狀態不一致導致命令幽靈可見

症狀:把「註冊快取」誤認為「可見性快取」,會錯估命令在不同身份/模式下的實際可用狀態。

防護:區分兩層:COMMANDS() 快取註冊表;getCommands() 每次重新跑 availability 與 isEnabled()

Failure 3:命令委派失敗但缺乏回饋

症狀:命令成功比對並委派到工具層或服務層,但目標執行層拋出例外或回傳錯誤,命令層未捕獲也未向使用者顯示任何訊息。

防護:命令層在委派時以 try/catch 包裹呼叫,捕獲下游錯誤後轉換為使用者可理解的提示訊息,並記錄錯誤細節供開發者除錯。

實作驗證(你改完要怎麼確認)

  • 確認 /help 正確列出所有目前可用的命令,且清單與 COMMANDS 陣列一致。
  • 確認關閉特定 feature flag(如 VOICE_MODE)時,對應的命令從清單中消失,使用者無法觸發。
  • 確認輸入不存在的命令(如 /foobar)時,系統回傳友善的錯誤提示而非靜默失敗。
  • 確認命令委派到工具層後,工具層錯誤能被捕獲並轉換為使用者可讀的訊息。
  • 確認 memoize 快取生效:多次呼叫 COMMANDS 回傳同一參考(reference equality)。

前三項是最低可接受驗證集,後兩項針對快取與錯誤傳播做回歸測試。

← 上一頁 下一頁:工具系統 →