Skip to content

Hook Events Reference

Chimera’s hook system lets external code react to lifecycle events that fire during an agent run. Events are dispatched by HookEmitter, executed by HookExecutor, and matched against HookMatcher records loaded from .claude/settings.json (or ~/.claude/settings.json).

This page is the full event reference for every wired event. The 27 events are organised below by phase: tool, session, sub-agent, compaction, permission, task, CLI, and filesystem.

EventTriggerWired inPayload
PreToolUseBefore each tool dispatch. May mutate input or deny.chimera/core/tool_executor.py (3 executors)tool_name, tool_input
PostToolUseAfter a tool returns successfully.chimera/core/tool_executor.py (3 executors)tool_name, tool_input, tool_output
PostToolUseFailureAfter a tool raises or returns success=False.chimera/core/tool_executor.py (3 executors)tool_name, tool_input, tool_error
EventTriggerWired inPayload
UserPromptSubmitFirst loop step when context carries a user message.chimera/core/loop.py (sync + async); chimera/commands/processor.py for /-commandsuser_prompt
SessionStartFirst instruction of iter_steps / async_iter_steps.chimera/core/loop.py; chimera/core/agent_loop.py
SessionEndLast instruction on every termination path of the loop.chimera/core/loop.py; chimera/core/agent_loop.py
StopLoop exited cleanly (no further tool calls).chimera/core/loop.py; chimera/core/agent_loop.py
StopFailureLoop terminated abnormally (cost limit, max steps, loop break, cancellation).chimera/core/loop.py; chimera/core/agent_loop.pytool_error
NotificationFires alongside Stop carrying the agent’s final text.chimera/core/loop.py; chimera/core/agent_loop.pytool_output
EventTriggerWired inPayload
SubagentStartJust before a sub-agent’s first turn.chimera/core/agent_spawner.pytool_name (subagent name)
SubagentStopAfter a sub-agent finishes.chimera/core/agent_spawner.pytool_name, tool_output
TeammateIdleWhen a sub-agent goes idle awaiting input.chimera/core/agent_spawner.pytool_name
EventTriggerWired inPayload
PreCompactBefore context compaction runs.chimera/core/compaction_integration.py
PostCompactAfter context compaction completes.chimera/core/compaction_integration.py
EventTriggerWired inPayload
PermissionRequestWhen the permission checker asks for a decision.chimera/permissions/checker.pytool_name, tool_input
PermissionDeniedWhen the permission checker denies a tool.chimera/permissions/checker.pytool_name, tool_input
ElicitationBefore an interactive permission prompt.chimera/permissions/prompt_handler.py
ElicitationResultAfter an interactive permission prompt resolves.chimera/permissions/prompt_handler.py
EventTriggerWired inPayload
TaskCreatedWhen the task manager creates a new task.chimera/core/task_manager.pytool_name (task subject)
TaskCompletedWhen the task manager marks a task done.chimera/core/task_manager.pytool_name (task subject)
EventTriggerWired inPayload
SetupOnce at CLI startup, after settings are loaded.chimera/cli/main.pytool_name (subcommand)
ConfigChangeWhen ~/.claude/settings.json is written through the mink CLI.chimera/mink/settings.py
EventTriggerWired inPayload
WorktreeCreateAfter EnterWorktree succeeds.chimera/tools/worktree_tool.pytool_input (path, branch)
WorktreeRemoveAfter ExitWorktree succeeds (or fails).chimera/tools/worktree_tool.pytool_input
EventTriggerWired inPayload
InstructionsLoadedWhen CLAUDE.md / AGENTS.md files are picked up.chimera/context/agent_memory.py; chimera/otter/rules.pymessages (loaded files)
CwdChangedWhen the file watcher detects a working-directory change.chimera/hooks/file_watcher.py
FileChangedWhen the file watcher detects a tracked-file edit.chimera/hooks/file_watcher.pytool_input (path)

Hooks are declared per-project in .claude/settings.json under the hooks key. Each event maps to a list of matchers; each matcher carries a list of command, prompt, or function hooks.

{
"hooks": {
"PreToolUse": [
{
"matcher": "tool_name == 'bash'",
"hooks": [
{"type": "command", "command": "scripts/audit-bash.sh"}
]
}
]
}
}
{
"hooks": {
"Stop": [
{"hooks": [{"type": "command", "command": "scripts/notify-done.sh"}]}
]
}
}
{
"hooks": {
"PostToolUse": [
{
"matcher": "tool_name == 'write_file' and 'production' in tool_input.get('path', '')",
"hooks": [{"type": "command", "command": "scripts/audit-prod-write.sh"}]
}
]
}
}

The matcher string is evaluated against a small Python expression context with tool_name, tool_input, tool_output, tool_error, user_prompt, and messages bound from the HookInput.

The mink CLI parses these files in order and merges them into the HookEmitter carried on LoopConfig.hook_emitter:

  1. ~/.claude/settings.json
  2. <cwd>/.claude/settings.json
  3. <cwd>/.claude/settings.local.json
  4. <cwd>/.chimera/settings.json

Later sources override earlier ones key-by-key.

  1. Add the value to HookEvent in chimera/hooks/events.py.
  2. Wire an emitter.emit(...) call (or emit_sync(...) for sync code paths) at the canonical trigger point. For loop-lifecycle events, call _fire_loop_hook / _fire_loop_hook_async from chimera/core/loop.py so failures never break the loop.
  3. Add a row to one of the tables above documenting the trigger and payload.
  4. Add a recording-emitter test under tests/events/test_hook_events.py that fires a minimal agent flow and asserts the new event appears.
  • Chimera installed: pip install chimera-run
  • A .claude/settings.json (or one of the other discovery paths) containing your hooks map
  • For command-type hooks: an executable on the path or a script with the right shebang
  • Permission modes — the events that fire on every approval decision.
  • File undoFileChanged is what feeds the otter /undo snapshot store.