SSD Nodes Learn 🎉 VPS $5.50/月〜
ガイド Matt Connor著者 Matt Connor ・更新日 2026-08-13

コーディングエージェントが指示を無視する理由

命令ファイルに「停止」と書いても実行される理由を解説します。Claude Codeの読み込みとコンテキスト競合を切り分ける診断方法で、ルールを書き直す前に原因を特定できます。

コーディングエージェントが指示を無視する理由

コーディングエージェントが指示を無視する理由は4つあります。指示が丁寧すぎたことが原因ではありません。ルールがコンテキストウィンドウに入っていなかった可能性があります。ルールが曖昧で、行動と照合できなかった可能性もあります。コンテキスト内の別の内容、通常はエージェントが直前に読んだコードが、ルールと矛盾していた可能性もあります。また、ルールは読み込まれていても、現在のターンから遠い位置にあり、エージェントが近くにある内容を基に処理している可能性があります。

原因ごとに対処方法は異なります。そのため、最初に原因を区別する必要があります。大文字や IMPORTANT という語を使っても、原因の特定にはなりません。以下では、2026年8月時点で読み込みとコンパクションの動作が詳しく文書化されている Claude Code を例に説明します。ほかのツールでは細部が異なりますが、基本的な動作は同じです。

まず、2つの用語を確認します。コンテキストウィンドウとは、特定のターンでモデルが参照するテキストのまとまりです。システムプロンプト、指示ファイル、会話、エージェントが読み込んだすべてのファイルが含まれます。ハーネスとは、モデルの周囲で動作するプログラムです。ディスク上のファイルを読み込み、そのまとまりを組み立てます。この投稿での不満のほとんどは、実際にはモデルではなくハーネスに対する不満です。

命令ファイルは設定ではなくメッセージです

命令ファイルは設定ではありません。実行時に CLAUDE.md を読み取り、強制する仕組みはありません。ハーネスはディスク上のファイルを読み取り、その内容を会話に貼り付けます。Claude Code では、その内容は system prompt の後に置かれた user message として渡されます。つまり、モデルにとって命令ファイルのルールは、入力した他のテキストと同じように認識されます。

これには注意すべき結果があります。ルールは、ウィンドウ内にある他のすべてのテキストと同じ条件で競合します。ルールは主張です。一方、エージェントが直前に開いたファイルは証拠です。両者が一致しない場合、証拠が優先されることが多くあります。モデルから見ると異常は発生していないため、エラーも発生しません。

公式ドキュメントにも、この点は明記されています。命令ファイルは、強制される設定ではなくコンテキストとして扱われます。モデルの判断にかかわらずアクションをブロックするには、文ではなくフックが必要です。この原則を覚えておいてください。この記事の後半にある修正方法の多くは、この原則を個別のケースに適用したものです。

読み込まれる指示ファイルと読み込みのタイミング

Claude Code は、起動したディレクトリからディレクトリツリーを上方向にたどります。ファイルシステムのルートから作業ディレクトリまでにあるすべての CLAUDE.mdCLAUDE.local.md が、起動時に完全な形で読み込まれます。これらはその順序で連結されるため、起動場所に最も近いファイルが最後に読み込まれます。また、同じディレクトリ内では .local ファイルがメインのファイルの後に追加されます。

作業ディレクトリより下のサブディレクトリにあるファイルは、動作が異なります。起動時には読み込まれません。エージェントがそのディレクトリ内のファイルを読み取った時点で読み込まれます。.claude/rules/ 内で paths: frontmatter フィールドを持つパススコープのルールも同じです。一致するファイルが読み取られた時点でコンテキストに追加され、毎ターン読み込まれるわけではありません。

この違いだけで、報告されている失敗の多くを説明できます。packages/api/CLAUDE.md にルールを記述し、API について質問したところ、エージェントが packages/api/ 配下のファイルを一度も開かずに回答したとします。そのルールが無視されたわけではありません。最初から存在していなかったのです。リポジトリで モノレポ内のパッケージごとの指示ファイル にガイダンスを分割している場合は、毎回まずここを確認してください。

もう 1 つ、最もよくある「エージェントが指示を無視した」原因となる読み込み上の落とし穴があります。Claude Code が読み取るのは CLAUDE.md であり、AGENTS.md ではありません。AGENTS.md を標準化していて CLAUDE.md がないリポジトリでは、Claude Code に読み込むものが何もありません。対応する橋渡し方法は、1 行目が @AGENTS.md になっている CLAUDE.md を用意することです。このファイルによって、起動時に対象ファイルが読み込まれ、その下に Claude 固有の注意事項を記述できます。追加する内容がない場合は、シンボリックリンクでも構いません。そもそもそのファイルに何を記述するかは別の問題であり、エージェント向け指示と人間向けドキュメントの分離で説明します。

