Hooks
Hooks are shell commands that fire before or after any tool call, filtered by tool-name glob patterns. They’re the main way to customize AI Butler’s behavior without writing Go code.
Use Cases
Section titled “Use Cases”- Auto-format on save — run
gofumptorprettierafter everyfile.edit - Block dangerous commands — refuse
shell.execwhen the command matches a dangerous pattern - Audit tool use — append every
shell.execto a log file - Notify on completion — ping a webhook when a long task finishes
- Enforce policy — run a linter and block commits that fail it
Configuration
Section titled “Configuration”Hooks live in config.yaml under configurations.hooks. There are two events: pre_tool_use (before the tool runs) and post_tool_use (after it completes).
Each hook has a shell command and a list of tool-name tools glob patterns. If the tool being called matches any pattern, the hook fires.
configurations: hooks: pre_tool_use: - command: "echo 'blocked' >&2 && exit 2" tools: ["shell.exec"] # fires on every shell call
post_tool_use: - command: "gofumpt -w ." tools: ["file.edit", "file.write"]
- command: "echo '$(date) $TOOL_NAME' >> /var/log/aibutler-audit.log" tools: ["*"] # fires on every tool callTool Name Patterns
Section titled “Tool Name Patterns”Glob-style, matched against the tool name:
| Pattern | Matches |
|---|---|
file.edit | Exact match only |
file.* | All file tools (file.read, file.write, file.edit, file.list, file.search) |
git.* | All git tools |
iot.safety.* | Safety-tier IoT tools only |
* | Every tool call |
Environment Variables
Section titled “Environment Variables”Hook commands run with these environment variables set:
| Variable | Value |
|---|---|
TOOL_NAME | Name of the tool being called (e.g. file.edit) |
TOOL_INPUT | JSON-encoded tool input |
TOOL_OUTPUT | Tool output (post-hooks only) |
TOOL_STATUS | success or error (post-hooks only) |
SESSION_ID | Current session ID |
CHANNEL | Channel name (telegram, terminal, etc.) |
Exit Code Semantics
Section titled “Exit Code Semantics”Pre-hooks can block tool execution by their exit code:
| Exit code | Meaning |
|---|---|
0 | Success — tool call proceeds |
1 | Non-fatal failure — warning logged, tool call still proceeds |
2 | Block — tool call is refused, stderr is returned to the agent as a feedback message |
Post-hooks’ exit codes are logged but don’t affect the already-completed tool call.
Example: Block Destructive Shell Commands
Section titled “Example: Block Destructive Shell Commands”configurations: hooks: pre_tool_use: - command: | if echo "$TOOL_INPUT" | grep -qE 'rm -rf /|dd if=|mkfs\.'; then echo "Refused: destructive shell command" >&2 exit 2 fi tools: ["shell.exec"]Example: Auto-format Go Files
Section titled “Example: Auto-format Go Files”configurations: hooks: post_tool_use: - command: | path=$(echo "$TOOL_INPUT" | jq -r .path) if [[ "$path" == *.go ]]; then gofumpt -w "$path" fi tools: ["file.edit", "file.write"]Example: Audit Log
Section titled “Example: Audit Log”configurations: hooks: post_tool_use: - command: "printf '%s %s %s\n' \"$(date -Iseconds)\" \"$TOOL_NAME\" \"$TOOL_STATUS\" >> /var/log/aibutler-audit.log" tools: ["*"]Security Notes
Section titled “Security Notes”Hooks run as the same OS user as AI Butler itself. They inherit the same shell sandbox (if configured) — see Sandbox configuration. Do not put secrets in hook commands; they’re logged verbatim on failure.