◉CLAUDE LABEN
●2.1.312 — 巨大な CLAUDE.md の上書きや、cd のあとにスキルが見つからない問題を修正しました●2.1.307 — スリープやキーチェーンロックのあとに MCP が再接続されない問題を修正しました(10/21)。2.1.306 では claude -p の誤表示も解消●SONNET 4.5 — Claude API での提供終了は 11/30、残り32日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●API — 新しい API バージョン 2026-10-21 では temperature・top_p・top_k を渡すと 400 になります●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました●2.1.312 — 巨大な CLAUDE.md の上書きや、cd のあとにスキルが見つからない問題を修正しました●2.1.307 — スリープやキーチェーンロックのあとに MCP が再接続されない問題を修正しました(10/21)。2.1.306 では claude -p の誤表示も解消●SONNET 4.5 — Claude API での提供終了は 11/30、残り32日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●API — 新しい API バージョン 2026-10-21 では temperature・top_p・top_k を渡すと 400 になります●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました
記事一覧/Claude Code
⟐ Claude Code/2026-10-29中級

大きな CLAUDE.md を丸ごと書き換えられたとき、消えた見出しを探して戻し、次から止める

Claude Code 2.1.312 で、先頭しか見ていない巨大な CLAUDE.md を Claude が上書きする不具合が直りました。それ以前の版で起きたときの見出しの差分の見つけ方、git での戻し方、Write を止めるフックの置き方を書き残します。

Claude Code279CLAUDE.md8トラブルシューティング65git19フック3rules

Claude Code 2.1.312 の changelog を読んでいて、ある一行で手が止まりました。「とても大きな CLAUDE.md や rules ファイルを、先頭しか見ないまま Claude が上書きしていた」という修正です。自分の CLAUDE.md が何文字あるのかを、その場で答えられませんでした。

個人開発のアプリの運用ルールや、サイトの更新手順を書き足し続けた私自身の CLAUDE.md も、気づくと全体が見渡せなくなっていました。そこへ「整理しておいて」と頼む。便利な頼み方ですが、相手が前半しか読んでいなければ、後半は存在しないものとして扱われかねません。

最初にお伝えしたいのは、2.1.312 以降は Write が「全部読むか、その場で編集するか」を Claude に求めるようになったということです。ただ、版を上げていない環境や、チームの誰かの手元では、まだ起きうる話です。そこで、起きたことに気づく方法、戻す方法、次から止める方法を、順に書き残します。

なお、Claude Code 自体の挙動は changelog の記述に沿ったもので、不具合の再現は試しておりません。手元で確かめたのは、受け止める側の道具です。12 章・8,552 文字の検証用 CLAUDE.md を作り、後半を落として書き戻した状態を作って、下のスクリプトを通しました。

なぜ「後半だけ消える」ことが起きるのか

仕組みは単純です。大きな指示ファイルは、Claude に先頭の一部だけが渡されることがあります。サブフォルダの CLAUDE.md に文字数の上限がかかる話は、サブフォルダの CLAUDE.md の後半だけが効かないとき、数えるのは容量ではなく文字数でしたに書きました。

見えているのが先頭だけの状態で、Claude が「このファイルを整理して書き直そう」と考え、Write で全文を置き換えたとします。すると、見えていなかった後半は、書き込む内容の中にそもそも含まれないのです。編集ではなく置換になるので、消えたことを知らせる警告も出ません。

changelog が対象に挙げているのは、CLAUDE.md、rules ファイル、そして @ で取り込まれたファイルのうちサブフォルダにあるものです。同じ症状は、この範囲の外でも、別の理由で起きうると考えておくほうが安全です。

手順1:版と、指示ファイルの大きさを確かめます

まず版です。2.1.312 より前なら、次の手順で網を張っておく価値があります。

claude --version

次に、プロジェクトの指示ファイルを大きい順に並べます。日本語のファイルは wc -c(バイト数)だと実際の文字数の 2〜3 倍に見えるので、wc -m をロケール固定で使います。

# 何を解決するか: どの指示ファイルが「先頭しか読まれない」大きさか、先に把握する
find . -type f \( -name CLAUDE.md -o -path '*/.claude/rules/*.md' \) \
  -not -path '*/node_modules/*' | while read -r f; do
  printf '%7s 文字  %s\n' "$(LC_ALL=C.UTF-8 wc -m < "$f")" "$f"
done | sort -rn | head

