PreToolUse hook exit code 2 does not block Write tool
Resolved 💬 2 comments Opened May 28, 2026 by stranger2904 Closed Jun 1, 2026
Environment
- Claude Code (latest, auto-updates channel)
- macOS Darwin 25.3.0
- Permission mode: auto
skipAutoPermissionPrompt: truein settings
Problem
A PreToolUse hook configured for the Write tool with exit 2 (deny) does not actually block the write. The file is created/modified despite the hook returning a blocking exit code.
Hook configuration (settings.json)
{
"matcher": "Write",
"hooks": [{
"type": "command",
"command": "/Users/username/.claude/scripts/enforce-local-memory.sh",
"timeout": 5
}]
}
Hook script
#!/bin/bash
FILE_PATH="${CLAUDE_TOOL_INPUT_file_path:-}"
if [[ "$FILE_PATH" == *"/.claude/projects/"*"/memory/"* ]]; then
echo "BLOCKED: Do NOT write memory files to ~/.claude/projects/*/memory/."
exit 2
fi
exit 0
Manual test
Running the script directly with the matching path correctly outputs "BLOCKED" and exits with code 2.
Actual behavior
Claude writes to ~/.claude/projects/*/memory/*.md successfully. The hook either:
- Doesn't fire for auto-memory Write calls
- Fires but exit code 2 isn't enforced
- The
CLAUDE_TOOL_INPUT_file_pathenv var isn't set correctly
Expected behavior
Write should be blocked when hook returns exit 2.
Possible cause
The auto-memory system may bypass PreToolUse hooks, or the skipAutoPermissionPrompt: true setting may also skip hook enforcement.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