🦁
Claude CodeのHookでmdファイルへの書き込みを制限する
Claude Codeは強力なコーディングアシスタントですが、
ドキュメントファイル(.md)を過剰に作成してしまうことがあります。
本記事では、Hook機能を使ってこの問題を解決する方法を紹介します。
Claude CodeのHook機能とは
Claude Codeは~/.claude/settings.jsonでPreToolUse/PostToolUseフックを設定できます。これらのフックは、ツール実行の前後に任意のコマンドを実行する仕組みです。
{
"hooks": {
"PreToolUse": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "shコマンド"
}]
}]
}
}
Hook でのパラメータの受け取り方
JSONデータがSTDIN経由で渡されます。
つまりこんな感じで cat で受け取る必要があります。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "json=$(cat); file_path=$(echo \"$json\" | jq -r '.tool_input.file_path // empty'); if [[ \"$file_path\" == *.md ]]; then echo '{\"decision\": \"block\", \"reason\": \"Creating or editing .md files is prohibited\"}'; fi""
}
]
}
]
}
}
素直に書くと読めないぐらい長い
改行を含む入力の問題
また、Hookはシェルスクリプトが発火するため、改行やダブルクオートを含むコンテンツをjqでパースすることが難しかったりします。
実際、そこそこの行数のmdファイルはパースに失敗して読めませんでした。
最終形
そういうわけでこんな感じにしました。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "hook受取用のスクリプト"
}
]
}
]
}
}
「hook受取用のスクリプト」は
- 標準入力(STDIN)を受け取って
- 以下のような構造の標準出力
を行えばよいです。
{
"decision": "block", // もしくは allow
"reason": "Claude Codeに伝えるメッセージ"
}
参考コード
一応貼っておきますが、コードを読むよりこの記事をそのままClaude Codeに食わせたほうが作りたいものができると思います。
まとめ
参考コードはRustなのですが Claude Codeのおかげで実装コストはほぼゼロでした。
良い時代になりましたね。
Discussion