Home
cd ../playbooks
Developer ToolsBeginner

Hookify Guardrails

Create custom Claude Code guardrails with lightweight markdown rule files instead of hand-editing hooks.json — pattern matching, no restart required, rules live-load on the next tool call.

5 minutes
By AnthropicSource
#hooks#guardrails#automation#regex#safety#official

You've told Claude three times not to use console.log in this codebase, and it keeps happening because 'don't do X' in a conversation doesn't survive to the next session. You need a rule that actually enforces itself — without writing a hooks.json schema from scratch.

Who it's for: developers wanting reusable guardrails without hooks.json complexity, teams enforcing coding standards automatically, engineers who keep correcting the same AI behavior repeatedly, anyone wanting a warn-or-block layer on dangerous commands

Example

"Warn me when I use rm -rf commands" → A .claude/hookify.warn-rm.local.md file is generated with the regex pattern, event type, and warning message already filled in — active on the very next Bash tool call, no restart, no hooks.json editing

CLAUDE.md Template

New here? 3-minute setup guide → | Already set up? Copy the template below.

# Hookify Guardrails

## Your Role

You help me create custom guardrails for Claude Code without editing complex `hooks.json` files. Instead, you write lightweight markdown rule files that define patterns to watch for and messages to show when they match.

Two ways I'll ask:

- **With an instruction**: "Warn me when I use rm -rf commands" → write a rule from what I described
- **Without one**: "create a hookify rule" with no detail → analyze our recent conversation to find behaviors I corrected you on or got frustrated by, propose rules for those

Rules take effect on the very next tool use. No restart needed.

---

## Rule File Format

Rules live at `.claude/hookify.{descriptive-name}.local.md` in the **project root**, not a plugin directory.

### Simple rule (single pattern)

```markdown
---
name: block-dangerous-rm
enabled: true
event: bash
pattern: rm\s+-rf
action: block
---

⚠️ **Dangerous rm command detected!**

This command could delete important files. Please:
- Verify the path is correct
- Consider using a safer approach
- Make sure you have backups
```

### Advanced rule (multiple conditions)

```markdown
---
name: warn-sensitive-files
enabled: true
event: file
action: warn
conditions:
  - field: file_path
    operator: regex_match
    pattern: \.env$|credentials|secrets
  - field: new_text
    operator: contains
    pattern: KEY
---

🔐 **Sensitive file edit detected!**

Ensure credentials are not hardcoded and the file is in .gitignore.
```

**All conditions must match** for the rule to trigger.

---

## Frontmatter Reference

**`name`** (required) — unique identifier. Use kebab-case, start with a verb: `warn-dangerous-rm`, `block-console-log`, `require-tests`.

**`enabled`** (required) — `true` or `false`. Toggle without deleting the rule.

**`event`** (required) — which hook event triggers the check:

| Event | Fires on |
|-------|----------|
| `bash` | Bash tool commands |
| `file` | Edit, Write, MultiEdit tools |
| `stop` | When Claude wants to stop |
| `prompt` | When you submit a prompt |
| `all` | Every event |

**`action`** (optional, defaults to `warn`):
- `warn` — shows the message, allows the operation
- `block` — prevents the operation (PreToolUse) or stops the session (Stop events)

**`pattern`** — regex for simple single-condition rules. Matches against `command` for bash events, `new_text` for file events. Python regex syntax.

**`conditions`** — list form for multi-field rules. Each entry has `field`, `operator`, and `pattern`.

### Fields by event type

| Event | Available fields |
|-------|------------------|
| bash | `command` |
| file | `file_path`, `new_text`, `old_text`, `content` |
| prompt | `user_prompt` |
| stop | general matching on session state |

### Operators

`regex_match` (most common) · `contains` · `equals` · `not_contains` · `starts_with` · `ends_with`

---

## Writing Good Patterns

Python regex syntax. Common metacharacters:

| Token | Matches |
|-------|---------|
| `\s` | whitespace |
| `\d` | digit |
| `\w` | word character |
| `.` | any character |
| `+` | one or more |
| `*` | zero or more |
| `?` | zero or one |
| `\|` | OR |

Escape literals: `\.` for a dot, `\(` for a paren, `\[` for a bracket.

### Examples

```
rm\s+-rf              → rm -rf, rm  -rf
console\.log\(        → console.log(
(eval|exec)\(         → eval( or exec(
chmod\s+777           → chmod 777, chmod  777
API_KEY\s*=           → API_KEY=, API_KEY =
\.env$                → .env, .env.local
```

### Pitfalls

**Too broad:** `pattern: log` also matches "login", "dialog", "catalog". Use `console\.log\(|logger\.` instead.

**Too specific:** `pattern: rm -rf /tmp` only catches that exact path. Use `rm\s+-rf`.

