← 所有文章

解剖一隻爪:84個Hook作為編排層

From the guide: Claude Code Comprehensive Guide

第一個hook只花了四分鐘就寫完了。它阻止模型在純Anthropic工作流程中推薦OpenAI產品。兩個月後,這單一的hook變成了84個。這84個hook連接了43個skill、19個專門代理和30個程式庫模組。在某個時間點,這些集合不再只是一組腳本,而是成為了一個編排層。

我並非刻意如此設計。沒有人會坐下來說「我要建構15,000行的代理基礎設施」。您解決一個問題,然後另一個,接著解決問題之間互相影響的問題。當您注意到架構時,它已經存在了。

Andrej Karpathy也注意到了。2026年2月,他將「Claws」描述為一個新的計算層:建構在LLM代理之上的編排、排程、上下文管理和工具路由,就像代理建構在LLM之上一樣。1這個框架將實踐者一直在建構卻未命名的東西具象化了。本文是這樣一個系統的解剖:它包含什麼、如何成長、哪裡有效、哪裡失敗。

TL;DR

Karpathy的「Claws」層描述了建構在代理CLI之上的編排系統。我在Claude Code上經過兩個月有機地建構了一個:84個hook橫跨15種事件類型、43個skill、19個代理和30多個程式庫模組。該系統清楚地對應到五個Claws功能(編排、排程、上下文管理、工具路由、品質執行),但有一個顯著缺口(宣告式工作流程定義)。關鍵發現:規劃與執行的分離是hook式編排的自然屬性,而非設計目標。Lattner觀察到「判斷力與抽象能力仍是核心,而AI自動化實作」,這直接對應到hook架構:治理hook行使判斷力,自動化hook執行實作。


Claws分類法

Karpathy的描述指出了Claws層執行的五種功能。每種功能在我過去兩個月於Claude Code上建構的hook系統中都有直接對應。1

Claws功能 描述 實作
編排 協調多個代理達成目標 Ralph自主迴圈審議系統
排程 決定任務何時執行 Cron hook、activity-heartbeat.sh、夜間安全掃描
上下文管理 跨輪次維持相關資訊 Prompt調度器、哲學注入器、記憶膠囊
工具路由 將工具呼叫導向適當的處理器 84個hook橫跨PreToolUse、PostToolUse、UserPromptSubmit事件
品質執行 驗證輸出符合標準 品質關卡、證據要求、7個審查代理

這個分類法之所以有用,是因為它分離了實踐者傾向以糾纏方式建構的關注點。我早期的hook將上下文管理與品質執行混在一起。成本追蹤hook同時注入預算上下文(上下文管理)並阻擋昂貴操作(品質執行)。將這些分離成獨立的hook提升了可靠性,因為每個hook可以獨立失敗而不破壞另一個功能。


完整系統

截至2026年2月的數據:

元件 數量 用途
Hook 84 橫跨15種hook事件類型的事件驅動函式
Skill 43 可透過名稱呼叫的可重用能力模組
代理 19 用於審查、探索、開發的專門子代理
程式庫模組 30+ 共用的Python和Bash工具程式
程式碼行數 約15,000 橫跨hook、skill、代理、程式庫、設定檔

Hook在各事件類型的分佈揭示了編排複雜度集中之處:

事件類型 Hook數量 範例
UserPromptSubmit 9(透過調度器) 上下文注入、成本追蹤、使用分析
PreToolUse:Bash 12 安全掃描、憑證檢查、敏感指令阻擋
PostToolUse:Bash 6 輸出掃描、部署驗證
PreToolUse:Write 4 憑證偵測、路徑驗證
PreToolUse:Edit 3 模式執行
PreToolUse:Task 3 遞迴防護、產生預算
PreCompact 1 記憶膠囊、死亡螺旋偵測
SessionStart 1 環境初始化
WorktreeCreate 1 隔離分支的環境設定
WorktreeRemove 1 清理前的安全檢查
其他事件類型 約43 分佈於PreToolUse:Read、PostToolUse:Write、PreToolUse:WebFetch、NotebookEdit及另外8種事件類型

