Los hooks inyectan lógica personalizada en puntos clave del ciclo de vida del agente de Qoder CN. Mediante un archivo de configuración JSON, usted puede:
Bloquear operaciones peligrosas antes de llamar a una herramienta.
Ejecutar un linter después de cada escritura de archivo para aplicar el estilo de código.
Recibir una notificación de escritorio cuando el agente termina una tarea.
A diferencia de las instrucciones del prompt, los hooks son deterministas. Cuando ocurre un evento registrado, el script se ejecuta sin importar la interpretación del modelo.
Eventos compatibles
Qoder CN es compatible con cinco eventos de hook:
|
Nombre del evento |
Activador |
Bloqueable |
|
|
Después de que el usuario envía un prompt, pero antes de que el agente lo procese. |
Sí |
|
|
Antes de ejecutar una llamada a una herramienta. |
Sí |
|
|
Después de que una llamada a una herramienta se completa correctamente. |
No |
|
|
Después de que falla una llamada a una herramienta. |
No |
|
|
Cuando el agente termina su respuesta. |
No |
Inicio rápido
Este ejemplo configura un hook que bloquea rm -rf.
Paso 1: Cree el script
mkdir -p ~/.lingma/hooks
cat > ~/.lingma/hooks/block-rm.sh << 'EOF'
#!/bin/bash
input=$(cat)
command=$(echo "$input" | jq -r '.tool_input.command')
if echo "$command" | grep -q 'rm -rf'; then
echo "Dangerous command blocked: $command" >&2
exit 2
fi
exit 0
EOF
chmod +x ~/.lingma/hooks/block-rm.sh
Paso 2: Agregue la configuración
Agregue a continuación el contenido en ~/.lingma/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "~/.lingma/hooks/block-rm.sh"
}
]
}
]
}
}
Paso 3: Compruebe el resultado
Reinicie el IDE. En el panel de Qoder CN, pida al agente que ejecute un comando que contenga rm -rf. El hook bloquea la ejecución y devuelve el mensaje de error al agente.
Casos de uso
|
Escenario |
Evento |
Descripción |
|
Bloquear comandos peligrosos |
|
Bloquee comandos como |
|
Validar rutas de archivos |
|
Restrinja la escritura de archivos a directorios designados. |
|
Lint o formato automático |
|
Ejecute ESLint o Prettier automáticamente después de escribir archivos. |
|
Registro de auditoría |
|
Registre todas las llamadas a herramientas del agente para auditorías de seguridad. |
|
Supervisión de errores |
|
Envíe alertas o registre errores cuando falle una llamada a una herramienta. |
|
Filtrar contenido de prompts |
|
Analice los prompts en busca de datos confidenciales, como contraseñas o claves. |
|
Inyección automática de contexto |
|
Agregue directrices del proyecto o convenciones de código a los prompts. |
|
Notificaciones de escritorio |
|
Envíe una notificación de escritorio cuando el agente termine. |
Cómo funciona
Los hooks requieren dos pasos: escribir un script y registrarlo en el archivo de configuración.
Cuando el agente alcanza un evento del ciclo de vida, la extensión busca los hooks correspondientes:
El IDE carga todas las configuraciones de hooks al iniciar.
El agente alcanza un nodo de evento (por ejemplo, PreToolUse).
La extensión recorre los grupos de hooks y los compara con el contexto actual.
Los scripts coincidentes se ejecutan en el orden declarado.
El script recibe el contexto del evento (JSON) mediante stdin y devuelve una decisión a través del código de salida y stdout.
El IDE usa el resultado para permitir o bloquear la operación.
Requisitos previos
jq: se usa para analizar sintácticamente JSON en los ejemplos. Instálelo con
brew install jq(macOS) oapt install jq(Linux).Permisos del script: los scripts de hook deben tener permisos de ejecución (
chmod +x).
Creación de hooks
Paso 1: Defina el requisito
Determine cuándo intervenir y qué debe coincidir:
I want to intercept/handle "what operation" "when"?
↓ ↓
Write matcher Choose event
|
Requisito |
Evento |
Matcher |
|
|
Inspeccionar comandos de shell antes de ejecutarlos. |
PreToolUse |
|
|
|
Procesar archivos después de escribirlos o editarlos. |
PostToolUse |
|
Edit"` |
|
Registrar cuando falla una llamada a una herramienta del agente. |
PostToolUseFailure |
|
|
|
Filtrar todos los prompts del usuario. |
UserPromptSubmit |
Omitir (coincide con todo) |
|
|
Activar una notificación cuando el agente se detiene. |
Stop |
Omitir (coincide con todo) |
|
|
Interceptar solo herramientas MCP. |
PreToolUse |
|
Paso 2: Escriba el script del hook
Los scripts de hook siguen este protocolo:
Entrada: recibe el contexto del evento como un objeto JSON mediante
stdin.Salida: controla el comportamiento mediante su
exit code.
exit 0 → Allow (proceed with execution)
exit 2 → Block (stop the operation; stderr is fed back to the Agent)
Other → Error (proceed with execution; stderr is displayed to the user)
Plantilla de script:
#!/bin/bash
# 1. Read JSON input from stdin.
input=$(cat)
# 2. Extract the fields you need with jq.
# Different events have different fields; see the "Event Reference" section for details.
tool_name=$(echo "$input" | jq -r '.tool_name')
tool_input=$(echo "$input" | jq -r '.tool_input')
# 3. Write your validation logic.
if [ "$tool_name" = "Bash" ]; then
command=$(echo "$input" | jq -r '.tool_input.command')
# Check for dangerous operations.
if echo "$command" | grep -qE 'rm\s+-rf|DROP\s+TABLE'; then
# Block: exit 2 + stderr message is fed back to the Agent.
echo "Operation denied: $command" >&2
exit 2
fi
fi
# 4. Allow the operation.
exit 0
También puede generar JSON con exit 0 para obtener un control más preciso:
#!/bin/bash
input=$(cat)
# Output JSON for fine-grained control (only takes effect on exit 0).
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"This operation is not allowed"}}'
exit 0
Paso 3: Registre el script en el archivo de configuración
Registre el script bajo el evento correspondiente:
{
"hooks": {
"EventName": [
{
"matcher": "MatchCondition (optional)",
"hooks": [
{
"type": "command",
"command": "/path/to/your/script.sh"
}
]
}
]
}
}
Paso 4: Pruebe y depure
Pruebe los hooks si canaliza la entrada JSON desde la terminal:
# Simulate a PreToolUse event
echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /"},"hook_event_name":"PreToolUse"}' \
| ~/.lingma/hooks/block-rm.sh
echo "Exit code: $?"
Revise la salida de stderr (mensaje de bloqueo):
echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /"}}' \
| ~/.lingma/hooks/block-rm.sh 2>&1
Configuración de hooks
Ubicaciones de los archivos de configuración
Los hooks se combinan a partir de estos archivos, de menor a mayor prioridad:
|
Ubicación |
Alcance |
Prioridad |
Compartible |
Descripción |
|
|
Usuario |
1 (la más baja) |
No |
Se aplica a todos los proyectos. |
|
|
Proyecto |
2 |
Sí |
Se puede confirmar en git para compartirlo con el equipo. |
|
|
Proyecto (local) |
3 (la más alta) |
No |
Anulaciones personales. Agréguelo a |
No se admite la recarga en caliente. Reinicie el IDE para que los cambios de configuración surtan efecto.
Formato de configuración
{
"hooks": {
"EventName": [
{
"matcher": "MatchCondition",
"hooks": [
{
"type": "command",
"command": "command_to_run"
}
]
}
]
}
}
|
Campo |
Obligatorio |
Descripción |
|
|
Sí |
Debe establecerse en |
|
|
Sí |
El comando de shell o la ruta del script que se va a ejecutar. |
|
|
No |
Tiempo de espera en segundos. Valor predeterminado: 30. |
|
|
No |
Filtra cuándo se ejecuta el hook. Si se omite, se activa en todas las invocaciones del evento. |
Un solo evento puede tener varios grupos de matchers, cada uno con varios comandos de hook.
Reglas de coincidencia del matcher
Un matcher restringe cuándo se activa un hook. Los campos evaluados varían según el evento.
|
Sintaxis |
Significado |
Ejemplo |
||
|
Omitir o |
Coincidir con todo |
Se activa para todas las herramientas. |
||
|
Valor exacto |
Coincidencia exacta |
|
||
|
Separado por |
` |
Coincidir con varios valores |
|
Edit"` se activa para las herramientas Write o Edit. |
|
Expresión regular |
Coincidencia de expresión regular |
|
Asignación de nombres de herramientas
Qoder CN asigna dos conjuntos de nombres de herramientas en tiempo de ejecución: nativos y compatibles. Por ejemplo, matcher: "Bash" y matcher: "run_in_terminal" son equivalentes.
|
Nombre nativo |
Nombre compatible |
Descripción |
|
run_in_terminal |
Bash |
Ejecuta un comando de shell. |
|
read_file |
Read |
Lee el contenido de un archivo. |
|
create_file |
Write |
Crea un archivo o escribe en él. |
|
search_replace |
Edit |
Edita un archivo. |
|
delete_file |
- |
Elimina un archivo. |
|
grep_code |
Grep |
Busca contenido en archivos. |
|
search_file |
Glob |
Coincide con nombres de archivos. |
|
list_dir |
LS |
Enumera el contenido de un directorio. |
|
task |
Task |
Inicia una subtarea o un subagente. |
|
mcp__<server>__<tool> |
Igual que el nativo |
Una herramienta MCP. |
Escritura de scripts de hook
Los scripts de hook reciben JSON mediante stdin e indican decisiones a través de exit code y stdout. Los campos específicos de cada evento se describen en la sección Referencia de eventos.
Entrada
Todos los eventos comparten estos campos de stdin:
|
Campo |
Descripción |
|
|
El identificador de la sesión actual. |
|
|
El directorio de trabajo actual. |
|
|
El nombre del evento activado. |
|
|
La ruta del archivo al JSON del contexto de la sesión. |
Los eventos agregan campos adicionales a esta base (enumerados en la Referencia de eventos). Analícelos con jq:
#!/bin/bash
input=$(cat)
tool_name=$(echo "$input" | jq -r '.tool_name')
Salida
Un script indica su decisión mediante su exit code y los datos escritos en stdout.
El código de salida determina el comportamiento básico:
|
Código de salida |
Significado |
Comportamiento |
|
0 |
Correcto |
Continúa la ejecución y analiza sintácticamente el JSON de stdout. |
|
2 |
Bloqueo |
Bloquea la operación y envía stderr al agente (solo en eventos bloqueables). |
|
Otro |
Error |
Continúa la ejecución y muestra stderr al usuario. |
JSON de stdout (opcional; solo surte efecto cuando el código de salida es 0):
{
"continue": true,
"stopReason": "",
"suppressOutput": false,
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow | deny | ask",
"permissionDecisionReason": "Reason for the decision"
}
}
Referencia de eventos
UserPromptSubmit
Activador: después de que el usuario envía un prompt, pero antes de que el agente lo procese.
Bloqueable: sí (el código de salida 2 cancela la solicitud).
Campos de entrada adicionales:
prompt(el texto sin procesar que ingresó el usuario).
PreToolUse
Activador: antes de que el agente ejecute una llamada a una herramienta.
Bloqueable: sí (el código de salida 2 rechaza la llamada a la herramienta).
Campo del matcher:
tool_name.Campos de entrada adicionales:
tool_name,tool_input.
PostToolUse
Activador: después de que una llamada a una herramienta se completa correctamente.
Bloqueable: no.
Campo del matcher:
tool_name.Campos de entrada adicionales:
tool_name,tool_input,tool_response.
PostToolUseFailure
Activador: después de que falla una llamada a una herramienta.
Bloqueable: no.
Campo del matcher:
tool_name.Campos de entrada adicionales:
tool_name,tool_input,error.
Stop
Activador: cuando el agente termina su respuesta.
Bloqueable: no.
Campos de entrada adicionales:
stop_hook_active,last_assistant_message.
Preguntas frecuentes
¿Por qué los cambios de configuración no surten efecto?
No se admite la recarga en caliente. Reinicie el IDE después de modificar settings.json.
¿Qué sucede si un script de hook supera el tiempo de espera?
Un tiempo de espera agotado (valor predeterminado: 30 s) se trata como un error. La ejecución continúa y se muestra stderr al usuario.
¿Cómo se determina el orden de ejecución de varios hooks?
Los hooks del mismo evento se ejecutan en el orden declarado. Entre archivos se aplica la siguiente prioridad: usuario (la más baja) → proyecto → proyecto local (la más alta).
¿A qué variables de entorno pueden acceder los scripts de hook?
Los hooks se ejecutan en la raíz del proyecto con el usuario actual y heredan el entorno del proceso del IDE.
¿Cómo consulto los registros de ejecución de los hooks?
La salida de stderr se envía al agente o al usuario. Para consultar registros detallados, busque el prefijo [hook] en los registros de ejecución de Qoder CN.