Claude Media
Claude Code auto modeのBash優先指示がCLAUDE.mdと衝突する問題

Claude Code auto modeのBash優先指示がCLAUDE.mdと衝突する問題

auto modeが注入するBash優先の指示が、CLAUDE.mdの編集ルール・/rewind・blockReadsOutsideWorkingDirectoriesと食い違う3件のissueを読み分け、フックで守る手順をまとめます。

auto modeが注入する「作業はBashで済ませる」という指示は、CLAUDE.mdの編集ルール、/rewind、blockReadsOutsideWorkingDirectoriesの3か所で別々に衝突します。GitHubの3件のissue(#94441、#94657、#95238)がそれぞれ別の側面を報告しており、3件とも原因は同じ指示です。

CLAUDE.mdに「sedやheredocでの編集は禁止」と書いてあっても、それは強制ではありません。守らせたいルールはPreToolUseフックに移すのが確実です。手順は後半に置きました。

3件のissueは何を報告しているか

どれも、auto modeが追加するシステム指示が発端です。報告者が引用している文面は次のとおりです。

Do your work through the Bash tool wherever it can accomplish the job: read files with cat, head, or sed -n, search with grep and find, and make file changes with sed, heredocs, or short scripts, rather than using the dedicated Read, Edit, or Write tools.

この指示の仕組みと止め方はCLAUDE_CODE_THRIFTY_SONICの記事にあります。ここでは、同じ指示から生じる別系統の副作用を扱います。

issue起きること報告時の環境
#94441起きることCLAUDE.mdの「Edit/Writeで編集する」ルールと正反対の指示になる。サブエージェントにも届く報告時の環境Linux、2.1.234〜2.1.270
#94657起きること編集が全部Bash経由になり、/rewindに「Restore code」が出ない報告時の環境macOS、2.1.273
#95238起きることblockReadsOutsideWorkingDirectories有効時に許可プロンプトが大量に出る報告時の環境macOS、2.1.258(2.1.289でも再現のコメント)

3件とも、状態はopenです。最後の更新は#94441が9月21日、#94657が9月16日、#95238が10月9日でした。

#94441: CLAUDE.mdのルールと注入文が正反対になる

報告者のCLAUDE.mdには、ファイルの変更にはEditかWriteを使い、sed・awk・heredocによるその場編集は禁止、という規則がありました。注入された指示は、その真逆を求めます。

問題は優先順位がどこにも書かれていないことです。issueは3つの点を挙げています。

  • 注入文は、CLAUDE.mdの内容を並べたブロックの末尾に、区切りなしで足される
  • 注入文は<system-reminder>で包まれており、公式の指示に見える
  • サブエージェントにも届く。届き方は、最初のツール呼び出しより後が大半

最初の点は見落としやすいところです。報告者が全21個のCLAUDE.mdを検索しても、注入文はどこにも書かれていませんでした。ハーネスがプロンプト組み立て時に付け足すだけなので、エージェントからは「ユーザー自身のファイルが自己矛盾している」ように見えます。複数のエージェントが、これをプロンプトインジェクションと誤認して報告していました。

数字も出ています。9月14日時点で809件のトランスクリプトを数えると、bashFirst: trueの添付を受けたのは212件で、うち190件がサブエージェントでした。194件は最初のツール呼び出しより後に届き、サブエージェント190件は例外なく後でした。サブエージェントの指示文に「Edit/Writeを使え」と明記してあったのは、32〜38件ほどです。

もう一つ、設定した範囲より広く効いているという指摘があります。autoModeの環境記述は特定の1リポジトリ向けでしたが、指示は10の作業ディレクトリで発火し、そのリポジトリ内は216件中80件でした。

提案された直し方は、小さい順に次の4つです。

  1. 注入文に「CLAUDE.mdの指定があればそちらを優先」の一節を足す
  2. 最初のツール呼び出しの前に注入する
  3. auto modeの適用範囲をリポジトリ単位にするか明確にする
  4. CLAUDE.mdに矛盾する規則があるときは注入自体を止める

コメントでは、別の利用者がauto modeはCLAUDE.md全般を無視することがあると書いています。ファイル編集に限らない、という見立てです。

#94657: 編集が全部Bashになり/rewindに復元が出ない

こちらは/rewindの話です。報告者のセッションは124回のプロンプトで、Bashツールの呼び出しが96回、Edit・Write・NotebookEditは0回でした。

項目値
Bashツール呼び出し値96
Edit / Write / NotebookEdit値0
file-history-snapshot値14
trackedFileBackupsが空でないスナップショット値0

変更はすべてpython3 - <<'PY'のheredocスクリプトで行われました。この結果、/rewindのどのエントリにも「Restore code」の選択肢が出ず、会話の巻き戻しと要約だけが残ります。

公式のチェックポイントのページは、Bashコマンドの変更を追跡しないと書いています。Claudeがファイル編集ツールで一度編集したファイルなら、その後のBash変更も戻せます。Bashだけが触ったファイルは追跡されません。

報告者の観察に、この仕様がよく表れています。別の兄弟セッションではWriteが3回だけ呼ばれ、バックアップされたのはその3回が触ったファイルだけでした。同じセッションでBash経由で変えた約40ファイルは、バックアップされていません。

thrifty-sonicの記事にある「成功と表示されるのに戻らない」ケースとは症状が違います。あちらはEditとsedが混在した場合で、こちらは復元の選択肢そのものが出ません。どちらも、根は同じ仕様です。制限の全体像はcheckpointの制限、操作はrewindコマンドにまとめています。

報告者が望む姿は、ファイルを変更する操作だけEdit・Writeを必須にするか、Bashの変更もスナップショットに取るかのどちらかです。最低限、/rewindに「この方法の編集は戻せない」という警告を出してほしいとも書かれています。

#95238: 許可プロンプトが1日に何千回も出る

3件目は、ファイルを変える話ではなく、読む側の副作用です。permissions.blockReadsOutsideWorkingDirectoriesを有効にしていると、Bash優先の指示に沿ったコマンドが、ほぼ全部プロンプトに変わります。

このブロックは、コマンドが触るパスをすべて作業ディレクトリ内と証明できる場合だけ、プロンプトなしで通します。コマンド置換、グロブ、変数参照があると証明できず、確認が必要になります。Bash優先の指示が勧める形(cat $(...)、forループ、heredoc)が、まさにその対象です。報告者の環境では、1日に数千回のプロンプトが出たとあります。

2.1.289で再現したコメントが、具体的な引き金を挙げています。

  • ruff format $(git diff --name-only)のようなコマンド置換
  • for n in 1 2 3; do gh issue view $n; doneのようなループ
  • python3 - <<'EOF'のように、標準入力でコードを渡すインタープリタ
  • cdの後で相対パスを使い、同じコマンドに2>&1・;・||も含む場合

許可ルールのBash(cat:*)などを足しても、このプロンプトは消えません。コメントによると、読み取りブロックの判定が許可ルールの照合より先に走り、しかも分類器の承認対象にもなりません。

公式の権限モードのページは、この挙動を仕様として書いています。blockReadsOutsideWorkingDirectoriesが有効なとき、ファイル読み取りを認識したBashコマンドは、auto modeとbypassPermissionsでもプロンプトになります。つまり、ブロック側は想定どおりに動いています。噛み合っていないのは、Bashに寄せる指示のほうです。

blockReadsOutsideWorkingDirectoriesの解説の設定を入れているチームは、ここで効いてきます。報告者の提案は、ブロック有効時には注入を止める、またはReadツールに複数パスをまとめて渡せる形を足す、の2つです。

issueには、副作用がもう一つ書かれています。Write|EditにマッチさせたPrettierのPostToolUseフックは、sedやheredocによる変更では発火しません。auto modeの編集だけ整形されない、という形で表に出ます。

CLAUDE.mdで止められる範囲と、フックに移す判断

ここまでの3件を読むと、「CLAUDE.mdにもっと強く書けば」と考えたくなります。ただ、メモリのページには、CLAUDE.mdはコンテキストであって強制される設定ではない、とはっきり書かれています。確実に止めたい操作にはPreToolUseフックを使う、という案内も同じ場所にあります。

#95238のコメントの書き手も、CLAUDE.mdに規則を書いて回避していました。コマンド置換・ループ・標準入力へのコード渡しをやめ、ファイル操作にはRead・Editを使う、という内容です。プロンプトは減ったものの、システムプロンプトとぶつかり続け、サブエージェントは元の形に戻ると書いています。

守らせたいルールが「Bashでのその場編集を許さない」なら、フックなら言葉の解釈に左右されません。公式のフックの例(rm -rfを止めるもの)に沿うと、sed -iを止める構成は次の形になります。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "if": "Bash(sed -i *)",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-sed-edit.sh",
            "args": []
          }
        ]
      }
    ]
  }
}

