intermediate45 minLição 2 de 6

Hooks Personalizados para Automação

Crie hooks personalizados para automatizar tarefas repetitivas no OpenCode. Aprenda o ciclo de vida dos hooks, tipos de eventos e como criar hooks que validam, transformam e protegem seu fluxo de trabalho.

Hooks Personalizados para Automação

O que são Hooks?

Hooks são scripts que são executados automaticamente em pontos específicos do ciclo de vida do Eles permitem:

  • Validação — Verificar entradas/saídas antes do processamento
  • Transformação — Modificar dados entre etapas
  • Proteção — Bloquear operações perigosas
  • Registro — Rastrear atividades para auditoria

Eventos de Hook

EventoQuando é DisparadoCaso de Uso
session.startSessão iniciaCarregar contexto, verificar ambiente
session.endSessão terminaLimpeza, salvar estado
file.writeAntes do arquivo ser escritoValidar conteúdo, formatar código
file.readAntes do arquivo ser lidoControle de acesso, registro
tool.execute.beforeAntes da ferramenta executarVerificações de permissão, validação
tool.execute.afterDepois da ferramenta executarPós-processamento, registro

Estrutura do Hook

.opencode/hooks/my-hook/ ├── hook.json # Hook configuration ├── scripts/ │ └── handler.py # Hook script └── examples/ └── sample-input.json

hook.json

json
{ "name": "validate-frontmatter", "description": "Validates YAML frontmatter in lesson files", "event": "file.write", "pattern": "content/courses/**/*.md", "script": ".opencode/hooks/validate-frontmatter/scripts/handler.py", "blocking": true }
CampoDescrição
nameIdentificador único
descriptionO que o hook faz
eventQuando acionar
patternPadrão de arquivo para correspondência (glob)
scriptCaminho para o script do manipulador
blockingSe verdadeiro, bloqueia operação em caso de falha

Criando um Hook de Validação

Passo 1: Criar Diretório

bash
mkdir -p .opencode/hooks/validate-frontmatter/scripts

Passo 2: Criar hook.json

json
{ "name": "validate-frontmatter", "description": "Validates YAML frontmatter in Markdown files", "event": "file.write", "pattern": "**/*.md", "script": ".opencode/hooks/validate-frontmatter/scripts/handler.py", "blocking": true }

Passo 3: Criar Script do Manipulador

python
#!/usr/bin/env python3 """Validate YAML frontmatter in Markdown files. Exit Codes: 0 - Validation passed 1 - Warning (non-blocking) 2 - Validation failed (blocking) """ import os import sys import yaml from pathlib import Path def extract_frontmatter(content: str) -> tuple[str | None, str]: """Extract YAML frontmatter from Markdown content.""" if not content.startswith("---"): return None, content parts = content.split("---", 2) if len(parts) < 3: return None, content return parts[1].strip(), parts[2] def validate_frontmatter(frontmatter: str) -> list[str]: """Validate frontmatter structure and return errors.""" errors = [] try: data = yaml.safe_load(frontmatter) except yaml.YAMLError as e: return [f"Invalid YAML: {e}"] required_fields = ["title", "description", "order"] for field in required_fields: if field not in data: errors.append(f"Missing required field: {field}") if "order" in data: if not isinstance(data["order"], int): errors.append("Field 'order' must be an integer") elif data["order"] < 1: errors.append("Field 'order' must be >= 1") return errors def main() -> int: """Main hook entry point.""" file_path = os.environ.get("OPENCODE_FILE_PATH", "") if not file_path: print("WARNING: OPENCODE_FILE_PATH not set", file=sys.stderr) return 1 path = Path(file_path) if not path.exists(): print(f"ERROR: File not found: {file_path}", file=sys.stderr) return 2 try: content = path.read_text(encoding="utf-8") except Exception as e: print(f"ERROR: Cannot read file: {e}", file=sys.stderr) return 2 frontmatter, _ = extract_frontmatter(content) if frontmatter is None: print(f"WARNING: No frontmatter found in {file_path}") return 1 errors = validate_frontmatter(frontmatter) if errors: for error in errors: print(f"VALIDATION ERROR: {error}", file=sys.stderr) return 2 print(f"VALIDATION PASSED: {file_path}") return 0 if __name__ == "__main__": sys.exit(main())

Passo 4: Tornar o Script Executável

bash
chmod +x .opencode/hooks/validate-frontmatter/scripts/handler.py

Registrando Hooks

Adicione hooks ao opencode.json:

json
{ "hooks": { "file.write": [ { "name": "validate-frontmatter", "pattern": "content/courses/**/*.md", "script": ".opencode/hooks/validate-frontmatter/scripts/handler.py", "blocking": true } ], "session.start": [ { "name": "load-context", "script": ".opencode/hooks/load-context/scripts/handler.py", "blocking": false } ] } }

Hooks de Proteção

Hooks de proteção bloqueiam operações perigosas:

python
#!/usr/bin/env python3 """Block writes to protected directories.""" import os import sys from pathlib import Path PROTECTED_PATTERNS = [ ".env", "secrets/**", "*.key", "*.pem", ] def is_protected(path: Path) -> bool: """Check if path matches protected patterns.""" from fnmatch import fnmatch path_str = str(path) for pattern in PROTECTED_PATTERNS: if fnmatch(path_str, pattern): return True if fnmatch(path.name, pattern): return True return False def main() -> int: file_path = os.environ.get("OPENCODE_FILE_PATH", "") if not file_path: return 0 path = Path(file_path) if is_protected(path): print(f"BLOCKED: Cannot write to protected file: {file_path}", file=sys.stderr) return 2 return 0 if __name__ == "__main__": sys.exit(main())

Depuração de Hooks

Ativar Registro de Depuração

bash
export OPENCODE_DEBUG=1 opencode

Testar Hooks Manualmente

bash
OPENCODE_FILE_PATH=test.md python .opencode/hooks/validate-frontmatter/scripts/handler.py

Verificar Códigos de Saída

CódigoSignificadoAção
0AprovadoContinuar operação
1AvisoRegistrar, continuar
2BloqueadoParar operação, mostrar erro

Practice Questions

Practice Question

What happens when a blocking hook returns exit code 2?

Practice Question

Which hook event fires before a file is written?

Practice Question

What field in hook.json specifies which files trigger the hook?

Practice Question

How do you test a hook manually?

Practice Question

What is a guard hook used for?


Success

Key Takeaways

  • Hooks são scripts que são executados automaticamente em pontos específicos do ciclo de vida
  • O evento file.write é ideal para validar conteúdo antes de salvar
  • Use código de saída 0 para aprovação, 1 para aviso, 2 para bloqueio
  • Hooks de proteção protegem arquivos sensíveis e operações perigosas
  • Hooks são registrados em opencode.json sob a chave hooks
  • O campo pattern usa sintaxe glob para corresponder a arquivos
  • Teste hooks manualmente definindo OPENCODE_FILE_PATH e executando o script
Progresso33%