Crush 的設定檔是一段 Bash,Claude Code 的 JSON 也會跑指令:差別在誰替你點頭
一個 coding agent 的專案設定危不危險,要看它在你點頭之前做了哪些事。場景很普通:你 clone 了一個陌生的 repo,想叫 agent 幫你讀懂它,cd 進去,手指停在 Enter 上。repo 裡的設定檔你一行都還沒看,它卻會比你更早被 agent 讀進去。
直覺會說,答案取決於設定檔的格式。JSON 只是資料,不會動;Bash 會跑,所以危險。把 Crush 跟 Claude Code 的文件並排讀完,我覺得這個直覺只對一半,錯的那一半剛好是最該小心的地方。
Crush:設定檔本人就會動手
Crush 是 Charmbracelet 做的終端機 AI coding agent。2026 年 10 月 6 日用 GitHub API 查,它有 28,502 顆星,最新 release 是 9 月 29 日發布的 v0.97.1。我沒有安裝過 Crush,下面講它的部分全部出自 README 和 docs/config/README.md。
它的設定檔叫 crushrc,README 的形容很直接:「A crushrc is just Bash with some Crush-specific builtins. It’s a lot like a .bashrc, just for your Crush.」裡面可以寫 provider add、model add、permissions allow view edit 這類內建指令,也能寫一般的 Bash。README 的範例在 mcp add 的 header 裡用 $(op read ...) 去 1Password 拿 token,也示範了用 if [[ $HOSTNAME == ... ]] 依機器載入不同設定。
表達力很高。密鑰不用躺在設定檔裡,一行 $(...) 從密碼管理器拿;家裡和公司兩台機器共用一份設定,靠 if 分流。寫程式的人會喜歡這種設計,因為它就是程式。
麻煩在查找順序。Crush 會找 ./.crushrc、./crushrc、~/.config/crush/crushrc 三個位置,找到的全部合併,排越前面的越優先。專案目錄裡的設定,壓過你家目錄的那份。陌生 repo 如果帶了一個 .crushrc,它會跟你自己的設定一起跑,兩邊衝突時聽它的。
文件沒有迴避這件事。README 的「A note on security」原文是:
Both
crushrcandcrush.jsonare trusted code;crushrcruns in a full shell, and any$(...)incrush.jsonruns at load time. Don’t launch Crush in a directory whose config you haven’t reviewed, and don’t randomlysourcefiles from the internet into your config.
docs 那頁再補一句,這些設定「run with your shell privileges before the UI appears」。舊格式 crush.json 已經標成 deprecated,而且只有特定字串欄位(API key、URL、MCP 與 LSP 的指令和參數、headers)會在載入時做 shell 展開;crushrc 沒有這層限制,文件的說法是「it’s all just Bash」。
Crush 的信任邊界畫在你身上:開之前,自己讀。
我本來想找的是另一樣東西,第一次打開某個資料夾時,會不會跳一個「你信任這裡嗎」的確認。在 README、docs/config/README.md、docs/config/FUTURE.md 裡搜 trust,命中的只有上面那句「trusted code」。這只說明我讀到的文件沒寫,不代表程式裡沒有;原始碼我沒讀,Crush 也沒跑過。這題要回答得去翻原始碼,搜文件這條路走到這裡就斷了。
Claude Code:JSON 也會跑指令
換到 Claude Code,直覺錯的那一半就露出來了。
它的設定是 JSON,有公開的 schema(https://json.schemastore.org/claude-code-settings.json)。可是 JSON 裡有幾個欄位,填進去的就是指令:hooks 在事件發生時執行指令,apiKeyHelper 用你指定的指令產生 API 金鑰。env 雖然不是指令,卻會替每個 session 和它底下的子行程設定環境變數。格式是資料,內容照樣能動手。
優先序也沒站在你這邊。官方 settings 文件列的順序由高到低是 managed settings、命令列的 --settings、.claude/settings.local.json、.claude/settings.json,最後才是 ~/.claude/settings.json。專案層一樣壓過使用者層,跟 Crush 沒兩樣。
格式和優先序都對不上直覺,那差別在哪?在它把欄位分成兩種,各自在不同時間點生效。
想像你搬進一間別人住過的房子,門上貼著前房客留的紙條。紙條寫「多加一道鎖」,照做不會吃虧,最壞是自己進出麻煩一點。紙條寫「把備份鑰匙交給樓下那位」,就該先問這人是誰。Claude Code 處理專案設定的方式很像這樣。依 permissions 文件,專案層的 permissions.allow、additionalDirectories、extraKnownMarketplaces 和多數 env 值,要等你在 workspace trust 對話框按下接受才生效;deny 和 ask 不用等,原文是「deny and ask rules apply right away」。(deny 自己的優先序怎麼運作,之前拿 opencode 對照的那篇寫過,這裡不重談。)
那個對話框也不只問一句「你信任這裡嗎」。文件說它會列出這個資料夾要放行的規則和額外目錄,讓你接受之前先看過。session 裡用 /cd 換到沒信任過的資料夾時,提示還會連 hooks 和 helper commands 一起列出來,拒絕的話 session 就留在原地。
讀到這裡,Claude Code 看起來是把 Crush 交給你自律的那件事,做成了一道關卡。故事如果停在這裡很好收尾,可是同一頁還有另一張表。
那張表上寫著 Used
permissions 文件有一段「What runs before you trust a folder」,列了兩種沒有信任對話框的情境:一種是你只信任過它的上層資料夾,另一種是用 claude -p 或 SDK 在從沒信任過的資料夾裡執行。
這兩種情境下,settings 檔裡的 hooks、env 區塊、apiKeyHelper 這類 helper command,表上標的都是 Used,會被使用。標 Not used 的是 permissions.allow 和 additionalDirectories,另外專案 subagent frontmatter 裡的 hooks、@skills-dir plugin、extraKnownMarketplaces 也不用。-p 不跳對話框,只在 stderr 印一行 this workspace has not been trusted。
所以「Claude Code 在你信任之前什麼都不執行」是錯的。互動式 session 會先把你攔下來;-p 和 SDK 不會,專案設定裡那些會執行的東西照樣執行,被擋下的是擴權的 allow 規則、額外目錄,和上面列的那幾樣。
這條規則落的位置有點微妙。-p 和 SDK 都不經過互動畫面,如果你在 CI 裡拿它去跑別人送來的 PR,那份設定正是你最沒讀過的。互動模式有人坐在螢幕前,對話框有人看;沒人看著的時候,偏偏沒有對話框。
這個行為我只讀了官方那張表,沒有在本機用 -p 實際驗證。要在 CI 對外部 PR 跑 Claude Code 的話,permissions 文件另外提到 --bare 啟動時不讀專案的 hooks、skills、custom commands、subagents、plugins 和 .mcp.json,細節在 headless 文件,那頁我還沒打開。
兩條線畫在不同位置
Crush(crushrc) |
Claude Code(settings JSON) | |
|---|---|---|
| 設定格式 | 帶專屬指令的 Bash | JSON,有公開 schema |
| 設定裡會執行的東西 | 整份檔案,以你的 shell 權限執行 | hooks、apiKeyHelper 等 helper command;env 設定環境變數 |
| 專案層 vs. 使用者層 | ./.crushrc、./crushrc 優先於 ~/.config/crush/crushrc |
.claude/settings.local.json、.claude/settings.json 優先於 ~/.claude/settings.json |
| 第一次開資料夾的確認 | 我讀到的文件沒有描述 | 互動式 session 跳 workspace trust 對話框 |
| 你點頭之前就生效的 | 整份設定(文件原話:before the UI appears) | 文件明寫立即生效的是 deny、ask 規則 |
-p/SDK、只信任上層資料夾 |
我沒查到相關文件,也沒實際跑過 | hooks、env、apiKeyHelper 會被使用;allow、additionalDirectories 不生效 |
我的立場:要我選,我選 Claude Code 這種切法。收緊的規則誰寫都害不到你,讓它立刻生效;放寬的規則才需要你點頭。「要不要信任這個資料夾」從一整包的是非題,拆成只在擴權的地方問你。Crush 用 Bash 換來的表達力是真的,$(op read ...) 讓密鑰不落地;Claude Code 這邊要用指令拿 API 金鑰,得透過 apiKeyHelper 這種專門的欄位。Crush 付出的代價是,它的邊界只剩文件裡的一段提醒。
有三種情況會讓我改口。第一,如果 Crush 的原始碼裡有文件沒寫的信任提示,上面關於它的那一欄就得重寫,這點我沒查。第二,如果你只在自己寫的 repo、自己的機器上開 agent,這篇的差異幾乎都可以忽略,設定檔的作者就是你。第三,如果你主要在 CI 裡用 -p 跑,兩邊的距離比互動模式近得多:Claude Code 的對話框在那裡不會出現,hooks 照跑,你一樣得先讀過設定。
還有一件同時裝了兩個 agent 才會碰到的事。Crush 支援 Agent Skills 標準,README 列的搜尋路徑包括 ~/.claude/skills 和專案內的 .claude/skills。陌生 repo 裡替 Claude Code 準備的 skill,Crush 也會撈到。Crush 讀專案 .claude/skills 時受不受任何信任機制約束,文件沒寫,我也沒查到。
設定檔是資料還是程式,是你自己寫設定的時候才需要在意的事。打開別人的資料夾時,該問的是另一題:在我點頭之前,這個 agent 會替這份設定做什麼?Crush 的答案是整份照跑,所以它要你先讀 .crushrc、crushrc、crush.json。Claude Code 的答案在互動模式是先跳對話框,點頭前文件明寫會生效的只有收緊的 deny 和 ask;到了 -p,hooks、env、apiKeyHelper 照用,被擋下的是 allow 規則。兩個答案不同,你該先打開的檔案也就不同,而 .claude/skills 那個資料夾,兩邊都會看。
參考來源
- Crush repo 與 README(Configuration、A note on security、Agent Skills 段):https://github.com/charmbracelet/crush(星數與 release 為 2026-10-06 以 GitHub API 查詢的結果)
- Crush 設定文件:https://github.com/charmbracelet/crush/blob/main/docs/config/README.md
- Claude Code settings
- Claude Code permissions:Project allow rules and workspace trust、What runs before you trust a folder
- Claude Code security










