Three hooks that show what the system can do. Each is a small POSIX shell script rook runs on a lifecycle event, reading a JSON context on stdin:
{ "event": "pre-tool", "tool": "run_command", "args": "{\"command\":\"...\"}" }args is the tool call's raw arguments (itself a JSON string).
| Script | Event | Match | What it does |
|---|---|---|---|
deny-dangerous.sh |
pre-tool |
run_command |
Exits non-zero to block a command matching a dangerous pattern (rm -rf /, mkfs, a fork bomb, ...). The message goes back to the model as the reason. |
format-on-edit.sh |
post-tool |
write_file, edit_file |
Re-formats the file rook just touched (rvpm fmt). Reads the path from the context with jq; without jq it formats the whole project. |
notify-turn-end.sh |
turn-end |
(all) | Posts a desktop notification when a turn ends, via notify-send, osascript, a PowerShell beep, or the terminal bell. |
Copy the hooks block from settings.json here into a settings.json
at a root rook reads:
.agents/settings.jsonin your project (project-scoped), or~/.agents/settings.json(every session), or- inside a plugin bundle, so installing the plugin ships the hooks.
The example paths (sh examples/hooks/...) assume you run rook from this
repository. Point them at wherever you keep the scripts.
- Only
pre-toolhooks can block; every other event is observe-only, so their exit codes are ignored. - Hook launch failures produce one notice per command and error. They fail
open unless a
pre-toolhook sets"fail_closed": true. matchis a glob on the tool name and applies only to the tool events (pre-tool,post-tool); omit it, or use*, to match every tool.- On Windows the command runs through
cmd, so invoke these.shscripts withsh(from Git Bash), or write.cmdequivalents. - A hook command runs synchronously on the turn's goroutine, so keep it quick; a slow hook slows the turn.