Max Nardit
← 記事
9 mindev

Claude Code の Code Mode:auto mode はツール呼び出しごとではなくスクリプトを審査するようになった

Code Mode のセッションでは、auto mode の分類器はスクリプトを一度読むだけで、その中の呼び出しは見ません。実行時に決まるパスやホストは分類器の審査を受けません。起動できない、あるいはタイムアウトした PreToolUse フックは呼び出しを拒否するようになりましたが、exit 1 で終わるフックはこれまでどおり呼び出しを通します。実際の値を見られるのは、自分のルールとフック、そしてサンドボックスだけです。

目次

11月12日にリリースされた Claude Code 2.1.323 に、実験的なオプトイン機能 Code Mode が加わりました。通常、Claude はツール呼び出しを一つずつ要求し、結果を読んでから次に何を呼ぶかを決めます。Code Mode では、呼び出しを自分で行う JavaScript を書き、REPL というツールがそのコードをセッション内で実行します。ドキュメントにあるリトライ上限を引き上げる例がこちらです。

javascript
const files = await $`rg -l "function retryPolicy" src`.text();
const target = files.trim().split("\n")[0];
await edit(target, "maxAttempts: 3", "maxAttempts: 5");
({ edited: target, tests: $`npm test -- retryPolicy`.nothrow() });

ドキュメントが想定しているのは、関連するツール呼び出しが多い作業です。多数のファイルにまたがる一つの変更、Claude が読む前に結果を絞り込む検索、並列で実行できるコマンドなどです。会話に表示されるのはツール呼び出しで、スクリプトそのものではありません。コードは Ctrl+O で開く折りたたまれた Code 行の中にあります。有効にする前に権限のセクションを読んでください。auto mode の分類器が確認する範囲が狭くなり、壊れたフックの挙動も変わるからです。以下の内容はドキュメントとリリースノートに基づいています。Code Mode は実際には動かしていないので、ここに測定結果はありません。

Claude Code の Code Mode で権限チェックはどう変わるのか

auto mode では、分類器はコードを実行前に一度だけ審査し、その中のツール呼び出しは審査しません。ドキュメントはその代償をはっきり書いています。分類器は「doesn't see values computed at run time, such as a path taken from search output, so keep rules or hooks for calls you must control.」と説明しています。コードからの呼び出しはどれも、これまでどおり deny と ask のルール、そして PreToolUse フックを通ります。

Permission modes のページを見ると、分類器がどれほどリテラルな値に頼っているかがわかります。デフォルトでは、変数が分類器から見える場所で代入されていない rm -rf "$VAR" をブロックします。「can't tell what the command would delete」、つまりコマンドが何を削除するのか判断できないからです。Claude が実際のパスをコマンドに書いて削除をやり直せば、このブロックは解除されます。Code Mode では、そのパスが審査の対象として現れる後の呼び出しがありません。分類器が読んだのはスクリプトで、スクリプトにあったのは変数です(上の例の edit は、どのみち分類器には届きません。作業ディレクトリ内の編集は、Code Mode かどうかに関係なく auto mode で自動承認されます)。

ほかの権限モードでは、コードは審査なしで始まり、そのモードで確認が出る呼び出しにはいつもどおり確認が出ます。bypassPermissions では分類器がなく、確認もほとんど出ないので、止める手段は自分のルールとフックだけです。スクリプトそのものを検査したいなら、REPL にマッチする PreToolUse フックを追加し、tool_input.code から JavaScript を読みます。このフックが読むのは分類器と同じテキストで、同じ死角を抱えています。Bash や Edit に掛けたフックは別物で、コードからの呼び出しのたびに、解決済みの引数を入力として受け取って発火します。これは「すべての呼び出しがフックを通る」というドキュメントの記述からの推論で、検証はしていません。

Code Mode で Claude Code の PreToolUse フックはどう動くのか

