以前要決定 Claude Code 跑哪個模型,能動的地方只有兩個:~/.claude/settings.json 裡的 model,還有你在對話裡打的 /model。檔案管長期、指令管當下,衝突的時候誰贏也很直覺,就是後打的那個贏。整件事三十秒查得完。

八月過完之後,這個題目變成五個地方。

先說這篇跟站上另外兩篇的分工。〈Claude Code keybindings 完整教學〉那篇提過 modelPicker,但它整篇在講綁鍵,modelPicker 只是路過。〈pilotfish 把模型綁死在八個角色上〉那篇提過 CLAUDE_CODE_SUBAGENT_MODEL,講的是別人家專案怎麼設計角色分工,不是 Claude Code 自己的解析順序。站上也有不少「該選哪個模型」的選型建議。這篇跟那些都不同:不談選哪個,只談同一件事有五個地方可以設的時候,實際生效的是哪一個。

從前:檔案一層,指令一層

舊的心智模型只需要記一條規則。設定檔有層級(managed settings 最高,往下是 --settings.claude/settings.local.json.claude/settings.json~/.claude/settings.json),高的蓋低的。model 這個鍵就跟其他鍵一樣,照這個順序比大小。

環境變數在這個心智裡是「另一種寫設定的方式」,大家預設它排在某個位置,通常猜它比檔案高一點。猜得對不對其實沒差,因為以前也只有一個 ANTHROPIC_MODEL

現在:環境變數根本不在那個堆疊裡

settings 文件裡有一句話,把上面那套心智直接拆掉。逐字是這樣寫的:

Environment variables aren’t a level in this stack. When a behavior has both a shell variable and a settings key, which one applies is decided per pair, not by level: ANTHROPIC_MODEL exported in your shell applies over the model key from any file, while ANTHROPIC_DEFAULT_MODEL applies only when no file sets model.

同一個堆疊,兩個環境變數,一個在檔案的上面、一個在檔案的下面。它們不是「環境變數這一層」的兩個成員,它們各自跟 model 這個鍵單獨配對,各自約定誰大誰小。

這件事用開機票來想比較清楚。設定檔那五層像是公司的核銷規則:公司政策最大,接著是這趟出差的簽呈,再來是部門慣例,最後才是你自己的偏好,一層蓋一層。ANTHROPIC_MODEL 不在這條鏈上,它是一張已經開好的票,票在手上,上面所有規則都沒有意義。ANTHROPIC_DEFAULT_MODEL 也不在鏈上,但它站在另一頭:它是「沒有人填單的時候就照這個開」,只要任何一張單子填了,就輪不到它。

兩張票,一張在最前面,一張在最後面,中間夾著那五層檔案。

想給新 session 一個預設,以前只能寫死

以前想讓每個新 session 都從某個模型起跑,做法是把 model 寫進 ~/.claude/settings.json。但這個做法有個副作用:你在某個 session 裡用 /model 換過去之後,下次開新的又回到檔案裡那個值。你要的是「預設」,你設到的是「規定」。

ANTHROPIC_DEFAULT_MODEL 是 2.1.236 補上的,npm 上的發布時間是 2026 年 8 月 19 日。CHANGELOG 的描述是:它設定新 session 起跑的模型,而 /model 選過的仍然蓋得掉它,並且會跨重啟保存——這一點跟 ANTHROPIC_MODEL 不同。

差別就在這裡。一個是「除非你另有指示,否則從這裡開始」,一個是「不管你說什麼,就是這個」。以前只有後者,現在兩個都有,而且它們的名字只差一個 DEFAULT_

從前:/model 給你的清單就是那份清單

modelPicker 是 2.1.243 加的,npm 發布時間是 8 月 24 日,需要 v2.1.242 以上。它讓你自訂 /model 跳出來的那份清單。

