Claude Codeで/modelの「デフォルトとして保存」を使うとhooksが消える不具合を追った

Claude Codeで/modelの「デフォルトとして保存」を使うとhooksが消える不具合を追った

/modelでモデルを選んで「デフォルトとして保存」した瞬間、settings.jsonが古いスナップショットで丸ごと上書きされhooksが消える不具合をGitHub Issueの一次情報から整理した。

エンジニアのゆとです。

/modelでモデルを選んで「デフォルトとして保存」を選ぶ。それだけの操作で、settings.jsonに書いていたhooksが黙って消えることがある。しかもエラーは出ないし、modelの値自体はちゃんと新しいものに変わっている。壊れたのが分かりやすい形で壊れてくれるならまだいい。今回のはそうじゃなくて、一見すると保存は成功していて、消えたものだけが静かに消えているというやつだった。

2026年9月11日にanthropics/claude-codeへ報告されたIssue #93742がその実例で、報告者は~/.claude/settings.jsonをdotfilesリポジトリでgit管理していたおかげで、消えたタイミングと消えた内容を正確に特定できていた。この記事では、その報告の中身と、同じ症状を報告している別の2件のIssue、それに公式ドキュメントが今のところこの挙動をどこまでカバーしているかを整理する。

まず結論 — 長時間セッションで/modelの保存プロンプトを受けると起きる

Issue #93742の要点を先に書く。

症状: /modelでモデルを選び、「今後のセッションのデフォルトとして保存しますか」に「はい」と答えると、~/.claude/settings.jsonが丸ごと上書きされる。このとき書き込まれる内容は、そのセッションが起動した時点・または最後に読み込んだ時点でメモリに保持していた設定のスナップショットであって、ディスク上の最新の内容ではない。

影響: 報告者の環境では、直近3日以内に追加したPreToolUse/PostToolUseのhookエントリ5件が、この上書きで消えていた。危険なコマンドをブロックしたり、作業内容を検証したりするための安全装置が、マシン上の全セッションで約3日間、誰も気づかないまま無効化されていたことになる。

再現条件: 新しく起動したセッションからの保存では再現しない。古いセッション(長時間起動しっぱなし、または--resumeで再開したセッション)から/modelの保存プロンプトを受けたときにだけ起きる。報告者はこの条件を「ディスクを一度直して、新規セッションから保存 → 全19件が無事」「同じディスク内容から、古いセッションで保存 → 5件が消える」という比較実験で確認している。

github.com
Issue #93742 - /model save-as-default rewrites all of settings.json from a stale session snapshot git管理されたdotfilesリポジトリのコミット履歴を使って、消えたエントリの追加日時とシリアライザの指紋から上書きの仕組みを特定した報告。

なぜこんなことが起きるのか — 「スナップショット書き込み」という仕組み

報告者が挙げている3つの根拠が分かりやすかったので、そのまま紹介する。

  1. 時系列で綺麗に分かれる: 消えた5件のhookは全て2026-09-07 22:16〜2026-09-08 00:18の間に追加されたもので、生き残った12件は全て2026-08-27以前に追加されたものだった。例外は1件もない。部分的な書き込み失敗やランダムな破損なら、こんなに綺麗な日付の境界線は出ない。
  2. シリアライザの指紋: ファイル内の\uXXXXエスケープが、その書き込みで一斉にリテラルなUTF-8文字に変わっていた。Node.jsのJSON.stringifyはリテラルUTF-8を出力し、Pythonのjson.dumpはデフォルトでエスケープする。つまりこの書き込みはCLI自身のシリアライザによるもので、外部ツールが編集したのではない。
  3. modelだけ未来、他は過去: 書き込み後のファイルは、modelキーだけ新しく選んだ値になっていて、hooksブロックは古いスナップショットの内容に戻っていた。「現在の変更を、古い土台に適用した」状態であり、これはディスクを読んで書き戻す(read-modify-write)方式では起きない。メモリ上に保持していた古い設定を、そのまま丸ごと書き出す(スナップショット書き込み)方式だからこそ起きるパターンだと報告者は分析している。

