Lesson
Guide Claude Code with Rich PreToolUse Feedback
Return structured JSON from PreToolUse hooks to deny commands with clear reasons and suggestions, creating a self-correcting feedback loop.
- Access
- Included
- Transcript
- Needs source
Guiding Claude Code with rich feedback turns blocked commands into learning opportunities. Return structured JSON with denial reasons and alternatives so Claude self-corrects in real time.
Exit code vs. JSON output
Exit code 2 (lesson 15):
- Blocks tool execution
- Shows error to Claude
- No structured guidance
JSON output (this lesson):
- Blocks with
permissionDecision: "deny" - Provides
permissionDecisionReasonwith clear alternatives - Creates a self-correcting feedback loop
Return structured feedback
Use HookJSONOutput to deny with guidance:
import { type PreToolUseHookInput, type HookJSONOutput } from "@anthropic-ai/claude-agent-sdk"
const input = await Bun.stdin.json() as PreToolUseHookInput
type BashToolInput = {
command: string
description: string
}
if (input.tool_name === "Bash") {
const toolInput = input.tool_input as BashToolInput
if (toolInput.command.startsWith("echo")) {
const output: HookJSONOutput = {
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny", // "allow" | "deny" | "ask"
permissionDecisionReason: "echo is not allowed. Always use node -e and console.log instead."
}
}
console.log(JSON.stringify(output, null, 2))
}
}
Key fields:
permissionDecision:"allow"(bypass permission),"deny"(block + feedback), or"ask"(prompt user)permissionDecisionReason: Message shown to Claude (for deny) or user (for allow/ask)
See it self-correct
Prompt Claude to use a blocked command:
use echo to echo hello world
Sequence:
- Claude attempts
echo - Hook denies with reason: "use node -e and console.log"
- Claude immediately retries with
node -e 'console.log("hello world")' - Command succeeds
Permission decisions
Three options for permissionDecision:
-
"deny"- Block tool + show reason to Claude Use case: Enforce conventions with guidance -
"allow"- Bypass permission system + show reason to user Use case: Auto-approve safe operations -
"ask"- Prompt user for confirmation + show reason Use case: Require manual approval for sensitive operations
Why this pattern works
- Self-correction: Claude learns your conventions in real-time
- Clear guidance: Explains why something's blocked and what to use instead
- No dead ends: Every denial includes the path forward
- Consistent enforcement: Same rules across all sessions
Try it
Prompts:
use echo to echo hello world