真正值得記的是它的 scope。文件寫得很白:Claude Code 只從 managed settings、--settings 與 user settings 讀這個鍵,在 project 與 local 設定裡忽略它,理由是「so a repository you clone can’t relabel the picker」。你 clone 一個陌生的 repo,它的 .claude/settings.json 不能改你的模型清單。

還有一句:那三個來源裡最高的那個提供整份清單,Claude Code 從不把兩個來源的清單合起來。要嘛照它的,要嘛照你的,沒有混搭。

一個設定鍵的 scope 被刻意縮小,通常代表有人想過「如果這裡可以被別人寫,最壞會發生什麼」。這個問題比「這個功能要不要做」值錢得多。

CLAUDE_CODE_SUBAGENT_MODEL 這一格,八月翻了兩次

這一段是八月變動最劇烈的地方,而且它翻了兩次。

原本 CLAUDE_CODE_SUBAGENT_MODEL 的行為是覆蓋一切:你設了它,所有 subagent 都跑那個模型,agent 定義檔裡寫的 model: 不算數,派工時明確指定的也不算數。

2.1.251(npm 發布時間 8 月 28 日)把它改成只當預設。agent 定義檔的 model: 跟每次派工時明確指定的模型,都排在它前面。同一個版本還有另一件事:/effort 改成按模型分別記住預設的 effort 等級,不再是全域一個值。

然後 2.1.257(9 月 1 日,也就是昨天)加了 CLAUDE_CODE_SUBAGENT_MODEL_FORCE,把舊行為還回來:套用到每一個 subagent,忽略 per-spawn 與 agent 定義檔的覆寫。

8 月 28 日改掉語意,9 月 1 日給了一個開關可以翻回去,中間隔四天。如果你的腳本是 8 月 27 日寫的、機器上跑著 9 月 1 日的版本,中間這一段沒有任何東西會提醒你行為變了——它不會報錯,只會用不一樣的模型跑完。

/effort 那個改動也是同一種形狀。以前「我明明調過 effort 怎麼又變回去了」是玄學,現在它有解釋了:你調的是那個模型的 effort,換了模型就換一組。

真正變掉的是問題本身

把上面幾段疊起來看,這一年裡改變的不是選項變多。

以前這件事的問題是「我要用哪個模型」,那是一個選型問題,答案在你腦子裡,你想清楚了寫下去就結束。現在的問題是「這個 session 的模型是誰替我決定的」,那是一個解析問題,答案不在你腦子裡,在五個地方的優先序裡,而且那個優先序在八月被動了四次。

選型問題可以靠讀文章解決,解析問題不行。解析問題只能靠一句一句對規則,因為它會在你沒有做任何事的情況下變答案。

照文件組出來的話,大概是這樣分工:想固定整個團隊的模型,寫 managed settings;想固定自己一台機器的,寫 ~/.claude/settings.jsonmodel;想讓新 session 有個起點但保留 /model 的臨場覆寫,用 ANTHROPIC_DEFAULT_MODEL;想強壓所有 subagent 不留餘地,用 CLAUDE_CODE_SUBAGENT_MODEL_FORCE。這張表是我照文件的描述組出來的建議,不是官方推薦的組合。

誠實邊界

這篇的內容全部來自官方 settings 文件、settings reference 與 CHANGELOG。文件的兩句逐字引用(環境變數不是層級、modelPicker 的 scope)可以直接當事實看。

版本對應的日期不是從 CHANGELOG 讀的,因為 CHANGELOG 只有版本號沒有日期;那些日期是查 npm registry 的 time 欄位得到的。「四天內語意翻了一次又給了翻回去的開關」是比對 2.1.251 與 2.1.257 兩則 CHANGELOG 的描述得到的結論,不是實跑驗證的。

我沒有做的事:沒有實際設過 modelPicker、沒有測過任何一組優先序、沒有驗證過 subagent 模型的行為變化。上面每一句「誰壓過誰」都是文件寫的,不是我跑出來的。真的要把它寫進團隊的設定之前,自己開兩個 session 對照一次比較安全。