Feature Request: Allow Permission Mode Switching in PermissionRequest Hooks

Resolved 💬 8 comments Opened Dec 15, 2025 by vikvorona Closed Apr 9, 2026

Feature Request: Allow Permission Mode Switching in PermissionRequest Hooks

Summary

Add ability to programmatically switch Claude CLI permission modes when responding to PermissionRequest hooks.

Problem Statement

Currently, there's no way to programmatically control the session's permission mode from hooks. The permission_mode field in hook input is read-only, and there's no API to change it.

Current behavior: When approving a permission request via a PermissionRequest hook, Claude remains in its current permission mode. There's no way to replicate the native approval prompt options like "Yes, accept all edits" (switch to acceptEdits) vs "Yes" (stay in current mode).

Desired behavior: Allow hook responses to optionally switch permission modes when approving permission requests.

Use Case

When building external approval workflows for any PermissionRequest (not just ExitPlanMode), it would be valuable to programmatically control the permission mode. This enables emulating the native approval prompt options:

In Plan Mode (ExitPlanMode approval):

  1. "Yes, accept all edits" - Approve and switch to acceptEdits mode
  2. "Yes" - Approve and switch to default mode

In Default Mode (general tool approvals):

  1. "Yes, allow all edits during this session" - Approve and switch to acceptEdits mode
  2. "Yes" - Approve and stay in default mode

This would enable external tools to offer the same flexibility that exists in the native Claude Code interactive approval prompts.

Proposed Solution

Option 1: Add switchToMode Field in Hook Response

Allow hooks to request a permission mode switch in the decision response:

{
  "hookSpecificOutput": {
    "hookEventName": "PermissionRequest",
    "decision": {
      "behavior": "allow",
      "switchToMode": "acceptEdits"
    }
  }
}

Valid values: "default", "plan", "acceptEdits", "bypassPermissions" (or null to leave unchanged)

Option 2: Add permission_mode to Tool Input

Instead of permission_mode being session-level metadata only, include it as a modifiable field in tool_input. This would allow hooks to change the mode via updatedInput:

Current structure:

{
  "session_id": "...",
  "permission_mode": "plan",  // Read-only, not in tool_input
  "tool_name": "ExitPlanMode",
  "tool_input": {
    "plan": "..."
  }
}

Proposed structure:

{
  "session_id": "...",
  "tool_name": "ExitPlanMode",
  "tool_input": {
    "plan": "...",
    "permission_mode": "plan"  // Now modifiable via updatedInput
  }
}

Hook response:

{
  "hookSpecificOutput": {
    "hookEventName": "PermissionRequest",
    "decision": {
      "behavior": "allow",
      "updatedInput": {
        "permission_mode": "acceptEdits"
      }
    }
  }
}

Example Hook Implementation

Using Option 1 (switchToMode):

#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
CURRENT_MODE=$(echo "$INPUT" | jq -r '.permission_mode')

# External logic determines user's approval preference
DESIRED_MODE=$(get_user_approval_preference "$TOOL_NAME" "$CURRENT_MODE")

if [[ "$DESIRED_MODE" == "current" ]]; then
  echo '{"hookSpecificOutput":{"hookEventName":"PermissionRequest","decision":{"behavior":"allow"}}}'
else
  echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PermissionRequest\",\"decision\":{\"behavior\":\"allow\",\"switchToMode\":\"$DESIRED_MODE\"}}}"
fi

Using Option 2 (updatedInput):

#!/bin/bash
INPUT=$(cat)
DESIRED_MODE=$(get_user_approval_preference)

echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PermissionRequest\",\"decision\":{\"behavior\":\"allow\",\"updatedInput\":{\"permission_mode\":\"$DESIRED_MODE\"}}}}"

Benefits

  • Enables external automation tools to fully replicate native approval UX
  • Works for all permission requests, not just specific tools
  • Consistent with existing hook decision structure (Option 1) or existing updatedInput pattern (Option 2)
  • No breaking changes - feature is opt-in
  • Provides parity with native interactive approval prompts

Additional Context

  • Platform: macOS (but issue affects all platforms)
  • Related keyboard shortcut: Shift+Tab cycles modes interactively, but there's no programmatic equivalent
  • This applies to all PermissionRequest hooks, not just ExitPlanMode

View original on GitHub ↗

This issue has 8 comments on GitHub. Read the full discussion on GitHub ↗