你在 auto mode 裡跟 Claude 一起改程式,想定一條規矩:push 之前一定要先問我。這句話該寫進 CLAUDE.md、在對話裡交代一聲、加進 settings 的 permissions.ask,還是寫進 autoMode.soft_deny?

官方的 auto mode 設定頁寫得很直白:auto mode 預設就允許 push 到你正在工作的 repo 的任何分支,包括 default branch,也允許開 pull request。只有名字看起來像部署或發布目標的非預設分支,例如 production、release、gh-pages,classifier 才會另外判斷,必要時當成正式部署來看。另一頁 permission-modes 則寫著,從 v2.1.283 起,auto mode 是所有方案、所有 provider 在互動終端與 VS Code session 的內建起始模式。2.1.283 上 npm 的時間是 2026 年 9 月 25 日;我寫這篇時(10 月 13 日)npm 最新版是 10 月 9 日上架的 2.1.296。

所以只要最近升過版,你很可能已經在 auto mode 裡了,而 push 不會先停下來問你。

能放這條邊界的地方,這篇比八個:對話、CLAUDE.md、permissions.ask、permissions.deny,以及 autoMode 底下的 soft_deny、hard_deny、allow、environment。我判斷該寫在哪,只問一件事:這條邊界,誰蓋得掉它?

一棟大樓的警衛

把 classifier 想成大樓門口的警衛。住戶進出要做什麼,大部分由他當場判斷。他會讀一本守則,也記得你剛剛跟他交代過的話。可是大樓裡有些門,在警衛被問到之前就已經上鎖了,輪不到他決定。

邊界寫在哪,決定的就是它屬於哪一種:警衛記得的事、警衛照守則判斷的事,還是根本不經過警衛的鎖。

官方文件自己也是這樣分的。auto-mode-config 頁有一張表,開頭那句是:

Pick the mechanism that matches how firm the boundary needs to be

表裡只有三列:要在動作前先問你,用 permissions.ask;永遠不准做,用 permissions.deny;只限這個 session 的一次性邊界,就在對話裡說,例如「don’t push until I review」。

對話裡說的話,會被整理掉

對話裡講的那句,classifier 確實會擋下符合的動作。問題在它存放的方式。permission-modes 頁說,這種邊界不會被存成規則,classifier 每次檢查都是從對話紀錄重讀一遍。所以只要 context compaction 把講那句話的訊息整理掉,邊界就跟著不見了。

像是貼在警衛桌上的便利貼。桌子一清,便利貼就沒了,警衛也不會記得它曾經存在。

這種邊界有一點設計得很好:它會一直有效,直到你在後面的訊息裡親口解除。Claude 自己判斷「條件已經達成」並不算數。可惜它撐不過 compaction,文件的建議也很乾脆,要持久的保證就改用 ask 或 deny rule。

CLAUDE.md:兩邊都讀得到的守則

CLAUDE.md 不在上面那張表裡,但文件另外交代了它的位置。classifier 讀的 CLAUDE.md 內容,跟 Claude 自己載入的是同一份,所以在專案的 CLAUDE.md 寫一句「never force push」,等於同時告訴了 Claude 跟 classifier。文件的說法是,專案慣例與行為規則從這裡開始寫。

permission-modes 頁也列出了 classifier 看得到的東西:使用者訊息、除了讀檔與搜尋這類唯讀查詢以外的工具呼叫,以及你的 CLAUDE.md 內容。工具執行的結果會被拿掉。

CLAUDE.md 適合放「我們這裡習慣這樣做」的事。它是給模型讀的文字,跟警衛手上那本守則一樣,有人在判斷。文件講到要持久或硬性的保證,指向的是 ask 或 deny rule,從來不是 CLAUDE.md。

ask 與 deny:在警衛被問到之前就定案

permission-modes 頁描述 classifier 怎麼處理每個動作時,用的是固定的決策順序,第一個符合的步驟定案。第一步就是:符合 allow、ask、deny 規則的動作,直接照規則處理(文件另列了幾個例外)。後面才輪到唯讀動作與工作目錄內的檔案編輯自動核准,再後面才送進 classifier。

所以「push 前先問我」最直接的寫法是這樣:

1
2
3
4
5
6
7
{
"permissions": {
"ask": [
"Bash(git push *)"
]
}
}

文件對 ask 的描述是:符合 content-scoped 規則的指令一律會跳出確認,classifier 沒辦法自動核准。換成 permissions.deny,就是在 classifier 被詢問之前直接擋掉,classifier 和使用者的意圖都蓋不過它。permissions 頁另外寫明了這三種規則彼此的順序:deny 先、ask 次、allow 最後,第一個符合的決定結果,規則寫得多精確都不會改變這個順序。

ask 有個洞,文件自己講出來了。這類規則比對的是「以 git push 開頭的指令」,Claude 如果寫成 git -C <dir> push 或 git -c <key>=<value> push,就不符合規則,這次 push 也就不會停下來問你。文件給的補法是加一支 PreToolUse hook,去檢查完整的指令文字。deny 規則的漏擋形態我在〈你寫的 deny 規則,可能根本沒擋到〉整理過,同一類問題。

還有一個容易忽略的細節。進入 auto mode 時,Claude Code 會先把幾種寬鬆的 allow 規則丟掉:整片放行的 Bash(*)、像 Bash(python*) 這種帶萬用字元的直譯器規則、套件管理器的 run 指令、Agent 與 Monitor 的 allow 規則;Bash(npm test) 這種窄規則則保留。離開 auto mode 時,被丟掉的規則會還原。照上面的決策順序推下去,這些規則原本放行的動作在第一步不再命中,就會往後落,可能被送去給 classifier 判斷。這是我從順序推的,文件沒有直接寫這句。

autoMode 那四格,比較像是拿來「放」的

autoMode 底下有四個清單。文件的定義是:hard_deny 是無條件的安全邊界;soft_deny 是使用者意圖可以解除的破壞性動作;allow 是 soft block 規則的例外;environment 告訴 classifier 哪些 repo、bucket、網域是可信的。四個清單裡的條目都是一句句自然語言,environment 那段還特別強調,不是 regex,也不是工具 pattern。

它們在 classifier 裡的順序,文件寫得很精確:hard_deny 先擋,而且無條件,使用者意圖與 allow 例外都不適用;接著是 soft_deny,這層可以被 allow 例外或使用者意圖解除;最後,如果你的訊息直接、具體地描述了 Claude 正要做的那個動作,剩下的 soft block 就會放行。

「具體」要多具體?文件舉的例子很好記:

Asking Claude to “clean up the repo” doesn’t authorize force-pushing, but asking Claude to “force-push this branch” does.

只講動詞也不夠。permission-modes 頁說,你的訊息要點出那個動作,以及讓它危險的那個具體對象,例如 force push 的是哪個分支。只說「you can force-push」,block 照樣在。而且這種當面核准預期只涵蓋一次動作,想讓某個例行模式不必一次次點頭,就把它加進 autoMode.allow。

文件說,對大多數組織而言,autoMode.environment 是唯一需要設的欄位。預設狀態下,classifier 只信任工作目錄與目前 repo 已設定的 remote;推到公司的原始碼組織、寫進團隊的雲端 bucket 這類動作,在你把它們加進 environment 之前都會被擋。classifier 拿 environment 來決定什麼叫「外部」,沒列進去的目的地,都可能被當成資料外流的去處。

鬆緊指引是這樣排的:classifier 一再誤擋某個例行模式,就加 allow;你的環境有內建規則沒涵蓋到的破壞性風險,才加 soft_deny;絕不能跨過的安全邊界,才加 hard_deny。要的如果是「照指令 pattern 在 classifier 之前硬擋」,文件明講用 permissions.deny。

什麼時候寫了 autoMode 反而更糟

換個方向問:寫了 autoMode.soft_deny,什麼情況下比不寫還糟?

第一種是寫錯檔案。classifier 不讀專案 settings 裡的 autoMode,也就是 .claude/settings.json 和 .claude/settings.local.json 都不算。理由是這兩個檔案都在 repo 目錄裡,一個 checked-in 的 repo 或某個 build step 就能塞進自己的 allow 規則。它只從三個地方讀:個人的 ~/.claude/settings.json、組織的 managed settings,以及 --settings flag 或 Agent SDK 傳進來的 inline JSON。依照 settings 分層的直覺,把 autoMode 放進專案設定是很自然的動作(分層的來龍去脈在〈設定檔為什麼長成五層〉),但在這裡它就是被無視。