書き換える前にファイルが読み込まれたことを確認する

エージェントがファイルを参照できる証拠を得るまで、文言を変更しないでください。確認方法は 2 つあります。まず、負荷の低い方法を実行します。

セッション内で /context を実行します。現在のウィンドウをカテゴリ別に表示し、Memory files リストに実際に読み込まれたすべての指示ファイルが表示されます。このリストにないファイルは会話に含まれていないため、そのファイル内に何を書いても反映されません。/memory ではファイルの場所を一覧表示し、まだ存在しないファイルも含めて編集用に開けます。

より確実に確認するには、読み込みを記録します。InstructionsLoaded フックイベントは、CLAUDE.md またはルールファイルがコンテキストに入るたびに実行されます。matcher により、読み込みの理由が session_startnested_traversalpath_glob_matchincludecompact のいずれかとして示されます。.claude/settings.json に次の内容を記述します。

{
  "hooks": {
    "InstructionsLoaded": [
      {
        "matcher": "nested_traversal",
        "hooks": [
          {
            "type": "command",
            "command": "cat >> /tmp/instructions-loaded.log"
          }
        ]
      }
    ]
  }
}

フックは標準入力から JSON としてペイロードを受け取るため、cat でレコード全体を追記できます。作業中は tail -f /tmp/instructions-loaded.log で監視してください。このイベントの終了ステータスは無視されるため、フックにできるのは監視だけで、処理をブロックすることはできません。読み込まれるはずのセッションでネストしたファイルがそのログに一度も現れない場合は、文言の修正を中止してください。問題は配置にあります。

長時間のセッションがルールに与える影響

ここでは、別々の 2 つの影響が発生します。それぞれ異なる対応が必要です。

距離。 turn 1 で示したルールは turn 90 でもウィンドウ内に残っています。ただし、現在の作業により新しく、より具体的な 90 turn 分のテキストと競合する状態になります。これを設定で解消することはできませんが、測定はできます。同じタスクを新しいセッションで実行してください。そこでルールが維持され、長時間のセッションの深い位置で失敗するなら、原因は距離です。

コンパクション。 ウィンドウが満杯になると、harness はそれまでの会話を要約し、その要約から処理を続けます。残るのは、要約担当が重要と判断した内容です。これは、あなたが重要と考える内容と同じとは限りません。Claude Code は機構ごとの結果を文書化しており、その違いは大きくなります。プロジェクトルートの CLAUDE.md とスコープ指定のないルールは、コンパクション後にディスクから再注入されます。自動メモリもディスクから再注入されます。paths: frontmatter を持つルールは、対応するファイルが再び読み込まれるまで失われます。サブディレクトリ内の入れ子になった CLAUDE.md ファイルは、そのサブディレクトリ内のファイルが再び読み込まれるまで失われます。

この表に従って指示の優先順位を付けると、壊れやすさの順序が明確になります。チャットに直接入力したルールは、セッション内で最も壊れやすい情報です。要約に残った場合にだけ維持されます。packages/api/CLAUDE.md 内のルールが次に続きます。これは 1 回読み込まれた後、要約で失われ、そのディレクトリで次に読み込まれるまで戻りません。プロジェクトルートのファイルにあるルールは、毎回ディスクから再読み込みされるため、最も永続的です。

そのため、セッション全体で維持する必要がある指示は、paths: frontmatter を付けずにプロジェクトルートのファイルへ記述してください。それ以外は、目的を明確にしたうえで選択すべきトレードオフです。コンテキストウィンドウに残す内容の管理では、フォーカス引数を使用した /compact と、無関係なタスク間での /clear を扱っています。どちらも、要約担当があなたのルールの内容を判断する頻度を変えます。

周囲のコードがルールに勝る理由

これは、最も頻繁に説明される一方で、最も見落とされやすい失敗です。ファイルには、データベースアクセスはリポジトリ層を経由すると書かれています。しかしエージェントは、ORM(オブジェクト関係マッパー)を直接呼び出すハンドラーを作成します。スタイル上の理由で無視されたのではありません。根拠の比較で負けたのです。

