ブラウザの操作もエージェントに任せられるかを、Claude Code を何本もヘッドレスで動かす技術検証の中で試したところ、claude -p に --chrome を付けても、ブラウザの道具は使えるようになりませんでした。-p を付けると、--chrome は無視されます。私たちは、PreToolUse フックで人の承認を挟む関門を保ったまま、ブラウザを使えるかを確かめました。
結論
-pを付けると、--chromeは無視されました(2.1.170・2.1.227 の両方)。-pを外し、--input-format stream-json --output-format stream-json --verbose --chromeで起こして、プロンプトを stdin に1行の JSON で渡すと、claude-in-chrome が繋がりました(道具は 22 本)。- この起こし方でも、フックの発火・deny・defer・
--resume・TTY の無いパイプでの実行が、すべて-pのときと同じに効きました。 - この起こし方ではプロセスが自分では終わらないので、最後の
resultを受けたら stdin を閉じます。
試した環境
- Mac、Claude Code 2.1.227。
-pで--chromeが無視されることは、2.1.170 でも見ました。
-p を外して stream-json の入力で起こす
起こし方は次のとおりです。
claude --input-format stream-json --output-format stream-json --verbose --chrome …
プロンプトは引数ではなく、stdin に1行の JSON で渡します。TTY の無いパイプから起こしても動きました。これで claude-in-chrome が繋がり、ブラウザの道具が 22 本使えるようになりました。
フックの関門は -p と同じに効いた
ブラウザを操作させるなら、どの操作で人の承認を挟むかが大事になります。そこで、-p で確かめてあった関門の振る舞いが、この起こし方でも同じかを測りました。
| 確かめたこと | 結果 |
|---|---|
フックの発火(matcher: "*" で全部の道具に掛けた) | -p と同じに発火した |
| deny | 効いた |
| defer | 効いた。stop_reason が tool_deferred になり、deferred_tool_use の形も -p と同じだった |
--resume | 効いた |
| TTY の無いパイプ | -p と同じに動いた |

終わらせ方
-p のときと違い、この起こし方では、仕事が済んでもプロセスが自分では終わりません。起こす側が stdin を閉じて終わらせます。
閉じる合図を「最初の result」ではなく「最後の result」にしているのには理由があります。-p で --resume したとき、1つのプロセスの中で result が2回流れることを、私たちは見ていました。ただし、この起こし方でどの result が最後かを確かに見分ける方法は、私たちは詰めていません。
MCP の絞り方
--strict-mcp-config を付けると、claude.ai のコネクタ(Figma・Gmail・Drive・Calendar)だけが外れ、claude-in-chrome は残りました。ブラウザの道具は残したまま、ほかのコネクタをエージェントに渡さないようにできます。
渡さなかった道具
22 本のうち browser_batch は、中に複数の操作をまとめて実行します。フックは呼び出しを1件ずつ確かめるので、まとめられた中身はその確認をすり抜けると判断し、エージェントには渡しませんでした。実際にすり抜けるかどうかは測っていません。
ブラウザを操作させるときは、相手のサービスの規約も確かめてください。
確かめていないこと
browser_batchが、実際にフックの確認をすり抜けるかどうか。- stream-json の入力で起こしたとき、最後の result を確かに見分ける方法(
--resumeで result が2回流れることは-pで見ただけ)。 - 2.1.227 より後の版でも同じかどうか。
おわりに
-p を外して stream-json の入力で起こすと、ブラウザの道具と、フックによる承認の関門を両立できました。-p との違いは、プロセスを終わらせるのが起こす側の仕事になることでした。
※ この記事に書いた Claude Code の振る舞いは、執筆時点で私たちが測ったものです。いまは変わっている可能性があります。