以前より多くのケースで拒否するようになりましたが、すべてではありません。Code Mode の外では、起動できない、クラッシュした、タイムアウトした command フックや http フックはブロックしないエラー扱いで、"onFailure": "block" を設定しない限り、呼び出しは通常の権限チェックへ進みます。フックの解説記事のためにこのデフォルトを検証したところ、存在しないスクリプトを指すフックは呼び出しを通しました。

Code Mode では、Claude のコードからの呼び出しに対して、起動できなかった、強制終了された、126、127 または 128 を超えるコードで終了した、HTTP エラーや不正な出力を返した PreToolUse フックは、onFailure を設定していなくても呼び出しを拒否します。エラーメッセージは the hook failed です。タイムアウトも the hook did not finish というメッセージで拒否になり、このルールはコードの外にも及びます。セッション内で Claude が一度でもコードを実行すると、タイムアウトしたフックはどのツール呼び出しも拒否します。

それでも通ってしまうケースが二つあります。一つは、1 のような普通のコードで終了するフックです。捕捉されない Python の例外はまさにこれで、"onFailure": "block" を設定しない限り呼び出しは通ります。もう一つは、内部で壊れても 0 で終了するガードで、解説記事の jq ガードのように、これまでどおり通ります。command フックと http フックでは、"onFailure": "continue" で以前の挙動に戻せます。

プロンプトのフィルターにも変化があります。コードがバックグラウンドで動けるセッションでは、UserPromptSubmit に掛けた command、http、mcp_tool フックがコードの出力に対しても実行され、source は poll_event になります。ユーザーの入力向けに書いたフィルターが、ビルドの出力を握りつぶす可能性があるということです。

無人の Claude Code セッションは Code Mode でどうなるのか

フォアグラウンドのコードは、確認待ちも含めて最大 10 分待ち、その後停止します。バックグラウンドのコードは最大 2 時間動けますが、auto mode か bypassPermissions で開始したセッションに限られます。

auto mode で、前のコードがまだ動いているうちに Claude が新しいコードを始めると、前のコードは審査済みの扱いを失い、残りの呼び出しのうち審査が必要なものについて Claude Code が確認を求めます。IDE が接続されていなければ、確認はカウントダウンになります。ドキュメントの例は「Claude Code will automatically block this request in 1:59, to avoid holding up an unattended session」です。応答しないとその呼び出しは拒否され、カウントダウンが出るはずの以降の呼び出しも、誰かが Claude にメッセージを送るまで確認なしで拒否されます。

審査されていない呼び出しを実行するよりは拒否のほうがよいので、誰も見ていないセッションにとっては正しい失敗の仕方だと考えます。ドキュメントに書かれていないのは、Claude に返るエラー以外に拒否がどう通知されるかです。誰かが検証するまでは、denyInsteadOfPrompting で確認したのと同じだと想定しておきます。対話セッションはアイドルに戻り、エラーはどこにも上がらず、フックが別の場所に書き出さない限り、拒否の記録はセッションの中にしか残りませんでした。

そもそも対象になるセッションはそれほど多くありません。Code Mode が動くのは、ターミナルで対話的に起動した claude セッションで、Anthropic に直接接続し、対応モデルを使っている場合だけです。-p、Agent SDK、バックグラウンドセッションや Remote Control、ゲートウェイやクラウドプロバイダー経由、Zero Data Retention では使えず、ツール呼び出しを検査する mod とも併用できません。残りの条件はドキュメントに一覧があります。

Claude Code の Code Mode を有効にするかは誰が決めるのか

自分です。シェルか ~/.claude/settings.json に CLAUDE_CODE_EXPERIMENTAL_CODE_MODE=1 を設定します。プロジェクトの settings にあるこの変数は無視されるので、クローンしたリポジトリが勝手に有効にすることはできません。組織は managed settings に 0 を設定して Code Mode を無効にでき、各ユーザーの次回再起動から効きますが、強制的に有効にすることはできません。

