claude-code - 💡(How to fix) Fix Allow hooks to trigger interactive terminal prompts with custom options [1 participants]

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…
GitHub stats
anthropics/claude-code#52343Fetched 2026-04-24 06:09:41
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Participants
Timeline (top)
labeled ×3

Code Example

Hook: protect-files wants to confirm

  Edit to .git/info/exclude — this is a protected path.

  1. Allow once
  2. Block
  3. Allow for this session

---

{
  "prompt": {
    "message": "Edit to .git/info/exclude — this is a protected path.",
    "options": [
      {"key": "1", "label": "Allow once", "value": "allow"},
      {"key": "2", "label": "Block", "value": "block"},
      {"key": "3", "label": "Allow for session", "value": "allow_session"}
    ]
  }
}
RAW_BUFFERClick to expand / collapse

Preflight Checklist

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

Problem Statement

Hooks communicate with Claude Code via exit codes and stderr, but can only hard-block (exit 2) or silently allow (exit 0). There's no way for a hook to pause and ask the user a question with custom options — like the built-in permission prompt does with Allow/Deny/Always Allow.

Real use case: I have a protect-files.sh PreToolUse hook that blocks edits to sensitive files (.env, .pem, lockfiles, .git/). Currently it hard-blocks every attempt, and I have to manually work around it. I'd like the hook to show a prompt like:

Hook: protect-files wants to confirm

  Edit to .git/info/exclude — this is a protected path.

  1. Allow once
  2. Block
  3. Allow for this session

...and return the user's choice to the hook so it can decide the exit code.

Related: #51255 (asks for "ask" to work reliably in auto mode — adjacent but different; this request is about custom prompts with user-defined options, not reusing the existing permission dialog).

Proposed Solution

A hook should be able to output a structured JSON prompt request on stdout that Claude Code intercepts and renders as a terminal prompt — reusing the same TUI as the existing permission system.

Example hook stdout:

{
  "prompt": {
    "message": "Edit to .git/info/exclude — this is a protected path.",
    "options": [
      {"key": "1", "label": "Allow once", "value": "allow"},
      {"key": "2", "label": "Block", "value": "block"},
      {"key": "3", "label": "Allow for session", "value": "allow_session"}
    ]
  }
}

Claude Code renders the prompt, waits for a keypress, and pipes the selected value back to the hook's stdin (or sets an env var like $HOOK_USER_CHOICE) so the hook can decide the final exit code.

Alternative Solutions

  • macOS osascript dialogs — works but pops a separate window outside the terminal, breaking the workflow
  • Exit code 2 + stderr message — blocks unconditionally and relies on Claude (the model) to relay the message and ask the user; indirect, the user has no direct control, and the model may not relay it faithfully
  • PermissionRequest hook with "behavior": "ask" — only intercepts existing permission dialogs, can't define custom questions or options

Additional Context

The infrastructure already exists — Claude Code's terminal UI renders interactive prompts with keyboard shortcuts for the permission system. Hooks are child processes of Claude Code and already communicate via structured JSON on stdin/stdout. Bridging these two would make hooks significantly more powerful for safety and workflow gates without requiring hard blocks.

extent analysis

TL;DR

To enable custom prompts with user-defined options in hooks, modify the hook to output a structured JSON prompt request on stdout that Claude Code can intercept and render as a terminal prompt.

Guidance

  • Define a JSON prompt structure with a message and options, as proposed in the issue, to be output by the hook on stdout.
  • Modify Claude Code to intercept this JSON prompt and render it as a terminal prompt, reusing the existing TUI for the permission system.
  • Implement a mechanism for Claude Code to pipe the selected option's value back to the hook's stdin or set an environment variable like $HOOK_USER_CHOICE for the hook to decide the final exit code.
  • Test this functionality with the protect-files.sh PreToolUse hook to ensure it works as expected for the real use case described.

Example

{
  "prompt": {
    "message": "Edit to .git/info/exclude — this is a protected path.",
    "options": [
      {"key": "1", "label": "Allow once", "value": "allow"},
      {"key": "2", "label": "Block", "value": "block"},
      {"key": "3", "label": "Allow for session", "value": "allow_session"}
    ]
  }
}

Notes

This solution builds upon the existing infrastructure of Claude Code's terminal UI and hook communication via structured JSON on stdin/stdout, making it a feasible enhancement without requiring significant architectural changes.

Recommendation

Apply the proposed workaround by implementing the JSON prompt structure and modifying Claude Code to handle these prompts, as this approach leverages existing functionality and provides a direct, user-controlled workflow.

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…

Still need to ship something?

×6

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

Back to top recommendations

TRENDING