Claude Codeのbashコマンドを柔軟に制御するツールを作ってみた(rm -rf ~/も防げます)
はじめに
Claude Code は便利ですが、rm -rf ~/
のような危険なコマンドも実行してしまう可能性があります。そこで、Claude Code のhooks 機能を活用して、bash コマンドの実行を安全かつ柔軟に制御するツールを作ってみました。
実際に rm -rf ~/
をブロックしているところ
セットアップ
1. リポジトリのクローン
git clone https://github.com/miyaoka/claude-hooks.git
2. settings.json へのフック設定
Claude Code のsettings.json
に以下を追加:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "[cloneしたリポジトリ内のスクリプトパス]"
}
]
}
]
}
}
3. ルールファイルの配置
.claude/hooks.config.json
を作成し、制御ルールを定義します
ルール設定
{
"PreToolUse": {
"Bash": {
"ls": [
{
"reason": "lsコマンドは安全なので自動承認",
"decision": "approve"
}
],
"git": [
{
"pattern": "^(status|log|diff)",
"reason": "読み取り専用のgitコマンドは自動承認",
"decision": "approve"
},
{
"pattern": "^push",
"reason": "⚠️ pushはユーザーが行います",
"decision": "block"
}
],
"npm": [
{
"pattern": "^install.*(-g|--global)",
"reason": "グローバルインストールは確認が必要"
}
],
"curl": [
{
"reason": "⚠️ curlの代わりにWebFetchツールを使用してください",
"decision": "block"
}
]
}
}
}
ルールの構成要素
本ツールはClaude Code の PreToolUse Decision Control仕様に準拠し、pattern
フィールドを独自拡張として追加しています。
項目 | 説明 | 値 |
---|---|---|
pattern | コマンド引数に対する正規表現(独自拡張・省略可) | 正規表現文字列 |
decision | マッチ時の動作(Claude 仕様準拠) |
block 、approve 、未指定(確認) |
reason | Claude へのメッセージ(Claude 仕様準拠) | 文字列 |
ルール評価の優先順位
- pattern 指定ありのルールが優先
- pattern 未指定はデフォルトルール
- block が最優先(安全側に倒す)
動作例
上記の設定により:
-
git push
:ブロック(ユーザーが手動実行すべき) -
curl
:ブロック(WebFetch ツールへ誘導) -
git status
:自動承認(読み取り専用)
高度な設定
設定ファイルの優先順位
CLAUDE.md と同様に、グローバル設定とプロジェクトローカル設定の両方が利用可能です:
- グローバル設定:
~/.config/claude/hooks.config.json
- プロジェクト設定:
.claude/hooks.config.json
設定は以下の順序でマージされます:
// グローバル (例: ~/.config/claude/hooks.config.json)
{
"PreToolUse": {
"Bash": {
"rm": [
{
"pattern": "-rf",
"reason": "強制削除は危険",
"decision": "block"
}
]
}
}
}
// プロジェクトローカル (.claude/hooks.config.json)
{
"PreToolUse": {
"Bash": {
"rm": [
{
"pattern": "\\.tmp$",
"reason": "一時ファイルの削除はOK",
"decision": "approve"
}
]
}
}
}
// 実際に評価される結合結果
{
"rm": [
// グローバルルールが先
{
"pattern": "-rf",
"reason": "強制削除は危険",
"decision": "block"
},
// ローカルルールが後
{
"pattern": "\\.tmp$",
"reason": "一時ファイルの削除はOK",
"decision": "approve"
}
]
}
複合コマンドと複数引数の処理
{
"touch": [
{
"reason": "touchコマンドのデフォルトは承認",
"decision": "approve"
},
{
"pattern": "/etc",
"reason": "⚠️ システムファイルへのtouchは禁止",
"decision": "block"
},
{
"pattern": "\\.conf$",
"reason": "設定ファイルの作成は要確認"
}
],
"echo": [
{
"pattern": "hello",
"reason": "⚠️ あいさつ禁止",
"decision": "block"
}
]
}
評価結果
コマンド | 結果 | 理由 |
---|---|---|
touch foo.txt |
✅ 承認 | デフォルトルールで承認 |
echo hello && touch bar.txt |
❌ ブロック | "hello"が禁止パターン |
echo world && touch /etc/bar.txt |
❌ ブロック | /etc への touch が禁止 |
touch file.txt /etc/hosts app.conf |
❌ ブロック | 引数に/etc が含まれる |
ルール評価アルゴリズム
マッチング優先順位
- pattern 指定ルールが最優先
- pattern 未指定はデフォルトルール
- 複数マッチ時は安全側(block > 確認 > approve)を採用
処理フロー
- コマンドごとに全ルールを評価
- block ルールにマッチしたら即座に実行停止
- 確認が必要なルールがあればユーザーに確認
- すべて approve の場合のみ自動実行
ルールの安全なテスト方法
実際にパターンマッチが意図通り指定できているか確認するため、Claude Code を通さずに、シェルスクリプトで直接テストできます:
# 危険なコマンドのテスト
echo '{"tool_input": {"command": "rm -rf ~/"}}' | ./hooks/pretooluse/bash/hook.sh
# → {"decision": "block", "reason": "⚠️ ホームディレクトリの削除は禁止"}
# 安全なコマンドのテスト
echo '{"tool_input": {"command": "ls -la"}}' | ./hooks/pretooluse/bash/hook.sh
# → {"decision": "approve", "reason": "lsコマンドは安全なので自動承認"}
# ルール未定義コマンドのテスト
echo '{"tool_input": {"command": "echo test"}}' | ./hooks/pretooluse/bash/hook.sh
# → {} (ユーザー確認が必要)
ブロックするだけじゃない。permissions 設定より柔軟で正確な制御
従来のsettings.json
のpermissions.allow
設定では、&&
や;
で連結されたコマンドの評価が難しく、意図通りに動作しないケースがありました。
// 従来の方法(settings.json)
{
"permissions": {
"allow": ["Bash(ls)", "Bash(git status)", "Bash(npm run test:*)"],
"deny": ["Bash(rm -rf)", "Bash(curl:*)"]
// 問題点:
// - ワイルドカード(*)のみで正規表現が使えない
// - 同一コマンドで引数によるallow/denyの分岐が難しい
// - 複合コマンド(&&や;)の評価が不明確
}
}
本ツールのアプローチ:
// 本ツールの方法
{
"git": [
{ "pattern": "^(status|log|diff)", "decision": "approve" },
{ "pattern": "^push", "decision": "block" }
],
"npm": [
{ "pattern": "^install$", "decision": "approve" },
{
"pattern": "^install.*(-g|--global)",
"reason": "グローバルインストールは確認が必要"
}
]
}
主な利点
-
複合コマンドの正確な評価:
&&
や;
で連結された各コマンドが個別に評価される - 柔軟なパターンマッチング:正規表現で引数の一部をマッチできる
- approve と block の混在:同じコマンドでも引数によって異なる動作を設定可能
- hooks 機能の活用:reason で代替手段の提案や理由を Claude に伝えられる
まとめ
Claude Code の hooks 機能を活用して、正規表現による柔軟なパターンマッチングを実現するツールを作りました。従来の permissions 設定では難しかった複合コマンドの制御や、同一コマンドでの approve/block の混在が可能になり、より安全で効率的な開発環境を構築できます。
詳細なドキュメントはGitHub リポジトリをご覧ください。
(本記事は人力で書きましたが最終的にclaudeに推敲して編集してもらいました)
Discussion