スクリプト側は、公式の例と同じく標準入力のJSONを読みます。

#!/bin/bash
COMMAND=$(jq -r '.tool_input.command')
 
if echo "$COMMAND" | grep -Eq 'sed +(-[a-zA-Z]*i|--in-place)'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "ファイルの編集はEditまたはWriteツールを使う"
    }
  }'
else
  exit 0
fi

上は公式の例を、この用途に合わせて書き換えた形です。判定の正規表現は最小限なので、実際に使うときは自分のコマンドで試してください。heredocを丸ごと止めるのはお勧めしません。git commitのメッセージ渡しなど、正当な用途でも使われるためです。

この方法には限界もあります。止められるのは「Bashで編集する」経路だけで、/rewindの記録そのものが直るわけではありません。そして、フックは拒否するだけです。Claudeが次にEditを呼ぶかどうかは、理由文の書き方とモデルの判断になります。

症状から原因を切り分ける

自分の症状がどの報告にあたるか、次の表で見分けられます。

症状当てはまる報告先にやること
/rewindに「Restore code」が出ない当てはまる報告#94657先にやること大きな編集の前にコミットする。指示自体を止める手順はthrifty-sonicの記事へ
CLAUDE.mdの編集ルールが守られない当てはまる報告#94441先にやることルールをPreToolUseフックにも書く
許可プロンプトが急に増えた当てはまる報告#95238先にやることblockReadsOutsideWorkingDirectoriesの設定とBashの形を見直す
サブエージェントだけ規則を破る当てはまる報告#94441先にやることサブエージェントの指示文にも明記する
サブディレクトリのCLAUDE.mdが効かない当てはまる報告別件先にやることauto modeでCLAUDE.mdとhooksが無視される問題を参照

実際の動きを知りたいときは、トランスクリプトのauto_mode添付を見ます。#94441の報告者は、"bashFirst":trueを含む添付を数える方法を示しています。実行した結果の読み方は、同じissueのコメントに沿うのが安全です。文面の検索では、指示について書いているだけのログまで拾います。

PreToolUseフックそのものの書き方はPreToolUse hookの解説にまとめています。

まとめ

3件はどれも、auto modeがBashに寄せる一つの指示から生じています。CLAUDE.mdのルールが負けるのは、そこに優先順位の記述がないからです。/rewindが使えなくなるのは、Bashの変更が追跡されないからです。許可プロンプトが増えるのは、Bashの形が読み取りブロックの解析を超えるからです。

読者側でできる対処は、コミットで退路を確保することと、守りたいルールをフックに移すことの2つです。いずれもissueが解決されたあとも無駄になりません。3件とも修正の報告はまだ出ていないため、最新の状況は各issueで確かめてください。

この記事を共有:XはてブLinkedIn