[FEATURE] PreToolUse hook: let "ask" decisions set the default-highlighted prompt option

Open 💬 4 comments Opened May 31, 2026 by karlkfi

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

I maintain a PreToolUse Bash hook that returns ask when a command targets a file outside the project root ($CLAUDE_PROJECT_DIR). The
hook's purpose is to add deliberation at a security boundary — preventing Claude from quietly reading or writing files outside the workspace.

When the hook returns ask, Claude Code renders its standard permission
prompt:

> 1. Yes

  1. Yes, allow reading from etc/ from this project
  2. No

Option 1 ("Yes") is always pre-highlighted. For a hook whose entire purpose is to flag a command as crossing a policy boundary, having "Yes" be a single Enter-press away undercuts the guard. An inattentive operator defaults to approval, and the friction the hook was designed to add gets bypassed.

The hook has already classified the action as out-of-policy. It should be able to express "...and the safe default is No."

Proposed Solution

Let the PreToolUse hook's JSON output include an optional field naming the default-highlighted choice, e.g.:

{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "ask",
"permissionDecisionReason": "Outside-workspace path(s): /etc/passwd",
"defaultPermissionChoice": "deny"
}
}

Values: "allow" | "deny"; unset = current behavior (Yes pre-highlighted). When set to "deny", the prompt opens with the rejection option pre-highlighted instead of "Yes".

Alternative or complement: a permissions.defaultPromptChoice key in settings.json for a project- or user-level global preference.

Alternative Solutions

  • Switch the hook from ask to deny. Removes the prompt entirely, losing the legitimate-override path — the user has to edit settings or re-prompt the model to recover.
  • Inject guidance via additionalContext asking Claude to double-check. Indirect, model-dependent, doesn't change UI behavior.
  • Instead of just specifying the default, it might be nice to specify all the ask options.

Priority

Medium - Would be very helpful

Feature Category

Interactive mode (TUI)

Use Case Example

  1. I install claude-workspace-guard (currently a private repo), which registers a PreToolUse Bash hook.
  2. I ask Claude: "find the auth error in the logs."
  3. Claude issues grep auth /var/log/system.log.
  4. The hook resolves the path outside $CLAUDE_PROJECT_DIR and returns ask with defaultPermissionChoice: "deny".
  5. Claude Code shows the permission prompt with "No" pre-highlighted.
  6. I read the prompt, confirm /var/log/system.log isn't what I wanted, press Enter to reject.
  7. The safe default protected me when I was context-switching or moving fast — exactly the moments a security guard is supposed to help.

Today step 5 highlights "Yes," so a reflexive Enter approves an out-of-scope file read.

Additional Context

Plugin demonstrating the use case: https://github.com/karlkfi/claude-workspace-guard (currently a private repo, possibly OSS soon)

Precedent in other tools: many security-adjacent CLIs let the caller pick the safe default per-prompt — sudo's password-required-on-timeout, apt's APT::Get::Assume-No, git's confirmation prompts. The pattern is well understood: when a tool has flagged something as risky, the default should match the risk classification.

This is a small surface (one optional field) with outsized impact for the class of hooks doing policy enforcement.

View original on GitHub ↗

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