Codebase Context Docs
在儲存庫根目錄產生一份精簡的 CLAUDE.md,以及一組位於 .claude/docs/ 下的深度參考文件。
目標不是「為專案撰寫文件」。而是:讓未來的代理在第一回合執行任務時就有效率,同時花費越少 token 越好。 CLAUDE.md 會在每一回合都被載入到 context 中,永遠如此。每一行都是一種稅。一行只有當它能改變代理在尚未見過的任務上做出的行為時,才值得存在。其他所有內容都應放在 .claude/docs/,只有在相關時才載入。
這個取捨驅動了底下的每一條規則。
工作流程
請依此順序進行。先寫 CLAUDE.md 是最常見的失敗模式──它會產生一個看似合理但充滿猜測的檔案,然後文件會為了符合這些猜測而寫,而非符合實際程式碼。
- 調查──機械式地調查儲存庫(使用下方指令)。
- 閱讀──閱讀進入點、設定檔以及代表性的原始碼切片。
- 撰寫
.claude/docs/*.md──細節放在這裡。 - 最後才寫
CLAUDE.md──它是你剛剛所學內容的索引。 - 驗證──檢查行數、每個指令、每個
file:line。
步驟 1 — 調查
在閱讀任何程式碼之前先執行這些指令。它們成本低廉,且能防止對規模、語言組合與工具做出錯誤猜測。
# 形狀與規模
git ls-files | wc -l
git ls-files | sed 's|/[^/]*$||' | sort | uniq -c | sort -rn | head -40
git ls-files | grep -oE '\.[a-z0-9]+$' | sort | uniq -c | sort -rn | head -20
# 工具與進入點(讀取此指令找到的每個檔案)
ls -a
git ls-files | grep -iE '(package\.json|pyproject\.toml|setup\.py|requirements.*\.txt|Cargo\.toml|go\.mod|pom\.xml|build\.gradle|Gemfile|composer\.json|pubspec\.yaml|Makefile|justfile|Taskfile|docker-compose|Dockerfile)'
git ls-files '.github/workflows/*' '.gitlab-ci.yml' '.circleci/*'
# 現有文件──閱讀這些,它們蘊含了你無法從程式碼推斷出的意圖
git ls-files | grep -iE '(readme|contributing|architecture|adr|docs/)' | head -30
# 近期活動顯示了儲存庫中哪些部分仍然活躍
git log --oneline -15
git log --pretty=format: --name-only -n 200 | sort | uniq -c | sort -rn | head -20
注意調查未能找到的任何東西。一個沒有 CI 設定檔且沒有測試目錄的儲存庫,是一個真實的發現,而不是一個需要掩飾的缺口。
步驟 2 — 閱讀
依照此順序閱讀:
- 清單檔案(
package.json、pyproject.toml……)──從頭到尾,包含 scripts/tasks 區段。這裡是實際指令的所在地。 - CI 工作流程檔案──CI 執行的指令才是真正能用的指令。
README.md以及任何CONTRIBUTING.md/docs/──為了為何這麼做,這是程式碼無法告訴你的。- 應用程式的進入點,然後是分散在各主要目錄中的 5–15 個代表性原始碼檔案。
當儲存庫很大且子代理可用時,為原始碼閱讀階段使用並行子代理──每個主要目錄一個,各自回報該目錄的用途、使用的模式,以及這些模式的 file:line 錨點。這樣比較快,也能將原始檔案傾印排除在主 context 之外。
在閱讀時,持續記錄候選模式清單,並附上你看到該模式的確切 path/to/file.ts:142。你稍後會需要這些錨點,回頭尋找的代價很高。
步驟 3 — 撰寫 .claude/docs/
只建立程式碼庫實際支援的檔案。空的或填充的文件比遺漏更糟,因為它會讓代理學會不信任整套文件。
| 檔案 | 建立時機 | 內容 |
|---|---|---|
architectural_patterns.md | 總是建立(除非儲存庫極小) | 重複出現的結構性決策:依賴注入、狀態管理、錯誤處理、模組邊界、API 設計慣例、分層規則 |
testing_strategy.md | 存在測試 | 框架、測試位置、fixture/factory 慣例、如何執行單一測試 vs 測試套件、什麼被 mock 什麼是真實的 |
build_and_deploy.md | 建置工具或 CI 非顯而易見 | 建置管線、環境變數及其宣告位置、產出物、發行/部署流程、本地開發設定陷阱 |
data_model.md | 存在持久化資料、schema 或遷移 | 核心實體與關係、schema/遷移位置與工作流程、驗證層 |
api_reference.md | 專案暴露或消費一個重要的 API | 路由/端點組織、請求/回應慣例、認證、版本化、錯誤格式 |
當程式碼庫有一個大型子系統不符合上述分類時,你可以新增一個領域特定檔案(例如 realtime_sync.md、billing.md)。偏好少量但內容充實的檔案,而非許多薄弱的檔案。
多檔案證據規則
這條規則區分了有用的模式文件和憑空想像的文件。
只有在至少三個不同的檔案中觀察到的模式才納入文件,並且至少引用其中兩個。 單一精巧的抽象化是瑣事。而在整個程式碼庫中重複出現的慣例,才是新代理必須遵循以寫出符合風格的程式碼的關鍵。
當你發現某個看起來像模式但只出現一次的東西時,請捨棄它,或使用 grep 來確認它是否具有普遍性:
rg -n 'useAppDispatch' --stats # 它有多普遍?
rg -l 'implements Repository' | head # 哪些檔案共享此形狀?
如果一個慣例的應用不一致──一半的程式碼庫用一種方式,另一半用另一種──請明確說明,並指出哪一種較新(透過 git log 查看檔案)。知道程式碼庫正在進行遷移的代理,會比假設一切都統一的代理寫出更好的程式碼。
透過錨點而非片段來引用
撰寫 請參閱 src/services/base.py:34 而非貼上該類別。片段一旦有人編輯檔案就會過時,而過時的片段會積極誤導──反之,過時的行號則明顯值得重新檢查。這也能讓文件保持足夠簡短以便閱讀。
將符號名稱與行號一同列出,這樣錨點才能在小幅編輯後存活:PaymentProcessor.execute — src/billing/processor.py:88。
不要管程式碼風格
使用者會執行 linter 和 formatter。不要記錄縮排、引號風格、行長度、匯入順序或命名大小寫。這些由工具機械式地強制執行;在一個始終載入的檔案中重複它們,是為了重複一個工具的功能而浪費 context。應該記錄的是 linter 無法強制執行的慣例──哪一層可以匯入哪一層、何時該新增遷移、新的路由在哪裡註冊。
步驟 4 — 撰寫 CLAUDE.md
嚴格控制在 150 行以下。使用此結構:
# <專案名稱>
<2–4 句話:這是什麼專案,服務誰/什麼。WHY──它解決的問題。這是無法從程式碼推斷出的部分,因此也是最值得仔細撰寫的部分。>
## 技術棧
<精簡清單:語言 + 版本、框架、資料庫、關鍵基礎設施。只列出會影響程式碼撰寫方式的項目。跳過 transitive dependency 傾印。>
## 專案結構
<表格或清單,列出頂層目錄,每行說明其用途,並在不明顯之處說明不屬於該目錄的內容。>
## 指令
<只包含已驗證、普遍有用的指令:安裝、開發、建置、測試、執行單一檔案測試、lint、型別檢查。如果套件管理器不是該生態系的預設選項,請註明。>
## 慣例
<3–8 行,僅包含適用於整個儲存庫且 linter 無法捕捉的規則。如果某條規則特定於某個子系統,則應放在 docs 檔案中。>
## 額外文件
當任務需要時才閱讀這些──請勿預先載入。
- `.claude/docs/architectural_patterns.md`──<何時閱讀>
- `.claude/docs/testing_strategy.md`──<何時閱讀>
讓「額外文件」區段成功或失敗的兩個關鍵:
- 每一行都說明何時閱讀,而非內容是什麼。「在新增端點或變更回應格式前閱讀」能正確引導代理;而「記錄了 API」則不能。
- 這個清單是專業細節被引用的唯一地方。如果你發現自己在
CLAUDE.md和testing_strategy.md中都說明了測試設定,請從CLAUDE.md中刪除它。
請參閱 references/templates.md 以取得 CLAUDE.md 及各個 docs 檔案的填寫範例。
步驟 5 — 驗證
不要跳過這一步。 這項任務的每一種失敗模式都是一個聽起來很有自信的謊言,而且每一種都很容易逮到。
wc -l CLAUDE.md # 必須 < 150
然後:
- 執行你寫下的每一個指令,或至少確認每個指令都存在於清單檔案 / CI 設定中。
CLAUDE.md中的npm test如果不在package.json中,將會在未來的每一個工作階段浪費代理的時間。如果你無法執行一個指令,請將其標記為「從原始碼讀取」而非「已驗證」。 - 抽查每一個
file:line──打開其中幾個,確認引用的符號確實存在。 - 重新以冷靜的態度閱讀
CLAUDE.md,就像一個初次看到此儲存庫的代理。刪除任何不會改變你行為的行。泛泛的建議(「寫乾淨的程式碼」、「適當地處理錯誤」)是常見的罪魁禍首。 - 報告最終的行數以及所建立的檔案清單。
如果 CLAUDE.md 超過 150 行,請刪減而非壓縮──將整個區段移到一個 docs 檔案中,只留下一行索引。將散文壓縮以符合行數限制,會產生一個沒人能解析的密集檔案。
處理既有的 CLAUDE.md
如果已存在一個 CLAUDE.md,不要盲目覆寫。先閱讀它,然後根據目前的程式碼進行驗證:不再存在的指令、被重新命名的目錄、被遷移走的模式。保留任何編碼了人類偏好且你無法從程式碼推斷出的手寫指示(「永遠不要碰 vendor 的 SDK」、「新增相依套件前先詢問」)──這些是檔案中價值最高的行,也是最容易被破壞的。在刪除任何重大內容之前,向使用者展示你要移除的內容及其原因。