claude-code - 💡(How to fix) Fix PreToolUse hook exit code 2 does not block Write tool

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Code Example

{
  "matcher": "Write",
  "hooks": [{
    "type": "command",
    "command": "/Users/username/.claude/scripts/enforce-local-memory.sh",
    "timeout": 5
  }]
}

---

#!/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
RAW_BUFFERClick to expand / collapse

Environment

  • Claude Code (latest, auto-updates channel)
  • macOS Darwin 25.3.0
  • Permission mode: auto
  • skipAutoPermissionPrompt: true in 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_path env 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.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Write should be blocked when hook returns exit 2.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING