# GUIA COMPLETO: Claude Code Hooks > **Versão:** 1.0.0 | **Data:** 2026-02-04 | **Autor:** Descomplicar® --- ## Índice 1. [Arquitectura de Hooks](#1-arquitectura-de-hooks) 2. [Configuração](#2-configuração) 3. [Variáveis de Ambiente](#3-variáveis-de-ambiente) 4. [Casos de Uso Práticos](#4-casos-de-uso-práticos) 5. [Padrões e Anti-Padrões](#5-padrões-e-anti-padrões) 6. [Exemplos de Código](#6-exemplos-de-código) 7. [Limitações e Workarounds](#7-limitações-e-workarounds) 8. [Debugging e Troubleshooting](#8-debugging-e-troubleshooting) --- ## 1. ARQUITECTURA DE HOOKS ### 1.1 O que são Hooks? Hooks são **comandos shell ou prompts LLM** que executam automaticamente em pontos específicos do ciclo de vida do Claude Code. Funcionam como **checkpoints programáveis** que permitem: - Injectar lógica custom - Enforçar padrões de código - Integrar ferramentas externas - Validar acções antes/depois da execução **Diferença entre Hooks e Skills:** | Aspecto | Hooks | Skills | |---------|-------|--------| | Execução | Determinística (sempre que evento dispara) | Por decisão do agente | | Trigger | Automático por evento | Quando Claude escolhe usar | | Controlo | Total sobre flow | Sugestivo | ### 1.2 Ciclo de Vida Completo ``` SessionStart ↓ UserPromptSubmit → [Hook: validar/enriquecer prompt] ↓ PreToolUse → [Hook: bloquear/modificar tool] ↓ PermissionRequest → [Hook: auto-aprovar/negar] ↓ [Tool Execution] ↓ PostToolUse → [Hook: formatar/validar resultado] ou PostToolUseFailure → [Hook: log erro/recuperação] ↓ SubagentStart → [Hook: enriquecer contexto subagent] ↓ SubagentStop → [Hook: validar resultado subagent] ↓ Stop → [Hook: decidir se continua] ↓ PreCompact → [Hook: preparar compactação] ↓ SessionEnd → [Hook: cleanup/logging] ``` ### 1.3 Ordem de Execução 1. **Matching:** Claude Code verifica se matcher combina com evento 2. **Parallel Execution:** Todos os hooks que combinam correm em paralelo 3. **Deduplication:** Comandos idênticos executam uma vez só 4. **Serial Blocking:** Se hook bloqueia (exit 2), acção é cancelada 5. **Output Processing:** Claude Code processa JSON output **Importante:** Hooks rodam **sequencialmente em relação a tool calls** mas **em paralelo entre si**. ### 1.4 Eventos Disponíveis (12 total) | Evento | Quando | Bloqueia? | Matcher Support | |--------|--------|----------|-----------------| | **SessionStart** | Início/resumo sessão | Não | `startup`, `resume`, `clear`, `compact` | | **UserPromptSubmit** | Antes Claude processar prompt | Sim | Nenhum (sempre fire) | | **PreToolUse** | Antes tool executar | Sim | Tool name (Bash, Edit, Write, etc) | | **PermissionRequest** | Quando permission dialog mostra | Sim | Tool name | | **PostToolUse** | Após tool sucesso | Não | Tool name | | **PostToolUseFailure** | Após tool falha | Não | Tool name | | **Notification** | Quando notificação dispara | Não | `permission_prompt`, `idle_prompt`, etc | | **SubagentStart** | Quando subagent spawns | Não | Agent name (Explore, Plan, etc) | | **SubagentStop** | Quando subagent termina | Sim | Agent name | | **Stop** | Quando Claude termina resposta | Sim | Nenhum (sempre fire) | | **PreCompact** | Antes compactação contexto | Não | `manual`, `auto` | | **SessionEnd** | Quando sessão termina | Não | `clear`, `logout`, `prompt_input_exit`, `other` | ### 1.5 Tipos de Hooks ``` Hook ├── Command Hook (type: "command") │ ├── Sync (default) │ └── Async (async: true) ← Não bloqueia Claude ├── Prompt Hook (type: "prompt") │ └── Single-turn LLM evaluation └── Agent Hook (type: "agent") └── Multi-turn LLM com tool access ``` --- ## 2. CONFIGURAÇÃO ### 2.1 Ficheiros de Configuração Hooks são definidos em **JSON settings** com hierarquia de scopes: ``` ~/.claude/settings.json (User scope - Global) ↑ (precedência) .claude/settings.json (Project scope - Shared via git) ↑ .claude/settings.local.json (Project scope - .gitignored) ↑ Managed policy settings (Organization - Highest precedence) ↑ Plugin hooks/hooks.json (When plugin enabled) ↑ Skill/Agent frontmatter (While active) ``` **Regra Precedência:** Higher scope sobrescreve lower scope. Não é cumulativo. ### 2.2 Estrutura JSON Completa ```json { "hooks": { "EventName": [ { "matcher": "regex_pattern_or_*", "hooks": [ { "type": "command|prompt|agent", "command": "shell_command_or_script_path", "prompt": "LLM prompt text", "model": "sonnet|haiku|opus", "timeout": 600, "async": false, "statusMessage": "Custom spinner text" } ] } ] } } ``` **Campos por tipo:** | Campo | Command | Prompt | Agent | |-------|---------|--------|-------| | `type` | ✓ | ✓ | ✓ | | `command` | ✓ | - | - | | `prompt` | - | ✓ | ✓ | | `model` | - | ✓ | ✓ | | `timeout` | ✓ | ✓ | ✓ | | `async` | ✓ | - | - | | `statusMessage` | ✓ | ✓ | ✓ | ### 2.3 Matcher Patterns (Regex) Matchers são **regex strings** que filtram eventos: ```json { "matcher": "Edit|Write", "matcher": "Bash", "matcher": "mcp__memory__.*", "matcher": "mcp__.*__write.*", "matcher": "*", "matcher": "" } ``` **Matcher por evento:** | Evento | Matcher contra | |--------|---------------| | PreToolUse/PostToolUse/PermissionRequest | tool_name (Bash, Write, Edit, Read, Glob, Grep, Task, WebFetch, WebSearch) | | SessionStart | source (startup, resume, clear, compact) | | SessionEnd | reason (clear, logout, prompt_input_exit, other) | | Notification | notification_type (permission_prompt, idle_prompt) | | SubagentStart/SubagentStop | agent_type (Bash, Explore, Plan, custom) | | PreCompact | trigger (manual, auto) | | UserPromptSubmit/Stop | SEM matcher (sempre fire) | ### 2.4 Path References com Variáveis ```json { "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/my-script.sh" } ``` **Variáveis disponíveis:** | Variável | Descrição | |----------|-----------| | `$CLAUDE_PROJECT_DIR` | Raiz do projecto | | `${CLAUDE_PLUGIN_ROOT}` | Raiz do plugin | | Qualquer env var | Variáveis do sistema | ### 2.5 Gestão via Menu Interactivo ```bash claude /hooks ``` O menu permite: - Ver todos hooks por evento - Adicionar novo hook - Deletar hook existente - Desabilitar temporariamente todos hooks - Validar JSON syntax **Nota:** Edições directas a ficheiros JSON só tomam efeito após reload via `/hooks` ou restart da sessão. --- ## 3. VARIÁVEIS DE AMBIENTE ### 3.1 Input JSON (via stdin) Todos os hooks recebem **JSON estruturado via stdin**: ```json { "session_id": "abc123-def456", "transcript_path": "/path/to/transcript.jsonl", "cwd": "/current/working/dir", "permission_mode": "default|plan|acceptEdits|dontAsk|bypassPermissions", "hook_event_name": "PreToolUse" } ``` ### 3.2 Input Schema por Evento #### SessionStart ```json { "source": "startup|resume|clear|compact", "model": "claude-opus-4-5-20251101", "agent_type": "CustomAgent" } ``` #### UserPromptSubmit ```json { "prompt": "User's exact prompt text here" } ``` #### PreToolUse (Bash Example) ```json { "tool_name": "Bash", "tool_use_id": "toolu_01ABC123...", "tool_input": { "command": "npm test", "description": "Run test suite", "timeout": 120000, "run_in_background": false } } ``` #### Tool-specific Input Schemas ```javascript // Write tool tool_input: { "file_path": "/path/to/file", "content": "file content" } // Edit tool tool_input: { "file_path": "/path/file", "old_string": "...", "new_string": "...", "replace_all": false } // Read tool tool_input: { "file_path": "/path/file", "offset": 10, "limit": 50 } // Glob tool tool_input: { "pattern": "**/*.ts", "path": "/optional/dir" } // Grep tool tool_input: { "pattern": "TODO.*fix", "path": "/dir", "glob": "*.ts", "output_mode": "content", "-i": true } // WebFetch tool tool_input: { "url": "https://api.example.com", "prompt": "Extract endpoints" } // WebSearch tool tool_input: { "query": "react hooks", "allowed_domains": [...], "blocked_domains": [...] } // Task tool (Subagent) tool_input: { "prompt": "...", "description": "...", "subagent_type": "Explore", "model": "sonnet" } ``` #### PostToolUse ```json { "tool_name": "Write", "tool_input": { }, "tool_response": { "filePath": "/path", "success": true }, "tool_use_id": "toolu_01ABC123..." } ``` #### PostToolUseFailure ```json { "tool_name": "Bash", "tool_input": { "command": "npm test" }, "tool_use_id": "toolu_01ABC123...", "error": "Command exited with non-zero status code 1", "is_interrupt": false } ``` #### Stop ```json { "stop_hook_active": false } ``` #### SubagentStop ```json { "stop_hook_active": false, "agent_id": "agent-abc123", "agent_type": "Explore", "agent_transcript_path": "~/.claude/.../subagents/agent-abc123.jsonl" } ``` ### 3.3 Environment Variables Hook scripts herdam **todas env vars do sistema** + especiais: | Variável | Descrição | Disponível em | |----------|-----------|---------------| | `CLAUDE_PROJECT_DIR` | Raiz do projecto | Todos | | `CLAUDE_CODE_REMOTE` | "true" se cloud | Todos | | `CLAUDE_ENV_FILE` | Path para persistir vars | SessionStart apenas | ### 3.4 Persistir Environment Variables (SessionStart) Apenas **SessionStart hooks** podem settar env vars permanentemente: ```bash #!/bin/bash # ~/.claude/hooks/setup-env.sh if [ -n "$CLAUDE_ENV_FILE" ]; then echo 'export NODE_ENV=production' >> "$CLAUDE_ENV_FILE" echo 'export DEBUG=1' >> "$CLAUDE_ENV_FILE" echo 'export PATH="$PATH:./node_modules/.bin"' >> "$CLAUDE_ENV_FILE" fi exit 0 ``` --- ## 4. CASOS DE USO PRÁTICOS ### 4.1 Validação e Bloqueio Pré-Execução **Caso:** Bloquear comandos perigosos ```bash #!/bin/bash # .claude/hooks/block-dangerous.sh INPUT=$(cat) COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty') if echo "$COMMAND" | grep -qE 'rm -rf|DROP TABLE|DELETE FROM'; then jq -n '{ "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": "Comando destrutivo bloqueado." } }' exit 0 fi exit 0 ``` **Config:** ```json { "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-dangerous.sh" } ] } ] } } ``` ### 4.2 Auto-Formatação Pós-Edição **Caso:** Rodar Prettier/Ruff após file write ```bash #!/bin/bash # .claude/hooks/format-after-write.sh INPUT=$(cat) FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty') case "$FILE_PATH" in *.ts|*.tsx|*.js|*.jsx) npx prettier --write "$FILE_PATH" 2>/dev/null ;; *.py) ruff format "$FILE_PATH" 2>/dev/null ;; *.go) gofmt -w "$FILE_PATH" 2>/dev/null ;; esac exit 0 ``` **Config:** ```json { "hooks": { "PostToolUse": [ { "matcher": "Write|Edit", "hooks": [ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/format-after-write.sh", "timeout": 30 } ] } ] } } ``` ### 4.3 Logging e Auditoria **Caso:** Log de todos bash commands ```bash #!/bin/bash # .claude/hooks/audit-bash.sh INPUT=$(cat) COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty') TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ") echo "$TIMESTAMP | $COMMAND" >> ~/.claude/bash-audit.log exit 0 ``` **Config:** ```json { "hooks": { "PostToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/audit-bash.sh", "async": true } ] } ] } } ``` ### 4.4 Protecção de Ficheiros Sensíveis **Caso:** Prevenir edições a .env, package-lock.json, .git ```bash #!/bin/bash # .claude/hooks/protect-files.sh INPUT=$(cat) FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty') PROTECTED_PATTERNS=(".env" "package-lock.json" ".git/" "secrets/" "credentials") for pattern in "${PROTECTED_PATTERNS[@]}"; do if [[ "$FILE_PATH" == *"$pattern"* ]]; then jq -n '{ "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": "Ficheiro protegido: '"$pattern"'" } }' exit 0 fi done exit 0 ``` ### 4.5 Re-inject Context após Compactação **Caso:** Re-injectar regras do projecto após compact ```json { "hooks": { "SessionStart": [ { "matcher": "compact", "hooks": [ { "type": "command", "command": "echo 'CONTEXT RE-INJECTED:\n\n1. Use Bun, not npm\n2. Run bun test before commits\n3. Follow functional style'" } ] } ] } } ``` ### 4.6 Notificações Desktop **Linux:** ```json { "hooks": { "Notification": [ { "matcher": "idle_prompt", "hooks": [ { "type": "command", "command": "notify-send 'Claude Code' 'Aguarda input'" } ] } ] } } ``` **macOS:** ```json { "hooks": { "Notification": [ { "matcher": "idle_prompt", "hooks": [ { "type": "command", "command": "osascript -e 'display notification \"Claude waiting\" with title \"Claude Code\"'" } ] } ] } } ``` ### 4.7 Validação de Testes antes de Stop **Caso:** Não deixar Claude parar se testes falharem ```json { "hooks": { "Stop": [ { "hooks": [ { "type": "agent", "prompt": "Run the test suite. Respond with {\"ok\": true} if all tests pass, or {\"ok\": false, \"reason\": \"Test failed\"} if any fail. $ARGUMENTS", "timeout": 120 } ] } ] } } ``` ### 4.8 Enriquecer Contexto no UserPromptSubmit **Caso:** Auto-adicionar info de git/time ```bash #!/bin/bash # .claude/hooks/enrich-context.sh echo "" echo "=== CONTEXT ===" echo "Last 3 commits:" git log --oneline -3 2>/dev/null || echo "No git repo" echo "" echo "Modified files:" git status --short 2>/dev/null | head -5 exit 0 ``` ### 4.9 Modificação de Input (v2.0.10+) **Novidade:** PreToolUse pode modificar tool inputs antes da execução: ```bash #!/bin/bash # .claude/hooks/force-dry-run.sh INPUT=$(cat) COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty') # Forçar --dry-run em comandos npm if [[ "$COMMAND" == npm* ]] && [[ "$COMMAND" != *"--dry-run"* ]]; then MODIFIED="$COMMAND --dry-run" jq -n --arg cmd "$MODIFIED" '{ "hookSpecificOutput": { "hookEventName": "PreToolUse", "modifiedInput": { "command": $cmd } } }' exit 0 fi exit 0 ``` --- ## 5. PADRÕES E ANTI-PADRÕES ### 5.1 BOAS PRÁTICAS #### 1. Always Quote Variables ```bash # CORRECTO FILE="$CLAUDE_PROJECT_DIR/.file" jq -r ".tool_input.file_path" <<< "$INPUT" # ERRADO FILE=$CLAUDE_PROJECT_DIR/.file ``` #### 2. Validate JSON Input ```bash #!/bin/bash INPUT=$(cat) if ! echo "$INPUT" | jq empty 2>/dev/null; then echo "Invalid JSON input" >&2 exit 1 fi COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty') ``` #### 3. Block Path Traversal ```bash FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty') if [[ "$FILE_PATH" == *".."* ]]; then echo "Path traversal detected" >&2 exit 2 fi ``` #### 4. Use Absolute Paths ```bash # CORRECTO HOOK_SCRIPT="$CLAUDE_PROJECT_DIR/.claude/hooks/script.sh" # ERRADO HOOK_SCRIPT=".claude/hooks/script.sh" ``` #### 5. Timeout Configurado por Tipo ```json { "type": "command", "timeout": 30 } { "type": "prompt", "timeout": 30 } { "type": "agent", "timeout": 120 } ``` #### 6. Async para Side Effects ```json { "type": "command", "async": true } ``` ### 5.2 ANTI-PADRÕES #### ❌ Confiar em cwd ```bash # ERRADO cd .claude && ./hooks/script.sh # CORRECTO bash "$CLAUDE_PROJECT_DIR/.claude/hooks/script.sh" ``` #### ❌ Infinite Stop Hooks ```bash # ERRADO - loop infinito if [ some condition ]; then echo '{"decision": "block"}' fi # CORRECTO INPUT=$(cat) if [ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ]; then exit 0 fi ``` #### ❌ Não citar paths com spaces ```bash # ERRADO npx prettier --write $FILE_PATH # CORRECTO npx prettier --write "$FILE_PATH" ``` #### ❌ Shell profile echo statements ```bash # ~/.zshrc - ERRADO echo "Shell ready" # CORRECTO if [[ $- == *i* ]]; then echo "Shell ready" fi ``` #### ❌ Síncrono para long-running ```json // ERRADO { "command": "npm run test-suite", "async": false } // CORRECTO { "command": "npm run test-suite", "async": true } ``` ### 5.3 Performance Considerations | Padrão | Impacto | Recomendação | |--------|---------|--------------| | Multiple hooks mesmo evento | O(n) paralelo | OK até 5 hooks | | Timeout muito alto | Bloqueia Claude | Use defaults | | Shell scripts lentos | Latência | Considerar async | | JQ parsing complex | CPU intensive | Python/Node | | File I/O em hook | Disk latency | Minimizar | **Benchmarks típicos:** | Operação | Tempo | |----------|-------| | Simple bash | 10-50ms | | JQ parsing | 5-20ms | | Prettier format | 100-500ms | | Test suite | 5-30s | --- ## 6. EXEMPLOS DE CÓDIGO ### 6.1 Validador Inteligente de Bash ```bash #!/bin/bash # .claude/hooks/validate-bash.sh set -euo pipefail INPUT=$(cat) if ! COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null); then echo "Failed to parse hook input" >&2 exit 1 fi declare -a DENY_PATTERNS=( 'rm -rf' 'DROP TABLE' 'DELETE FROM' '> /etc/' 'sudo' 'chmod 777' ) for pattern in "${DENY_PATTERNS[@]}"; do if echo "$COMMAND" | grep -qiF "$pattern"; then jq -n '{ "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": "Padrão perigoso: '"$pattern"'" } }' exit 0 fi done exit 0 ``` ### 6.2 Code Quality Enforcement ```bash #!/bin/bash # .claude/hooks/enforce-quality.sh INPUT=$(cat) FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty') [ -z "$FILE_PATH" ] && exit 0 case "$FILE_PATH" in *.ts|*.tsx|*.js|*.jsx) npx eslint --fix "$FILE_PATH" 2>/dev/null || true npx prettier --write "$FILE_PATH" 2>/dev/null || true ;; *.py) ruff format "$FILE_PATH" 2>/dev/null || true mypy "$FILE_PATH" 2>/dev/null || true ;; *.go) gofmt -w "$FILE_PATH" 2>/dev/null || true ;; *.rs) rustfmt "$FILE_PATH" 2>/dev/null || true ;; esac exit 0 ``` ### 6.3 Auto-Approval com Lógica Custom ```bash #!/bin/bash # .claude/hooks/smart-permissions.sh INPUT=$(cat) TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty') # Read-only tools: auto-approve case "$TOOL_NAME" in Read|Glob|Grep|WebFetch|WebSearch) jq -n '{ "hookSpecificOutput": { "hookEventName": "PermissionRequest", "decision": { "behavior": "allow" } } }' exit 0 ;; esac exit 0 ``` ### 6.4 Context Injection na Sessão ```bash #!/bin/bash # .claude/hooks/inject-session-context.sh CONTEXT="" if [ -d .git ]; then CONTEXT+="=== Git Status ===$(printf '\n')" CONTEXT+="$(git status --short | head -5)$(printf '\n\n')" CONTEXT+="=== Recent Commits ===$(printf '\n')" CONTEXT+="$(git log --oneline -3)$(printf '\n\n')" fi if [ -f package.json ]; then CONTEXT+="=== Test Suite ===$(printf '\n')" CONTEXT+="Ready to run: npm test$(printf '\n\n')" fi jq -n --arg ctx "$CONTEXT" '{ "hookSpecificOutput": { "hookEventName": "SessionStart", "additionalContext": $ctx } }' exit 0 ``` ### 6.5 Async Test Runner ```bash #!/bin/bash # .claude/hooks/run-tests-async.sh INPUT=$(cat) FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty') [[ ! "$FILE_PATH" =~ \.(ts|js|py|rs)$ ]] && exit 0 TEST_OUTPUT=$(npm test 2>&1 || true) EXIT_CODE=$? if [ $EXIT_CODE -eq 0 ]; then jq -n '{ "systemMessage": "✓ Tests passed" }' else jq -n --arg output "$TEST_OUTPUT" '{ "systemMessage": "✗ Tests failed", "additionalContext": "Test output:\n" + $output }' fi exit 0 ``` ### 6.6 Prompt-Based Hook: Stop Decision ```json { "hooks": { "Stop": [ { "hooks": [ { "type": "prompt", "prompt": "Evaluate if Claude should stop. Check:\n1. All tasks complete?\n2. Any errors need fixing?\n3. Follow-up needed?\n\nRespond: {\"ok\": true} or {\"ok\": false, \"reason\": \"...\"}", "timeout": 30, "model": "sonnet" } ] } ] } } ``` ### 6.7 Agent-Based Hook: Test Validation ```json { "hooks": { "Stop": [ { "hooks": [ { "type": "agent", "prompt": "Verify all tests pass. Use Bash to run test suite. Respond {\"ok\": true} if pass or {\"ok\": false, \"reason\": \"...\"} if fail.", "timeout": 300, "model": "sonnet" } ] } ] } } ``` --- ## 7. LIMITAÇÕES E WORKAROUNDS ### 7.1 Limitações Técnicas | Limitação | Detalhe | Workaround | |-----------|---------|-----------| | Sem tool calls directos | Hooks não chamam tools | Agent hooks | | PostToolUse não bloqueia | Tool já executou | Use PreToolUse | | Timeout 10min default | Long-running bloqueia | `async: true` | | Sem slash commands | Não pode `/compact` | Script manipulation | | Single-turn prompts | One-shot apenas | Agent hooks | | Matcher case-sensitive | "Bash" ≠ "bash" | Exact case | | PermissionRequest em -p | Não dispara | Use PreToolUse | ### 7.2 Workarounds Comuns #### Infinite Stop Loop ```bash # CORRECTO if [ "$(jq -r '.stop_hook_active' <<< "$INPUT")" = "true" ]; then exit 0 fi ``` #### Shell Profile Noise ```bash # ~/.zshrc if [[ $- == *i* ]]; then echo "Shell ready" fi ``` #### Hooks não Triggering ```bash # Debug checklist: claude --debug # 1. Matcher case-sensitive? # 2. JSON syntax valid? # 3. Ficheiro executable? # 4. Event name correcto? # 5. File path existe? ``` ### 7.3 Feature Gaps | Feature | Status | Alternative | |---------|--------|-------------| | Hook para Custom Subagents | ❌ | Skill frontmatter | | Hook Output Transforms | Parcial | JSON output fields | | Conditional Execution | ❌ | Prompt/Agent hooks | | Hook Chaining | ❌ | Multiple hooks | | Rollback Actions | ❌ | Logging + manual | --- ## 8. DEBUGGING E TROUBLESHOOTING ### 8.1 Técnicas de Debug #### 1. Debug Mode ```bash claude --debug 2>&1 | grep -i hook ``` #### 2. Verbose Mode ``` Ctrl+O # Toggle verbose mode ``` #### 3. Manual Testing ```bash echo '{ "session_id": "test", "hook_event_name": "PreToolUse", "tool_name": "Bash", "tool_input": { "command": "rm -rf /tmp" } }' | /path/to/hook.sh echo "Exit code: $?" ``` #### 4. JSON Validation ```bash ./hook.sh < input.json | jq empty echo "Valid: $?" ``` ### 8.2 Common Errors | Erro | Causa | Solução | |------|-------|---------| | `command not found` | Path incorrecto | `$CLAUDE_PROJECT_DIR` | | `JSON validation failed` | Invalid output | Test com `jq empty` | | `jq: command not found` | jq não instalado | `apt install jq` | | `Permission denied` | Não executable | `chmod +x` | | `Hook timed out` | Script lento | Aumentar timeout | | `Exit code 127` | Script not found | Verificar path | | `Matcher mismatch` | Case errado | Use correct case | ### 8.3 Troubleshooting Checklist ``` 1. [ ] Hook aparece em /hooks menu? 2. [ ] Hook dispara quando esperado? 3. [ ] Script executa correctamente? 4. [ ] JSON output processado? 5. [ ] Performance aceitável? 6. [ ] Infinite loops ou side effects? ``` ### 8.4 Debug Session Completa ```bash # 1. Run with debug $ claude --debug 2>&1 | tee debug.log # 2. Look for errors $ grep -i "hook.*error" debug.log # 3. Test manually $ cat > test_input.json << 'EOF' { "session_id": "test", "hook_event_name": "PreToolUse", "tool_name": "Bash", "tool_input": {"command": "npm test"} } EOF $ cat test_input.json | .claude/hooks/my-hook.sh $ echo "Exit code: $?" # 4. Validate JSON $ cat test_input.json | .claude/hooks/my-hook.sh | jq empty # 5. Check matcher $ grep -A2 "matcher" .claude/settings.json # 6. Reload hooks /hooks # no Claude Code ``` --- ## REFERÊNCIAS - [Hooks reference - Claude Code Docs](https://code.claude.com/docs/en/hooks) - [Automate workflows with hooks](https://code.claude.com/docs/en/hooks-guide) - [Claude Code power user customization](https://claude.com/blog/how-to-configure-hooks) - [GitHub - claude-code-hooks-mastery](https://github.com/disler/claude-code-hooks-mastery) - [Complete guide to hooks - Eesel AI](https://www.eesel.ai/blog/hooks-in-claude-code) --- **Descomplicar®** | 2026