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
| Event | When it fires |
|---|---|
PreToolUse | Before a tool call executes. |
PostToolUse | After a tool call completes. |
Notification | When the AI sends a notification. |
UserPromptSubmit | When the user submits a prompt. |
SubagentStart | When a subagent starts. |
SubagentStop | When a subagent stops. |
Hook entry fields
| Field | Type | Required | Description |
|---|---|---|---|
matcher | string | Yes | Regex pattern for which tool or event triggers the hook. Use * to match all. |
type | string | Yes | command — run a shell command. prompt — inject a prompt into the conversation. |
command | string | If type: command | Shell command to execute. |
prompt | string | If type: prompt | Prompt text to inject. |
timeout | number | No | Timeout in seconds. Default varies by tool. |
Variable substitution
For PreToolUse and PostToolUse hooks, the following variables are available in command:
| Variable | Description |
|---|---|
$FILE | The file path being edited (for Edit/Write tools). |
$TOOL | The tool name being called. |
Common hook patterns
Auto-lint on file save
PreToolUse: - matcher: "Edit|Write" type: command command: "npx eslint --fix $FILE" timeout: 30Security 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: 5Log 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 -euis the first executable line — wrappers abort on any command failure and on reference to an unset variable. If yourcommandreferences$ENV_VARand 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
0o755is set on every emitted.sh/.bash/.zshfile sorunner exec-style invocation works without an explicitchmod +xstep. - 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-editordescription: Editor agent with pre-commit validationhooks: 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.