From 898b52edcb47bcb3e9d6106e74ca73e74ea01e70 Mon Sep 17 00:00:00 2001 From: sillylaird Date: Thu, 3 Sep 2026 00:33:59 +0000 Subject: import live www.sillylaird.ca webroot --- .../hook-development/references/migration.md | 369 +++++++++++++++++++++ 1 file changed, 369 insertions(+) create mode 100644 .agents/skills/hook-development/references/migration.md (limited to '.agents/skills/hook-development/references/migration.md') diff --git a/.agents/skills/hook-development/references/migration.md b/.agents/skills/hook-development/references/migration.md new file mode 100644 index 0000000..587cae3 --- /dev/null +++ b/.agents/skills/hook-development/references/migration.md @@ -0,0 +1,369 @@ +# Migrating from Basic to Advanced Hooks + +This guide shows how to migrate from basic command hooks to advanced prompt-based hooks for better maintainability and flexibility. + +## Why Migrate? + +Prompt-based hooks offer several advantages: + +- **Natural language reasoning**: LLM understands context and intent +- **Better edge case handling**: Adapts to unexpected scenarios +- **No bash scripting required**: Simpler to write and maintain +- **More flexible validation**: Can handle complex logic without coding + +## Migration Example: Bash Command Validation + +### Before (Basic Command Hook) + +**Configuration:** +```json +{ + "PreToolUse": [ + { + "matcher": "Bash", + "hooks": [ + { + "type": "command", + "command": "bash validate-bash.sh" + } + ] + } + ] +} +``` + +**Script (validate-bash.sh):** +```bash +#!/bin/bash +input=$(cat) +command=$(echo "$input" | jq -r '.tool_input.command') + +# Hard-coded validation logic +if [[ "$command" == *"rm -rf"* ]]; then + echo "Dangerous command detected" >&2 + exit 2 +fi +``` + +**Problems:** +- Only checks for exact "rm -rf" pattern +- Doesn't catch variations like `rm -fr` or `rm -r -f` +- Misses other dangerous commands (`dd`, `mkfs`, etc.) +- No context awareness +- Requires bash scripting knowledge + +### After (Advanced Prompt Hook) + +**Configuration:** +```json +{ + "PreToolUse": [ + { + "matcher": "Bash", + "hooks": [ + { + "type": "prompt", + "prompt": "Command: $TOOL_INPUT.command. Analyze for: 1) Destructive operations (rm -rf, dd, mkfs, etc) 2) Privilege escalation (sudo) 3) Network operations without user consent. Return 'approve' or 'deny' with explanation.", + "timeout": 15 + } + ] + } + ] +} +``` + +**Benefits:** +- Catches all variations and patterns +- Understands intent, not just literal strings +- No script file needed +- Easy to extend with new criteria +- Context-aware decisions +- Natural language explanation in denial + +## Migration Example: File Write Validation + +### Before (Basic Command Hook) + +**Configuration:** +```json +{ + "PreToolUse": [ + { + "matcher": "Write", + "hooks": [ + { + "type": "command", + "command": "bash validate-write.sh" + } + ] + } + ] +} +``` + +**Script (validate-write.sh):** +```bash +#!/bin/bash +input=$(cat) +file_path=$(echo "$input" | jq -r '.tool_input.file_path') + +# Check for path traversal +if [[ "$file_path" == *".."* ]]; then + echo '{"decision": "deny", "reason": "Path traversal detected"}' >&2 + exit 2 +fi + +# Check for system paths +if [[ "$file_path" == "/etc/"* ]] || [[ "$file_path" == "/sys/"* ]]; then + echo '{"decision": "deny", "reason": "System file"}' >&2 + exit 2 +fi +``` + +**Problems:** +- Hard-coded path patterns +- Doesn't understand symlinks +- Missing edge cases (e.g., `/etc` vs `/etc/`) +- No consideration of file content + +### After (Advanced Prompt Hook) + +**Configuration:** +```json +{ + "PreToolUse": [ + { + "matcher": "Write|Edit", + "hooks": [ + { + "type": "prompt", + "prompt": "File path: $TOOL_INPUT.file_path. Content preview: $TOOL_INPUT.content (first 200 chars). Verify: 1) Not system directories (/etc, /sys, /usr) 2) Not credentials (.env, tokens, secrets) 3) No path traversal 4) Content doesn't expose secrets. Return 'approve' or 'deny'." + } + ] + } + ] +} +``` + +**Benefits:** +- Context-aware (considers content too) +- Handles symlinks and edge cases +- Natural understanding of "system directories" +- Can detect secrets in content +- Easy to extend criteria + +## When to Keep Command Hooks + +Command hooks still have their place: + +### 1. Deterministic Performance Checks + +```bash +#!/bin/bash +# Check file size quickly +file_path=$(echo "$input" | jq -r '.tool_input.file_path') +size=$(stat -f%z "$file_path" 2>/dev/null || stat -c%s "$file_path" 2>/dev/null) + +if [ "$size" -gt 10000000 ]; then + echo '{"decision": "deny", "reason": "File too large"}' >&2 + exit 2 +fi +``` + +**Use command hooks when:** Validation is purely mathematical or deterministic. + +### 2. External Tool Integration + +```bash +#!/bin/bash +# Run security scanner +file_path=$(echo "$input" | jq -r '.tool_input.file_path') +scan_result=$(security-scanner "$file_path") + +if [ "$?" -ne 0 ]; then + echo "Security scan failed: $scan_result" >&2 + exit 2 +fi +``` + +**Use command hooks when:** Integrating with external tools that provide yes/no answers. + +### 3. Very Fast Checks (< 50ms) + +```bash +#!/bin/bash +# Quick regex check +command=$(echo "$input" | jq -r '.tool_input.command') + +if [[ "$command" =~ ^(ls|pwd|echo)$ ]]; then + exit 0 # Safe commands +fi +``` + +**Use command hooks when:** Performance is critical and logic is simple. + +## Hybrid Approach + +Combine both for multi-stage validation: + +```json +{ + "PreToolUse": [ + { + "matcher": "Bash", + "hooks": [ + { + "type": "command", + "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/quick-check.sh", + "timeout": 5 + }, + { + "type": "prompt", + "prompt": "Deep analysis of bash command: $TOOL_INPUT", + "timeout": 15 + } + ] + } + ] +} +``` + +The command hook does fast deterministic checks, while the prompt hook handles complex reasoning. + +## Migration Checklist + +When migrating hooks: + +- [ ] Identify the validation logic in the command hook +- [ ] Convert hard-coded patterns to natural language criteria +- [ ] Test with edge cases the old hook missed +- [ ] Verify LLM understands the intent +- [ ] Set appropriate timeout (usually 15-30s for prompt hooks) +- [ ] Document the new hook in README +- [ ] Remove or archive old script files + +## Migration Tips + +1. **Start with one hook**: Don't migrate everything at once +2. **Test thoroughly**: Verify prompt hook catches what command hook caught +3. **Look for improvements**: Use migration as opportunity to enhance validation +4. **Keep scripts for reference**: Archive old scripts in case you need to reference the logic +5. **Document reasoning**: Explain why prompt hook is better in README + +## Complete Migration Example + +### Original Plugin Structure + +``` +my-plugin/ +├── .claude-plugin/plugin.json +├── hooks/hooks.json +└── scripts/ + ├── validate-bash.sh + ├── validate-write.sh + └── check-tests.sh +``` + +### After Migration + +``` +my-plugin/ +├── .claude-plugin/plugin.json +├── hooks/hooks.json # Now uses prompt hooks +└── scripts/ # Archive or delete + └── archive/ + ├── validate-bash.sh + ├── validate-write.sh + └── check-tests.sh +``` + +### Updated hooks.json + +```json +{ + "PreToolUse": [ + { + "matcher": "Bash", + "hooks": [ + { + "type": "prompt", + "prompt": "Validate bash command safety: destructive ops, privilege escalation, network access" + } + ] + }, + { + "matcher": "Write|Edit", + "hooks": [ + { + "type": "prompt", + "prompt": "Validate file write safety: system paths, credentials, path traversal, content secrets" + } + ] + } + ], + "Stop": [ + { + "matcher": "*", + "hooks": [ + { + "type": "prompt", + "prompt": "Verify tests were run if code was modified" + } + ] + } + ] +} +``` + +**Result:** Simpler, more maintainable, more powerful. + +## Common Migration Patterns + +### Pattern: String Contains → Natural Language + +**Before:** +```bash +if [[ "$command" == *"sudo"* ]]; then + echo "Privilege escalation" >&2 + exit 2 +fi +``` + +**After:** +``` +"Check for privilege escalation (sudo, su, etc)" +``` + +### Pattern: Regex → Intent + +**Before:** +```bash +if [[ "$file" =~ \.(env|secret|key|token)$ ]]; then + echo "Credential file" >&2 + exit 2 +fi +``` + +**After:** +``` +"Verify not writing to credential files (.env, secrets, keys, tokens)" +``` + +### Pattern: Multiple Conditions → Criteria List + +**Before:** +```bash +if [ condition1 ] || [ condition2 ] || [ condition3 ]; then + echo "Invalid" >&2 + exit 2 +fi +``` + +**After:** +``` +"Check: 1) condition1 2) condition2 3) condition3. Deny if any fail." +``` + +## Conclusion + +Migrating to prompt-based hooks makes plugins more maintainable, flexible, and powerful. Reserve command hooks for deterministic checks and external tool integration. -- cgit v1.2.3