ルールは好みを示します。コードは実例を示します。エージェントが編集対象のモジュール内で 3 つのファイルを開き、その 3 つすべてが ORM を直接呼び出している場合、コンテキストには、一方に抽象的な文が 1 つ、もう一方に具体的で最近の、今回の作業に一致する例が 3 つあることになります。通常、ローカルのパターンをコピーするのは正しい動作です。ここで誤りになるのは、そのコンテキストにはない情報をあなたが知っているからです。そのファイルはレガシーコードです。

そのため、その情報をルールに書き込みます。反証となるコード自身にも言及するルールは、実際のリポジトリでも機能します。単なる好みを述べるだけのルールは機能しません。

新しいデータベースアクセスは app/repositories/ を経由します。app/legacy/ 配下のファイルは、現在も ORM を直接呼び出しています。これは古いコードであり、標準パターンではありません。コピーしないでください。

この 2 番目の文が重要な役割を果たします。エージェントがコードを見つける前に、何を見つけることになるのか、そしてそれをどう解釈すべきかを伝えます。同じ修正は、リポジトリが明らかに矛盾しているあらゆるルールに適用できます。たとえば、履歴が従っていないコミット形式、テストスイートの半分が無視しているテスト配置、新しいコードでだけ守られている import の規約などです。コードとファイルの記述が食い違う場合は、その食い違いをファイル内で明示してください。

曖昧なルールは確認できないため、従うこともできません

「クリーンなコードを書く」「過剰設計をしない」「シンプルに保つ」「マイグレーションには注意する」。これらは、エージェントにもあなたにも、特定の操作に対して確認できません。自分の出力と照合できないルールを与えられたエージェントは推測するしかなく、あなたはその推測を感覚で評価することになります。

ファイル内のすべての行に、次のテストを適用してください。ルールに違反した場合に非ゼロで終了するシェルコマンドを書きます。そのコマンドを書けないなら、そのルールは確認可能ではありません。次の組み合わせを比較してください。

  • 確認不可: 「関数を小さく保つ」 確認可能: 「60 行を超える関数の直上には、その理由を説明するコメントが必要」
  • 確認不可: 「変更をテストする」 確認可能: 「タスクを完了とする前に npm test を実行し、失敗数を貼り付ける」
  • 確認不可: 「ファイルを整理して保つ」 確認可能: 「HTTP ハンドラーは src/api/handlers/ に置く。それ以外のものはそのディレクトリに置かない」
  • 確認不可: 「コードを適切にフォーマットする」 確認可能: 「.ts ファイルでは 2 スペースのインデントを使用する」

「過剰設計をしない」が最初に諦められやすいのは、修正が短い文ではなく長い文になるためです。実際に機能する最小の変更の意味を明記することにより、エージェントが自分の差分と照合できる基準を示せます。

サイズも、別の形で同じ問題になります。Claude Code のガイダンスでは、1 つの指示ファイルを 200 行未満にすることを推奨し、ファイルが長いほど遵守率が下がると明記しています。700 行のファイルは、より強い指示ではありません。相互に矛盾する可能性が高い主張が 700 行並んでいるだけです。また、毎回のターンでコンテキストウィンドウを消費するため、トークン使用量に直接現れます。各ルールを読者が見出しの下で確認できるように構成する方法については、エージェントが実行できる指示ファイルの書き方で説明しています。

10 分で診断する方法

次の手順を順番に実行します。最後の手順に飛ぶと、強い表現のルールを長いファイルに追加しても、問題が解決しない状態になります。

  1. 読み込まれていることを確認します。 /context を実行し、Memory files の一覧を確認します。ファイルが一覧にない場合は、場所を修正して調査を中止します。この一覧の他の手順は、まだ適用できません。
  2. 新しいセッションで再現します。 新しいセッションを開始し、ルールが適用されるはずの最小限のタスクを実行します。新しいセッションでは適用されるのに、長いセッションでは失敗する場合は、距離または圧縮が原因です。新しいセッションでも失敗する場合は、ルール自体に問題があります。
  3. 競合する指示を取り除きます。 既存のコードがすでにルールに従っているディレクトリで、同じ変更を依頼します。そこで準拠するようになる場合は、周囲のコードの指示が、指定した文より優先されていました。
  4. 競合を検索します。 同じ動作について異なる指示を記載したファイルが 2 つあると、既知の失敗パターンになります。モデルはそのうち 1 つを任意に選ぶ可能性があり、選んだことを通知しません。
  5. 確認可能な形にして再テストします。 具体的なパスと条件を含むようにルールを書き直します。準拠率が大きく向上する場合は、表現が原因でした。

