How to Safely Use Claude Code: Prevent Dangerous Commands with Hooks
This guide explains how Claude Code’s powerful automation can unintentionally run risky commands and shows how to use Hooks—configurable event‑driven scripts—to enforce safety checks, format code, send notifications, and debug issues across the Claude Code workflow.
Claude Code can edit files, run shell commands, and execute scripts, which makes it easy to hand over many tasks to the model but also risky if it runs commands like rm -rf or modifies sensitive files such as .env or .git. Prompt‑based restrictions are insufficient; the reliable solution is to use Hooks that automatically trigger at specific lifecycle events.
What Hooks Are
A Hook consists of an event (when it runs) and a handler (what it does). Events include SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, PermissionRequest, Stop, PreCompact, etc. Handlers can be of five types: command, http, mcp_tool, prompt, and agent.
Hook Types and Typical Uses
Notification: runs when Claude needs user attention; useful for desktop alerts. PreToolUse: runs before a tool executes; ideal for blocking dangerous commands or protecting sensitive files. PostToolUse: runs after a successful tool call; perfect for formatting, logging, or injecting additional context.
Configuration Files
Hooks are defined in JSON files placed in one of three locations: ~/.claude/settings.json – applies to all projects for the current user. .claude/settings.json – project‑level configuration that can be committed. .claude/settings.local.json – private per‑machine settings that should not be committed.
Each entry contains a matcher (filter) and a hooks array with handler definitions.
Minimal Example
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}This runs prettier on every file edited or written by Claude.
Three Practical Hook Scenarios
1. Notification Hook
Shows a macOS notification when Claude requests permission:
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
}
]
}
]
}
}2. Post‑Tool Formatting Hook
Automatically formats JavaScript, TypeScript, JSON, etc., after Claude edits a file:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}3. Pre‑Tool Safety Hook
Blocks dangerous Bash commands and prevents editing of sensitive paths:
#!/usr/bin/env bash
set -euo pipefail
input=$(cat)
tool=$(echo "$input" | jq -r '.tool_name // empty')
command=$(echo "$input" | jq -r '.tool_input.command // empty')
file=$(echo "$input" | jq -r '.tool_input.file_path // empty')
if [[ "$tool" == "Bash" ]] && [[ "$command" =~ rm[[:space:]]+-rf|chmod[[:space:]]+-R[[:space:]]+777 ]]; then
echo "Blocked risky shell command: $command" >&2
exit 2
fi
if [[ "$tool" =~ ^(Edit|Write)$ ]] && [[ "$file" =~ ^(.*/)?(.env|.git/|.*id_rsa.*|.*id_ed25519.*)$ ]]; then
echo "Blocked sensitive file edit: $file" >&2
exit 2
fi
exit 0Save the script, make it executable, and reference it in .claude/settings.json under PreToolUse with a matcher like "Bash|Edit|Write".
Choosing the Right Handler
Use command for deterministic local scripts, http for remote audit services, mcp_tool for existing MCP tools, and prompt or agent only when a model‑driven decision is required.
Debugging Hooks
When a Hook does not behave as expected:
Run /hooks in Claude Code to verify the configuration is loaded.
Execute the script manually with a sample JSON payload to check exit codes and output.
Log debugging information to stderr or a temporary file, never to stdout (which is parsed as JSON).
Enable only one Hook at a time to isolate failures.
Hooks vs. Skills
Hooks are automatic, fixed actions tied to lifecycle events and are best for formatting, security checks, and notifications. Skills are on‑demand knowledge bundles loaded when Claude needs higher‑level reasoning, such as code review or complex troubleshooting.
Practical Roll‑out Strategy
Start with the three core Hooks in this order: Notification, then PostToolUse for formatting, and finally PreToolUse for safety. Verify each step works before adding more advanced events like SessionStart, ConfigChange, or PreCompact.
Summary
Hooks let you enforce deterministic safety policies in Claude Code without relying on prompt engineering alone. Use PostToolUse for automatic formatting, PreToolUse to block risky commands or protect sensitive files, and Notification to stay informed. Combine Hooks with Skills for complex, context‑aware tasks, and follow the debugging checklist to keep your workflow reliable.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Tech Enthusiast
Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
