surshar / claude-code
Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.
Built by Anthropic · github.com/anthropics
| 1 | # Hook Development Utility Scripts |
| 2 | |
| 3 | These scripts help validate, test, and lint hook implementations before deployment. |
| 4 | |
| 5 | ## validate-hook-schema.sh |
| 6 | |
| 7 | Validates `hooks.json` configuration files for correct structure and common issues. |
| 8 | |
| 9 | **Usage:** |
| 10 | ```bash |
| 11 | ./validate-hook-schema.sh path/to/hooks.json |
| 12 | ``` |
| 13 | |
| 14 | **Checks:** |
| 15 | - Valid JSON syntax |
| 16 | - Required fields present |
| 17 | - Valid hook event names |
| 18 | - Proper hook types (command/prompt) |
| 19 | - Timeout values in valid ranges |
| 20 | - Hardcoded path detection |
| 21 | - Prompt hook event compatibility |
| 22 | |
| 23 | **Example:** |
| 24 | ```bash |
| 25 | cd my-plugin |
| 26 | ./validate-hook-schema.sh hooks/hooks.json |
| 27 | ``` |
| 28 | |
| 29 | ## test-hook.sh |
| 30 | |
| 31 | Tests individual hook scripts with sample input before deploying to Claude Code. |
| 32 | |
| 33 | **Usage:** |
| 34 | ```bash |
| 35 | ./test-hook.sh [options] <hook-script> <test-input.json> |
| 36 | ``` |
| 37 | |
| 38 | **Options:** |
| 39 | - `-v, --verbose` - Show detailed execution information |
| 40 | - `-t, --timeout N` - Set timeout in seconds (default: 60) |
| 41 | - `--create-sample <event-type>` - Generate sample test input |
| 42 | |
| 43 | **Example:** |
| 44 | ```bash |
| 45 | # Create sample test input |
| 46 | ./test-hook.sh --create-sample PreToolUse > test-input.json |
| 47 | |
| 48 | # Test a hook script |
| 49 | ./test-hook.sh my-hook.sh test-input.json |
| 50 | |
| 51 | # Test with verbose output and custom timeout |
| 52 | ./test-hook.sh -v -t 30 my-hook.sh test-input.json |
| 53 | ``` |
| 54 | |
| 55 | **Features:** |
| 56 | - Sets up proper environment variables (CLAUDE_PROJECT_DIR, CLAUDE_PLUGIN_ROOT) |
| 57 | - Measures execution time |
| 58 | - Validates output JSON |
| 59 | - Shows exit codes and their meanings |
| 60 | - Captures environment file output |
| 61 | |
| 62 | ## hook-linter.sh |
| 63 | |
| 64 | Checks hook scripts for common issues and best practices violations. |
| 65 | |
| 66 | **Usage:** |
| 67 | ```bash |
| 68 | ./hook-linter.sh <hook-script.sh> [hook-script2.sh ...] |
| 69 | ``` |
| 70 | |
| 71 | **Checks:** |
| 72 | - Shebang presence |
| 73 | - `set -euo pipefail` usage |
| 74 | - Stdin input reading |
| 75 | - Proper error handling |
| 76 | - Variable quoting (injection prevention) |
| 77 | - Exit code usage |
| 78 | - Hardcoded paths |
| 79 | - Long-running code detection |
| 80 | - Error output to stderr |
| 81 | - Input validation |
| 82 | |
| 83 | **Example:** |
| 84 | ```bash |
| 85 | # Lint single script |
| 86 | ./hook-linter.sh ../examples/validate-write.sh |
| 87 | |
| 88 | # Lint multiple scripts |
| 89 | ./hook-linter.sh ../examples/*.sh |
| 90 | ``` |
| 91 | |
| 92 | ## Typical Workflow |
| 93 | |
| 94 | 1. **Write your hook script** |
| 95 | ```bash |
| 96 | vim my-plugin/scripts/my-hook.sh |
| 97 | ``` |
| 98 | |
| 99 | 2. **Lint the script** |
| 100 | ```bash |
| 101 | ./hook-linter.sh my-plugin/scripts/my-hook.sh |
| 102 | ``` |
| 103 | |
| 104 | 3. **Create test input** |
| 105 | ```bash |
| 106 | ./test-hook.sh --create-sample PreToolUse > test-input.json |
| 107 | # Edit test-input.json as needed |
| 108 | ``` |
| 109 | |
| 110 | 4. **Test the hook** |
| 111 | ```bash |
| 112 | ./test-hook.sh -v my-plugin/scripts/my-hook.sh test-input.json |
| 113 | ``` |
| 114 | |
| 115 | 5. **Add to hooks.json** |
| 116 | ```bash |
| 117 | # Edit my-plugin/hooks/hooks.json |
| 118 | ``` |
| 119 | |
| 120 | 6. **Validate configuration** |
| 121 | ```bash |
| 122 | ./validate-hook-schema.sh my-plugin/hooks/hooks.json |
| 123 | ``` |
| 124 | |
| 125 | 7. **Test in Claude Code** |
| 126 | ```bash |
| 127 | claude --debug |
| 128 | ``` |
| 129 | |
| 130 | ## Tips |
| 131 | |
| 132 | - Always test hooks before deploying to avoid breaking user workflows |
| 133 | - Use verbose mode (`-v`) to debug hook behavior |
| 134 | - Check the linter output for security and best practice issues |
| 135 | - Validate hooks.json after any changes |
| 136 | - Create different test inputs for various scenarios (safe operations, dangerous operations, edge cases) |
| 137 | |
| 138 | ## Common Issues |
| 139 | |
| 140 | ### Hook doesn't execute |
| 141 | |
| 142 | Check: |
| 143 | - Script has shebang (`#!/bin/bash`) |
| 144 | - Script is executable (`chmod +x`) |
| 145 | - Path in hooks.json is correct (use `${CLAUDE_PLUGIN_ROOT}`) |
| 146 | |
| 147 | ### Hook times out |
| 148 | |
| 149 | - Reduce timeout in hooks.json |
| 150 | - Optimize hook script performance |
| 151 | - Remove long-running operations |
| 152 | |
| 153 | ### Hook fails silently |
| 154 | |
| 155 | - Check exit codes (should be 0 or 2) |
| 156 | - Ensure errors go to stderr (`>&2`) |
| 157 | - Validate JSON output structure |
| 158 | |
| 159 | ### Injection vulnerabilities |
| 160 | |
| 161 | - Always quote variables: `"$variable"` |
| 162 | - Use `set -euo pipefail` |
| 163 | - Validate all input fields |
| 164 | - Run the linter to catch issues |