言いたいことの全て
Claude Code セッション中では ! で好きなコマンドを実行できます。エージェントと対話しているのと同じコンソール内でコマンド実行できるのが便利ですが、以下がネックです。
- リモートコントロールからは
!は実行できません。 -
!を実行すると、実行結果がエージェントに届くので、反応してほしくなくてもエージェントが一々反応してきます。
そこで、コマンドをスキル (カスタムスラッシュコマンド) でラップしておけば、上記の課題をどちらも解決できます。
コマンドをラップするスキル (カスタムスラッシュコマンド) を用意する手順
通常のスキル (カスタムスラッシュコマンド) を用意するときと何も変わりません。
以下のように (カスタムスラッシュコマンド) を用意しておけば、セッション中で /tool aaa bbb ccc のようにコマンドを実行できます。リモートコントロール時も実行できます。
- セッション内で実行したいコマンドをシェルスクリプト
tool.sh(好きな名前でよい) に書きます。シェルスクリプトは引数を取っても構いません。 - Bash ツールで 1. のシェルスクリプトを実行するスキル (またはカスタムスラッシュコマンド) を定義します。ここで、標準出力だけをそのまま返すよう指示します。
-
settings.jsonで 2. のスキル (カスタムスラッシュコマンド) を許可します。また、シェルスクリプト自体の読み取り・編集の拒否もしておくほうが安全だと思います。 - もし Bash ツールに PreToolUse フックを仕込んでいる場合は、2. での呼び出しパターンが拒否されないようにしておきます。
以下は 2. の定義例です。$ARGUMENTS で引数を受け渡せます。私はカスタムスラッシュコマンドにしていますが、スキルの場合はフロントマターに disable-model-invocation: true を書いてエージェントの自動利用を防ぐのがよいのではないかと思います。
project/.claude/commands/tool.md
---
allowed-tools: Bash(bash -c 'source $(pwd)/tool.sh':*)
---
【注意】これからユーザがコマンドを実行します。
このターン、あなたはあなたに届いた標準出力をそのままユーザに提示してください。
成功しても、「ほげほげが実行されました」などと実況しないでください。
失敗しても、原因を分析したり、リトライを促したりしないでください。
!`bash -c 'source $(pwd)/tool.sh' _ $ARGUMENTS`
以下は 3. の設定例です。
project/.claude/settings.json
{
"permissions": {
"allow": [
"Bash(bash -c 'source $(pwd)/tool.sh':*)"
],
"deny": [
"Read(./tool.sh)",
"Edit(./tool.sh)"
]
}
}
備考
-
readを含むシェルスクリプトの場合 — 手元では、元々使用していた、引数不足だと対話モードで引数を問うシェルスクリプトを Claude Code セッション内から呼べるようにしました。このとき、Claude Code から呼ぶ場合に限っては引数不足で対話モードになったら即座に終了したいという要望がありました。とりあえずシェルスクリプトを呼べるようにして、わざと引数不足にしてみると、数秒で勝手に落ちました。内部でタイムアウトがあるのかreadしようとすると落ちるのかはわかりませんが、結果的に要件は満たされていました。