第二種更危險,出在 "$defaults"。文件用 Danger 框標出來:environment、allow、soft_deny、hard_deny 任何一個,只要你設了陣列卻沒放 "$defaults",那一區的整份預設清單就會被你的內容取代。soft_deny 會丟掉每一條內建的 soft block,包括 force push、curl | bash、正式環境部署、繞過 auto mode;hard_deny 會丟掉內建的資料外流規則。

你想多擋一件事,結果把原本擋著的一整排都拆了。

保險的寫法是把 "$defaults" 留在陣列裡,再加你自己的條目,而且寫進 ~/.claude/settings.json:

1
2
3
4
5
6
7
8
{
"autoMode": {
"environment": [
"$defaults",
"Source control: git.example.com, including every repo under the example-org group"
]
}
}

第二行的內容是我編的示意,網域與組織名都是假的,重點在結構。"$defaults" 當成陣列裡的一個元素,官方設定頁的範例就是這樣寫,預設條目會插在它所在的位置,你的條目放前放後都行。我只讀了文件,沒有實際跑過這份設定,存檔後用下面提到的 claude auto-mode config 確認實際生效的規則。每一區是獨立評估的,只設 environment,allow、soft_deny、hard_deny 的預設清單都原封不動。真要拿掉 "$defaults"、自己接管整份清單,文件建議先跑 claude auto-mode defaults 印出內建規則,複製進設定檔,再逐條檢查。

第三種是團隊情境。各個 scope 的條目是疊加的,開發者可以補自己的 environment、allow、soft_deny、hard_deny,但刪不掉 managed settings 給的條目。偏偏 allow 在 classifier 裡就是 soft block 的例外,所以開發者自己加的一條 allow,可以蓋掉組織設的 soft_deny。文件的原話是這個組合「is additive, not a hard policy boundary」。組織若要一條不管使用者意圖、不管 classifier 怎麼設都不能跨的線,文件指的是 managed settings 裡的 permissions.deny。

我的選法

照「誰蓋得掉它」排一遍,我會這樣選:能寫成指令 pattern 的邊界,一律寫在 permissions,要問就 ask、絕對不准就 deny;autoMode 先只設 environment,用來告訴 classifier 你的世界有多大,而不是拿來擋東西。

會讓我改變想法的情況有兩個。一是邊界本身寫不成指令開頭,例如「原始碼不能送到我們以外的任何地方」,它在乎的是目的地,而 git push、curl、scp 都可能是那條路,pattern 列不完;這種邊界交給 classifier 用 environment 劃出「外部」,比硬湊 deny pattern 可靠。二是你非常在意 ask 那個 git -C <dir> push 的洞,那就照文件補 PreToolUse hook,而不是指望 soft_deny。

CLAUDE.md 留給專案慣例,對話留給「今天這個 session 先別 push」這種一次性的事。

設完之後可以接著做三件事。claude auto-mode config 會印出實際生效的規則;claude auto-mode critique 會讓 AI 檢查你寫的自訂規則,標出模稜兩可、重複、或容易誤擋的條目;/auto-mode-setup 會讀你的 CLAUDE.md、README、git remotes 和近期 session 的指令(文件特別註明不讀你的訊息),起草一份設定寫進 ~/.claude/settings.json,只能整份接受或整份捨棄,它需要 Pro、Max 或 Team 方案以及 v2.1.228 以上(2.1.228 上 npm 是 2026 年 8 月 11 日)。auto mode 本身的啟用方式與判斷邏輯,3 月那篇〈Claude Code Auto Mode〉寫過;它為什麼開始擋 git reset --hard,在 6 月那篇〈auto mode 學會踩煞車〉。

回到開頭那句「push 之前一定要先問我」:寫進 permissions.ask,今天就寫。

原文來源:Claude Code Docs:auto-mode-config(2026 年 10 月 13 日讀取)、Claude Code Docs:permission-modes、Claude Code Docs:permissions(後兩頁以 2026 年 10 月 12 日讀取的版本為準);版本發布時間取自 npm view @anthropic-ai/claude-code time(2026 年 10 月 13 日)。本文只讀文件,沒有實際執行任何 claude auto-mode 指令,也沒有寫過 autoMode 設定測試效果。