Double-Check: It Runs Through the Rules Before Every Move

When Claude decides to call a tool, the system runs through a decision process before actually executing:

Claude decides to call a tool (e.g. Bash("rm temp.txt"))
  ↓
Gate 1: Permission mode check
  ├── bypassPermissions? → Execute directly, skip all checks
  └── Other modes → Continue
  ↓
Gate 2: Rule matching
  ├── Matching allow rule? → Auto-execute
  ├── Matching deny rule?  → Reject outright, return error to Claude
  └── No matching rule → Continue
  ↓
Gate 3: Hook check (see Section V)
  ├── PreToolUse hook returns block? → Reject
  └── Passes → Continue
  ↓
Gate 4: Tool's own checkPermissions()
  ├── Tool judges it dangerous? → Show confirmation dialog
  └── Safe → Execute
  ↓
Execute tool
  ↓
PostToolUse hook runs (post-execution processing)

When a confirmation dialog appears, the prompt message shown to the user is generated by createPermissionRequestMessage(), which accurately states which rule requires confirmation or which Hook triggered the interception.