Skip to content

How to Set Up Guardrails for Claude Code and AI Coding Tools

I watched in horror as my AI coding assistant casually executed git push --force to the main branch. No confirmation, no warning, just a destructive action that wiped out my teammate’s work. That was the moment I realized: AI coding tools need guardrails, not just clever prompts.

The Problem: AI Agents Have Too Much Power

Modern AI coding assistants like Claude Code, Cursor, and GitHub Copilot can execute terminal commands, modify files, push to git repositories, and even deploy to production. This power is incredibly useful but also dangerous. Without proper constraints, a misunderstanding or hallucination can lead to:

  • Force-pushing to protected branches
  • Deleting critical files or databases
  • Exposing secrets in commits
  • Deploying unreviewed code to production
  • Running destructive commands like kubectl delete without approval

The solution isn’t to avoid AI tools—it’s to implement multi-layered defenses that catch mistakes before they happen.

Layer 1: Hooks as Hard Blockers

Hooks are your first line of defense. They run before or after tool execution and can block dangerous actions. In Claude Code, you configure hooks in ~/.claude/settings.json:

~/.claude/settings.json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "echo 'Blocking destructive git operations'"
}
]
}
]
}
}

The key principle: use hooks as hard blockers for destructive or unwanted actions. Don’t just log warnings—actually prevent the action from executing.

Here’s a more sophisticated example that blocks force pushes:

block-force-push.sh
#!/bin/bash
# Check if command contains force push
if echo "$CLAude_CODE_COMMAND" | grep -qE "git\s+push.*--force|git\s+push.*-f"; then
if echo "$CLAUDE_CODE_COMMAND" | grep -qE "main|master"; then
echo "BLOCKED: Force push to main/master is not allowed"
exit 1
fi
fi
exit 0

Layer 2: Allowlists to Constrain Access

Constraining which paths and tools the agent can access is more effective than catching mistakes after the fact. Allowlists limit the blast radius before any action is taken.

For file system access, define allowed paths:

allowed-paths.yaml
allowedPaths:
- /Users/username/projects/my-app
- /Users/username/projects/my-app/src
- /Users/username/projects/my-app/tests
# Explicitly deny sensitive paths
deniedPaths:
- /Users/username/.ssh
- /Users/username/.aws
- /Users/username/.env

For tool access, specify which MCP (Model Context Protocol) servers the agent can use:

mcp-config.json
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/allowed/path"],
"disabled": false
},
"dangerous-admin-tools": {
"disabled": true
}
}
}

As one developer noted: “More useful upfront: constrain which paths and tools the agent can access—allowlists limit blast radius better than catching mistakes after the fact.”

Layer 3: Least-Privilege Cloud Permissions

If you’re giving AI tools access to cloud resources, apply the principle of least privilege rigorously. A common mistake is providing admin-level credentials just for convenience.

For AWS, this means:

minimal-iam-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
]
}
]
}

The guidance is clear: “If you’re going to give it AWS SSO, give it read only, or heavily scoped IAMs.” Never grant write, delete, or admin permissions unless absolutely necessary—and then only for specific resources.

For Kubernetes access, be equally careful:

kubeconfig-scoped.yaml
users:
- name: ai-assistant
user:
token: <limited-scope-token>
# This token should only have read access to specific namespaces

Layer 4: Manual Approval for Sensitive Operations

Some operations should always require human approval, regardless of how smart your AI assistant is. Terminal commands that affect production infrastructure fall into this category.

Set up approval requirements for commands like:

  • kubectl delete - Could delete production resources
  • kubectl apply - Could modify running infrastructure
  • Database migrations - Could cause data loss
  • git push --force - Could destroy commit history

In Claude Code, you can configure this:

approval-settings.json
{
"permissions": {
"requireApproval": [
"Bash:kubectl*",
"Bash:*delete*",
"Bash:*drop*",
"Bash:*truncate*",
"Bash:git push*--force*"
]
}
}

The rule is simple: “Any terminal execution of kubectl commands needs to be manually approved.”

Layer 5: Skills, Rules, and Iterative Refinement

Guardrails aren’t set-and-forget. They require ongoing refinement as you discover edge cases and learn from near-misses.

The recommended approach:

  1. Set up your skills, rules, and access to protect yourself
  2. Start with strict permissions
  3. Use --dangerously-skip-permissions only when you trust your setup
  4. Prompt well with clear constraints
  5. Refine your rules over time as issues arise
  6. Build more skills for repetitive tasks

Your CLAUDE.md file should document project-specific constraints:

CLAUDE.md
# Project Constraints
## Never Do These Things
- Never run migrations without approval
- Never commit to main branch directly
- Never push to remote without reviewing diff
- Never delete files matching pattern *.env*
## Required Approvals
- Any kubectl command
- Any npm publish command
- Any git push with --force flag

A Complete Guardrails Configuration Example

Here’s how a comprehensive setup might look:

Complete Guardrails Architecture
+---------------------------+
| User Prompt |
+---------------------------+
|
v
+---------------------------+
| PreToolUse Hooks | <-- Block destructive patterns
| - Check command intent |
| - Validate paths |
| - Require approval |
+---------------------------+
|
v
+---------------------------+
| Allowlist Filter | <-- Constrain accessible tools/paths
| - Allowed MCP servers |
| - Allowed file paths |
| - Denied sensitive dirs |
+---------------------------+
|
v
+---------------------------+
| Least-Privilege Creds | <-- Minimal cloud permissions
| - Read-only AWS IAM |
| - Scoped k8s tokens |
| - No admin access |
+---------------------------+
|
v
+---------------------------+
| Manual Approval Gate | <-- Human in the loop
| - kubectl commands |
| - Database operations |
| - Force pushes |
+---------------------------+
|
v
+---------------------------+
| Safe Execution |
+---------------------------+

Testing Your Guardrails

Before trusting your setup, test it:

test-guardrails.sh
# This should be blocked
echo "Testing force push block..."
claude-code "force push to main" # Should fail or require approval
# This should be blocked
echo "Testing kubectl access..."
claude-code "delete all pods in production" # Should require approval
# This should work
echo "Testing safe operation..."
claude-code "read the README file" # Should succeed

Document your guardrails and review them periodically. As your AI tools get smarter, your defenses should too.

Common Guardrail Mistakes to Avoid

  1. Over-reliance on prompts alone - Prompts can be misunderstood; code-level constraints cannot
  2. Granting admin credentials for convenience - Always use minimal permissions
  3. Skipping hooks during development - Test with the same restrictions you’ll use in production
  4. Not logging blocked actions - You need visibility into what the AI tried to do
  5. Forgetting to update rules - New tools and commands require new constraints

Summary

Setting up guardrails for AI coding tools requires a multi-layered approach:

  1. Hooks as hard blockers for destructive actions
  2. Allowlists to constrain accessible paths and tools
  3. Least-privilege permissions for cloud resources
  4. Manual approval for sensitive operations
  5. Iterative refinement based on real-world usage

The goal isn’t to limit AI capabilities but to ensure that mistakes are caught before they cause damage. Your AI assistant can still be powerful—just safely powerful.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments