CLAUDE_CODE_BASH_EDIT_DIFFで全パーミッションモードのBash差分を記録する
Bashコマンドが変更したファイルの差分を、どのパーミッションモードでも記録させる環境変数の使い方と、設定との優先関係を扱います。
CLAUDE_CODE_BASH_EDIT_DIFFで何ができるか
CLAUDE_CODE_BASH_EDIT_DIFFは、Bashコマンドの実行中にリポジトリ内のファイルがどう変わったかを、パーミッションモードに関係なく記録させる環境変数です。1を設定すると、通常モードや計画モードのように本来は記録されない場面でも差分が残ります。0を設定すると記録そのものを止められます。Claude Code v2.1.269以降が対象です。
対になる仕組みが設定キーbashEditDiffEnabledです。両者はどちらも「Bashコマンドが変更したファイルを記録するか」を制御しますが、有効化できる場所と優先順位が違います。この違いを知らずに設定だけ触ると、チーム全体には効かず自分のセッションだけ動く、といったすれ違いが起きます。
使いどころとして考えられるのは、Claudeが自律的にBashを何度も呼び出すセッションを、あとから振り返って確認する場面です。通常モードでは1コマンドごとに承認するので変更点を目視できますが、自動実行モードでは連続してコマンドが走るため、どのタイミングでどのファイルが動いたかを追いにくくなります。全モード記録はこのギャップを埋める手段で、計画モードで想定外の書き込みが起きていないかを確認する用途にも使えそうです。
bashEditDiffEnabled設定との優先関係
既定の挙動では、Claude CodeはBashツール経由でClaudeがファイル編集を指示したときに限り、自動実行モードとbypassPermissionsモードでだけ差分を記録します。それ以外のモードでは記録しません。bashEditDiffEnabledをtrueにすると、この制限を外してすべてのパーミッションモードで記録するようになります。
CLAUDE_CODE_BASH_EDIT_DIFFはこの設定より優先されます。値が1ならその1セッションだけ強制的に全モード記録になり、0なら設定側がtrueでもそのセッションでは記録を止められます。渡し方によって効く範囲が変わる点に注意してください。シェルでexportした場合はそのセッション限りの上書きですが、settings.jsonのenvブロックに書けば起動のたびに読み込まれるため常設のポリシーになります。
値の書式にも注意が必要です。オン・オフを切り替える環境変数は1またはtrueでオン、0またはfalseでオフになり、大文字・小文字は区別されません。CLAUDE_CODE_BASH_EDIT_DIFF=TRUEでもCLAUDE_CODE_BASH_EDIT_DIFF=1でも同じ扱いです。
bashEditDiffEnabledはtrueだけがユーザー設定と管理者設定に限られる
Claude Codeには環境変数と設定キーが対になっているペアが複数あり、どちらを先に読むかは組ごとに違います。たとえばANTHROPIC_MODELとCLAUDE_CODE_AUTO_CONNECT_IDEは、環境変数が設定されていれば常にそちらを優先し、設定キー(modelやautoConnectIde)は環境変数が未設定のときだけ参照します。CLAUDE_CODE_BASH_EDIT_DIFFとbashEditDiffEnabledも、環境変数が設定キーより優先されるという同じ型です。
このペアで別に確認すべき点は2つあります。ひとつは、環境変数はシェルでexportしただけならその1セッション限りの上書きで終わる一方、settings.jsonのenvブロックに書けば設定キーと同じように常設できることです。もうひとつは、設定キー側のtrueが効く範囲が狭いことです。bashEditDiffEnabled: trueはユーザー設定・--settingsで渡すJSON・管理者設定からしか有効にならず、プロジェクトやローカルの設定ファイルに書いても記録は始まりません(詳しくは後述します)。
パーミッションモード別の記録状況
記録の既定値はパーミッションモードごとに違います。CLAUDE_CODE_BASH_EDIT_DIFF=1を立てると、この差を無視してすべて「記録する」に揃えられます。
| パーミッションモード | 既定の記録 | CLAUDE_CODE_BASH_EDIT_DIFF=1のとき |
|---|---|---|
| 通常モード(都度確認) | 既定の記録記録しない | CLAUDE_CODE_BASH_EDIT_DIFF=1のとき記録する |
| 計画モード | 既定の記録記録しない | CLAUDE_CODE_BASH_EDIT_DIFF=1のとき記録する |
| 自動実行モード | 既定の記録Bash経由でClaudeがファイル編集を指示したときだけ記録 | CLAUDE_CODE_BASH_EDIT_DIFF=1のとき記録する(バックグラウンド実行・読み取り専用コマンドを除く) |
bypassPermissionsモード | 既定の記録同上 | CLAUDE_CODE_BASH_EDIT_DIFF=1のとき記録する(バックグラウンド実行・読み取り専用コマンドを除く) |
通常モードや計画モードは既定で差分を記録しないため、Bashが実行された後にどのファイルが書き換わったのかを、あとから差分として追うことはできません。レビュー目的で全モードの記録を確認したいときに、この環境変数が効きます。
設定方法 — シェルと設定ファイル
シェルで一時的に切り替えるなら次のように実行します。
CLAUDE_CODE_BASH_EDIT_DIFF=1 claude常設したい場合はsettings.jsonのenvブロックに書きます。
{
"env": {
"CLAUDE_CODE_BASH_EDIT_DIFF": "1"
}
}bashEditDiffEnabled側は次の形です。
{
"bashEditDiffEnabled": true
}PostToolUseフックが受け取るデータ
記録が有効なとき、Bashツールの実行結果はPostToolUseフックにtool_response.bashEditDiffとして渡されます。中身は次のフィールドで構成されます。
| フィールド | 内容 |
|---|---|
changedFiles | 内容変更されたファイルの絶対パス配列(最大200件) |
files | 内容表示用の差分。最大5ファイルぶんのhunkを含み、追加・削除はcreated/deletedで示す |
moreFiles | 内容filesに差分が入らなかった変更ファイルの件数 |
unavailable | 内容差分が不完全、または取得できなかったときに立つ |
skipped | 内容git checkoutやgit stashのように作業ツリーごと動かすGitコマンドで、差分を取らなかったときに立つ |
shared | 内容サブエージェント等、別のBashツール呼び出しが同じリポジトリで同時に走っていたときに立つ |
sharedが立っている場合、リストされた変更が自分のコマンドではなく並行して動いていた別の呼び出しによるものである可能性があります。Gitが無視するファイルとサブモジュール内のファイルは、そもそもリストに載りません。バックグラウンド実行のコマンドと読み取り専用のコマンドには差分が付きません。
記録が有効なら、コマンド直後にターミナルへこの差分が表示されます。ディスク上の変更そのものを検知したいだけなら、FileChanged hookの方が用途に合う場面もあります。
実際のペイロードはおおよそ次の形になります(公式ドキュメントの例に沿った形)。
{
"changedFiles": ["/repo/src/app.ts", "/repo/src/utils.ts"],
"files": [
{
"filePath": "/repo/src/app.ts",
"hunks": ["@@ -10,3 +10,4 @@ ...diff本体..."]
}
],
"moreFiles": 1,
"unavailable": false,
"skipped": false,
"shared": false
}変更ファイルが6件以上あるケースでは、filesに入るのは表示用の5件までで、残りはmoreFilesの件数としてしか分かりません。どのファイルが6件目以降なのかは、この情報だけでは特定できません。
PostToolUseフックで差分を使う
tool_response.bashEditDiffはフック側から読めるので、変更されたファイルに対して自動でリンタやフォーマッタをかけるフックを組めます。次の例は、Bashコマンドが変更したファイルの一覧をjqで取り出し、ESLintの--fixに渡します。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_response.bashEditDiff.changedFiles[]? // empty' | xargs -r npx eslint --fix"
}
]
}
]
}
}changedFilesが空ならフックは何もせず終わります。unavailableがtrueのとき、つまり差分の取得自体に失敗しているときは、このフックはそれを検知しません。差分の有無を条件分岐に使う場合はunavailableとskippedもあわせてチェックし、両方ともfalseのときだけchangedFilesを信用するようにフック側を書くと安全です。
シェルとsettings.jsonで値が食い違ったとき
CLAUDE_CODE_BASH_EDIT_DIFFをシェルのプロファイルでexportしつつ、settings.jsonのenvブロックにも同じキーを書いていると、どちらが勝つか迷う場面があります。Claude Codeはenvの値をプロセス環境に書き込んでシェルから継承した値を置き換えるため、設定ファイル側の値が優先されます。シェルで0にしていても、ユーザー設定のsettings.jsonが"1"を指定していれば記録は有効になります。
公式ドキュメントの「環境変数がいつ適用されるか」を扱う節は、モデル選択やタイムアウトなどの機能トグル系の環境変数について、プロジェクト設定・ローカル設定が設定できない変数のリスト(CLAUDE_CONFIG_DIRやOpenTelemetryのエクスポーター関連など)に載っていない限り、プロジェクト設定・ローカル設定を含むすべてのsettings fileから起動時に適用される、と明記しています。CLAUDE_CODE_BASH_EDIT_DIFFはこの除外リストに含まれないため、プロジェクトの.claude/settings.jsonやローカルの.claude/settings.local.jsonのenvブロックからも有効化できます。設定キーのbashEditDiffEnabledはtrueをユーザー設定・管理者設定に限定しているので、環境変数と設定キーとで有効化できる場所が異なる非対称な関係になっています。
複数の設定ファイルにまたがって同じキーを書いている場合は、管理者設定 > コマンドライン引数 > プロジェクトローカル設定(.claude/settings.local.json)> 共有プロジェクト設定(.claude/settings.json)> ユーザー設定、の順で優先されます。「シェルで無効にしたはずなのに記録が消えない」と感じたら、まず優先度の高い設定ファイルのenvブロックを確認してください。
よくある誤解と注意点
- 「記録されない」と「変更が無い」は別:
git checkoutやgit stashのように作業ツリーごと動くGitコマンドはskipped: trueになり、差分を取りに行きません。これは「変更が無かった」のではなく「そもそも差分を取っていない」状態です。空のchangedFilesと混同しないでください。 - バージョン要件を先に確認する: この環境変数も
bashEditDiffEnabled設定も、Claude Code v2.1.269より前のバージョンには存在しません。古いバージョンで動かないときは、まずアップデートを疑ってください。 - 監査やポリシー強制の代わりにはならない: 公式ドキュメントは、この差分記録をベストエフォート・パブリックベータの機能と位置づけています。変更の取りこぼし、他プロセスによる変更の混入、最大200件のファイルパスと最大5件のhunkへの切り詰め、フィールド形状の将来変更が起こり得ます。用途はレビューすべき箇所を見つけることに限られます。コンプライアンス上の変更履歴が必要な場面では、Gitのコミット履歴やCIのログのような、切り詰めのない記録手段を別に用意してください。
bashEditDiffEnabledはプロジェクト設定でtrueにできず、環境変数は個人のセッションで上書きできる
bashEditDiffEnabledのtrueが効くのはユーザー設定・--settingsで渡すJSON・管理者設定だけで、プロジェクトの.claude/settings.jsonや.claude/settings.local.jsonに書いても記録は始まりません(falseはどちらに書いても有効です。より優先度の高い設定ファイルがtrueにしていない限り)。
管理者が組織全体に効かせたいなら管理者設定側で、個々の開発者が自分のセッションだけ試したいならCLAUDE_CODE_BASH_EDIT_DIFF=1という環境変数側で、という役割の分かれ方です。組織のポリシーとしての一斉オンと、個人の一時的なオンとで、触るべき場所が違います。
Bashの実行そのものを制限するsandbox.enabledとは目的が異なる点にも注意してください。sandbox.enabledはコマンドの実行環境を隔離する設定で、bashEditDiffEnabledとその環境変数は「実行を許すかどうか」ではなく「実行後に変更を記録するかどうか」だけを担当します。両者は独立した設定なので、片方だけ有効にしても矛盾は起きません。
まとめ
CLAUDE_CODE_BASH_EDIT_DIFFはbashEditDiffEnabled設定より優先される、Bash実行中のファイル変更差分をセッション単位で全パーミッションモードに広げる環境変数です。差分はPostToolUseフックのtool_response.bashEditDiffにchangedFiles・files・moreFiles・unavailable・skipped・sharedとして渡り、レビュー補助の情報として設計されています。設定キーbashEditDiffEnabledはプロジェクト設定ではtrueにできないため、組織全体に効かせるか個人のセッションだけ試すかで設定する場所を選びます。BASH_DEFAULT_TIMEOUT_MSのような他のBash関連環境変数と同様、v2.1.269以降でしか使えない点も確認してから導入してください。
導入の判断に迷ったら、まず自分のセッションでCLAUDE_CODE_BASH_EDIT_DIFF=1を一時的に試し、PostToolUseフックのペイロードでどんな情報が取れるかを確認してから、組織のポリシーとして管理者設定へ広げるかを決めます。個人のセッションで検証してから展開すれば、フックの実装ミスを組織全体に広げずに済みます。