Because 'trust me' isn't a permission model for your AI coding agent.
Published Aug 13, 2026, 3:00 PM EDT
Yadullah Abidi is a Computer Science graduate from the University of Delhi and holds a postgraduate degree in Journalism from the Asian College of Journalism, Chennai. With over a decade of experience in Windows and Linux systems, programming, PC hardware, cybersecurity, malware analysis, and gaming, he combines deep technical knowledge with strong editorial instincts.
Yadullah currently writes for MakeUseOf as a Staff Writer, covering cybersecurity, gaming, and consumer tech. He formerly worked as Associate Editor at Candid.Technology and as News Editor at The Mac Observer, where he reported on everything from raging cyberattacks to the latest in Apple tech.
In addition to his journalism work, Yadullah is a full-stack developer with experience in JavaScript/TypeScript, Next.js, the MERN stack, Python, C/C++, and AI/ML. Whether he's analyzing malware, reviewing hardware, or building tools on GitHub, he brings a hands-on, developer’s perspective to tech journalism.
Claude Code may be great at reasoning through code, but it does not always pause and think about consequences the way a cautious human would. And that's exactly the gap that hooks are built to close.
These are shell commands, HTTP endpoints, or even LLM prompts that fire automatically at specific points in Claude Code's lifecycle, like right before a tool call or right after it's done. And since they're deterministic scripts and not suggestions in a prompt, they work the same way every time, not how Claude thinks they should.
Blocking destructive commands before they run Because 'rm -rf' is not a personality trait
The most obvious and perhaps the most important hook is a PreToolUse guard on the Bash tool that scans every command before it runs and blocks anything destructive. Things like rm -rf, disk utilities like dd or mkfs, or a curl-pipe-to-shell pattern that downloads and executes a script blindly.
The hook reads the proposed command from stdin as JSON, checks it against a list of regex patterns, and if it matches, exits with code 2. That exit code tells Claude to block the action and feeds the reason back to Claude as stderr, so it understands why it got stopped and can propose alternate actions instead of just retrying blindly.
#!/bin/bash
command=$(cat | jq -r '.tool_input.command')
[[ "$command" =~ rm\ -rf|dd\ if=|mkfs\. ]] && echo "Blocked: destructive command" >&2 && exit 2
exit 0
Protecting environments and secrets
Because Claude really wants to 'fix' your .env file
Another rather useful development hook is something that targets the Edit and Write tools specifically to stop Claude from accessing .env files or anything with secrets or credentials in the path. This one matters more than you'd think because Claude has a tendency to "fix" the environment file while debugging configuration issues, and that is exactly the kind of file edit you don't want an AI to make, especially unsupervised.
The hook checks the file path being written to, and if it matches a protected pattern, it exits with code 2 and refuses the edit outright. The rest of the pipeline works exactly as described above.
#!/bin/bash
path=$(cat | jq -r '.tool_input.file_path')
[[ "$path" =~ \.env|secrets|credentials ]] && echo "Blocked: protected file" >&2 && exit 2
exit 0
Stopping force pushes and other git disasters
History is only sacred until Claude decides it's not
Git accidents are some of the most painful terminal mistakes because they can rewrite shared history. A hook on the Bash matcher can specifically look for git push --force or any push targeting main or master and block it before it executes.
You can even go further and also block git reset --hard, since that command silently destroys uncommitted work with no option to undo it. This can easily prevent a ruined afternoon when Claude decides wiping uncommitted files is the fastest way to clean up a messy working directory.
#!/bin/bash
command=$(cat | jq -r '.tool_input.command')
[[ "$command" =~ push\ --force|push\ .*\ main|reset\ --hard ]] && echo "Blocked: dangerous git command" >&2 && exit 2
exit 0
Blocking reckless database operations
DROP TABLE should never happen by accident
If your workflow involves a database, whether that is Postgres for a project or something you self-host, you want a hook that can catch destructive SQL before it reaches the terminal. The same PreToolUse pattern applies here: check the Bash command for keywords like DROP TABLE or TRUNCATE, and if found, deny the permission with a clear reason stated instead of letting the command run.
Since Claude Code can return a structured JSON response with a permissionDecision of deny and an explanation, you get more useful feedback than a simple exit code. This helps Claude course-correct on the next attempt rather than just complaining that it was blocked.
#!/bin/bash
command=$(cat | jq -r '.tool_input.command')
[[ "$command" =~ DROP\ TABLE|TRUNCATE ]] && echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"Destructive SQL detected"}}'
Keeping your package manager and CI config in check
Small mistakes add up faster than big ones
This is more about outright disaster and more about the small mistakes that add up, like Claude running npm install in a project that standardized on pnpm, or editing a lockfile it should not touch. A PreToolUse hook can check for the presence of a pnpm-lock.yaml and block any npm commands that would create a conflicting lockfile, nudging Claude towards the correct tool every time instead of relying on it to remember your project conventions from context alone.
You can extend the same idea to block changes to CI configuration files and even production deployment scripts unless a human explicitly approves them. It also helps keep your context more compact.
#!/bin/bash
command=$(cat | jq -r '.tool_input.command')
[[ -f pnpm-lock.yaml && "$command" =~ ^npm\ install ]] && echo "Blocked: use pnpm instead" >&2 && exit 2
exit 0
One JSON file, and Claude finally behaves
All of these hooks live in a .claude/settings.json file, either per project or in your home directory for global coverage, under a PreToolUse hooks array with a matcher for the relevant tool, usually Bash, Edit, or Write. Since hooks are just scripts, you can write them in Bash with jq or in Python if you prefer more readable logic, and check them into your repository so anyone using your codebase inherits the same guardrails.
{
"hooks": {
"PreToolUse": [
{ "matcher": "Bash", "hooks": [{ "type": "command", "command": ".claude/hooks/block-destructive-bash.sh" }] },
{ "matcher": "Edit|Write", "hooks": [{ "type": "command", "command": ".claude/hooks/protect-secrets.sh" }] }
]
}
}
Once these are in place, Claude Code stops being a tool you have to babysit constantly. Instead, you get something that you can actually trust with the keyboard.
| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | Auto Mode will soon be the default in Claude Code — because humans can’t be trusted | 0 | 7.23 | 07-08-2026 |
| 2 | The New Agency Stack: How Dev Shops Use Claude, Cursor, and Copilot in Production | 0 | 8.46 | 24-07-2026 |
| 3 | Security Challenges of Autonomous AI Coding Agents: Insights from Early Real-World Use #programming #artificialintelligence | 0 | 10.35 | 26-05-2026 |
| 4 | Claude Sonnet 5: Everything to Know About Anthropic’s New Model | 0 | 5 | 30-06-2026 |
| 5 | Best AI Coding Agents in 2026: The Complete Beginner’s Guide | 0 | 9.13 | 18-02-2026 |
| 6 | Découvrir les niveaux de maturité de l'adoption des Coding Agents | 0 | 5 | 17-03-2026 |
| 7 | entelligence-cli 0.1.105 | 5 | 7 | 20-07-2026 |
| 8 | Should I use Claude Code or n8n? | 0 | 6.6 | 14-07-2026 |
| 9 | Code Faster Today … Fail Faster Tomorrow? | 0 | 8.12 | 29-07-2026 |
| 10 | This ChatGPT Codex feature is its best and worst at the same time | 0 | 10 | 12-08-2026 |