つまり、長時間起動したセッションはその起動時点(または最後に設定ファイルを読み込んだ時点)のsettings.jsonの内容をメモリに持ち続けていて、/modelの保存操作がそのメモリ上の内容を丸ごとディスクに書き戻してしまう。その間に別のプロセスや別のセッションがsettings.jsonに追記していても、その追記分はメモリに反映されていないので、書き戻しと同時に消える。

公式ドキュメントは「書き込めない場合」しか想定していない

公式の設定ファイルと優先順位には、「Claude Codeで行った変更は新しいセッションで失われます」というトラブルシューティング項目がすでに存在する。

Claude Code内から新しいセッションの選択を保存する場合(/modelでデフォルトモデルなど)、Claude Codeはそれをユーザー設定ファイル~/.claude/settings.jsonに書き込みます。そのファイルに書き込むことができない場合(別のツールがそれを生成するか、読み取り専用コピーにリンクするため)、変更は現在のセッションに適用され、次のセッションで消えます。

ここで想定されている原因は「ファイルへの書き込み自体ができない」ケースだけで、「書き込みは成功するけど、その内容が古いスナップショットになっている」というIssue #93742のケースには触れていない。/statusで読み込まれたファイルを確認する手順や、優先順位が原因で値が無視されるケースの説明は充実しているんだけど、ファイルは書き込めていて、しかも壊れてもいないのに、意図しない内容で上書きされるという今回のパターンは、現時点でこのページの守備範囲の外にある。

Claude Codeのsettings.jsonが読み込まれない・反映されない原因を、公式ドキュメントとGitHub Issueの実例で整理した
Claude Codeのsettings.jsonが読み込まれない・反映されない原因を、公式ドキュメントとGitHub Issueの実例で整理したsettings.jsonは構文エラーが1つあるだけでファイル全体が丸ごとスキップされる。過去に報告された7件のGitHub Issueと公式ドキュメントの現在の挙動を照らし合わせ、症状別の原因切り分けと確認手順をまとめた。読む →

これは初めてじゃない — 同じ「スナップショット書き込み」系統の報告が過去にもある

報告者自身がIssue内で関連付けているとおり、この不具合は単発の事故ではなく、同じ仕組みで発生していると見られる報告が複数ある。

Issue #76749 — Windowsでsettings.jsonが{"env": {}}まで縮む

Issue #76749(2026-09-03クローズ)では、約15個のセッションを同時に開いていたWindows環境で、1.9KBあった~/.claude/settings.json(プラグイン12個・マーケットプレイス・permissions・model・theme等を含む)が、ある瞬間に{"env": {}}という15バイトのファイルに置き換わっていた。しかもこれは壊れたJSONではなく完全に有効なJSONで、キーの並び順もCLI自身のシリアライザと一致していた。報告者の推測は、大量のセッションが同時起動するタイミングか/model保存のタイミングで、いずれかのセッションが空に近い設定を一時的に読み込んでメモリに保持し、それを約2時間後のセッション終了時に書き戻した、というものだった。

Issue #93469 — ~/.claudeディレクトリごと初期化される

Issue #93469(現在オープン中)はさらに広い範囲が消えるパターンで、settings.jsonが{"model": "opus[1m]"}だけに縮んだのに加え、~/.claude/skills/配下のカスタムスキルとプロジェクトごとのmemory/フォルダが丸ごと消失していた。一方でOAuth・利用履歴を保持する~/.claude.json(起動回数209回、月単位の履歴あり)は無傷だった。報告者はWindowsのイベントログを確認し、外部ツールやMDMポリシーが介入した形跡がないこと、~/.claude/.last-cleanupというClaude Code自身が書き込むマーカーファイルの更新時刻が消失タイミングの直後にあることを突き止めている。

3件を並べると、共通しているのは「壊れたJSONではなく、有効なJSONとして意図的に上書きされる」「modelキーなど一部の新しい値だけは反映されている」という2点になる。プラットフォーム(Linux単一セッション/Windows多重セッション/Windowsの内部クリーンアップ処理)も引き金もバラバラなので、根本原因は1つに特定できていないが、症状の型は同じ系統だと考えたほうが対処しやすい。

