Hooks let you run shell commands or HTTP requests at specific points in the agent's lifecycle. Use them for auto-formatting, linting, notifications, or custom validation.

Configuration

# .agent/settings.toml

# Auto-format Rust files after any write
[[hooks]]
event = "post_tool_use"
tool_name = "FileWrite"
[hooks.action]
type = "shell"
command = "cargo fmt"

# Lint after edits
[[hooks]]
event = "post_tool_use"
tool_name = "FileEdit"
[hooks.action]
type = "shell"
command = "cargo clippy --quiet"

# Notify on session start
[[hooks]]
event = "session_start"
[hooks.action]
type = "http"
url = "https://hooks.slack.com/services/T.../B.../..."
method = "POST"

Hook events

EventWhen it fires
session_startSession begins
session_stopSession ends
user_prompt_submitUser submits input (incl. steered mid-turn input)
pre_turn / post_turnAround each agent turn
pre_tool_useBefore a tool executes (non-zero exit / failure vetoes the call)
post_tool_useAfter a tool completes
file_changedAfter a file-mutating tool completes
pre_compact / post_compactAround history compaction
task_completedA background task (bash … & or a spawned subagent) finished
stopAgent finished responding; about to yield to the user
notificationAgent needs user attention (budget / context full)
permission_deniedA tool call was denied (per-denial, batched per turn)
cwd_changed / config_change / errorWorking dir changed / extensions reloaded / turn errored

Hook context

Every hook receives the event's context (which task finished, which tool ran, the prompt, etc.):

  • stdin — the full context as a single JSON line.
  • environmentAGENT_CODE_HOOK_EVENT, AGENT_CODE_HOOK_TOOL (when applicable), and AGENT_CODE_HOOK_CONTEXT (the JSON, when small enough to pass safely; large contexts omit it and set AGENT_CODE_HOOK_CONTEXT_TRUNCATED=1 — use stdin instead).
  • HTTPhttp hooks receive the context as the request body (POST).

The task_completed context carries id, kind, status, description, and duration_secs.

Hook actions

Shell

Run a command in the project directory:

[hooks.action]
type = "shell"
command = "make lint"

HTTP

Send a request to a URL:

[hooks.action]
type = "http"
url = "https://example.com/webhook"
method = "POST"

Filtering by tool

Use tool_name to run hooks only for specific tools:

[[hooks]]
event = "pre_tool_use"
tool_name = "Bash"
[hooks.action]
type = "shell"
command = "echo 'Bash command about to run'"

Without tool_name, the hook fires for all tools.

Commands

> /hooks
Hook system active. Configure hooks in .agent/settings.toml:
  [[hooks]]
  event = "pre_tool_use"
  action = { type = "shell", command = "./check.sh" }