enforceAvailableModelsでDefaultモデルの抜け穴を塞ぐ — Claude Code
enforceAvailableModelsはavailableModelsだけでは効かないDefaultモデルの選択を許可リストの範囲に収める設定です。Defaultが書き換わる条件と、リストの書き方で結果が逆になる落とし穴まで扱います。
enforceAvailableModelsは何を解決する設定か
enforceAvailableModelsは、モデルピッカーの「Default」オプションが解決する先まで、availableModelsの許可リストの範囲に収める設定です。単独では動かず、availableModelsと組み合わせて初めて効きます。Claude Code v2.1.175以降で使え、既定値はfalseです。
falseのままなら、Defaultは従来どおりアカウント種別のランタイム既定値にそのまま解決され、許可リストの外にあっても素通りします。availableModelsだけを先に配って影響範囲を確認してからenforceAvailableModelsを有効にする、という段階導入もこの既定値のおかげで選べます。
Defaultの実体がアカウント種別でどう変わるかや、有効化前後の詳しい比較はClaude Code v2.1.175の解説にあります。ここでは設定キー自体の挙動と、リストの書き方で結果が変わる落とし穴を扱います。Defaultに切り替えられないときの切り分けはDefaultに戻せない原因の解説にあります。
なぜavailableModelsだけでは足りないのか
availableModelsは、モデルを名指しする経路のほぼ全てに効きます。/model・--modelフラグ・ANTHROPIC_MODEL環境変数、サブエージェントやスキルのfrontmatter、フォールバックチェーンまで対象です。ただし効くのは名指しされた選択だけです。
「Default」は名指しではありません。組織の既定モデルも、アカウントに記録されたモデルもない場合、アカウント種別のランタイム既定値に解決されます。Pro・Max・Team・Enterprise・Anthropic APIではOpus 5.5です(v2.1.280以降。それ以前は版ごとに異なります)。Claude Platform on AWS・Amazon Bedrock・Google CloudのAgent PlatformもOpus 5.5で、Microsoft FoundryではSonnet 4.5です。
許可リストにsonnetとhaikuしか入れていなくても、利用者が何も選ばずセッションを始めれば、リストの外のOpus 5.5が使われます。この抜け穴を塞ぐのがenforceAvailableModelsです。
Defaultはどう書き換わるのか
書き換えの判定は単純です。ただし「リストに入っているか」だけを見るので、リストの中身しだいで結果が変わります。
enforceAvailableModels: trueのときのDefaultの決まり方
- 1
Defaultの解決先を求める
組織の既定モデル、アカウントに記録されたモデル、アカウント種別の既定値の順で候補が決まります。
- 2
許可リストに入っているか見る
入っていれば書き換えは起きず、そのモデルがDefaultになります。
- 3
入っていなければ先頭エントリへ
リストの先頭から数えて、許可され利用可能なモデルを名指ししている最初のエントリに置き換わります。
/modelピッカーのDefault行にもそのモデルが表示されます。
書き換えは、起動時だけでなく/modelでDefaultを選ぶとき、フォールバックチェーンの"default"キーワード、除外された選択が捨てられたときの代替先にも及びます。ANTHROPIC_DEFAULT_MODEL環境変数は、enforceAvailableModelsがオンのとき無視されます。環境変数でDefaultを動かす経路も、この設定で閉じる側に入ります。
落とし穴: opusを許可リストに入れるとDefaultはOpusのまま
Defaultを安価なモデルに寄せるつもりで、次のように書いたとします。
{
"availableModels": ["haiku", "sonnet", "opus"],
"enforceAvailableModels": true
}この書き方では、Defaultはhaikuになりません。Pro・Max・Team・Enterprise・APIのDefaultはOpus 5.5で、opusは許可リストの中にあります。判定は「リストに入っているか」だけなので、書き換えは起きずDefaultはOpus 5.5のままです。
Defaultをhaikuへ寄せたいなら、リストからopusを外します。
同じ設定キーでも、リストしだいで結果が変わる
["haiku", "sonnet", "opus"]
Defaultの解決先(Opus 5.5)がリストに入っているため、書き換えは起きません。/model opusで名指しすることもできます。
["haiku", "sonnet"]
Opus 5.5がリストの外なので、先頭のhaikuに置き換わります。代わりに、/model opusのような名指しも拒否されます。
つまり「Defaultは安く、必要なときだけ手動でOpusへ」という運用は、この設定キーだけでは作れません。enforceAvailableModelsは、Defaultを許可リストの内側に閉じ込める設定であって、Defaultだけを別扱いにする設定ではないためです。初期モデルだけを変えたいなら、modelキーが別にあります。modelは起動時の初期選択にすぎず、利用者が/modelでDefaultを選べば、Opus 5.5(上記の条件下)へ戻れます。
個人設定でも組織の管理設定でも使えるのか
enforceAvailableModelsのスコープは、設定リファレンス上ではavailableModelsと同じ「Any file」です。ユーザー設定・プロジェクト設定・ローカル設定・管理設定のどこにも書けます。
ただし、組織が何らかの管理設定を配布している環境では、Claude Codeはこのキーを管理設定のソースからだけ読み、他のファイルの値を無視します。
管理設定が一切ない個人利用では、この制約は当てはまりません。モデルの設定ページが管理設定での配布を前提に書かれている点には注意が要ります。個人設定での動作は設定リファレンスのスコープ表記が根拠で、管理設定の例ほど詳しい記述はありません。
| 利用形態 | 効くか | 備考 |
|---|---|---|
| 個人利用(管理設定なし) | 効くか自分の設定が読まれる | 備考Defaultの解決先をリスト内に収めるコスト対策に使える |
| 組織(管理設定を配布) | 効くか管理設定側の値だけが有効 | 備考個人のuser/project設定に書いても無視される |
| 組織所属だが管理設定が未到達の端末 | 効くか個人設定が読まれる | 備考統制対象から外れている端末の可能性がある |
availableModelsのほうは、管理設定側で配布されたリストが単独で適用されます。ユーザー・プロジェクト・ローカル設定のエントリで広げることはできません。v2.1.175より前は、下位スコープのエントリが管理リストへ混ざっていました。管理設定がない個人利用では、ユーザー・プロジェクト・ローカルの各ファイルのリストが連結され、重複が除かれます。
プロジェクトの.claude/settings.jsonにもリストを書いている場合、どのエントリが先頭になるかは連結の結果で決まります。Defaultの置き換え先は先頭エントリなので、リストは1か所にまとめておくと挙動を追いやすくなります。
設定方法
組織でモデル利用を統制する場合は、managed-settings.jsonに次の形で書きます。
{
"availableModels": ["sonnet", "haiku"],
"enforceAvailableModels": true
}配置先はOSごとに決まっています。
- macOS:
/Library/Application Support/ClaudeCode/managed-settings.json - Linux / WSL:
/etc/claude-code/managed-settings.json - Windows:
C:\Program Files\ClaudeCode\managed-settings.json
2つのキーは、配布する管理ソースのうち最上位のものに両方そろえて置きます。既定では最上位のソースだけが読まれるため、管理コンソールが何らかの設定を配っていれば、ファイル側に置いたペアは無視されます。
順番を間違えやすいのが、availableModelsを書かずにenforceAvailableModelsだけtrueにするケースです。availableModelsが未設定または空のままだと、enforceAvailableModelsは何もしません。
設定が壊れているとき、読み込まれないときの挙動
スキーマに合わない値は、書いた場所によって扱いが変わります。
managed-settings.jsonの不正値には、キーごとのフォールバックが決まっています。availableModelsの値全体が不正なら、空の許可リストとして扱われ、Defaultしか使えません。個別のエントリだけが不正なら、そのエントリが取り除かれ、残りは有効です。一方、enforceAvailableModelsには、管理設定の不正値一覧に専用の行がありません。制限側の単一値を持つbooleanキーには、読めない値をその制限値として扱う一般規則があり(v2.1.282以降)、このキーも該当する可能性があります。ただし対象キーの列挙がないため、断定はできません。
非管理のファイルでは、claude doctorが不正な値を報告します。v2.1.287で、一時ディレクトリに次のプロジェクト設定を置いて実行しました。
{
"availableModels": ["haiku", "sonnet"],
"enforceAvailableModels": "yes"
}$ claude doctor
...
Invalid settings
- .../.claude/settings.json › enforceAvailableModels: Expected boolean, but received string
Suggested fix: Use true or false without quotes. Example: "includeCoAuthoredBy": true非管理のファイルでは、引用符で囲んだ"true"のような文字列もtrueとしては読まれません。doctorがExpected booleanと報告します。管理設定は扱いが違い、規則の対象になるbooleanキーでは"true"がtrueとして読まれ、/statusに引用符を外すよう促す注意が出ます(v2.1.282以降)。なお、Suggested fixの例文に出てくるincludeCoAuthoredByは、エラー文の定型例で、このキーとは関係ありません。
正しく読み込めていても、構成が行き詰まる場合があります。availableModelsが空でないのに、どのエントリも許可され利用可能なモデルに解決できないと、enforcement自体がスキップされ、Defaultはアカウント種別の既定値に戻ります。この警告は--debugでしか見えません。許可リストには、そのアカウントで確実に使えるモデルを最低1つ残しておくと避けられます。
availableModels: []と空配列で指定した場合は別の挙動で、名指しの選択がすべて拒否されます。enforceAvailableModelsは何もしません。
関連する設定と組み合わせるときの注意点
enforceAvailableModelsは単体で完結せず、関連設定と絡みます。
model: セッションの初期モデルを決めるキーです。値(--modelやANTHROPIC_MODELの指定も含む)が許可リスト外だと、起動時に警告が出て、既定モデルでセッションが始まりますfallbackModel: 過負荷時の自動切り替え先です。チェーンの各エントリも許可リストで絞り込まれるため、リストの外に置くと切り替え先が残りません。詳細はClaude Code fallbackModelで過負荷に備えるにありますmodelOverrides: Bedrock等のプロバイダー固有IDへのマッピングです。許可リストは、上書きした値ではなくAnthropicのモデルIDで判定されるため、"opus"のようなエントリは上書き後も一致しますdeniedModelsとavailableModelsMatch: 許可リストが通してしまう特定バージョンを塞ぐ管理設定のキーです。availableModelsMatchはModel IDエントリを、書かれたバージョンだけに絞りますmodelPicker(v2.1.242以降):/modelピッカーに出す選択肢を整えるキーで、enforceAvailableModelsの判定には関与しませんmaxEffortLevel(v2.1.267以降): モデルの制限とeffortの制限は別軸です。モデルを絞っても、effortは別にキャップしない限り高いレベルのまま動きます
組織の既定モデルの決め方はClaude組織のデフォルトモデル設定とロール別の優先順位で扱っています。
availableModelsの効果は、メインセッションだけではありません。サブエージェント・スキル・advisorが指定するモデルにも同じ許可リストが及びますが、外れたときの扱いは2種類に分かれます。
サブエージェントやチームメイトのオーバーライドが許可リスト外なら、リクエストを失敗させず、フォールバックモデルで実行されます。スキルやコマンドのオーバーライドが許可リスト外なら、その指定自体が無視され、セッションのモデルで実行されます。サブエージェント内で走るスキルは前者に従います。外部から取り込んだ定義の中身も確認しておくと、想定外の挙動を避けられます。
適用されているかを確認する方法
効いているかは、設定を置いた場所によって見る場所が違います。
管理設定は/statusで確認します。管理ソースが選ばれていれば、Setting sources行にEnterprise managed settingsとソースの種類が出ます。個人設定だけの運用では、この行にUser settingsやProject settingsが並び、Enterprise managed settingsの項目が含まれないのが正常です。
/status端末に複数の管理設定ソースがあるのに1つしか選ばれなかった場合は、Skipped sourcesという2行目が出ます(v2.1.242以降)。配布したファイルが効かないとき、原因が「届いていない」のか「届いたが優先度の高い別のソースに負けた」のかを、この行で切り分けられます。
ファイルの解釈を見たいときは、ターミナルからclaude doctorを実行します。不正な値は前述のようにInvalid settingsとして並びます。
claude doctor組織で配布した直後は、1台の端末で確認してから残りへ展開すると、トラブルを早く見つけられます。
v2.1.175とv2.1.176でどこまで塞がったか
enforceAvailableModelsが加わったv2.1.175では、Defaultが許可外のモデルに解決される場合に先頭の許可モデルへ戻るようになりました。同じ版で、ユーザー設定やプロジェクト設定が管理側のavailableModelsを広げられなくなっています。有効化前後の比較はClaude Code v2.1.175の解説にあります。
同日のv2.1.176では、別の抜け道が塞がれました。エイリアスで選んだモデルがANTHROPIC_DEFAULT_*_MODEL環境変数を通じてブロック対象へ振り替えられる経路と、/fastが許可外のモデルへ切り替える経路です。許可リストで統制する組織は、この2つの版以降を端末にそろえると、Default経由と環境変数経由の両方が閉じます。
組織全体の統制設計(配信経路・バージョン強制・サンドボックス強制との組み合わせ)はClaude Code組織管理ガイドで扱っています。
まとめ
この設定が答えるのは「Defaultを許可リストの外に出さない」ことだけです。「普段は安く、必要なときだけ上位モデル」を求めるなら、許可リストではなくmodelキーと運用ルールの側で設計することになります。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。