Tidy · 項目整潔規範
倉庫裡的每個檔案都必須能回答三個問題:
- 為什麼存在?(必要性)——刪掉它會壞掉什麼?
- 為什麼在這裡?(歸屬)——按本項目的目錄約定,它屬於哪個目錄?
- 別人看得懂嗎?(可讀性)——只看檔案名和 README,新人能猜到它是幹什麼的嗎?
使用者輸入
/tidy時,直接執行下文「模式二:整理已有專案」。
三層機制
| 層 | 作用 | 由誰執行 |
|---|---|---|
目錄約定 .claude/tidy.json | 聲明每個頂層目錄放什麼,把「該放哪」從判斷變成查表 | 你在整理專案時生成,之後長期維護 |
| Hooks(隨插件安裝) | 會話開始注入規則和目錄約定;攔截不合規的新檔案;每輪結束檢查新增檔案 | 自動,見下文「收到 hook 提示時」 |
| 本 skill | 寫程式碼時的判斷標準、整理老項目的流程 | 你 |
Hooks 只檢查新增的檔案,老項目已有的問題由「模式二」整理。
三種檢查粒度
| 時機 | 做什麼 |
|---|---|
| 新建檔案時 | 過一遍下面的 4 問(有 hooks 時自動攔截) |
| 階段交付 / 任務結束 | audit.py <根目錄> --changed(git 項目,只看相對 HEAD 的變化)或 --since 2h(按修改時間,非 git 項目也能用)。沒有 hooks 的工具(Codex、Cursor)每次交付前都跑一次。 |
| 使用者要求整理專案 | 全量 audit.py <根目錄>,走「模式二」 |
核實後確認無需處理的警報(有意的交付副本、第三方檔案名),用 audit.py <根目錄> --review <規則> <路徑> --reason <結論> 記下來,之後不再報告;檔案內容變化後會重新出現,提醒你複核。
模式一:寫程式碼時(每次都適用)
新建檔案前的 4 問
| 問題 | 不通過時怎麼做 |
|---|---|
| 必要嗎? 能否寫進已有檔案?是否只是一次性的? | 合併進已有檔案;一次性內容寫在回覆裡,不落盤 |
放哪? 符合 .claude/tidy.json 的 layout 嗎? | 放進已聲明的目錄;確需新頂層目錄時,先在 layout 和 README「目錄結構」登記 |
| 叫什麼? 名字能說明用途、和同目錄風格一致嗎? | 按 references/naming.md 命名 |
| 該提交嗎? 是生成物、依賴、金鑰、大檔案嗎? | 加進 .gitignore,不進版本庫 |
AI 最常見的壞習慣(禁止)
| ❌ 壞習慣 | ✅ 正確做法 |
|---|---|
在根目錄寫 test.py、debug.js、check_xxx.py 臨時腳本 | 寫到 .scratch/(確保已忽略)或系統臨時目錄,任務結束即刪 |
複製出 foo_v2.ts、foo_new.ts、foo.backup.ts、foo_old/ | 直接改原檔,歷史交給 git |
每做完一件事就生成 IMPLEMENTATION_SUMMARY.md、FIX_REPORT.md | 總結寫在回覆和 commit message 裡;長期知識合併進 README 或 docs/ 已有文件 |
提交 build/、out/、dist/、渲染出的影片音訊、日誌 | 加進 .gitignore;README 寫清楚怎麼生成 |
node_modules/、.venv/ 被提交或散落各處 | 忽略;多語言工具鏈各自歸位(見 structure.md「混合項目」) |
中文、空格、括號檔案名:提示詞分享.md、final (1).mp4 | 檔案名用英文 kebab-case,中文寫進檔案標題 |
| 腳手架樣板沒清理、大段註解掉的舊程式碼、沒用上的依賴 | 確認無引用後刪除 |
同一配置寫兩份(.prettierrc + package.json#prettier) | 只保留一處 |
| 為了「以後可能用」預先建空目錄、空檔案 | 用到時再建 |
收到 hook 提示時
- 新建檔案被攔截:按提示換做法——合併進已有檔案、換目錄、換名字,或者乾脆不落盤。不要為了繞過攔截改用 Bash 寫檔案(Stop 檢查照樣會發現)。
- 結束前檢查列出了問題:逐條處理(刪除臨時檔案、合併副本、移動、補
.gitignore),處理完再結束。 - 使用者明確要求這樣做(比如就要一個中文檔案名):按規則把路徑加進
.claude/tidy.json的allow(如{"non-portable-name": ["docs/課程/**"]}),並在回覆中說明。豁免範圍盡量小,不要用disable關掉整條規則,也不要自作主張加豁免。 - 本地要保留、但不該進 git 的檔案(成片、已驗收配音、模型權重等):登記到
keepLocal並寫明原因,再補.gitignore。不要刪除。 - 需要新的頂層目錄:先確認確實沒有合適的已有目錄,再在
layout和 README「目錄結構」中登記。
模式二:整理已有專案
腳本都在本 skill 的 scripts/ 目錄下,只依賴 Python 3.9+ 標準庫。
第 1 步:掃描
python3 <skill>/scripts/audit.py <專案根目錄> # 文字報告
python3 <skill>/scripts/audit.py <專案根目錄> --format json
第 2 步:理解專案,查引用
腳本是啟發式的,每條警報都要核實後再處理。文字報告會摺疊數量多的同類問題,需要逐條查看時加 --all。下結論前:
-
讀 README、
package.json/pyproject.toml的 scripts 和入口; -
對每個想刪除或移動的檔案查引用:
python3 <skill>/scripts/refs.py <專案根目錄> <檔案> [<檔案> ...]結論分四種:
in-use(有明確引用)、convention(框架按約定載入)、maybe(只有弱匹配)、unreferenced(沒找到)。unreferenced也要考慮動態路徑和外部呼叫,判斷標準見 references/file-necessity.md。
第 3 步:給出整理方案,等待確認
| 路徑 | 動作 | 目標位置 | 理由 |
|---|---|---|---|
提示詞分享.md | 移動+重新命名 | docs/prompts.md | 根目錄散落文件;非 ASCII 檔案名 |
out/ | 忽略 | — | 渲染產物,可由 npm run render 重新生成 |
src/Root_old.tsx | 刪除 | — | refs.py:unreferenced;內容與 Root.tsx 相同 |
動作只有七種:保留 / 移動 / 重新命名 / 刪除 / 歸檔 / 忽略 / 本地保留(忽略但不刪除,登記到 keepLocal)。拿不準的標「待確認」。警報屬於預期情況(交付副本、連續截幀)時,動作是按規則加 allow,而不是刪檔案。
刪除和批量移動必須先得到使用者確認。 方案確認前不要動檔案。
第 4 步:執行
- 確保工作區乾淨;不是 git 倉庫就先建議
git init並做一次初始提交作為快照。 python3 <skill>/scripts/audit.py <根目錄> --fix-gitignore:自動把未忽略的依賴、生成物、垃圾檔案、金鑰補進.gitignore(只追加,不刪除)。已被 git 追蹤的會列出來,需要git rm --cached。- 移動 / 重新命名用
git mv;之後對舊路徑執行 refs.py 或 grep,修復所有引用(import、staticFile()、配置、腳本、文件連結)。 - 跑建構 / 測試 / lint,確認沒有被破壞。
- 結構調整和程式碼修改分開提交。
第 5 步:固化目錄約定(不要跳過)
整理完後,生成目錄約定,讓以後的每個會話自動遵守:
python3 <skill>/scripts/audit.py <根目錄> --init # 按現有頂層目錄生成 .claude/tidy.json 草稿
然後補全每個目錄的說明(取代 TODO),寫法要能指導放置決策,例如 "public/": "staticFile() 讀取的素材:圖片、字型、配音",而不是只寫「靜態資源」。同步更新 README「目錄結構」。配置格式見 references/config.md。
安全底線
- 不可再生的檔案(使用者素材、錄音、手寫提示詞、資料)未經確認絕不刪除——移到合適目錄或歸檔。
- 不讀取、不輸出
.env等金鑰內容;若發現金鑰已被 git 追蹤,提醒使用者輪換金鑰並清理歷史,而不只是刪除檔案。 - 不確定一個檔案是否在使用時,標記為「待確認」,不要猜。
刪除還是歸檔?
「是否進 git」和「是否刪除」分開判斷。
這個檔案……
├─ 能低成本重新生成嗎?(建構產物、快取、日誌、依賴、臨時取幀)
│ └─ 是 → 刪除 + 加進 .gitignore
├─ 能重新生成,但成本高?(成片、已驗收配音、渲染好的課包、訓練好的模型——要花時間、費用或重新驗收)
│ └─ 是 → 本地保留 + 加進 .gitignore + 登記到 tidy.json 的 keepLocal(寫明原因),README 寫明生成方式
├─ 是已被 git 追蹤的過時代碼嗎?
│ └─ 是 → 直接刪除(git 歷史就是歸檔)
├─ 不可再生,且仍有參考價值?(調研筆記、舊提示詞、設計稿、決策記錄)
│ └─ 是 → 移到 docs/archive/,檔案名加日期前綴,在 docs/archive/README.md 記一行原因
├─ 是大體積素材?(音視訊、資料集、模型)
│ └─ 是 → 不進 git(或用 Git LFS),README 寫明取得方式
└─ 不可再生,也沒有價值 → 列出來,使用者確認後刪除
歸檔細則見 references/docs.md。
參考檔案
| 檔案 | 內容 | 何時讀 |
|---|---|---|
| references/structure.md | 根目錄白名單、各類專案的標準目錄佈局(Node/TS、Remotion、Python、混合專案) | 決定檔案放哪、設計 layout |
| references/file-necessity.md | 判斷檔案是否必要、常見可刪樣板 | 判斷能不能刪 |
| references/naming.md | 各語言命名約定、禁止的命名模式 | 新建或重新命名檔案 |
| references/docs.md | README 最低要求、docs/ 佈局、歸檔規則 | 寫文件、歸檔 |
| references/config.md | .claude/tidy.json 欄位說明與範例 | 生成或修改目錄約定 |
| assets/README.template.md | README 模板 | 專案缺 README |
| assets/gitignore/ | .gitignore 片段:通用、Node、Python、媒體 | 補全忽略規則 |
| assets/agents-rules.md | 可貼進 AGENTS.md 的規則(給不支援 hooks 的其他 AI 工具) | 專案也用 Cursor / Codex 等 |