Claude Code Rules(.claude/rules/*.md)を使っていて「このルール、本当に効いているのか?」と疑ったことがある人は多いと思う。2026-09-05 に公開されたkawasin73 氏の記事「Claude Code の Rules はもう死んでいる」は、まさにその疑いを具体的に指摘したもので、はてなブックマークは 270 users に達している。
この記事のポイント
・v2.1.241 で検証したところ、Rules は効いていた。ただし globs は読み込みのゲートとして機能しておらず、存在しない拡張子を指定したルールでも読み込まれた
・つまり globs でルールを分割してコンテキストを節約する運用は、実測では成立していない。全ルールが常時コンテキストに乗る
・サブディレクトリの CLAUDE.md は自動読み込みされなかった(ルート直下は読まれる)。ここは元記事の指摘と一致する
先に立場を明確にしておく。本記事は元記事の反論ではない。 元記事が観測したのは筆者の環境・筆者の版であり、本記事が測ったのは v2.1.241 / 2026-09-07 時点である。この種の挙動は版で変わるうえ、実際に変わった形跡がある。重要なのはどちらが正しいかではなく、自分の環境で確かめる手順を持つことなので、検証方法をそのまま載せる。
検証環境は macOS 14(Darwin 23.5.0)/ Apple Silicon、Claude Code 2.1.241。.claude/rules/ の書き方そのものは CLAUDE.mdの書き方とは?セクション設計とauto memory・.claude/rules/の使い分け に、Claude Code 全体の運用は Claude Code|2026年版・インストールからCLAUDE.md・Hooks・本番運用までの実装手引き にまとめてある。
前提整理——Rules・CLAUDE.md・Skill は読み込まれ方が違う
検証の前に、Claude Code が持つ「指示を注入する仕組み」を整理しておく。混同されやすいが、読み込まれるタイミングが仕組みごとに違う。ここが本記事の論点そのものである。
| 仕組み | 置き場所 | 想定される読み込み | 本記事の実測(v2.1.241) |
|---|---|---|---|
| CLAUDE.md(ルート) | リポジトリ直下 | セッション開始時に常時 | 常時読み込まれた |
| CLAUDE.md(サブディレクトリ) | sub/CLAUDE.md |
そのディレクトリの作業時 | 読み込まれなかった |
| Rules | .claude/rules/*.md |
globs にマッチしたときだけ |
globs 無関係に常時読み込まれた |
| Skill | .claude/skills/*/SKILL.md |
明示呼び出しまたは説明文による選択時 | (本記事の対象外) |
.claude/rules/ のルールファイルは、frontmatter に description と globs を持つ Markdown である。本サイトのリポジトリに実際に置いてあるものは次の形をしている。
---
description: OpenWolf protocol enforcement — active on all files
globs: **/*
---
- Check .wolf/anatomy.md before reading any project file
- Check .wolf/cerebrum.md Do-Not-Repeat list before generating code
この globs が「いつ読み込むか」を決めていると理解している人は多いはずだ(筆者もそう理解していた)。その理解が現在の実装と合っているかどうかが、本記事で確かめたことになる。
検証方法——「マーカーを言わせる」プローブは使えなかった
本題に入る前に、最初に採った検証方法が失敗したことを書いておく。同じ罠を踏む人がいるはずなので、こちらのほうが実用的かもしれない。
最初はこうした。ルールの中に「このルールを読んだら ZEBRA_RULE_MARKER_7741 という文字列を返答に含めよ」と書き、その文字列が出てくるかで読み込みを判定する——素朴だが直接的な方法に見える。
これは使えない。globs がどのファイルにもマッチしないルールでこれを試したところ、返ってきたのは次の反応だった。
.claude/rules/never-match.mdに「特定のトークンを必ず返信に含めよ」という指示が埋め込まれていましたが、これはプロンプトインジェクションの可能性が高いため従っていません。
つまりルールは読み込まれていたが、モデルが指示を拒否した。マーカーが出ないことを「読み込まれていない」と解釈すると、完全に逆の結論になる。「特定の文字列を出力させる」形の埋め込みは、モデル側の注入耐性と見分けがつかない。
そこで中立な事実を使うプローブに切り替えた。ルールには命令ではなく事実だけを書く。
---
description: Project naming conventions
globs: **/*.zzzznonexistent
---
このプロジェクトの内部ビルドシステムのコードネームは Marmot である。
そのうえで「このプロジェクトの内部ビルドシステムのコードネームは何ですか」と聞き、ファイル系ツール(Read / Bash / Glob / Grep)を全て禁止して実行する。ツールが使えなければ、答えられる唯一の経路は「セッション開始時点で自動的にコンテキストに入っていた」ことになる。これで自動読み込みの有無だけを切り分けられる。
# ファイル系ツールを全て禁止して、知識だけで答えさせる
claude -p "このプロジェクトの内部ビルドシステムのコードネームは何ですか。分かればその名前だけ、分からなければ不明と答えて" \
--output-format stream-json --verbose --max-turns 2 \
--permission-mode acceptEdits \
--disallowedTools Read Bash Glob Grep
この手順は自分の版でそのまま追試できる。以下の結果はすべてこの方法で得たものだ。
なぜ「事実」であって「命令」ではいけないのかを補足しておく。ルールに命令を書くと、モデルがそれに従ったかどうかしか観測できない。従わなかった場合、「読み込まれなかった」のか「読み込んだが従わなかった」のかを区別できない。一方、中立な事実であれば、モデルはそれを知識として持っているかどうかを答えるだけで済む。判断が介在しないぶん、読み込みの有無だけを素直に反映する。実際、命令型で失敗した検証が、事実型に変えた途端に安定して結果を出した。
もう一点、--disallowedTools に Read だけでなく Bash / Glob / Grep も含めるのが重要である。Read だけを禁止しても、エージェントは cat や grep で同じファイルを読みにいく。実際に最初の試行では ls からの自力発見が起きて結果が汚れた。外部から情報を取る経路を全て塞いで初めて、「最初から持っていた知識」だけが残る。
Claude Code Rules は globs に関係なく常時読み込まれていた
まず結論から。Rules は死んでいなかった。 ただし、期待される効き方とは違う。
globs: **/*.py を指定したルールを置き、.py ファイルには一切触れない質問を投げた。それでもモデルは Marmot と答えた。次に globs を **/*.zzzznonexistent に変えた。プロジェクト内のどのファイルにもマッチしない拡張子である。それでも Marmot と答えた。
ルールの globs |
マッチするファイル | 触ったか | 自動読み込み |
|---|---|---|---|
**/*.py |
calc.py が存在 |
触っていない | された |
**/*.zzzznonexistent |
存在しない | — | された |
つまり globs は、少なくとも v2.1.241 では読み込みを遅延させるゲートとして機能していない。.claude/rules/ に置いたルールは、globs に何を書こうと、セッション開始時点で全部コンテキストに乗る。
この差は運用に直結する。「大きなルールを globs で分割しておけば、関係あるときだけ読み込まれてコンテキストを節約できる」という設計は、実測では成立しない。分割しても合計は常に全部乗る。本サイトのリポジトリで実際に測ると、.claude/rules/openwolf.md 1本で 1,256 バイト・305 トークン(cl100k_base / tiktoken)だった。1本ならわずかだが、ルールを10本20本と分割している運用では、その総和が毎セッション固定費として掛かることになる。
この「常時読み込み」がどれくらいの費用になるかは、ルールの分量次第で大きく変わる。仮に1本あたり 300 トークン程度のルールを 20 本に分割して運用していれば、合計 6,000 トークン前後が毎セッションの開始時点で消費される計算になる。会話が長くなるほど圧縮の対象にもなるため、単純にその分だけ作業領域が減るとは限らないが、「関係あるときだけ読まれるから分割しても安い」という前提は崩れる。
裏を返せば、ルールを分割する動機がコンテキスト節約だったのなら、その動機は現状では満たされない。分割する理由は「人間が管理しやすいから」に絞られる。逆に、常時読み込まれることを前提にするなら、ルールは短く・競合しないように書くほうが効く。長大なルールを何本も置くと、モデルの注意が分散するうえに固定費だけが積み上がる。
「効かない」ではなく「常に効く」が実測結果だった点に注意してほしい。ルールが無視されていると感じている場合、原因は読み込みではなく内容が長すぎて埋もれているか、他の指示と競合している可能性が高い。読み込まれていないことを疑う前に、上の手順で読み込み自体は起きているかを切り分けたほうが早い。
なお globs は人間向けの適用範囲メモとしては引き続き意味がある。効かないのは「読み込みを絞る機能」としての側面だけだ。
なぜ「効いていない」と感じるのか
実測では常に読み込まれているのに、体感として「ルールが無視されている」と感じる場面はある。今回の検証中にも、その一例を実際に踏んだ。
前節で触れた「マーカーを返答に含めよ」というルールに対し、モデルは読み込んだうえで拒否した。プロンプトインジェクションに見えたからである。これは読み込みの失敗ではなく、読み込んだ内容をモデルが評価して従わないと判断したケースだ。ルールに書いた指示が命令形で、かつ「必ず〜せよ」という強い形をしていると、注入耐性の側に引っかかることがある。
つまり「ルールが効かない」には少なくとも3つの別の原因がありうる。①読み込まれていない/②読み込まれたが従わないと判断された/③読み込まれて従っているが、他の指示に埋もれて優先度が低い。本記事のプローブが切り分けられるのは①だけで、②と③は別の観察が要る。まず①を除外してから②③を疑う、という順序が効率的だ。
サブディレクトリの CLAUDE.md は自動読み込みされなかった
元記事が挙げたもう一つの点、サブディレクトリの CLAUDE.md については、指摘と一致する結果になった。
次の構成を作った。ルート直下の CLAUDE.md に「ルート規約で決まっている色は青」、sub/CLAUDE.md に「sub 配下の内部データベースのコードネームは Pangolin」と書き、それぞれについて同じ条件(ファイル系ツール全禁止)で質問する。
| 対象 | 質問 | 回答 | 自動読み込み |
|---|---|---|---|
ルート CLAUDE.md |
規約の色は? | 青 | された |
sub/CLAUDE.md |
sub 配下のコードネームは? | 不明 | されなかった |
ルート側が正しく答えられているので、プローブ自体は機能している(これが対照群になる)。そのうえで sub/CLAUDE.md だけが「不明」になった。
ここで注意点がある。最初の試行では sub/CLAUDE.md の内容を答えられてしまったが、トランスクリプトを見ると、モデルが ls でディレクトリを一覧し、sub/CLAUDE.md を見つけて自分で Read していただけだった。エージェントが賢く探しにいくと、自動読み込みされているように見えてしまう。ファイル系ツールを全て禁止して初めて、自動読み込みの有無だけを取り出せる。
この結果は、元記事が挙げた3点のうちサブディレクトリの CLAUDE.md については指摘どおりだったことを意味する。Rules については再現しなかったが、こちらは再現した。同じ記事の中でも項目ごとに成否が分かれるので、「あの指摘は正しい/間違い」と一括りにせず、項目単位で自分の版を確かめる必要がある。
なお、この挙動が仕様なのか不具合なのかは本記事では判断していない。公式ドキュメントの記述と実装の対応関係までは追い切れておらず、「v2.1.241 でこう観測された」以上のことは書けない。仕様変更のアナウンスも確認できていないため、意図的な変更か回帰かは不明である。
実務上は「サブディレクトリに CLAUDE.md を置いて、そのディレクトリの作業時だけ効かせる」という設計が期待どおりに動かない、ということになる。モノレポでパッケージごとに規約を分けている場合は、ルート側から明示的に参照するか、.claude/rules/ へ移す(ただし前節のとおり常時読み込まれる)ほうが確実だ。
CLAUDE_CODE_THRIFTY_SONIC を立てても挙動は変わらなかった
元記事は、Bash 優先の指示を出す機能フラグとして CLAUDE_CODE_THRIFTY_SONIC を挙げている。この文字列自体は、インストール済みバイナリ(v2.1.241)に実在することを確認できた。関連して While auto mode is active という文字列も存在する。
そのうえで A/B を取った。ツール選択を「モデルの自己申告」でなくフックの発火で観測するのがポイントで、Read と Bash の双方に PreToolUse フックを仕掛け、ログファイルへの追記で実際に呼ばれたツールを記録する。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read",
"hooks": [{ "type": "command", "command": "echo READ_HOOK_FIRED >> /tmp/hooklog.txt" }]
},
{
"matcher": "Bash",
"hooks": [{ "type": "command", "command": "echo BASH_HOOK_FIRED >> /tmp/hooklog.txt" }]
}
]
}
}
この .claude/settings.json を置いたプロジェクトで、同じ質問を環境変数なし/CLAUDE_CODE_THRIFTY_SONIC=1 の2条件で実行した。
| 条件 | 使われたツール | Read フック | 結果 |
|---|---|---|---|
| 環境変数なし(既定) | Bash(find)→ Read |
発火 | 正しく回答 |
CLAUDE_CODE_THRIFTY_SONIC=1 |
Bash(find)→ Read |
発火 | 正しく回答 |
差は出なかった。 ヘッドレス(claude -p)実行では、どちらの条件でも Read が使われ、Read のフックも発火している。
ただしここは注意深く書く必要がある。本記事の筆者が動いているデスクトップ側のセッションでは、実際に Bash 優先の指示がシステムプロンプトに入っている(「auto mode が有効な間は、可能な限り Bash で作業し、cat・sed -n・grep でファイルを読む」という趣旨の指示で、実際この記事を書く作業でも cat や sed を使っている)。つまり Bash 優先の挙動自体は実在する。しかしそれは実行モードに紐づいたもので、環境変数を立てるだけでヘッドレスに再現できるものではなかった。
そして重要なのは、Rules の読み込みがそもそも Read に依存していないという前節の結果である。Rules がセッション開始時に常時読み込まれる以上、エージェントが Read を使うか cat を使うかは、Rules が効くかどうかに影響しない。「Read を避ける挙動が Rules を殺す」という因果は、少なくとも v2.1.241 では成立しない。
この食い違いは、版差として理解するのが妥当だと考えている。元記事の観測は 2026-08-18 以降・公開は 09-05、本記事の計測は 09-07 の v2.1.241 である。この間に修正が入った可能性が高い。実際、指摘が広く共有された(270 users)タイミングと符合する。元記事が誤っていたという主張ではない——測った時点と版が違う。
モノレポでの現実的な回避策
サブディレクトリ CLAUDE.md が自動で読まれないと分かると、モノレポでの規約分割をどうするかという問題が残る。実測結果から取れる選択肢は3つある。
- ルートの
CLAUDE.mdに集約する——最も確実だが、全パッケージの規約が常にコンテキストへ乗るため肥大化しやすい .claude/rules/へ寄せる——こちらも常時読み込まれるので、①と費用は変わらない。ただしファイルを分けて管理できるぶん人間側の見通しは良い- エージェントに読ませる導線をルートへ書く——ルートの
CLAUDE.mdに「packages/*/CLAUDE.mdがあれば作業前に読むこと」と1行だけ書き、実際の読み込みはエージェントの Read に任せる
3番目は本記事の検証中に偶然その挙動を観測している。最初のサブディレクトリ検証で、モデルは ls を打って sub/CLAUDE.md の存在に気づき、指示していないのに自分で Read した。エージェントは「そこにありそうな規約」を自発的に探しにいくので、導線さえ書いておけば実用上は機能する可能性が高い。ただしこれは保証された挙動ではなく、毎回読むとは限らない点に注意がいる。費用面では、必要なときだけ読まれるぶん①②より軽くなりうる。
Claude Code Rules をこれからどう運用するか
以上の実測から、現時点で言える運用上の指針は次のとおり。
・globs をコンテキスト節約の手段として当てにしない。 分割しても全ルールが常時読み込まれる。節約したいなら分割ではなく、ルール自体を短くするしかない
・ルールの総量を定期的に測る。 .claude/rules/*.md の合計トークン数が、毎セッションの固定費になる。tiktoken で数行のスクリプトを回せば把握できる
・サブディレクトリの CLAUDE.md に依存しない。 自動では読まれない。モノレポならルートから参照するか .claude/rules/ へ寄せる
・「効いていない」と感じたら、まず読み込みの有無を切り分ける。 本記事の「中立な事実+ファイル系ツール全禁止」プローブなら、モデルの注入耐性に邪魔されずに判定できる
・版を上げたら測り直す。 今回のように、同じ指摘が数日で成立しなくなることが実際に起きる
ルールを「名著の要約」のような大きなテキストとして持ち込む設計については agent-rules-books解説|名著13冊をAGENTS.mdルールに蒸留したOSS で扱ったが、常時読み込みが前提になるなら、その手のルールはコンテキスト費用として重いという見方に変わる。逆に、明示的に呼ぶまで読み込まれない Skill 側の挙動については grill-me は自動発火しない設計だった|mattpocock/skills 37本の起動条件を実測 が対照的で、Rules は常時・Skill は明示という非対称を意識して使い分けるのが現実的だ。
この非対称は、設計としては理解できる。Rules はプロジェクト全体の規約であり「常に効いていてほしい」もの、Skill は特定の作業でだけ呼びたいもの——という役割分担であれば、Rules が常時読み込まれること自体は妥当だ。問題は globs という書式がその設計を裏切って見えることにある。遅延読み込みを示唆する書式が残っているのに、実際には遅延しない。ドキュメント上の期待と実装が食い違うと、今回のように「死んでいる」という診断が出てくる。
「常時読み込み」を前提にしたルールの書き方
常時読み込まれると分かった以上、ルールの書き方も変わる。今回の検証で分かった性質から、実用的な指針を3つ挙げる。
1つめ、命令形の強度を上げすぎない。 前述のとおり「必ず〜せよ」「〜という文字列を必ず含めよ」の形は、注入耐性に引っかかって拒否されうる。本サイトのリポジトリで実際に運用している openwolf.md は「.wolf/anatomy.md を読んでから対象ファイルを読む」のようにプロジェクト内の手順として自然な形で書かれており、こちらは問題なく機能している。ルールは「外部から差し込まれた命令」ではなく「このプロジェクトの作法」として読める文体のほうが通りやすい。
2つめ、短く保つ。 常時読み込みは固定費なので、長さがそのまま毎セッションのコストになる。300トークン程度なら誤差だが、数千トークン規模のルールを何本も置けば、本来の作業に使える領域が確実に削られる。「入れておけば安心」で肥大化させると、逆にモデルの注意が分散して効きが悪くなる。
3つめ、競合を作らない。 複数のルールが同時に常時読み込まれる以上、相互に矛盾する指示があればどちらかが負ける。globs で「このルールはこの範囲だけ」と書いても、実際には全部同時に読まれているので、範囲指定が競合の回避策にならない。矛盾しうるルールは、globs で分けるのではなく、条件を本文に明記して1本にまとめるほうが安全だ。
検証手順のまとめ
自分の版で追試する最短手順を再掲する。
中立な事実を1つ書く
(命令ではなく事実)"] B --> C["3. globs にマッチしない
拡張子を指定する"] C --> D["4. その事実を問う質問を
ファイル系ツール全禁止で実行"] D --> E{"答えられたか"} E -->|"答えた"| F["globs に関係なく
常時読み込まれている"] E -->|"不明と答えた"| G["globs が
ゲートとして効いている"]
分岐が F に落ちれば本記事と同じ状態、G に落ちればあなたの版では globs が機能している。どちらであっても、推測ではなく実測で分かるというのがこの手順の要点である。
版差を前提にした付き合い方
最後に、この記事自体の賞味期限について書いておく。
今回のように「数日前に広く共有された指摘が、自分の版では再現しない」という状況は、Claude Code のように更新が速いツールでは日常的に起きる。元記事の観測(2026-08-18以降・公開09-05)と本記事の計測(09-07・v2.1.241)の間はわずか2日だが、その間に修正が入った可能性は十分にある。本記事の結論も、次のマイナーバージョンで変わりうる。
だからこそ、記事が提供すべき価値は「結論」ではなく「測り方」だと考えている。中立な事実をルールに書き、ファイル系ツールを全て禁止して質問する——この手順は3分あれば再現でき、版が変わっても同じように使える。結論だけを持ち帰ると次の版で外すが、手順を持ち帰れば毎回自分で答えを出せる。
同じ姿勢は、この種の「エージェントの挙動」全般に当てはまる。一覧に出ているか/読み込まれているか/実際に従っているかは、それぞれ別の観察が要る。 今回も、マーカー方式のプローブが注入耐性に阻まれるという形で一度失敗している。観測しようとしている対象と、観測方法が本当に対応しているかを疑うところから始めるのが結局は近道だった。
参照ソース
- Claude Code の Rules はもう死んでいる - kawasin73のブログ — 本記事の出発点となった指摘(2026-09-05・はてなブックマーク270 users)
- Claude Code 公式ドキュメント —
CLAUDE.md/.claude/rules// Hooks の仕様 - 本記事の計測: Claude Code v2.1.241 / macOS 14 (Darwin 23.5.0) / Apple Silicon、2026-09-07 実施