UserPromptSubmit承載最多權重,因為它在每條使用者訊息時觸發。調度器(prompt-dispatcher.sh)在每個prompt上依序執行九個hook:安全過濾、分析、使用追蹤、系統監控、目標注入、時間估計阻擋、上下文注入、記憶主題注入和上下文壓力監控。2

每個hook都會增加延遲。九個循序hook每個prompt總共增加實測200毫秒。調度器循序執行它們(而非平行),因為在早期測試中,並行hook寫入共用JSON狀態檔案會導致資料損毀。兩個hook同時寫入jiro.state.json產生了截斷的JSON,破壞了每個下游hook。循序執行較慢但安全。200毫秒的開銷對使用者來說是無感的,因為人類打字速度才是瓶頸,而非hook延遲。


如何成長

成長並非線性。它遵循「問題—解決方案—整合」的循環模式。

第一階段:單一用途hook(第1-2週)。 每個hook解決一個問題。enforce-opus-model.sh阻擋非Opus模型請求。no-time-estimates.sh移除回應中的工作量估計。filter-sensitive.sh捕捉工具呼叫中的憑證。這些hook獨立運作,沒有任何hook知道其他hook的存在。

第二階段:協調問題(第3-4週)。 Hook開始互相干擾。憑證過濾器阻擋了合法的API呼叫。模型執行器與子代理產生發生衝突。解決方案:調度器。一個單一進入點(prompt-dispatcher.sh)取代了七個獨立的UserPromptSubmit hook,透過快取的stdin管道控制執行順序並共享狀態。

第三階段:複合能力(第5-8週)。 個別hook組合成系統。品質迴圈透過共用狀態檔案(jiro.state.json)連接了預工具hook(在問題發生前捕捉)和後工具hook(在問題發生後驗證結果)。審議系統使用遞迴防護、產生預算和共識協定來協調多個代理而不會產生無限迴圈。Ralph(自主開發迴圈)在單一編排管線中連接了PRD檔案、Claude產生、測試驗證和程式碼審查。

第四階段:自我意識(第9週以後)。 系統變得足夠龐大,需要工具來理解自身。跨hook系統的語意搜尋(/find skill)讓代理能按用途而非檔案名稱來發現hook。效能監控(/perf skill)追蹤系統自身的開銷是否正在拖慢機器。上下文壓力監控器在編排層注入的上下文消耗過多模型上下文窗口時發出警告。

從單一用途hook到自我監控基礎設施的演進,映射了Chris Lattner在審查Claude C Compiler專案時識別出的模式:「好的軟體取決於判斷力、溝通和清晰的抽象。AI放大了這一點。」3hook系統的架構揭示了同樣的真理。有價值的hook不是那些自動化任務的hook,有價值的hook是那些編碼了關於何時以及如何自動化任務之判斷的hook。


判斷Hook與自動化Hook

Lattner對Claude C Compiler的審查區分了AI善於自動化的部分(實作)和本質上仍屬人類的部分(判斷力與抽象能力)。3這個區分直接對應到hook系統。

判斷hook決定某事是否應該發生。它們編碼的是策略,而非程序。

Hook 判斷
quality-gate.sh 「這項工作是否足夠完整可以回報?」
filter-sensitive.sh 「這個指令是否有暴露憑證的風險?」
recursion-guard.sh 「代理是否產生了太多子代理?」
context-pressure.sh 「上下文窗口是否太滿而無法有效繼續?」
cost-gate.sh 「此工作階段是否已超過預算閾值?」

自動化hook執行預定動作。它們編碼的是程序,而非策略。

Hook 自動化
inject-context.sh 在每個prompt中注入日期、時間、工作目錄、分支
track-usage.sh 記錄token計數和工作階段指標
sysmon-snapshot.sh 擷取CPU、記憶體、磁碟狀態
memory-capsule-inject.sh 壓縮後恢復上下文
activity-heartbeat.sh 更新工作階段存活指標