検証用のファイルでは、次のように出ました。同じファイルは、wc -c だと 22,552 でした。

   8552 文字  ./sub/CLAUDE.md
   8552 文字  ./sub/.claude/rules/a.md
   8552 文字  ./CLAUDE.md

LC_ALL=C.UTF-8 を付けているのは、ロケールが C のままだと wc -m もバイトを数えてしまうためです。この罠は、先ほどの記事でも手を取られたところでした。

手順2:消えたかどうかを、見出しで確かめます

「何かおかしい」と感じたとき、最初に見るのは git の差分の形です。置換で後半が落ちたファイルは、追加がごくわずかで、削除だけが大きく並びます。

git diff --numstat
# 1	138	CLAUDE.md   ← 追加 1 行、削除 138 行

追加が 1 行で削除が 138 行。この形を見たら、整理ではなく切り落としを疑います。内容を目で追う前に、消えた見出しを機械的に出してしまうのが早道です。

#!/usr/bin/env bash
# lost_headings.sh — 基準の版にあって、いまのファイルから消えた見出しを出す
# 使い方: lost_headings.sh CLAUDE.md [基準のリビジョン(既定 HEAD)]
set -euo pipefail
f="${1:?file}"; rev="${2:-HEAD}"
old="$(mktemp)"; trap 'rm -f "$old"' EXIT
git show "${rev}:${f}" > "$old"
echo "行数:   $(wc -l < "$old") -> $(wc -l < "$f")"
echo "文字数: $(LC_ALL=C.UTF-8 wc -m < "$old") -> $(LC_ALL=C.UTF-8 wc -m < "$f")"
echo "--- 消えた見出し ---"
diff <(grep -E '^#{1,4} ' "$old") <(grep -E '^#{1,4} ' "$f") | grep '^<' | sed 's/^< //' || true

検証用の切り落とし状態に当てた結果です。

行数:   206 -> 68
文字数: 8552 -> 2850
--- 消えた見出し ---
## 第5章 ルール5
## 第6章 ルール6
(中略)
## 第12章 ルール12

見出しで比べる理由は、本文の言い換えと区別がつくからです。Claude が文言を整えただけなら見出しは残ります。見出しが丸ごと消えているなら、それは整えたのではなく、落ちたのです。

手順3:戻します

差分が切り落としだけなら、コミット済みの版へ戻すのが最短です。

git restore CLAUDE.md

ただし、コミットしていない自分の編集も同じファイルに入っていた場合は、git restore でそれも消えます。その場合は、元の版を別名で取り出し、消えた章だけを手で戻します。

git show HEAD:CLAUDE.md > /tmp/CLAUDE.old.md
# 消えた章だけを /tmp/CLAUDE.old.md から開いて、いまのファイルに貼り直す

git で管理していないフォルダなら、Dropbox や iCloud などの同期サービスの版履歴が最後の砦になります。ただ、版履歴は探し当てるまでに時間がかかります。指示ファイルはかならず git に入れる——これだけは先に決めておくのが、結局いちばん楽です。

手順4:次から止めます

戻せたあとは、同じことが起きても被害が出ない形にしておきます。効果の大きい順に 3 つです。

1つ目は、頼む前にコミットすることです。差分が出るのは、基準があるからです。「整理してもらう」前の 1 コミットが、いちばん安い保険になります。

2つ目は、頼み方です。「この節だけ Edit で直して。全文の書き直しはしないで」と一言添えます。Edit はその場の置き換えなので、読んでいない部分には触れません。

3つ目は、Write を止めるフックです。指示ファイルを全文置換しようとして、見出しが消える、または大きく縮むときだけ、Claude に差し戻します。

#!/usr/bin/env python3
# .claude/hooks/guard_instruction_rewrite.py
# 何を解決するか: 指示ファイルが Write で全文置換され、後半が消えるのを書き込み前に止める
import json, os, re, sys
 
WATCHED = re.compile(r"(^|/)(CLAUDE(\.local)?\.md|\.claude/rules/.+\.md)$")
MIN_CHARS = 6000      # これより小さいファイルは素通し
SHRINK_LIMIT = 0.7    # 新しい内容が既存の 70% 未満なら止める
 
def headings(text):
    return [l.strip() for l in text.splitlines() if re.match(r"#{1,4} ", l)]
 
def main():
    # stdin はバイトで受けて UTF-8 に固定する(Windows の cp932 対策)
    data = json.loads(sys.stdin.buffer.read().decode("utf-8"))
    if data.get("tool_name") != "Write":
        return 0
    inp = data.get("tool_input", {})
    path = inp.get("file_path", "")
    if not WATCHED.search(path.replace("\\", "/")) or not os.path.isfile(path):
        return 0
    old = open(path, encoding="utf-8", errors="replace").read()
    new = inp.get("content", "")
    if len(old) < MIN_CHARS:
        return 0
    lost = [h for h in headings(old) if h not in set(headings(new))]
    ratio = len(new) / len(old)
    if lost or ratio < SHRINK_LIMIT:
        print(f"[guard] {path}: 既存 {len(old)} 文字 → 新規 {len(new)} 文字"
              f"({ratio:.0%})、消える見出し {len(lost)} 件。"
              "全文を Read で読み直すか、Edit で該当箇所だけ直してください。",
              file=sys.stderr)
        return 2   # 終了コード 2 で書き込みを止め、stderr を Claude に返す
    return 0
 
if __name__ == "__main__":
    sys.exit(main())

.claude/settings.json には、Write だけを対象に登録します。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/guard_instruction_rewrite.py\""
          }
        ]
      }
    ]
  }
}

標準入力に模擬のリクエストを流して確かめた結果は、次のとおりです。

書き込もうとした内容終了コード理由
先頭の 3 分の 1 だけ2(止まる)33% に縮み、見出し 8 件が消える
同じ内容のまま0(通る)変化なし
末尾に 1 節を追記0(通る)見出しは減らず、縮まない
第 5 章の見出し 1 行だけ削除2(止まる)100% でも見出しが消える
CLAUDE.md 以外のファイル0(通る)対象外

見出しを 1 行消しただけでも止まる点は、意図したものです。意図して章を削るときは、フックを一時的に外すか、Edit で消す運用にしています。

落とし穴

フックが守れるのは Write だけです。Bash の cat > CLAUDE.md のようなリダイレクトは、matcher が違うので素通りします。そこまで締めたい場合は、拒否ルールとの組み合わせを検討することになります。

もうひとつは、フックそのものが静かに効いていない可能性です。日本語のパスを扱うフックが一度も止めてくれなかった経緯は、日本語フォルダ名を守るはずのフックが、一度も止めてくれませんでしたに書きました。設定を足したあとは、かならず模擬の入力で一度止めてみてください。設定の JSON を壊したときの復旧は、壊れた settings.json で Claude Code が起動しなくなったときにまとめています。

しきい値の MIN_CHARS と SHRINK_LIMIT は、私の検証用ファイルに合わせた値です。ご自身のファイルの大きさを手順1で見たうえで、調整していただければ幸いです。

次に、1つだけ

全部読んでいない文書は、部分でしか直さないことにします。 この線引きを、頼み方の側にも、道具の側にも置いておきたいと考えています。

まずは手順1の find を 1 回だけ流して、いちばん大きい指示ファイルの文字数を確かめ、そのファイルをコミットしてください。フックを入れるのは、そのあとで十分です。検証用の環境でも、この順番で整えてまいりました。

シェア

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

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

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

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

関連記事

⟐ Claude Code2026-10-20
席を離れて戻ると会話に要約が差し込まれていた — アイドル圧縮の見分け方と、消したくない細部の残し方
v2.1.299 で入ったアイドル圧縮により、約54分放置した長い会話は自動で要約されます。何が起きたかの見分け方、止め方、そして要約に消されたくない前提を CLAUDE.md へ退避させる手順をまとめます。
⟐ Claude Code2026-10-28
決済ページから「戻る」と処理中のまま固まるボタンを、pageshow で直すと決めた理由。監査したら 3 ファイルに残っていました
Stripe などの外部ページから戻ると、決済ボタンが「処理中」のまま動かなくなる bfcache の症状を実ブラウザで再現し、pageshow と no-store の比較、リポジトリ監査スクリプト、CLAUDE.md の一行までをまとめます。
⟐ Claude Code2026-10-23
夜間の claude -p で MCP が「認証が必要」と出る朝に、Mac のスリープとキーチェーンを疑う順番
無人で回した claude -p の朝のログに「needs authentication」や MCP のタイムアウトが残っているとき、Mac のスリープとログインキーチェーンのロックを先に確かめる手順です。v2.1.307 で変わった挙動と、版を上げても残る部分の線引きをまとめました。