Hooks
Run your own commands when the agent uses a tool, runs a shell command, fails or finishes, and block tools before they run.
8gent reads two hook files. Both are optional.
| File | Use it for |
|---|---|
~/.8gent/hooks.json | Run something when events happen: notify, log, lint |
~/.8gent/hooks.yaml | Check a tool call before it runs, and block it |
hooks.json
{
"hooks": [
{
"id": "done-sound",
"type": "onComplete",
"name": "Say done",
"mode": "shell",
"command": "say 'Task completed'",
"enabled": true,
"async": true,
"continueOnError": true
}
],
"globalTimeout": 30000,
"enabled": true
}Events
| Type | Fires |
|---|---|
beforeTool | Before a tool runs |
afterTool | After a tool finishes |
beforeCommand | Before a shell command runs |
afterCommand | After a shell command finishes |
onError | When a tool or the agent fails |
onComplete | When a task finishes |
onStart | When a session starts |
onExit | Defined, but nothing fires it on main today |
Modes
| Mode | Field | Runs |
|---|---|---|
shell | command | A shell command, with {variable} substitution |
script | scriptPath | A script file |
function | functionBody | Inline JavaScript, with context.variable |
Variables
{tool}, {command}, {result}, {error}, {sessionId}, {workingDirectory}, {duration} (ms), {exitCode}, {stdout}, {stderr}.
Examples
Lint after every file write:
{ "type": "afterTool", "name": "Lint", "mode": "shell", "command": "bunx biome check --write .", "enabled": true, "continueOnError": true }Log every shell command:
{ "type": "afterCommand", "name": "Log", "mode": "shell", "command": "echo '{command} -> {exitCode}' >> ~/.8gent/commands.log", "enabled": true, "async": true }hooks.yaml: block a tool before it runs
A list of hooks. Before each tool call, matching hooks get the call as JSON on stdin. If one prints {"block": true, "reason": "..."}, the tool does not run and the agent is told why.
- event: PreToolUse
matcher: write_file # a tool name, or "*" for every tool
command: ~/.8gent/hooks/no-writes-to-main.sh
timeout: 5000 # ms, default 5000The stdin payload has tool, args, sessionId and workingDirectory. EIGHT_HOOKS_YAML points at another file.
Only PreToolUse is fired on main today. PostToolUse, SessionStart, SessionEnd and OnError are accepted in the file but not yet fired.
A hook that fails or times out is logged and never stops the agent on its own.