claude-code - 💡(How to fix) Fix [Feature Request] PreToolUse hook result substitution primitive [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#52045Fetched 2026-04-23 07:38:02
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Participants
Timeline (top)
labeled ×2

Error Message

it renders as "PreToolUse:WebSearch hook blocking error". The model reads it fine, but the framing is adversarial (error, block) when the intent is cooperative (substitution, redirect). policy-filtered responses) without the error-framing wart.

Root Cause

Concrete use case. I built https://github.com/HeinrichvH/Exactor, a PreToolUse hook that intercepts
WebSearch/WebFetch and routes the query to a cheaper, cited, subagent-driven researcher (Mistral Vibe). The researcher returns a validated report with sources. The report is legitimate tool-result content — but because the only way to hand it to the model is via permissionDecision: "deny" + permissionDecisionReason (or exit 2 + stderr), it renders as "PreToolUse:WebSearch hook blocking error". The model reads it fine, but the framing is adversarial (error, block) when the intent is cooperative (substitution, redirect).

Fix Action

Fix / Workaround

Current workaround: exit 2 + stderr, or permissionDecision: "deny" + permissionDecisionReason. Both work
functionally; both render as blocking errors. Happy to discuss further — context at github.com/HeinrichvH/Exactor.

Code Example

[]
RAW_BUFFERClick to expand / collapse

Feature request: result-substitution primitive for PreToolUse hooks

PreToolUse hooks today can allow, deny, modify input, or inject systemMessage — but cannot replace a tool's output with synthetic content. I'd like a primitive that says "don't run the native tool; here's the result text to hand
the model as if the tool had returned it."

Concrete use case. I built https://github.com/HeinrichvH/Exactor, a PreToolUse hook that intercepts
WebSearch/WebFetch and routes the query to a cheaper, cited, subagent-driven researcher (Mistral Vibe). The researcher returns a validated report with sources. The report is legitimate tool-result content — but because the only way to hand it to the model is via permissionDecision: "deny" + permissionDecisionReason (or exit 2 + stderr), it renders as "PreToolUse:WebSearch hook blocking error". The model reads it fine, but the framing is adversarial (error, block) when the intent is cooperative (substitution, redirect).

Proposed shape:

{ "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "substitute",
"toolResult": "<content to render as if the tool returned it>" }
}

Or equivalent: a toolResultOverride field on the existing deny decision.

Why it matters. The "senior delegates crawling to cheap subagents" pattern is a genuinely useful abstraction —
subagents compact log/code/web exploration into cited JSON for pennies, saving main-loop context. PreToolUse hooks are the natural enforcement point, but the current API forces the pattern to surface as errors. A substitution
primitive would unlock a class of "augmentation hooks" (custom fetchers, cached crawlers, local-first search, policy-filtered responses) without the error-framing wart.

Current workaround: exit 2 + stderr, or permissionDecision: "deny" + permissionDecisionReason. Both work
functionally; both render as blocking errors. Happy to discuss further — context at github.com/HeinrichvH/Exactor.

Environment Info

  • Platform: darwin
  • Terminal: Apple_Terminal
  • Version: 2.1.117
  • Feedback ID: 31415c86-13b8-4ee0-b75c-3ba2b5f3e233

Errors

[]

extent analysis

TL;DR

Implement a result-substitution primitive for PreToolUse hooks to allow synthetic content replacement without error framing.

Guidance

  • Consider adding a toolResultOverride field to the existing deny decision to enable result substitution.
  • Evaluate the proposed shape of the hookSpecificOutput object to determine its feasibility and potential implementation.
  • Investigate the possibility of introducing a new permissionDecision value, such as "substitute", to facilitate result substitution.
  • Review the current workaround using exit 2 + stderr or permissionDecision: "deny" + permissionDecisionReason to understand its limitations and potential areas for improvement.

Example

No code snippet is provided as the issue focuses on proposing a new feature rather than resolving a specific coding error.

Notes

The implementation of the result-substitution primitive may require changes to the existing API and hook architecture. The proposed solution should be discussed further to ensure compatibility and feasibility.

Recommendation

Apply workaround: The current workaround using exit 2 + stderr or permissionDecision: "deny" + permissionDecisionReason can be used until a more robust solution is implemented, allowing for result substitution without error framing.

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

claude-code - 💡(How to fix) Fix [Feature Request] PreToolUse hook result substitution primitive [1 participants]