判斷hook更難撰寫、更難測試,也更有價值。quality-gate.sh需要七種命名的失敗模式、六項證據標準和一個模糊語言偵測器。inject-context.sh只需要五行bash。但兩者都是必要的。自動化hook提供判斷hook評估所需的資料。sysmon-snapshot.sh(自動化)將資料饋送給效能監控器,由其決定是否建議限制代理數量(判斷)。

比例很重要。在健康的編排層中,判斷hook應該多於自動化hook。如果大多數hook只是注入資料或記錄指標,系統自動化做得好但治理做得差。目前系統的驗證計數:35個判斷hook、44個自動化hook,大約4:5。自動化仍然領先。這個比例起初大約是1:6(幾乎全是注入和記錄hook),在兩個月內隨著治理約束的加入而向判斷傾斜——這些約束是在遭遇純自動化無法防止的失敗後添加的。比例尚未達到均衡,這本身就是一個有用的訊號:這個系統仍然自動化多於治理。


規劃與執行的分離

Boris Tane的「How I use Claude Code」文章在Hacker News上獲得936點,文中描述了一種工作流程模式:將規劃與執行分離。4用一個Claude工作階段進行規劃(研究、概述、設計),然後用一個全新的工作階段執行,該工作階段接收計畫作為結構化輸入。這個模式引起共鳴,因為它解決了一個真實問題:規劃和執行競爭上下文窗口空間。

hook系統透過不同的路徑達到了同樣的分離。審議系統產生專門代理來研究和辯論方法。輸出是結構化的PRD(產品需求文件),包含故事、驗收標準和驗證類型。Ralph迴圈讀取PRD並產生全新的Claude實例來實作每個故事。規劃代理從不實作,實作代理從不規劃。

這種分離並非設計目標。它源自兩個獨立的約束:

  1. 上下文窗口壓力。 規劃需要讀取許多檔案並探索選項。實作需要對當前任務的聚焦上下文。將兩者放在同一個上下文窗口意味著兩者都得不到足夠空間。分開的工作階段讓每個階段都有完整的上下文。

  2. 品質驗證獨立性。 如果同一個代理既規劃又實作,它就無法客觀地依據計畫驗證自己的實作。一個只有計畫和程式碼的全新代理提供了獨立驗證。Ralph迴圈強制執行這一點:實作代理執行測試,但三個獨立的審查代理(正確性、安全性、慣例)驗證結果。

Tane的手動工作流程與自動化hook系統之間的趨同暗示,規劃與執行的分離是代理系統的自然屬性,而不僅是實踐者的偏好。任何管理上下文窗口並驗證輸出的系統最終都會分離規劃與執行,因為替代方案(在一個上下文中同時進行)會在兩個階段都產生較差的結果。


Hook系統的失敗之處

該架構有三個顯著弱點,專門建構的編排框架可以解決這些問題。

沒有宣告式工作流程定義。 每個工作流程都以命令式方式編碼在bash腳本中。Ralph迴圈是1,320行bash,編碼了特定序列:讀取PRD、選擇故事、收集上下文、產生Claude、執行測試、執行審查、處理失敗、更新狀態。修改工作流程意味著編輯bash。宣告式系統會將工作流程定義為資料(YAML、JSON),由直譯器執行。宣告式工作流程更容易修改、組合和視覺化。命令式腳本最初更容易撰寫,但隨著成長更難維護。

Hook排序是脆弱的。 prompt調度器以寫死的序列執行hook。將memory-capsule-inject.sh移到inject-context.sh之前會破壞膠囊注入,因為它依賴於inject-context.sh解析的工作階段ID。這些相依性是隱式的(編碼在調度器的順序中)而非顯式的(宣告為hook之間的相依性)。專門建構的系統會將hook相依性表達為DAG並進行拓撲排序來決定執行順序。

沒有工作流程視覺化。 有84個hook,理解任何使用者操作的完整執行路徑需要閱讀調度器程式碼並手動追蹤hook鏈。沒有工具可以顯示「當使用者輸入訊息時,這9個hook按此順序觸發,hook 3呼叫程式庫函式X,該函式寫入狀態檔案Y」。系統可透過日誌觀察,但無法透過結構觀察。專門建構的編排框架會提供hook相依性、資料流和執行路徑的視覺化圖表。