Code Mode を有効にした Claude Code の auto mode は信頼できるのか

Code Mode のセッションでは、分類器が確認する範囲はそうでない場合より狭くなります。判断するのはスクリプトが何をしようとしているかで、スクリプトが生み出す値は見ません。削除やアップロードで決め手になるのは対象のほうです。以前、モデルが言いくるめられないかどうかで外向き通信の制御を順位づけたとき、そこに分類器は入っていませんでした。1 位がサンドボックスの許可リスト、次に自作のフック、次に組み込みの mod、最後が CLAUDE.md の一行です。分類器を入れるならフックの下に置きます。フックの記事にも書いたとおり、関門に置いたモデルは比較衡量しているだけで、強制はしていません。承認ゲートについてのエッセイが詳しく論じているのはこの点です。Code Mode はこの順位を変えません。真ん中の層が読む範囲が狭くなった分、上位の重要性が増します。

同じリリースで、フックが応答できないときの挙動も変わりました。ドキュメントは後者をセキュリティ機能ではなく制限事項の欄に載せていますが、この二つの変更はセットで読むべきだと考えています。また Code Mode はまだ出て 2 日です。リリース 2.1.325 では、EnterWorktree で入ったワークツリーをスクリプトが無視する問題、権限ダイアログで Yes と一緒に入力した言葉が Claude に届かない問題、スクリプトの途中で終わったセッションを再開すると Claude が勝手に作業を始める問題が修正されました。

今週 CLAUDE_CODE_EXPERIMENTAL_CODE_MODE=1 を設定するなら、先に二つやっておいてください。まず、絶対に起きてはならない呼び出しを書き出し、それぞれを何が止めるのかをメモします。シェルコマンドならサンドボックスにすべきです。Bash の deny ルールはコマンドの文字列を読むだけで、Code Mode の有無にかかわらず回避できるからです。ファイル系のツールなら、deny ルールかそのツールに掛けたフックです。どの行にも auto mode を書くべきではありません。次に、PreToolUse フックを見直します。すべてのガードに "onFailure": "block" を付けて exit 1 で落ちるクラッシュでも拒否されるようにし、ログや通知だけのフックには "onFailure": "continue" を付けて、そこでのタイムアウトが作業を拒否しないようにします。timeout を延ばすのは、自分で短く設定した箇所だけにしてください。

01 / ディスカッション

コメント欄はありません。議論は X で行っています。

Max Nardit@mnardit

02 / ほかの記事

  1. Claude Code の permissions.denyInsteadOfPrompting:夜間セッションは止まらなくなり、拒否された作業はエラーになりません

    この新しい設定がなくすのは待ち時間であって、失敗ではありません。拒否された呼び出しはクリーンな終了と success サブタイプで終わるので、設定はセットアップの半分にすぎず、残りの半分は「何が拒否されたか」の記録です。同じリリースでは、フィーチャーフラグを取得しないセッションから auto mode のフォールバックがなくなり、この設定が拒否する対象も増えました。

  2. Claude Code のスラッシュコマンド: 知っておきたい組み込みコマンドと、自作の /command がいまはスキルである理由

    commands フォルダはマクロではなく、Claude が呼び出せるコードとして扱ってください。どのファイルがモデルによる呼び出しを有効のままにしているかを監査し、スクリプト実行では終了コードを信用せずにターン数を確認し、副作用のある処理の保証は呼び出しフラグではなく権限とフックに置いてください。

  3. Claude Code と Gemini CLI の分業:開発者による 7 つの使い分けと、6 月 18 日を越えて残ったもの

    2 つのツールを組み合わせる 2025 年のセットアップは、無料の Google ログインと、より大きなコンテキストウィンドウに頼っていました。そのログインは 6 月に別のツールへ移り、ウィンドウでは Claude Code が追いつきました。どのセットアップが残ったかを決めたのは、ツールそのものではなく、各呼び出しの背後にあるアカウントでした。