◉CLAUDE LABEN
●2.1.289 — Claude Code 2.1.289(10月3日)で、複合シェルコマンドの deny/ask ルールと、コードブロックでの端末フリーズが修正されました●10/07 — Claude Desktop / Cowork の管理構成キー旧綴りの受付終了まで残り2日。締切後は fail-closed で読み込まれません●ENV — DISABLE_TELEMETRY を 0 にしても無効にならない、という報告(#89386)が出ています。真偽値の読み方が論点です●NEW — 11月30日に止まる claude-sonnet-4-5、置き換え前に請求の差分を確かめる●MODS — Claude Code 2.1.287 から Claude Mods が入りました。プラグインがより深い挙動を変えられるようになります●CONN — 同じ Connector を別アカウントで使い分けたいという要望(#27302)に260件超のコメント。仕事用と私用の分け方を考える題材です●2.1.289 — Claude Code 2.1.289(10月3日)で、複合シェルコマンドの deny/ask ルールと、コードブロックでの端末フリーズが修正されました●10/07 — Claude Desktop / Cowork の管理構成キー旧綴りの受付終了まで残り2日。締切後は fail-closed で読み込まれません●ENV — DISABLE_TELEMETRY を 0 にしても無効にならない、という報告(#89386)が出ています。真偽値の読み方が論点です●NEW — 11月30日に止まる claude-sonnet-4-5、置き換え前に請求の差分を確かめる●MODS — Claude Code 2.1.287 から Claude Mods が入りました。プラグインがより深い挙動を変えられるようになります●CONN — 同じ Connector を別アカウントで使い分けたいという要望(#27302)に260件超のコメント。仕事用と私用の分け方を考える題材です
記事一覧/Claude Code
⟐ Claude Code/2026-08-21中級

ANTHROPIC_MODEL を消さないまま ANTHROPIC_DEFAULT_MODEL を足しても、始まるモデルは変わりません

v2.1.236 で追加された ANTHROPIC_DEFAULT_MODEL は ANTHROPIC_MODEL の後継ではありません。二つの効き方の違いと、モデル指定の散らばりを一覧する Python スクリプトをまとめました。

Claude Code260環境変数7モデル選択5設定管理5

同じリポジトリを、昼はエディタ内のターミナルから、夜は別のシェルから開いています。ある晩、夜のセッションだけが数世代前のモデル名で始まっていることに気づきました。

心当たりを探すと、原因は数か月前の自分でした。モデルを一時的に固定したくて ~/.zshrc に書いた export ANTHROPIC_MODEL=... の一行が、消し忘れたまま残っていたのです。設定ファイルではなくシェル設定に書いたものは、画面のどこにも出てきません。開くたびに黙って注入されるので、気づく手がかりが「なんとなく応答の質が違う」しかありませんでした。

v2.1.236 で ANTHROPIC_DEFAULT_MODEL が追加されたと知ったとき、最初は「これに置き換えれば解決する」と考えました。実際には違いました。二つは役割が別で、片方が残っている限りもう片方は表に出てきません。

二つの環境変数は、置き換えの関係にありません

ANTHROPIC_MODEL は以前からある変数で、設定されている間はセッションのモデルをそれに固定します。ANTHROPIC_DEFAULT_MODEL は v2.1.236 で追加されたもので、新規セッションが開始するモデルを決めます。セッション中に /model で別のモデルを選べば、そちらが優先され、その選択は再起動をまたいで保持されます。

つまり前者は「動かせない指定」、後者は「動かしてよい初期値」です。両方が設定されていれば、固定の側が勝ちます。ここを取り違えたまま新しい変数だけを足しても、始まるモデルは一つも変わりません。

指定の場所効く範囲セッション中に /model で変えられるか忘れやすさ
ANTHROPIC_MODEL設定されている間の全セッション意図した固定なので基本的に変えない高い(シェル設定に書くと画面に出ない)
ANTHROPIC_DEFAULT_MODEL新規セッションの開始時のみ変えられる。選択は再起動をまたいで残る中
settings.json の modelそのユーザー/プロジェクト変えられる低い(ファイルとして見える)
settings.json の env 内の指定そのプロジェクトの全セッション固定として振る舞う高い(model 欄しか見ない人には気づけない)

厄介なのは右の2列です。効き方が違うものが同じ「モデル名の文字列」として4か所以上に散らばり、そのうち二つは目に入りにくい場所にあります。私自身、原因を探すのに /status の表示と設定ファイルを何度も往復しました。

いま何がモデルを決めているかを一覧する

必要だったのは「どれが勝つか」を推測する前に、「そもそも何が設定されているか」を一画面で見ることでした。環境変数・ユーザー設定・プロジェクト設定・ローカル設定・シェル設定を横断して拾い、固定と初期値を区別して並べるだけの小さなスクリプトを書きました。

#!/usr/bin/env python3
"""Claude Code の実行モデルを決めうる設定を一覧し、食い違いを報告する。
 
使い方:
    python3 model_sources.py [プロジェクトのルート]
 
引数を省略するとカレントディレクトリをプロジェクトルートとみなす。
"""
import json
import os
import re
import sys
import unicodedata
 
# テストしやすいようにホームを差し替えられるようにしておく
HOME = os.environ.get("MODEL_SOURCES_HOME") or os.path.expanduser("~")
 
# 環境変数は「効き方」が違う。ここを混同すると再起動後の挙動を読み違える。
ENV_VARS = [
    ("ANTHROPIC_MODEL", "pin", "設定されている間は全セッションでこのモデルを使う"),
    ("ANTHROPIC_DEFAULT_MODEL", "default", "新規セッションの開始モデル。/model の選択が優先される"),
    ("ANTHROPIC_SMALL_FAST_MODEL", "aux", "補助処理用。メインの応答モデルは変えない"),
]
 
# 後ろにあるものほど近い設定(プロジェクト固有 > ユーザー全体)
SETTINGS_FILES = [
    ("ユーザー設定", os.path.join(HOME, ".claude", "settings.json")),
    ("プロジェクト設定", os.path.join("{root}", ".claude", "settings.json")),
    ("ローカル設定", os.path.join("{root}", ".claude", "settings.local.json")),
]
 
# 「昔書いて忘れている」定番の置き場所
PROFILES = [".zshrc", ".zshenv", ".bashrc", ".bash_profile", ".profile"]
 
JSONC_COMMENT = re.compile(r"^\s*//")
 
 
def load_jsonc(path):
    """// 行コメントを許容して JSON を読む。壊れていても落とさない。"""
    try:
        with open(path, encoding="utf-8") as fh:
            body = "".join(l for l in fh if not JSONC_COMMENT.match(l))
        return json.loads(body), None
    except FileNotFoundError:
        return None, None
    except (json.JSONDecodeError, OSError) as exc:
        return None, f"読み取り失敗: {exc}"
 
 
def collect(root):
    found = []
 
    for name, kind, note in ENV_VARS:
        value = os.environ.get(name)
        if value:
            found.append(("環境変数", name, value, kind, note))
 
    for label, template in SETTINGS_FILES:
        path = template.format(root=root)
        data, error = load_jsonc(path)
        if error:
            # 壊れた JSON を黙って無視すると「設定したのに効かない」の原因を見失う
            found.append((label, path, "-", "error", error))
            continue
        if not data:
            continue
        if data.get("model"):
            found.append((label, path, data["model"], "config", "設定ファイルの model"))
        nested = (data.get("env") or {}).get("ANTHROPIC_MODEL")
        if nested:
            found.append((label, path, nested, "pin", "settings の env が ANTHROPIC_MODEL を注入"))
 
    for name in PROFILES:
        path = os.path.join(HOME, name)
        try:
            with open(path, encoding="utf-8") as fh:
                lines = fh.readlines()
        except OSError:
            continue
        for lineno, line in enumerate(lines, 1):
            if "ANTHROPIC_MODEL" in line or "ANTHROPIC_DEFAULT_MODEL" in line:
                found.append((
                    "シェル設定", f"{path}:{lineno}", line.strip(), "shell",
                    "新しいシェルを開くたびに再注入される",
                ))
    return found
 
 
def display_width(text):
    """全角を2桁として数える。日本語ラベルの表を崩さないため。"""
    return sum(2 if unicodedata.east_asian_width(ch) in "WF" else 1 for ch in text)
 
 
def pad(text, width):
    return text + " " * max(0, width - display_width(text))
 
 
def main():
    root = sys.argv[1] if len(sys.argv) > 1 else os.getcwd()
    rows = collect(root)
 
    if not rows:
        print("モデルを決めている設定は見つかりませんでした(CLI の既定に従います)")
        return 0
 
    width = max(display_width(r[0]) for r in rows)
    print(f"{pad('区分', width)}  種別        値 / 場所")
    print("-" * 72)
    for origin, where, value, kind, note in rows:
        print(f"{pad(origin, width)}  {kind.ljust(8)}  {value}")
        print(f"{' ' * width}            └ {where} — {note}")
 
    pins = {r[2] for r in rows if r[3] == "pin"}
    defaults = {r[2] for r in rows if r[3] in ("default", "config")}
 
    print()
    if len(pins) > 1:
        print(f"⚠ 強制指定が {len(pins)} 種類あります: {', '.join(sorted(pins))}")
    if pins and defaults - pins:
        print(f"⚠ 強制指定 {sorted(pins)} があるため、既定値 {sorted(defaults - pins)} は効きません")
    if not pins and len(defaults) > 1:
        print(f"ℹ 既定値の候補が {len(defaults)} 種類あります(より近い設定が勝ちます)")
    return 1 if len(pins) > 1 else 0
 
 
if __name__ == "__main__":
    sys.exit(main())

意図的にそうした点が三つあります。

一つ目は、settings.json の env の中まで見ていることです。model 欄だけを確認して「プロジェクト設定は空だから関係ない」と判断すると、いちばん見つけにくい固定を見落とします。

二つ目は、壊れた JSON を握りつぶさず error として行に出していることです。設定ファイルが構文エラーで読み飛ばされているとき、症状は「設定したのに効かない」になります。原因と症状が離れているので、ここは沈黙させたくありませんでした。

三つ目は、固定が複数見つかったときに終了コード 1 を返すことです。目視で眺めるだけなら不要ですが、個人開発では設定を見直す担当が自分ひとりしかいません。この手のものは、眺めるのをやめた頃に静かに壊れます。

手元で走らせた結果

私の設定を模した一式(ユーザー設定・プロジェクト設定・ローカル設定・シェル設定・環境変数)に対して実行した出力です。

区分              種別        値 / 場所
------------------------------------------------------------------------
環境変数          pin       claude-opus-4-1-20250805
                            └ ANTHROPIC_MODEL — 設定されている間は全セッションでこのモデルを使う
環境変数          default   claude-sonnet-5
                            └ ANTHROPIC_DEFAULT_MODEL — 新規セッションの開始モデル。/model の選択が優先される
ユーザー設定      config    claude-sonnet-5
                            └ /home/me/.claude/settings.json — 設定ファイルの model
プロジェクト設定  config    claude-opus-5
                            └ /work/proj/.claude/settings.json — 設定ファイルの model
プロジェクト設定  pin       claude-opus-5
                            └ /work/proj/.claude/settings.json — settings の env が ANTHROPIC_MODEL を注入
ローカル設定      config    claude-haiku-4-5-20251001
                            └ /work/proj/.claude/settings.local.json — 設定ファイルの model
シェル設定        shell     export ANTHROPIC_MODEL="claude-opus-4-1-20250805"
                            └ /home/me/.zshrc:2 — 新しいシェルを開くたびに再注入される
シェル設定        shell     export ANTHROPIC_DEFAULT_MODEL="claude-sonnet-5"
                            └ /home/me/.bash_profile:1 — 新しいシェルを開くたびに再注入される
 
⚠ 強制指定が 2 種類あります: claude-opus-4-1-20250805, claude-opus-5
⚠ 強制指定 ['claude-opus-4-1-20250805', 'claude-opus-5'] があるため、既定値 ['claude-haiku-4-5-20251001', 'claude-sonnet-5'] は効きません

読み方は単純です。8行のうち、実際に始まるモデルを決めているのは上から1行目だけで、残り7行のうち4行は書いた本人が「効いているはず」と思っている指定です。ANTHROPIC_DEFAULT_MODEL も、ユーザー設定の model も、ローカル設定の model も、この状態では一度も参照されません。

シェル設定の行から ANTHROPIC_MODEL を消し、プロジェクト設定の env からも外すと、同じスクリプトの出力はこうなります。

区分              種別        値 / 場所
------------------------------------------------------------------------
環境変数          default   claude-sonnet-5
                            └ ANTHROPIC_DEFAULT_MODEL — 新規セッションの開始モデル。/model の選択が優先される
ユーザー設定      config    claude-sonnet-5
                            └ /home/me/.claude/settings.json — 設定ファイルの model
プロジェクト設定  config    claude-opus-5
                            └ /work/proj/.claude/settings.json — 設定ファイルの model
ローカル設定      config    claude-haiku-4-5-20251001
                            └ /work/proj/.claude/settings.local.json — 設定ファイルの model
シェル設定        shell     export ANTHROPIC_DEFAULT_MODEL="claude-sonnet-5"
                            └ /home/me/.bash_profile:1 — 新しいシェルを開くたびに再注入される
 
ℹ 既定値の候補が 3 種類あります(より近い設定が勝ちます)

警告が「食い違い」から「候補が複数ある」に変わりました。この状態なら、どれが選ばれても /model で上書きできます。固定が消えた時点で、設定は読み手にとって理解可能なものに戻ります。

なお、このスクリプトが答えるのは「何が設定されているか」までです。「結局どれが勝つのか」は、claude を起動して /status の表示で確かめるのが確実です。バージョンによって優先順位の細部が変わる可能性がある以上、一覧と実測は分けておいたほうが安全だと考えています。

私の設定をどこに落ち着かせたか

個人開発で iOS と Android のアプリを並行して触っていると、リポジトリごとに求めるモデルが違ってきます。既存コードの読み解きが中心のプロジェクトと、まっさらな画面をゼロから組むプロジェクトでは、同じモデルが最適とは限りません。それでも指定の置き場所は減らしたほうがよい、というのが今回の結論でした。

何度か入れ替えてみて、私はこの形に落ち着きました。

  1. シェル設定からは、モデル指定を完全に消す。 見えない場所で効くものを一つも残さない、というのが最優先でした
  2. 常用モデルは ANTHROPIC_DEFAULT_MODEL に一本化する。 初期値として置き、その日の作業に応じて /model で動かします
  3. プロジェクトごとの違いは .claude/settings.json の model に書く。 ファイルとして残るので、半年後の自分にも見えます
  4. 固定したい場面では、そのコマンドの前だけに付ける。 恒久設定にせず ANTHROPIC_MODEL=claude-haiku-4-5-20251001 claude -p "..." の形で寿命をコマンド1回に閉じ込めます

4番目が今回いちばん効きました。固定は必要な道具ですが、寿命を長くした瞬間に「忘れられる設定」に変わります。プロファイルに書くのではなく実行するコマンドに添えるだけで、後から原因を追う必要がほぼなくなりました。

モデルの選び分けそのものについては、Claude Code のモデル選択戦略 に用途別の考え方をまとめています。無人で走らせるジョブがどのモデルで実行されたかを記録として残す方法は、昨夜の無人セッションはどのモデルで走ったのか で扱いました。

変更したあとに確かめる三つのこと

設定を触ったら、その場で次の三つを通しておくと、後から悩む時間がなくなります。

まず、新しいシェルを開いて env | grep ANTHROPIC を実行します。編集中のシェルには古い値が残っているので、必ず開き直してから確認します。ここで出てくるものが、次のセッションに持ち込まれるものです。

次に、claude を起動して /status で実行中のモデルを見ます。一覧と実測が一致していれば、その設定は自分の理解どおりに効いています。

最後に、スクリプトを終了コードごと使う場所に置きます。私は無人で走らせるジョブの前処理に入れて、固定が二つ以上見つかったらジョブを止めるようにしました。クレジットの上限管理まで含めて固定を仕組みとして扱いたい場合は、enforceAvailableModels で実行モデルを固定する のほうがより踏み込んだ設計を書いています。

今日できる最初の一歩としては、grep -rn ANTHROPIC_MODEL ~/.zshrc ~/.bashrc ~/.profile を一度走らせてみてください。何も出なければ、少なくとも見えない固定は存在しません。何か出てきたら、それがいま実際にモデルを決めています。

お読みいただきありがとうございました。設定の整理は地味な作業ですが、原因の分からない挙動が一つ減るだけで、翌日の集中の質がずいぶん変わると感じています。

シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

⟐ Claude Code2026-09-25
既定の Opus が 5.5 に変わった週、別名のまま残していた3箇所を数えました
Claude Code 2.1.280 で Opus 5.5 が既定になり、Pro の既定モデルも Sonnet から Opus へ変わりました。設定を触る前に確かめた3点(別名の解決先・/effort の引き継ぎ・キャッシュ読み $0.20 の見込み)を、手元で使った確認スクリプトと一緒に書き残します。
⟐ Claude Code2026-09-20
Pro を払っているのに Console に請求が立っていたとき、私が最初に見た一行
サブスクリプションと API の従量は別会計で、Claude Code はそのどちらでも動きます。どちらが選ばれているかを決めるのは優先順位で、ログインはその最下段です。status の読み方と、無人実行だけが別の答えを返す理由を書き残します。
⟐ Claude Code2026-09-12
巡回タスクが朝まで返らなかった原因は、WebFetch の待ち時間に上限がなかったことでした
Claude Code v2.1.268 で WebFetch に 300 秒の期限が付きました。応答を閉じないサーバーに当たると無人実行がどこで止まるのか、CLAUDE_CODE_WEBFETCH_DEADLINE_MS の 0 がなぜ「待たない」ではないのかを、手元で再現できる形で整理します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます