hookify

Easily create hooks to prevent unwanted behaviors by analyzing conversation patterns

Author: Anthropic Category: productivity

Installation

/plugin marketplace add giginet/claude-plugins-official
/plugin install hookify@claude-plugins-official
claude plugin marketplace add giginet/claude-plugins-official
claude plugin install hookify@claude-plugins-official

Skills

NameDescription
writing-rules This skill should be used when the user asks to "create a hookify rule", "write a hook rule", "configure hookify", "add a hookify rule", or needs guidance on hookify rule syntax and patterns.
namewriting-hookify-rules
version0.1.0

Writing Hookify Rules

Overview

Hookify rules are markdown files with YAML frontmatter that define patterns to watch for and messages to show when those patterns match. Rules are stored in .claude/hookify.{rule-name}.local.md files.

Rule File Format

Basic Structure

---
name: rule-identifier
enabled: true
event: bash|file|stop|prompt|all
pattern: regex-pattern-here
---

Message to show Claude when this rule triggers.
Can include markdown formatting, warnings, suggestions, etc.

Frontmatter Fields

name (required): Unique identifier for the rule - Use kebab-case: warn-dangerous-rm, block-console-log - Be descriptive and action-oriented - Start with verb: warn, prevent, block, require, check

enabled (required): Boolean to activate/deactivate - true: Rule is active - false: Rule is disabled (won't trigger) - Can toggle without deleting rule

event (required): Which hook event to trigger on - bash: Bash tool commands - file: Edit, Write, MultiEdit tools - stop: When agent wants to stop - prompt: When user submits a prompt - all: All events

action (optional): What to do when rule matches - warn: Show message but allow operation (default) - block: Prevent operation (PreToolUse) or stop session (Stop events) - If omitted, defaults to warn

pattern (simple format): Regex pattern to match - Used for simple single-condition rules - Matches against command (bash) or new_text (file) - Python regex syntax

Example:

event: bash
pattern: rm\s+-rf

Advanced Format (Multiple Conditions)

For complex rules with multiple conditions:

---
name: warn-env-file-edits
enabled: true
event: file
conditions:
  - field: file_path
    operator: regex_match
    pattern: \.env$
  - field: new_text
    operator: contains
    pattern: API_KEY
---

You're adding an API key to a .env file. Ensure this file is in .gitignore!

Condition fields: - field: Which field to check - For bash: command - For file: file_path, new_text, old_text, content - operator: How to match - regex_match: Regex pattern matching - contains: Substring check - equals: Exact match - not_contains: Substring must NOT be present - starts_with: Prefix check - ends_with: Suffix check - pattern: Pattern or string to match

All conditions must match for rule to trigger.

Message Body

The markdown content after frontmatter is shown to Claude when the rule triggers.

Good messages: - Explain what was detected - Explain why it's problematic - Suggest alternatives or best practices - Use formatting for clarity (bold, lists, etc.)

Example:

⚠️ **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

Event Type Guide

bash Events

Match Bash command patterns:

---
event: bash
pattern: sudo\s+|rm\s+-rf|chmod\s+777
---

Dangerous command detected!

Common patterns: - 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

Match Edit/Write/MultiEdit operations:

---
event: file
pattern: console\.log\(|eval\(|innerHTML\s*=
---

Potentially problematic code pattern detected!

Match on different fields:

---
event: file
conditions:
  - field: file_path
    operator: regex_match
    pattern: \.tsx?$
  - field: new_text
    operator: regex_match
    pattern: console\.log\(
---

Console.log in TypeScript file!

Common patterns: - Debug code: console\.log\(, debugger, print\( - Security risks: eval\(, innerHTML\s*=, dangerouslySetInnerHTML - Sensitive files: \.env$, credentials, \.pem$ - Generated files: node_modules/, dist/, build/

stop Events

Match when agent wants to stop (completion checks):

---
event: stop
pattern: .*
---

Before stopping, verify:
- [ ] Tests were run
- [ ] Build succeeded
- [ ] Documentation updated

Use for: - Reminders about required steps - Completion checklists - Process enforcement

prompt Events

Match user prompt content (advanced):

---
event: prompt
conditions:
  - field: user_prompt
    operator: contains
    pattern: deploy to production
---

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

Pattern Writing Tips

Regex Basics

Literal characters: Most characters match themselves - rm matches "rm" - console.log matches "console.log"

Special characters need escaping: - . (any char) → \. (literal dot) - ( )\( \) (literal parens) - [ ]\[ \] (literal brackets)

Common metacharacters: - \s - whitespace (space, tab, newline) - \d - digit (0-9) - \w - word character (a-z, A-Z, 0-9, _) - . - any character - + - one or more - * - zero or more - ? - zero or one - | - OR

Examples:

rm\s+-rf         Matches: rm -rf, rm  -rf
console\.log\(   Matches: console.log(
(eval|exec)\(    Matches: eval( or exec(
chmod\s+777      Matches: chmod 777, chmod  777
API_KEY\s*=      Matches: API_KEY=, API_KEY =

Testing Patterns

Test regex patterns before using:

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

Or use online regex testers (regex101.com with Python flavor).

Common Pitfalls

Too broad:

pattern: log    # Matches "log", "login", "dialog", "catalog"

Better: console\.log\(|logger\.

Too specific:

pattern: rm -rf /tmp  # Only matches exact path

Better: rm\s+-rf

Escaping issues: - YAML quoted strings: "pattern" requires double backslashes \\s - YAML unquoted: pattern: \s works as-is - Recommendation: Use unquoted patterns in YAML

File Organization

Location: All rules in .claude/ directory Naming: .claude/hookify.{descriptive-name}.local.md Gitignore: Add .claude/*.local.md to .gitignore

Good names: - hookify.dangerous-rm.local.md - hookify.console-log.local.md - hookify.require-tests.local.md - hookify.sensitive-files.local.md

Bad names: - hookify.rule1.local.md (not descriptive) - hookify.md (missing .local) - danger.local.md (missing hookify prefix)

Workflow

Creating a Rule

  1. Identify unwanted behavior
  2. Determine which tool is involved (Bash, Edit, etc.)
  3. Choose event type (bash, file, stop, etc.)
  4. Write regex pattern
  5. Create .claude/hookify.{name}.local.md file in project root
  6. Test immediately - rules are read dynamically on next tool use

Refining a Rule

  1. Edit the .local.md file
  2. Adjust pattern or message
  3. Test immediately - changes take effect on next tool use

Disabling a Rule

Temporary: Set enabled: false in frontmatter Permanent: Delete the .local.md file

Examples

See ${CLAUDE_PLUGIN_ROOT}/examples/ for complete examples: - dangerous-rm.local.md - Block dangerous rm commands - console-log-warning.local.md - Warn about console.log - sensitive-files-warning.local.md - Warn about editing .env files

Quick Reference

Minimum viable rule:

---
name: my-rule
enabled: true
event: bash
pattern: dangerous_command
---

Warning message here

Rule with conditions:

---
name: my-rule
enabled: true
event: file
conditions:
  - field: file_path
    operator: regex_match
    pattern: \.ts$
  - field: new_text
    operator: contains
    pattern: any
---

Warning message

Event types: - bash - Bash commands - file - File edits - stop - Completion checks - prompt - User input - all - All events

Field options: - Bash: command - File: file_path, new_text, old_text, content - Prompt: user_prompt

Operators: - regex_match, contains, equals, not_contains, starts_with, ends_with

Commands

NameDescription
configure Enable or disable hookify rules interactively
allowed-toolsGlob, Read, Edit, AskUserQuestion, Skill

Configure Hookify Rules

Load hookify:writing-rules skill first to understand rule format.

Enable or disable existing hookify rules using an interactive interface.

Steps

1. Find Existing Rules

Use Glob tool to find all hookify rule files:

pattern: ".claude/hookify.*.local.md"

If no rules found, inform user:

No hookify rules configured yet. Use `/hookify` to create your first rule.

2. Read Current State

For each rule file: - Read the file - Extract name and enabled fields from frontmatter - Build list of rules with current state

3. Ask User Which Rules to Toggle

Use AskUserQuestion to let user select rules:

{
  "questions": [
    {
      "question": "Which rules would you like to enable or disable?",
      "header": "Configure",
      "multiSelect": true,
      "options": [
        {
          "label": "warn-dangerous-rm (currently enabled)",
          "description": "Warns about rm -rf commands"
        },
        {
          "label": "warn-console-log (currently disabled)",
          "description": "Warns about console.log in code"
        },
        {
          "label": "require-tests (currently enabled)",
          "description": "Requires tests before stopping"
        }
      ]
    }
  ]
}

Option format: - Label: {rule-name} (currently {enabled|disabled}) - Description: Brief description from rule's message or pattern

4. Parse User Selection

For each selected rule: - Determine current state from label (enabled/disabled) - Toggle state: enabled → disabled, disabled → enabled

5. Update Rule Files

For each rule to toggle: - Use Read tool to read current content - Use Edit tool to change enabled: true to enabled: false (or vice versa) - Handle both with and without quotes

Edit pattern for enabling:

old_string: "enabled: false"
new_string: "enabled: true"

Edit pattern for disabling:

old_string: "enabled: true"
new_string: "enabled: false"

6. Confirm Changes

Show user what was changed:

## Hookify Rules Updated

**Enabled:**
- warn-console-log

**Disabled:**
- warn-dangerous-rm

**Unchanged:**
- require-tests

Changes apply immediately - no restart needed

Important Notes

  • Changes take effect immediately on next tool use
  • You can also manually edit .claude/hookify.*.local.md files
  • To permanently remove a rule, delete its .local.md file
  • Use /hookify:list to see all configured rules

Edge Cases

No rules to configure: - Show message about using /hookify to create rules first

User selects no rules: - Inform that no changes were made

File read/write errors: - Inform user of specific error - Suggest manual editing as fallback

help Get help with the hookify plugin
allowed-toolsRead

Hookify Plugin Help

Explain how the hookify plugin works and how to use it.

Overview

The hookify plugin makes it easy to create custom hooks that prevent unwanted behaviors. Instead of editing hooks.json files, users create simple markdown configuration files that define patterns to watch for.

How It Works

1. Hook System

Hookify installs generic hooks that run on these events: - PreToolUse: Before any tool executes (Bash, Edit, Write, etc.) - PostToolUse: After a tool executes - Stop: When Claude wants to stop working - UserPromptSubmit: When user submits a prompt

These hooks read configuration files from .claude/hookify.*.local.md and check if any rules match the current operation.

2. Configuration Files

Users create rules in .claude/hookify.{rule-name}.local.md files:

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

⚠️ **Dangerous rm command detected!**

This command could delete important files. Please verify the path.

Key fields: - name: Unique identifier for the rule - enabled: true/false to activate/deactivate - event: bash, file, stop, prompt, or all - pattern: Regex pattern to match

The message body is what Claude sees when the rule triggers.

3. Creating Rules

Option A: Use /hookify command

/hookify Don't use console.log in production files

This analyzes your request and creates the appropriate rule file.

Option B: Create manually Create .claude/hookify.my-rule.local.md with the format above.

Option C: Analyze conversation

/hookify

Without arguments, hookify analyzes recent conversation to find behaviors you want to prevent.

Available Commands

  • /hookify - Create hooks from conversation analysis or explicit instructions
  • /hookify:help - Show this help (what you're reading now)
  • /hookify:list - List all configured hooks
  • /hookify:configure - Enable/disable existing hooks interactively

Example Use Cases

Prevent dangerous commands:

---
name: block-chmod-777
enabled: true
event: bash
pattern: chmod\s+777
---

Don't use chmod 777 - it's a security risk. Use specific permissions instead.

Warn about debugging code:

---
name: warn-console-log
enabled: true
event: file
pattern: console\.log\(
---

Console.log detected. Remember to remove debug logging before committing.

Require tests before stopping:

---
name: require-tests
enabled: true
event: stop
pattern: .*
---

Did you run tests before finishing? Make sure `npm test` or equivalent was executed.

Pattern Syntax

Use Python regex syntax: - \s - whitespace - \. - literal dot - | - OR - + - one or more - * - zero or more - \d - digit - [abc] - character class

Examples: - rm\s+-rf - matches "rm -rf" - console\.log\( - matches "console.log(" - (eval|exec)\( - matches "eval(" or "exec(" - \.env$ - matches files ending in .env

Important Notes

No Restart Needed: Hookify rules (.local.md files) take effect immediately on the next tool use. The hookify hooks are already loaded and read your rules dynamically.

Block or Warn: Rules can either block operations (prevent execution) or warn (show message but allow). Set action: block or action: warn in the rule's frontmatter.

Rule Files: Keep rules in .claude/hookify.*.local.md - they should be git-ignored (add to .gitignore if needed).

Disable Rules: Set enabled: false in frontmatter or delete the file.

Troubleshooting

Hook not triggering: - Check rule file is in .claude/ directory - Verify enabled: true in frontmatter - Confirm pattern is valid regex - Test pattern: python3 -c "import re; print(re.search('your_pattern', 'test_text'))" - Rules take effect immediately - no restart needed

Import errors: - Check Python 3 is available: python3 --version - Verify hookify plugin is installed correctly

Pattern not matching: - Test regex separately - Check for escaping issues (use unquoted patterns in YAML) - Try simpler pattern first, then refine

Getting Started

  1. Create your first rule: /hookify Warn me when I try to use rm -rf

  2. Try to trigger it:

  3. Ask Claude to run rm -rf /tmp/test
  4. You should see the warning

  5. Refine the rule by editing .claude/hookify.warn-rm.local.md

  6. Create more rules as you encounter unwanted behaviors

For more examples, check the ${CLAUDE_PLUGIN_ROOT}/examples/ directory.

hookify Create hooks to prevent unwanted behaviors from conversation analysis or explicit instructions
argument-hintOptional specific behavior to address
allowed-toolsRead, Write, AskUserQuestion, Task, Grep, TodoWrite, Skill

Hookify - Create Hooks from Unwanted Behaviors

FIRST: Load the hookify:writing-rules skill using the Skill tool to understand rule file format and syntax.

Create hook rules to prevent problematic behaviors by analyzing the conversation or from explicit user instructions.

Your Task

You will help the user create hookify rules to prevent unwanted behaviors. Follow these steps:

Step 1: Gather Behavior Information

If $ARGUMENTS is provided: - User has given specific instructions: $ARGUMENTS - Still analyze recent conversation (last 10-15 user messages) for additional context - Look for examples of the behavior happening

If $ARGUMENTS is empty: - Launch the conversation-analyzer agent to find problematic behaviors - Agent will scan user prompts for frustration signals - Agent will return structured findings

To analyze conversation: Use the Task tool to launch conversation-analyzer agent:

{
  "subagent_type": "general-purpose",
  "description": "Analyze conversation for unwanted behaviors",
  "prompt": "You are analyzing a Claude Code conversation to find behaviors the user wants to prevent.

Read user messages in the current conversation and identify:
1. Explicit requests to avoid something (\"don't do X\", \"stop doing Y\")
2. Corrections or reversions (user fixing Claude's actions)
3. Frustrated reactions (\"why did you do X?\", \"I didn't ask for that\")
4. Repeated issues (same problem multiple times)

For each issue found, extract:
- What tool was used (Bash, Edit, Write, etc.)
- Specific pattern or command
- Why it was problematic
- User's stated reason

Return findings as a structured list with:
- category: Type of issue
- tool: Which tool was involved
- pattern: Regex or literal pattern to match
- context: What happened
- severity: high/medium/low

Focus on the most recent issues (last 20-30 messages). Don't go back further unless explicitly asked."
}

Step 2: Present Findings to User

After gathering behaviors (from arguments or agent), present to user using AskUserQuestion:

Question 1: Which behaviors to hookify? - Header: "Create Rules" - multiSelect: true - Options: List each detected behavior (max 4) - Label: Short description (e.g., "Block rm -rf") - Description: Why it's problematic

Question 2: For each selected behavior, ask about action: - "Should this block the operation or just warn?" - Options: - "Just warn" (action: warn - shows message but allows) - "Block operation" (action: block - prevents execution)

Question 3: Ask for example patterns: - "What patterns should trigger this rule?" - Show detected patterns - Allow user to refine or add more

Step 3: Generate Rule Files

For each confirmed behavior, create a .claude/hookify.{rule-name}.local.md file:

Rule naming convention: - Use kebab-case - Be descriptive: block-dangerous-rm, warn-console-log, require-tests-before-stop - Start with action verb: block, warn, prevent, require

File format:

---
name: {rule-name}
enabled: true
event: {bash|file|stop|prompt|all}
pattern: {regex pattern}
action: {warn|block}
---

{Message to show Claude when rule triggers}

Action values: - warn: Show message but allow operation (default) - block: Prevent operation or stop session

For more complex rules (multiple conditions):

---
name: {rule-name}
enabled: true
event: file
conditions:
  - field: file_path
    operator: regex_match
    pattern: \.env$
  - field: new_text
    operator: contains
    pattern: API_KEY
---

{Warning message}

Step 4: Create Files and Confirm

IMPORTANT: Rule files must be created in the current working directory's .claude/ folder, NOT the plugin directory.

Use the current working directory (where Claude Code was started) as the base path.

  1. Check if .claude/ directory exists in current working directory
  2. If not, create it first with: mkdir -p .claude

  3. Use Write tool to create each .claude/hookify.{name}.local.md file

  4. Use relative path from current working directory: .claude/hookify.{name}.local.md
  5. The path should resolve to the project's .claude directory, not the plugin's

  6. Show user what was created: ``` Created 3 hookify rules:

  7. .claude/hookify.dangerous-rm.local.md
  8. .claude/hookify.console-log.local.md
  9. .claude/hookify.sensitive-files.local.md

These rules will trigger on: - dangerous-rm: Bash commands matching "rm -rf" - console-log: Edits adding console.log statements - sensitive-files: Edits to .env or credentials files ```

  1. Verify files were created in the correct location by listing them

  2. Inform user: "Rules are active immediately - no restart needed!"

The hookify hooks are already loaded and will read your new rules on the next tool use.

Event Types Reference

  • bash: Matches Bash tool commands
  • file: Matches Edit, Write, MultiEdit tools
  • stop: Matches when agent wants to stop (use for completion checks)
  • prompt: Matches when user submits prompts
  • all: Matches all events

Pattern Writing Tips

Bash patterns: - Match dangerous commands: rm\s+-rf|chmod\s+777|dd\s+if= - Match specific tools: npm\s+install\s+|pip\s+install

File patterns: - Match code patterns: console\.log\(|eval\(|innerHTML\s*= - Match file paths: \.env$|\.git/|node_modules/

Stop patterns: - Check for missing steps: (check transcript or completion criteria)

Example Workflow

User says: "/hookify Don't use rm -rf without asking me first"

Your response: 1. Analyze: User wants to prevent rm -rf commands 2. Ask: "Should I block this command or just warn you?" 3. User selects: "Just warn" 4. Create .claude/hookify.dangerous-rm.local.md: ```markdown


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


⚠️ Dangerous rm command detected

You requested to be warned before using rm -rf. Please verify the path is correct. ``` 5. Confirm: "Created hookify rule. It's active immediately - try triggering it!"

Important Notes

  • No restart needed: Rules take effect immediately on the next tool use
  • File location: Create files in project's .claude/ directory (current working directory), NOT the plugin's .claude/
  • Regex syntax: Use Python regex syntax (raw strings, no need to escape in YAML)
  • Action types: Rules can warn (default) or block operations
  • Testing: Test rules immediately after creating them

Troubleshooting

If rule file creation fails: 1. Check current working directory with pwd 2. Ensure .claude/ directory exists (create with mkdir if needed) 3. Use absolute path if needed: {cwd}/.claude/hookify.{name}.local.md 4. Verify file was created with Glob or ls

If rule doesn't trigger after creation: 1. Verify file is in project .claude/ not plugin .claude/ 2. Check file with Read tool to ensure pattern is correct 3. Test pattern with: python3 -c "import re; print(re.search(r'pattern', 'test text'))" 4. Verify enabled: true in frontmatter 5. Remember: Rules work immediately, no restart needed

If blocking seems too strict: 1. Change action: block to action: warn in the rule file 2. Or adjust the pattern to be more specific 3. Changes take effect on next tool use

Use TodoWrite to track your progress through the steps.

list List all configured hookify rules
allowed-toolsGlob, Read, Skill

List Hookify Rules

Load hookify:writing-rules skill first to understand rule format.

Show all configured hookify rules in the project.

Steps

  1. Use Glob tool to find all hookify rule files: pattern: ".claude/hookify.*.local.md"

  2. For each file found:

  3. Use Read tool to read the file
  4. Extract frontmatter fields: name, enabled, event, pattern
  5. Extract message preview (first 100 chars)

  6. Present results in a table:

## Configured Hookify Rules

| Name | Enabled | Event | Pattern | File |
|------|---------|-------|---------|------|
| warn-dangerous-rm | ✅ Yes | bash | rm\s+-rf | hookify.dangerous-rm.local.md |
| warn-console-log | ✅ Yes | file | console\.log\( | hookify.console-log.local.md |
| check-tests | ❌ No | stop | .* | hookify.require-tests.local.md |

**Total**: 3 rules (2 enabled, 1 disabled)
  1. For each rule, show a brief preview:
### warn-dangerous-rm
**Event**: bash
**Pattern**: `rm\s+-rf`
**Message**: "⚠️ **Dangerous rm command detected!** This command could delete..."

**Status**: ✅ Active
**File**: .claude/hookify.dangerous-rm.local.md
  1. Add helpful footer:
---

To modify a rule: Edit the .local.md file directly
To disable a rule: Set `enabled: false` in frontmatter
To enable a rule: Set `enabled: true` in frontmatter
To delete a rule: Remove the .local.md file
To create a rule: Use `/hookify` command

**Remember**: Changes take effect immediately - no restart needed

If No Rules Found

If no hookify rules exist:

## No Hookify Rules Configured

You haven't created any hookify rules yet.

To get started:
1. Use `/hookify` to analyze conversation and create rules
2. Or manually create `.claude/hookify.my-rule.local.md` files
3. See `/hookify:help` for documentation

Example:

/hookify Warn me when I use console.log

Check `${CLAUDE_PLUGIN_ROOT}/examples/` for example rule files.

Agents

NameDescriptionModel
conversation-analyzer

You are a conversation analysis specialist that identifies problematic behaviors in Claude Code sessions that could be prevented with hooks.

Your Core Responsibilities: 1. Read and analyze user messages to find frustration signals 2. Identify specific tool usage patterns that caused issues 3. Extract actionable patterns that can be matched with regex 4. Categorize issues by severity and type 5. Provide structured findings for hook rule generation

Analysis Process:

1. Search for User Messages Indicating Issues

Read through user messages in reverse chronological order (most recent first). Look for:

Explicit correction requests: - "Don't use X" - "Stop doing Y" - "Please don't Z" - "Avoid..." - "Never..."

Frustrated reactions: - "Why did you do X?" - "I didn't ask for that" - "That's not what I meant" - "That was wrong"

Corrections and reversions: - User reverting changes Claude made - User fixing issues Claude created - User providing step-by-step corrections

Repeated issues: - Same type of mistake multiple times - User having to remind multiple times - Pattern of similar problems

2. Identify Tool Usage Patterns

For each issue, determine: - Which tool: Bash, Edit, Write, MultiEdit - What action: Specific command or code pattern - When it happened: During what task/phase - Why problematic: User's stated reason or implicit concern

Extract concrete examples: - For Bash: Actual command that was problematic - For Edit/Write: Code pattern that was added - For Stop: What was missing before stopping

3. Create Regex Patterns

Convert behaviors into matchable patterns:

Bash command patterns: - rm\s+-rf for dangerous deletes - sudo\s+ for privilege escalation - chmod\s+777 for permission issues

Code patterns (Edit/Write): - console\.log\( for debug logging - eval\(|new Function\( for dangerous eval - innerHTML\s*= for XSS risks

File path patterns: - \.env$ for environment files - /node_modules/ for dependency files - dist/|build/ for generated files

4. Categorize Severity

High severity (should block in future): - Dangerous commands (rm -rf, chmod 777) - Security issues (hardcoded secrets, eval) - Data loss risks

Medium severity (warn): - Style violations (console.log in production) - Wrong file types (editing generated files) - Missing best practices

Low severity (optional): - Preferences (coding style) - Non-critical patterns

5. Output Format

Return your findings as structured text in this format:

## Hookify Analysis Results

### Issue 1: Dangerous rm Commands
**Severity**: High
**Tool**: Bash
**Pattern**: `rm\s+-rf`
**Occurrences**: 3 times
**Context**: Used rm -rf on /tmp directories without verification
**User Reaction**: "Please be more careful with rm commands"

**Suggested Rule:**
- Name: warn-dangerous-rm
- Event: bash
- Pattern: rm\s+-rf
- Message: "Dangerous rm command detected. Verify path before proceeding."

---

### Issue 2: Console.log in TypeScript
**Severity**: Medium
**Tool**: Edit/Write
**Pattern**: `console\.log\(`
**Occurrences**: 2 times
**Context**: Added console.log statements to production TypeScript files
**User Reaction**: "Don't use console.log in production code"

**Suggested Rule:**
- Name: warn-console-log
- Event: file
- Pattern: console\.log\(
- Message: "Console.log detected. Use proper logging library instead."

---

[Continue for each issue found...]

## Summary

Found {N} behaviors worth preventing:
- {N} high severity
- {N} medium severity
- {N} low severity

Recommend creating rules for high and medium severity issues.

Quality Standards: - Be specific about patterns (don't be overly broad) - Include actual examples from conversation - Explain why each issue matters - Provide ready-to-use regex patterns - Don't false-positive on discussions about what NOT to do

Edge Cases:

User discussing hypotheticals: - "What would happen if I used rm -rf?" - Don't treat as problematic behavior

Teaching moments: - "Here's what you shouldn't do: ..." - Context indicates explanation, not actual problem

One-time accidents: - Single occurrence, already fixed - Mention but mark as low priority

Subjective preferences: - "I prefer X over Y" - Mark as low severity, let user decide

Return Results: Provide your analysis in the structured format above. The /hookify command will use this to: 1. Present findings to user 2. Ask which rules to create 3. Generate .local.md configuration files 4. Save rules to .claude directory

Hooks

EventMatcherType
PreToolUse command
PostToolUse command
Stop command
UserPromptSubmit command

README

Hookify Plugin

Easily create custom hooks to prevent unwanted behaviors by analyzing conversation patterns or from explicit instructions.

Overview

The hookify plugin makes it simple to create hooks without editing complex hooks.json files. Instead, you create lightweight markdown configuration files that define patterns to watch for and messages to show when those patterns match.

Key features: - 🎯 Analyze conversations to find unwanted behaviors automatically - 📝 Simple markdown configuration files with YAML frontmatter - 🔍 Regex pattern matching for powerful rules - 🚀 No coding required - just describe the behavior - 🔄 Easy enable/disable without restarting

Quick Start

1. Create Your First Rule

/hookify Warn me when I use rm -rf commands

This analyzes your request and creates .claude/hookify.warn-rm.local.md.

2. Test It Immediately

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

Ask Claude to run a command that should trigger the rule:

Run rm -rf /tmp/test

You should see the warning message immediately!

Usage

Main Command: /hookify

With arguments:

/hookify Don't use console.log in TypeScript files

Creates a rule from your explicit instructions.

Without arguments:

/hookify

Analyzes recent conversation to find behaviors you've corrected or been frustrated by.

Helper Commands

List all rules:

/hookify:list

Configure rules interactively:

/hookify:configure

Enable/disable existing rules through an interactive interface.

Get help:

/hookify:help

Rule Configuration Format

Simple Rule (Single Pattern)

.claude/hookify.dangerous-rm.local.md:

---
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

Action field: - warn: Shows warning but allows operation (default) - block: Prevents operation from executing (PreToolUse) or stops session (Stop events)

Advanced Rule (Multiple Conditions)

.claude/hookify.sensitive-files.local.md:

---
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 file is in .gitignore.

All conditions must match for the rule to trigger.

Event Types

  • bash: Triggers on Bash tool commands
  • file: Triggers on Edit, Write, MultiEdit tools
  • stop: Triggers when Claude wants to stop (for completion checks)
  • prompt: Triggers on user prompt submission
  • all: Triggers on all events

Pattern Syntax

Use Python regex syntax:

Pattern Matches Example
rm\s+-rf rm -rf rm -rf /tmp
console\.log\( console.log( console.log("test")
(eval\|exec)\( eval( or exec( eval("code")
\.env$ files ending in .env .env, .env.local
chmod\s+777 chmod 777 chmod 777 file.txt

Tips: - Use \s for whitespace - Escape special chars: \. for literal dot - Use | for OR: (foo|bar) - Use .* to match anything - Set action: block for dangerous operations - Set action: warn (or omit) for informational warnings

Examples

Example 1: Block Dangerous Commands

---
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.
Please verify the exact path and use a safer approach.

This rule blocks the operation - Claude will not be allowed to execute these commands.

Example 2: Warn About Debug Code

---
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.

This rule warns but allows - Claude sees the message but can still proceed.

Example 3: Require Tests Before Stopping

---
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, please run tests to verify your changes work correctly.

This blocks Claude from stopping if no test commands appear in the session transcript. Enable only when you want strict enforcement.

Advanced Usage

Multiple Conditions

Check multiple fields simultaneously:

---
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.

Operators Reference

  • regex_match: Pattern must match (most common)
  • contains: String must contain pattern
  • equals: Exact string match
  • not_contains: String must NOT contain pattern
  • starts_with: String starts with pattern
  • ends_with: String ends with pattern

Field Reference

For bash events: - command: The bash command string

For file events: - file_path: Path to file being edited - new_text: New content being added (Edit, Write) - old_text: Old content being replaced (Edit only) - content: File content (Write only)

For prompt events: - user_prompt: The user's submitted prompt text

For stop events: - Use general matching on session state

Management

Enable/Disable Rules

Temporarily disable: Edit the .local.md file and set enabled: false

Re-enable: Set enabled: true

Or use interactive tool:

/hookify:configure

Delete Rules

Simply delete the .local.md file:

rm .claude/hookify.my-rule.local.md

View All Rules

/hookify:list

Installation

This plugin is part of the Claude Code Marketplace. It should be auto-discovered when the marketplace is installed.

Manual testing:

cc --plugin-dir /path/to/hookify

Requirements

  • Python 3.7+
  • No external dependencies (uses stdlib only)

Troubleshooting

Rule not triggering: 1. Check rule file exists in .claude/ directory (in project root, not plugin directory) 2. Verify enabled: true in frontmatter 3. Test regex pattern separately 4. Rules should work immediately - no restart needed 5. Try /hookify:list to see if rule is loaded

Import errors: - Ensure Python 3 is available: python3 --version - Check hookify plugin is installed

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

Hook seems slow: - Keep patterns simple (avoid complex regex) - Use specific event types (bash, file) instead of "all" - Limit number of active rules

Contributing

Found a useful rule pattern? Consider sharing example files via PR!

Future Enhancements

  • Severity levels (error/warning/info distinctions)
  • Rule templates library
  • Interactive pattern builder
  • Hook testing utilities
  • JSON format support (in addition to markdown)

License

MIT License

License

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.