Chapter 13 — Hooks
Hooks are shell commands that fire on agent lifecycle events. They’re how you plug thClaws into your existing tooling: log every tool call, send a notification when a session ends, block commits until a test passes.
Events
| Event | Fires when | Env vars exposed |
|---|---|---|
pre_tool_use |
Right before a tool runs | THCLAWS_TOOL_NAME, THCLAWS_TOOL_INPUT |
post_tool_use |
After a tool returns successfully | THCLAWS_TOOL_NAME, THCLAWS_TOOL_OUTPUT |
post_tool_use_failure |
After a tool errors | THCLAWS_TOOL_NAME, THCLAWS_TOOL_ERROR |
permission_denied |
User types n on a tool prompt |
THCLAWS_TOOL_NAME |
session_start |
When a session begins | THCLAWS_SESSION_ID, THCLAWS_MODEL |
session_end |
On /quit or window close |
THCLAWS_SESSION_ID, THCLAWS_MODEL |
pre_compact |
Before history compaction | — |
post_compact |
After compaction finishes | — |
Configuring hooks
In .thclaws/settings.json (project) or
~/.config/thclaws/settings.json (user):
{
"hooks": {
"pre_tool_use": "echo \"tool: $THCLAWS_TOOL_NAME\" >> /tmp/thclaws.log",
"post_tool_use": "echo \"done: $THCLAWS_TOOL_NAME\" >> /tmp/thclaws.log",
"session_start": "osascript -e 'display notification \"thClaws started\"'",
"session_end": "osascript -e 'display notification \"thClaws ended\"'"
}
}
Each value is a shell snippet run via /bin/sh -c. Env vars are
available exactly as documented above.
Practical recipes
Log every bash command to a file
{
"hooks": {
"pre_tool_use": "[ \"$THCLAWS_TOOL_NAME\" = Bash ] && echo \"[$(date)] $THCLAWS_TOOL_INPUT\" >> ~/.thclaws-bash.log"
}
}
Desktop notification on turn complete
{
"hooks": {
"session_end": "notify-send 'thClaws' 'Session done'"
}
}
macOS: replace with osascript -e 'display notification "Session done" with title "thClaws"'.
Auto-commit after every successful edit
{
"hooks": {
"post_tool_use": "[ \"$THCLAWS_TOOL_NAME\" = Edit -o \"$THCLAWS_TOOL_NAME\" = Write ] && git add -A && git commit -m 'thclaws: edit' --no-verify"
}
}
(Add --no-verify cautiously — it skips pre-commit hooks.)
Ping a webhook on permission denial
{
"hooks": {
"permission_denied": "curl -s -X POST -H 'Content-Type: application/json' -d \"{\\\"tool\\\": \\\"$THCLAWS_TOOL_NAME\\\"}\" https://hooks.example.com/denied"
}
}
Failure handling
Hooks that exit with a non-zero status print a warning to stderr but
don’t stop the agent. They run in the same cwd as thClaws, so file
paths in the script are relative to the sandbox root. Long-running
hooks block the turn — keep them fast or background them
(command &).
Debugging
thclaws --cli --verbose
Verbose mode prints each hook invocation before running it.
What hooks aren’t
Hooks can’t mutate the tool call — they’re observers. To block a
tool, use the permissions.deny list (Chapter 5). To rewrite a tool
input, the model has to do it.