手順 4 は 1 つのコマンドで実行できます。編集していたファイルだけでなく、すべての指示ソースから対象のトピックを検索します。

grep -rni "migration" --include="CLAUDE.md" --include="CLAUDE.local.md" .
grep -rni "migration" .claude/rules/ ~/.claude/CLAUDE.md ~/.claude/rules/ 2>/dev/null

異なる内容を記載したファイルが 2 つ見つかった場合、それが問題です。片方を削除します。より強い表現で優先順位を付けようとしてはいけません。優先順位を判定する仕組みはありません。

効果の大きい修正から順に

以下の各手順は、上の手順よりも効果が大きく、その分、設定にもコストがかかります。ルールの言い換えで済む場合は、上から始めてください。ルールが重要になり、時々の見落としも許容できなくなった時点で、下の手順へ移ります。

  1. ルールを具体化する。 パス、コマンド、または条件を明示します。前述の例のように、エージェントがリポジトリ内で見つける反証も追加します。費用はかからず、意外に多くのケースを解決できます。
  2. ルールを適用対象の近くに移す。 ネストした CLAUDE.md.claude/rules/ 内でパスを対象にしたルール、またはファイル自体の先頭に置くコメントなどです。これにより、ルールと適用対象のコードが同じ読み込みで提示されます。ただし、次のコンパクションでその方法で読み込まれた内容は失われ、次に該当箇所が読み込まれた時に再び提示される点に注意してください。
  3. 適用をフックに移す。 文章は要求するだけです。フックは判定します。フックはライフサイクル上の決まったイベントでコードとして実行され、モデルの判断に関係なく適用されます。
  4. ルールを決定的なツールに任せ、文章を削除する。 フォーマット、import の順序、行の長さ、禁止された import、コミットメッセージの形式などです。ruff formatprettier --writeeslint、または pre-commit フックを使用します。フォーマッタは毎回正しく動作し、トークンを消費しません。文章はほとんどの場合に正しくても、ターンごとにトークンを消費します。

手順 3 の詳細を説明します。エージェントが migration ファイルを決して編集してはならないとします。.claude/settings.json に次の内容を配置します。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/guard-migrations.sh"
          }
        ]
      }
    ]
  }
}

次に、.claude/hooks/guard-migrations.sh に次の内容を配置します。

#!/usr/bin/env bash
set -euo pipefail

path=$(jq -r '.tool_input.file_path // empty')

