Skip to content

Hooks

Hooks let you run shell commands or inject prompts at specific points in the AI tool lifecycle. They live in .agentsmesh/hooks.yaml.

File format

PreToolUse:
- matcher: "Edit|Write"
type: command
command: "eslint --fix $FILE"
timeout: 30
PostToolUse:
- matcher: "Bash"
type: prompt
prompt: "Review the command output for security concerns before proceeding."
Notification:
- matcher: "*"
type: command
command: "./scripts/log-notification.sh"
UserPromptSubmit:
- matcher: "*"
type: command
command: "./scripts/prompt-guard.sh"

Hook event types

EventWhen it fires
PreToolUseBefore a tool call executes.
PostToolUseAfter a tool call completes.
NotificationWhen the AI sends a notification.
UserPromptSubmitWhen the user submits a prompt.
SubagentStartWhen a subagent starts.
SubagentStopWhen a subagent stops.

Hook entry fields

FieldTypeRequiredDescription
matcherstringYesRegex pattern for which tool or event triggers the hook. Use * to match all.
typestringYescommand — run a shell command. prompt — inject a prompt into the conversation.
commandstringIf type: commandShell command to execute.
promptstringIf type: promptPrompt text to inject.
timeoutnumberNoTimeout in seconds. Default varies by tool.

Variable substitution

For PreToolUse and PostToolUse hooks, the following variables are available in command:

VariableDescription
$FILEThe file path being edited (for Edit/Write tools).
$TOOLThe tool name being called.

Common hook patterns

Auto-lint on file save

PreToolUse:
- matcher: "Edit|Write"
type: command
command: "npx eslint --fix $FILE"
timeout: 30

Security review on Bash execution

PostToolUse:
- matcher: "Bash"
type: prompt
prompt: "Check the output of the previous command for security issues, unexpected errors, or sensitive data before continuing."

Prompt injection guard

UserPromptSubmit:
- matcher: "*"
type: command
command: "./scripts/check-prompt-injection.sh"
timeout: 5

Log all notifications

Notification:
- matcher: "*"
type: command
command: "echo \"$(date): $NOTIFICATION\" >> .agentsmesh/notifications.log"

Tool-specific behavior

See the Hooks row in the supported tools matrix for per-target support levels (native, partial, or unsupported).

Windows portability

For targets that embed the canonical command verbatim in a JSON config (executed by the agent at runtime), a portable command (pnpm test, npx eslint $FILE) works identically on Linux, macOS, and Windows.

Cline and Copilot are different: their native hook contracts are shell wrapper files. AgentsMesh emits them as .clinerules/hooks/*.sh and .github/hooks/scripts/*.sh with a #!/usr/bin/env bash header. These wrappers will not execute on Windows without a POSIX shell (git-bash or WSL). agentsmesh lint warns when hooks are configured for either target. If your team includes Windows developers, prefer a JSON-embedded hook target (see the hooks row in the support matrix) or supply a POSIX shell on the Windows machines.

Generated wrapper contract (Cline / Copilot)

Generated .sh wrappers carry three guarantees beyond the canonical command:

  • set -eu is the first executable line — wrappers abort on any command failure and on reference to an unset variable. If your command references $ENV_VAR and the variable is not exported, the hook now fails fast instead of silently expanding to an empty string. Use ${ENV_VAR:-default} syntax when an unset value is intentional.
  • Executable mode 0o755 is set on every emitted .sh/.bash/.zsh file so runner exec-style invocation works without an explicit chmod +x step.
  • CR/LF stripped from the metadata header — the # agentsmesh-matcher: and # agentsmesh-command: comment lines collapse newlines from the canonical YAML, so a multi-line block scalar in the canonical hook cannot break out of the comment header into executable shell.

Agent-level hooks

Hooks can also be defined per-agent in agents/*.md frontmatter:

---
name: safe-editor
description: Editor agent with pre-commit validation
hooks:
PreToolUse:
- matcher: "Edit|Write"
type: command
command: "npx tsc --noEmit"
timeout: 60
---

Agent-level hooks apply only when that agent is active and override project-level hooks for matching events.