這些弱點有一個共同原因:系統是從解決個別問題有機成長的,而非被設計為一個連貫的編排層。有機成長產生的系統可以運作(所有84個hook在生產環境中都正確運作),但難以作為整體來推理。這個取捨是真實的:預先設計編排層會產生更好的結構但更差的能力,因為許多能力(記憶膠囊、輸出白名單、產生預算)是在遭遇無法預測的失敗後才發明的。


實踐者應該帶走什麼

如果您正在代理CLI之上建構編排層,此系統的三個模式可以直接移植。

從調度器開始,而非個別hook。 最大的架構改進是將七個獨立的UserPromptSubmit hook替換為一個循序執行它們的調度器。如果您預期在任何事件類型上會有超過三個hook,請先建構調度器。花30分鐘撰寫調度器可以節省數小時的hook互動除錯。最小模式:

#!/bin/bash
# dispatcher.sh — sequential hook execution with shared stdin
HANDLERS=("inject-context.sh" "track-usage.sh" "quality-gate.sh")
HOOK_DIR="$(dirname "$0")/handlers"
INPUT=$(cat)  # Cache stdin once (each handler gets the same input)

for handler in "${HANDLERS[@]}"; do
    [ -x "$HOOK_DIR/$handler" ] && echo "$INPUT" | "$HOOK_DIR/$handler"
done

將此調度器註冊為您的hook進入點。隨著建構添加處理器到陣列中。每個處理器讀取相同的快取stdin(hook事件酬載)並獨立寫入stdout。

儘早分離判斷與自動化。 撰寫新hook時,請問:「這個hook是決定某事是否應該發生,還是執行預定動作?」判斷hook需要更多測試、更多邊界情況處理和更多迭代。自動化hook需要可靠性和效能。將它們同等對待會導致測試不足的判斷hook和過度工程的自動化hook。

讓規劃與執行的分離自然浮現。 不要在第一天就強制分離。建構最簡單可行的東西。當您注意到代理的上下文窗口對於規劃和實作來說都太滿時,將它們分開。當您注意到代理無法客觀驗證自己的工作時,添加獨立的審查代理。當約束要求時,分離會顯得理所當然。

基於hook的方法相比專門建構的編排框架有一個優勢:零承諾。每個hook都是獨立的。您可以採用一個hook、十個hook或八十四個hook。您可以刪除任何hook而不破壞其他hook(前提是維護調度器)。沒有需要學習的框架,沒有需要管理的相依性,沒有需要運營的執行環境。編排層就只是檔案。

Karpathy稱之為新的計算層。實作比名稱更早存在。自從實踐者第一次寫shell腳本來包裝代理CLI呼叫起,他們就一直在建構Claws。shell腳本和編排層之間的差異不是本質上的差異,而是您解決了多少問題,以及其中有多少解決方案必須互相解決的差異。


參考來源


  1. Andrej Karpathy,「Claws」討論,2026年2月,x.com/karpathy/status/2024987174077432126。經由Simon Willison轉載,simonwillison.net/2026/Feb/21/claws/。 

  2. 上下文注入架構詳見「Context Is Architecture」。 

  3. Chris Lattner,「The Claude C Compiler: What It Reveals About the Future of Software」,Modular部落格,2026年2月。經由Simon Willison轉載,simonwillison.net/2026/Feb/22/ccc/。 

  4. Boris Tane,「How I use Claude Code」,boristane.com,2026年2月。Hacker News上936點、569則留言。 

相關文章

The CLI Thesis

Three top HN Claude Code threads converge on one conclusion: CLI-first architecture is cheaper, faster, and more composa…

15 分鐘閱讀

Claude Code as Infrastructure

Claude Code is not an IDE feature. It is infrastructure. 84 hooks, 48 skills, 19 agents, and 15,000 lines of orchestrati…

12 分鐘閱讀

The Ralph Loop: How I Run Autonomous AI Agents Overnight

I built an autonomous agent system with stop hooks, spawn budgets, and filesystem memory. Here are the failures and what…

8 分鐘閱讀