Claude Code の --resume でセッションを復元する——クラッシュ後のリカバリと複数セッション管理の実践
Claude Code の --resume でセッションを復元する——クラッシュ後のリカバリと複数セッション管理の実践Claude Code の --resume フラグと会話履歴管理を徹底解説。クラッシュ後のセッション再開、セッションIDの特定方法、CLAUDE.md を使った状態の永続化、複数セッション並列管理まで実装例付きで解説。読む →

なぜこの不具合が特に厄介なのか

settings.jsonの内容が消えること自体は、報告者も書いているとおり「気づけば直せる」レベルの話ではある。厄介なのはhooksが消えるパターンとの組み合わせだ。

  • hookが発火しているのと、hookがそもそも存在しないのは、セッションの中からは見分けがつかない。ログにも出ないし、警告も出ない。
  • 今回消えた5件は、コマンド実行や完了報告の妥当性を検証するための安全装置だった。それが3日間、マシン上の全セッションで無効化されていたのに、見た目には何も異常がなかった。
  • settings.jsonの内側に「settings.jsonが壊れたら警告する」仕組みを置いても、それ自体が同じ書き込みで一緒に消えるので自己防衛にならない。

自分も似たような感覚をclaude-code-hooks-not-firing-guide-2026のときに書いたけど、あれは「設定は合っているのに発火しない」パターンで、今回は「設定自体が知らないうちに巻き戻る」パターン。原因のレイヤーが違うので、hooksが動かなくて困ったときのチェックリストをいくら丁寧にやっても、今回のケースには辿り着けない。

Claude Code hooksが動かない・発火しない原因を、公式トラブルシュートとGitHub Issueの実例から全部洗い出した
Claude Code hooksが動かない・発火しない原因を、公式トラブルシュートとGitHub Issueの実例から全部洗い出したClaude Codeのhooksを設定したのに動かない・発火しない原因を、公式ドキュメントの診断手順とGitHub Issueの実例をもとに整理。matcher・JSON構文・実行権限から、silentに死ぬ既知の不具合パターンまで症状別にまとめた。読む →

自分だったらどう検知・予防するか

Issue報告者が提案している修正案(保存直前にディスクから再読み込みしてマージする、変更したキーだけを書き込む)は、あくまでAnthropic側の実装待ちになる。ユーザー側でできることは「気づける状態にしておく」ことに尽きる。

1. ~/.claude/settings.jsonをgit管理する

報告者がこの不具合を特定できたのも、settings.jsonをdotfilesリポジトリでバージョン管理していたからだった。シンボリックリンクで運用しているならなおさら、git diff一発で「増えたはずのhookが消えている」ことに気づける。

cd ~/dotfiles
ln -sf ~/dotfiles/claude/settings.json ~/.claude/settings.json
git add claude/settings.json
git commit -m "add PreToolUse guard hooks"

以降は定期的にgit status・git diffを見るだけで、意図しない上書きを検知できる。手動チェックすら面倒なら、git log -p -- claude/settings.jsonをcronで日次実行してSlack/Telegramに投げる程度の仕組みでも十分。

2. ConfigChangeフックで自分自身のhooks件数を監視する

公式ドキュメントによれば、Claude Codeは検出した設定ファイルの変更ごとにConfigChangeフックを実行する。config_sourceフィールドでuser_settings(~/.claude/settings.json)の変更だけを拾えるので、変更のたびに現在のhooksブロックのエントリ数を記録しておけば、急に件数が減った瞬間を検知できる。

{
  "hooks": {
    "ConfigChange": [
      {
        "matcher": "user_settings",
        "hooks": [
          {
            "type": "command",
            "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/watch-hooks-count.sh"
          }
        ]
      }
    ]
  }
}
#!/bin/bash
# watch-hooks-count.sh — user settings変更のたびにhooks件数を記録し、減少したら警告
COUNT_FILE="$HOME/.claude/.hooks-count-history"
CURRENT=$(jq '[.hooks[]?[] | .hooks[]?] | length' ~/.claude/settings.json 2>/dev/null || echo 0)
LAST=$(tail -1 "$COUNT_FILE" 2>/dev/null || echo "$CURRENT")

if [ "$CURRENT" -lt "$LAST" ]; then
  echo "⚠️ settings.jsonのhooksが${LAST}件→${CURRENT}件に減少しました" >&2
fi
echo "$CURRENT" >> "$COUNT_FILE"
exit 0

これだけで完全に防げるわけではないけど、「静かに減った」ことにその場で気づけるだけでも、3日間気づかないよりはだいぶましになる。

3. 長時間セッションから/modelを保存しない

再現条件を踏まえるなら、一番シンプルな回避策は「hooksを追記した直後は、新しいセッションから/modelのデフォルト保存をする」こと。すでに開きっぱなしのセッションで/modelを選んだ場合、保存プロンプトで「はい」を選ばずに一度セッションを再起動してから保存すれば、少なくともIssue #93742で報告されている再現条件は避けられる。1セッションだけモデルを切り替えたいなら、/modelピッカーでsを押せばデフォルトを変更せずに切り替えられる、と公式ドキュメントにも明記されている。

Claude Codeの"Always allow"が効かない・保存されない原因を公式ドキュメントとGitHub Issueで切り分けた
Claude Codeの"Always allow"が効かない・保存されない原因を公式ドキュメントとGitHub Issueで切り分けた「Yes, and don't ask again」を選んでも毎回同じ許可を聞かれる問題を、allowルールの優先順位・workspace trust・Editツールとの競合など公式ドキュメントとGitHub Issueの一次情報から原因別に整理し、確認コマンドと対処法をまとめた。読む →

FAQ

hooksが本当に消えているか、今すぐ確認する方法は?

/hooksを実行して登録件数を目視するのが一番早い。git管理していない場合は、cat ~/.claude/settings.json | jq '.hooks'で現在の内容を確認し、自分で最後に設定した内容と記憶で突き合わせるしかない。今後のために、この記事を読んだタイミングで一度~/.claude/settings.jsonをどこかにバックアップしておくことを勧める。

/modelを使うたびに疑うべき?

いいえ。再現条件は「長時間起動・resumeしたセッションから保存プロンプトに『はい』と答えた」場合に限られていて、新規セッションからの保存では報告者自身が再現しないことを確認している。過度に恐れる必要はないが、hooksをsettings.jsonに追記した直後だけは注意したほうがいい。

macOS/Linuxでも起きる?

Issue #93742はLinuxでの単一セッションによる再現報告、Issue #76749はWindowsでの多重セッションによる報告で、プラットヲームを問わず起きている。OS依存の不具合ではなく、Claude Code本体の設定保存ロジックに起因すると考えたほうがいい。

すでに巻き込まれていた場合、消えたhooksを復元する方法は?

settings.jsonをgit管理していればコミット履歴から復元できる。していない場合は、hookスクリプト自体(.claude/hooks/配下のファイル)は多くの場合残っているはずなので、settings.json側のhooksブロックだけを記憶やドキュメントを元に書き直すことになる。これを機にgit管理へ移行するのが一番の対策だと思う。

hooksは「Claude Codeの挙動を決定論的に縛る」ための仕組みで、その性質上、静かに機能を失うこと自体がセキュリティ上のリスクになる。今回のケースは設定の書き方の問題ではなく、保存という操作そのものが引き金になっている分、いくら設定を丁寧に書いても防ぎきれない。せめて「消えたことに気づける」状態だけは作っておきたい。

code.claude.com
設定ファイルと優先順位 - Claude Code Docs スコープ・優先順位・トラブルシューティングを扱う一次情報。「変更が新しいセッションで失われる」項目はあるが、今回のスナップショット上書きパターンには触れていない。
github.com
anthropics/claude-code Issues 同じ症状の報告を検索したり、再現手順つきで新規に報告するならここ。
← 記事一覧に戻る