**Escaping:** in YAML, quoted strings need doubled backslashes (`"\\s"`). Unquoted works as written (`\s`). **Use unquoted patterns.**

### Test before shipping

```bash
python3 -c "import re; print(re.search(r'your_pattern', 'test text'))"
```

---

## Message Body

Everything after the frontmatter is shown to Claude when the rule fires. A good message:

- Explains what was detected
- Explains why it's problematic
- Suggests alternatives or best practices
- Uses formatting for clarity

```markdown
⚠️ **Console.log detected!**

You're adding console.log to production code.

**Why this matters:**
- Debug logs shouldn't ship to production
- Console.log can expose sensitive data
- Impacts browser performance

**Alternatives:**
- Use a proper logging library
- Remove before committing
- Use conditional debug builds
```

---

## Rule Library

### Block destructive operations

```markdown
---
name: block-destructive-ops
enabled: true
event: bash
pattern: rm\s+-rf|dd\s+if=|mkfs|format
action: block
---

🛑 **Destructive operation detected!**

This command can cause data loss. Operation blocked for safety.
Verify the exact path and use a safer approach.
```

### Warn about debug code

```markdown
---
name: warn-debug-code
enabled: true
event: file
pattern: console\.log\(|debugger;|print\(
action: warn
---

🐛 **Debug code detected**

Remember to remove debugging statements before committing.
```

### Require tests before stopping

```markdown
---
name: require-tests-run
enabled: false
event: stop
action: block
conditions:
  - field: transcript
    operator: not_contains
    pattern: npm test|pytest|cargo test
---

**Tests not detected in transcript!**

Before stopping, run tests to verify your changes work correctly.
```

Enable only when you want strict enforcement — this blocks Claude from ending the turn.

### Catch hardcoded credentials in TypeScript

```markdown
---
name: api-key-in-typescript
enabled: true
event: file
conditions:
  - field: file_path
    operator: regex_match
    pattern: \.tsx?$
  - field: new_text
    operator: regex_match
    pattern: (API_KEY|SECRET|TOKEN)\s*=\s*["']
---

🔐 **Hardcoded credential in TypeScript!**

Use environment variables instead of hardcoded values.
```

### Production deployment checklist

```markdown
---
name: prod-deploy-checklist
enabled: true
event: prompt
conditions:
  - field: user_prompt
    operator: contains
    pattern: deploy to production
---

Production deployment checklist:
- [ ] Tests passing?
- [ ] Reviewed by team?
- [ ] Monitoring ready?
```

---

## Common Pattern Targets

**Bash events** — dangerous commands (`rm\s+-rf`, `dd\s+if=`, `mkfs`), privilege escalation (`sudo\s+`, `su\s+`), permission issues (`chmod\s+777`, `chown\s+root`)

**File events** — debug code (`console\.log\(`, `debugger`, `print\(`), security risks (`eval\(`, `innerHTML\s*=`, `dangerouslySetInnerHTML`), sensitive files (`\.env$`, `credentials`, `\.pem$`), generated files (`node_modules/`, `dist/`, `build/`)

---

## Managing Rules

**Disable temporarily:** set `enabled: false` in the frontmatter
**Delete permanently:** remove the `.local.md` file
**Gitignore:** add `.claude/*.local.md` to `.gitignore`

Good filenames: `hookify.dangerous-rm.local.md`, `hookify.console-log.local.md`, `hookify.require-tests.local.md`

Bad filenames: `hookify.rule1.local.md` (not descriptive), `hookify.md` (missing `.local`), `danger.local.md` (missing `hookify` prefix)

---

## Troubleshooting

**Rule not triggering**
1. Confirm the file is in `.claude/` in the project root, not a plugin directory
2. Verify `enabled: true`
3. Test the regex separately
4. Rules work immediately — no restart needed

**Pattern not matching**
- Test it: `python3 -c "import re; print(re.search(r'pattern', 'text'))"`
- Use unquoted patterns in YAML to avoid escaping problems
- Start simple, then add complexity

**Hooks feel slow**
- Keep patterns simple, avoid complex regex
- Use specific event types (`bash`, `file`) instead of `all`
- Limit the number of active rules

---

## Requirements

Python 3.7+ on PATH. No external dependencies.

Get new playbooks like this one

One email a week with new Claude Code workflows. Free, like everything here.

No spam. Unsubscribe anytime.

README.md

What This Does

Turns hook creation into writing a markdown file instead of editing JSON. Describe a behavior you want caught — in plain language or as a specific regex — and get a .claude/hookify.{name}.local.md rule file that warns or blocks on Bash commands, file edits, session stops, or prompt submissions. Can also analyze recent conversation to auto-propose rules for behaviors you've already corrected Claude on.


Quick Start

Step 1: Navigate to Your Project

cd ~/your-project

Step 2: Download the Template

Click Download above, then:

mv ~/Downloads/CLAUDE.md ./

Step 3: Create Your First Rule

claude

Then ask: "Create a rule warning me about console.log in TypeScript files" — or just say "create a hookify rule" with no detail, and Claude analyzes recent conversation for behaviors you've been correcting.


Rule Anatomy

---
name: block-dangerous-rm
enabled: true
event: bash
pattern: rm\s+-rf
action: block
---

⚠️ **Dangerous rm command detected!**
This command could delete important files. Verify the path and make sure you have backups.
  • event — bash, file, stop, prompt, or all
  • action — warn (shows message, allows the operation) or block (prevents it)
  • pattern — a Python regex, matched against the command or new file content
  • Multi-condition rules use a conditions: list instead, where every condition must match

Supported Formats

Rules live at .claude/hookify.{name}.local.md in the project root. Simple rules use a single pattern:; advanced rules check multiple field / operator / pattern conditions across file_path, new_text, old_text, content, command, or user_prompt depending on event type.

Tips & Best Practices

  • Use unquoted patterns in YAML to avoid double-escaping backslashes
  • Test regex before shipping: python3 -c "import re; print(re.search(r'pattern', 'text'))"
  • Too broad beats too narrow at first — console\.log\(|logger\. catches more than pattern: log, which also matches "login" and "catalog"
  • Add .claude/*.local.md to .gitignore — these are meant to be local, not committed team policy
  • Rules apply immediately on the next matching tool call — no restart needed

Limitations

  • Requires Python 3.7+ on PATH, no external dependencies otherwise
  • Regex-only matching — no semantic understanding of what the code actually does
  • stop event rules that block can prevent Claude from ending a turn — enable those deliberately, not by default

Troubleshooting

Rule not triggering — confirm the file is in .claude/ at the project root (not a plugin directory), enabled: true is set, and the regex actually matches your test string.

Hooks feel slow — simplify the regex, use a specific event type instead of all, and limit the number of active rules.

$Related Playbooks

Developer Tools

Learning Mode Coding Coach

Interactive coding mode that hands you the meaningful 5-10 line decisions — business logic, trade-offs, design choices — while Claude handles the boilerplate and explains the codebase as you go.

2 minutes
Beginner
Developer Tools

Loopy: Build and Reuse Agent Loops

Mine your codebase and coding history for repeated work, turn it into bounded agent loops, and audit the loops you already have

10 minutes
Intermediate
Developer Tools

GPT Taste Skill: Strict Anti-Slop UI Rules

A stricter, more deterministic anti-slop frontend ruleset with GSAP motion patterns, despite the GPT-oriented name it works as a standard CLAUDE.md in Claude Code

5 minutes
Intermediate
Developer Tools

GitHub Contributor

A phase-based playbook for shipping pull requests maintainers actually merge — discovery, CONTRIBUTING compliance, PR-size checks, minimal diffs, and post-submission interaction.

20 minutes
Intermediate
Developer Tools

GitHub Operations

Comprehensive GitHub operations using the gh CLI and REST/GraphQL APIs — PRs, issues, repositories, workflows, and bulk operations across public and Enterprise GitHub.

10 minutes
Intermediate
Developer Tools

i18n Expert

Set up, audit, and enforce internationalization in UI codebases — install the i18n framework, replace hard-coded strings, ensure locale coverage, and validate key parity and pluralization.

20 minutes
Intermediate
Developer Tools

LLM Icon Finder

Find and download AI/LLM model brand icons from the lobe-icons library — Claude, GPT, Gemini, and more — as ready-to-use SVG, PNG, or WEBP URLs.

5 minutes
Beginner
Developer Tools

LLM Coding Guardrails

Four behavioral guidelines that reduce the most common Claude coding mistakes: silent assumptions, overcomplication, scope creep, and vague success criteria.

2 minutes
Beginner
Developer Tools

LangSmith Fetch

Debug LangChain and LangGraph agents by fetching execution traces from LangSmith Studio for error analysis and performance optimization.

10 minutes
Intermediate
Developer Tools

Explanatory Coding Mode

Get educational insights about implementation choices and codebase patterns as Claude works — formatted, codebase-specific commentary woven into the session, not a generic tutorial.

2 minutes
Beginner
Developer Tools

7-Phase Feature Development Workflow

Structured feature development that explores the codebase, asks every clarifying question up front, presents multiple architecture options with a recommendation, and runs a three-angle quality review before calling it done.

5 minutes
Intermediate
Developer Tools

Ginkgo Table and Dynamic Specs

Parameterize and generate Ginkgo test specs correctly — DescribeTable/Entry, the four ways to name an entry, DescribeTableSubtree for multi-It rows, reusable entry sets, and the one gotcha (Entry params evaluate at construction time, not BeforeEach time) that causes most table-spec bugs.

5 minutes
Intermediate

Browse all Developer Tools playbooks →