fix: guard hook uses shell script with full binary path

The original hook syntax `blue guard --path="$TOOL_INPUT:file_path"`
didn't work - Claude Code doesn't support that variable interpolation.

Created guard-write.sh that:
- Reads JSON from stdin using jq (Claude Code's recommended pattern)
- Extracts file_path from tool_input
- Calls blue guard with full path to target/release binary
- Closes stdin with </dev/null to prevent hanging

The full binary path is a workaround for an issue where PATH-based
command lookup hangs in Claude Code's hook subprocess environment.
A proper fix (making guard synchronous before tokio::main) is tracked
in RFC 0049.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Eric Garcia 2026-02-01 17:32:40 -05:00
parent ddce9e8b03
commit 21dc822d4c
2 changed files with 15 additions and 1 deletions

14
.claude/hooks/guard-write.sh Executable file
View file

@ -0,0 +1,14 @@
#!/bin/bash
# PreToolUse hook for Write/Edit/MultiEdit - enforces RFC 0038 worktree protection
# Extract file_path directly with jq (recommended pattern - avoids cat hanging)
FILE_PATH=$(jq -r '.tool_input.file_path // empty')
# If no file_path, allow (shouldn't happen for Write/Edit)
if [ -z "$FILE_PATH" ]; then
exit 0
fi
# Call blue guard with the extracted path
# Use full path to target/release binary and close stdin
/Users/ericg/letemcook/blue/target/release/blue guard --path="$FILE_PATH" </dev/null

View file

@ -6,7 +6,7 @@
"hooks": [
{
"type": "command",
"command": "blue guard --path=\"$TOOL_INPUT:file_path\""
"command": ".claude/hooks/guard-write.sh"
}
]
}