A hook is a shell command Geoff Code runs automatically when a specific event fires during an agent turn. Hooks let you auto-format edited files, block writes to sensitive paths, send notifications, or verify that work is complete — deterministically, without relying on the model to remember.

Configuring hooks

Hooks live in ~/.geoff/config.toml as an array of [[hooks]] tables:
After editing config.toml, run geoff doctor config to validate it, then start a new session. View active hooks in the TUI with the /hooks command.

Events

Hooks can fire on any of these lifecycle events:

Input and output protocol

Each hook command receives a single JSON object on stdin with the session ID, working directory, event name, and event-specific fields (such as tool_name, tool_input, or tool_output). It signals its decision through its exit code: For finer control, a hook can exit 0 and print structured JSON declaring a permissionDecision (allow / deny) with a reason.

Examples

Auto-format after edits

Protect sensitive files

Notify when a turn ends

Behavior notes

  • Fail-open — a hook that times out or crashes does not block the operation; the agent continues.
  • Parallel — multiple hooks bound to the same event run concurrently.
  • Loop-safeStop hooks carry a stop_hook_active flag so a hook that re-triggers a turn can’t loop forever.

Config Files

Where hooks are declared, alongside the rest of your config.

Command Reference

Use geoff doctor to validate your hook config.