case "$path" in
  */migrations/*)
    echo "Files under migrations/ are written by hand. Stop and ask first." >&2
    exit 2
    ;;
esac

exit 0

chmod +x .claude/hooks/guard-migrations.sh を実行してから、新しいセッションを開始し、エージェントに migrations/ 配下のファイルを編集するよう依頼します。編集は拒否され、その理由がメッセージとして返されます。PreToolUse の終了ステータス 2 により、ツール呼び出しは実行前にブロックされ、stderr のテキストがブロック理由としてモデルに渡されます。${CLAUDE_PROJECT_DIR} はプロジェクトルートに解決されるため、エージェントがどのディレクトリにいてもフックは機能します。エージェントがルールに同意したり、ルールを記憶したり、コンテキスト内にルールを保持していたりする必要はありません。編集は実行されません。

ロジックを含まない単純な禁止であれば、設定内の permissions.deny でも、保守するスクリプトなしで同じことができます。権限モードによって、ユーザーに確認せずに実行される処理が決まります。指示を本当にユーザーメッセージではなくシステムプロンプトのレベルに置く必要がある場合は、--append-system-prompt で配置できます。ただし、呼び出しのたびに渡す必要があるため、対話的な作業よりもスクリプトに適しています。

指示だけでは防げないこと

この問題のどこまでが自分の責任かを明確にしてください。配置、表現、ファイル間の矛盾、ファイルサイズは、作成者の問題であり、作成者が修正するものです。それ以外はモデルの挙動に関する問題です。よりよい表現にしても、こうした問題はなくなりません。

同意は遵守を意味しません。 エージェントはルールを認識し、正しく言い直したうえで、2 回後のツール呼び出しで破ることがあります。同意の表明にはコストがなく、遵守を予測する材料にもなりません。修正とみなしたり、テストとして数えたりしないでください。

一部の習慣は持続します。 コメントを追加する、予防的なエラー処理を加える、最後にまとめを書く、次に明らかなコマンドを実行する、といった行動です。これらは、禁止するルールがあっても、発生率が下がるだけでゼロにはなりません。同じタスクを新しいセッションで 10 回実行し、違反数を数えることで、自分の発生率を測定できます。その数をゼロにする必要がある場合、そのルールはプロンプトから外す必要があります。

現在のセッション自体が実例になります。 エージェントが turn 12 でルールを破り、それを見過ごした場合、その違反はコンテキストに実例として残ります。しかも、ルールよりはるかに新しい情報です。違反を見つけたら、その場で修正してください。修正されなかった違反は、セッションの残りに学習材料として伝わります。

指示ファイルはセキュリティ境界ではありません。 指示ファイルは挙動を形成しますが、強制はしません。見落としのコストが高いもの、たとえば認証情報や破壊的なコマンドは、権限設定または hook で制御してください。エージェントの手の届かない場所に Secret を置くでは、データについて同じ原則を適用しています。エージェントにファイルを読まないよう求めるのではなく、そのファイルを読み取れない状態にしてください。

要点は簡潔です。ファイルが読み込まれたことを確認し、ルールを検証可能にし、適用対象のすぐ近くに配置してください。それでも見落とし率が問題になる場合は、ルールを文章による指示から外してください。エージェントが無視できないルールは、エージェントに求めるルールではありません。

FAQ

Claude Code が CLAUDE.md を無視するのはなぜですか?

無視されたと判断する前に、読み込まれたか確認してください。/context を実行し、Memory files の一覧を確認します。そこに記載されていないファイルは、会話に含まれていません。指示ファイルは system prompt の後に user message として渡され、強制設定ではなくコンテキストとして扱われます。そのため、厳密に従う保証はありません。実際の原因は、主に次の4つです。ファイルがサブディレクトリにあり、エージェントがそこから読み込んでいない。2つのファイルの内容が食い違い、モデルが一方を任意に選んだ。ルールが曖昧で、アクションと照合できない。周囲のコードが、ルールと反対の動作を示している。

セッション中に指示ファイルを編集すると、何か変わりますか?

すでに会話に含まれているコピーには反映されません。作業ディレクトリより上位にあるファイルは起動時に全体が読み込まれるため、モデルが保持する内容は起動時点のものです。編集内容を反映するには、新しいセッションを開始するか、通常のファイル操作ツールでエージェントにファイルを読み込ませてください。これにより、現在の内容が新しいメッセージとして会話に追加されます。コンパクション後はプロジェクトルートのファイルがディスクから再読み込みされるため、その時点で新しい内容も反映されます。

ルートの CLAUDE.md とネストしたファイルの内容が食い違う場合、どちらが優先されますか?

どちらも確実には優先されません。検出されたファイルは上書きされるのではなく、コンテキストに連結されます。ファイルシステムのルートから作業ディレクトリに向かう順序で並ぶため、最も近いファイルが最後に読み込まれるだけです。矛盾を解決する優先順位エンジンはありません。Claude Code のドキュメントにも、矛盾するルールは任意に解決される場合があると記載されています。ネストしたファイルは、適用対象のパスを明記した追加ルールとして記述してください。優先順位で上回ろうとせず、矛盾する記述を削除してください。

指示は /compact 後も維持されますか?

読み込まれ方によって異なります。プロジェクトルートの CLAUDE.md、スコープ指定のないルール、自動メモリは、コンパクション後にディスクから再注入されます。paths: frontmatter を持つルールと、サブディレクトリにあるネストした CLAUDE.md ファイルは、対応するファイルが再度読み込まれるまで失われます。チャットに入力しただけの内容は、要約処理が保持した場合に限り残ります。セッション全体で維持する必要があるルールは、paths: frontmatter のないプロジェクトルートのファイルに記述してください。

ルールを文章ではなく hook にすべきなのは、どのような場合ですか?

チェックが決定的で、見落としの影響が小さなスクリプトを書くコストを上回る場合です。ファイルパスの制限、commit 前に必須のコマンド、禁止するツール呼び出しなどが該当します。status 2 で終了する PreToolUse hook は、ツール呼び出しを直接ブロックし、stderr の内容を理由としてモデルに返します。そのため、ルールがコンテキストに残っているかどうかに関係なく適用できます。formatter や linter で判定できる内容は、そのツールに任せ、指示ファイルから完全に削除してください。