Skip to contents

Tool hook registry

Tool hook registry

Details

Manages lifecycle hooks. Hooks are registered per event type and run in registration order.

PreToolUse callback: function(tool_name, tool_input)

Returns list with action:

  • "allow" – proceed normally

  • "deny" – block execution (add optional message)

  • "updated_input" – replace input with input field

PostToolUse callback: function(tool_name, tool_input, tool_output)

Returns list with action:

  • "allow" – pass output unchanged

  • "updated_output" – replace output with output field

PostToolUseFailure callback: function(tool_name, tool_input, error_message)

Return value ignored (informational only).

PermissionDenied callback: function(tool_name, tool_input, mode)

Return value ignored (informational only).

PermissionRequest callback: function(tool_name, tool_input, mode)

Returns list with action:

  • "allow" – grant permission

  • "deny" – reject

  • NULL / "ask" – fall through to default ask_fn

UserPromptSubmit callback: function(message)

Aligns with Claude Code's UserPromptSubmit contract. Returns a list with action:

  • "allow" (or NULL) – proceed unchanged

  • "block" – reject this turn; the user prompt never reaches the model (optional message becomes the response shown instead)

  • "add_context" – proceed, but APPEND additional_context to what is sent to the model (never rewrites the user's original text – matching CC, which only supports block + additionalContext, not redaction of user input)

AssistantMessage callback: function(message)

Return value ignored (informational only).

Methods


Method new()

Create a new registry.

Usage


Method register()

Register a hook for an event.

Usage

HookRegistry$register(event, fn, tool_pattern = NULL, timeout_ms = 2000L)

Arguments

event

Character. One of HookEvent values.

fn

Function. Hook callback.

tool_pattern

Character or NULL. Glob filter for tool name (only applies to tool-related events).

timeout_ms

Integer. Max ms before warning (default 2000).


Method register_pre()

Register a PreToolUse hook (legacy shorthand).

Usage

HookRegistry$register_pre(fn, tool_pattern = NULL, timeout_ms = 2000L)


Method register_post()

Register a PostToolUse hook (legacy shorthand).

Usage

HookRegistry$register_post(fn, tool_pattern = NULL, timeout_ms = 2000L)


Method run_pre()

Fire PreToolUse hooks.

Usage

HookRegistry$run_pre(tool_name, tool_input)


Method run_post()

Fire PostToolUse hooks.

Usage

HookRegistry$run_post(tool_name, tool_input, tool_output)


Method run_failure()

Fire PostToolUseFailure hooks (informational).

Usage

HookRegistry$run_failure(tool_name, tool_input, error_message)


Method run_permission_denied()

Fire PermissionDenied hooks (informational).

Usage

HookRegistry$run_permission_denied(tool_name, tool_input, mode)


Method run_permission_request()

Fire PermissionRequest hooks. Returns "allow", "deny", or NULL (fall through to ask_fn).

Usage

HookRegistry$run_permission_request(tool_name, tool_input, mode)


Method run_user_prompt_submit()

Fire UserPromptSubmit hooks (before the prompt reaches the model). Aligns with Claude Code's UserPromptSubmit: a hook may block the turn or append additional_context, but NEVER rewrites the user's original text. Returns a list: list(action = "block", message = ...) if any hook blocked, else list(action = "allow", additional_context = <appended text or NULL>).

Usage

HookRegistry$run_user_prompt_submit(message)


Method run_user_message()

Deprecated alias for run_user_prompt_submit() (kiro round-2 #14). The event was renamed to align with Claude Code's public UserPromptSubmit; this shim forwards to the new method for one release cycle so existing callers do not break. Prefer run_user_prompt_submit().

Usage

HookRegistry$run_user_message(message)


Method run_assistant_message()

Fire AssistantMessage hooks (informational).

Usage

HookRegistry$run_assistant_message(message)


Method run_session_start()

Fire SessionStart hooks at the top of a session/turn. Callback: function(context). Return value ignored.

Usage

HookRegistry$run_session_start(context = list())


Method run_stop()

Fire Stop hooks when the agent loop terminates. Callback: function(stop_reason, context). Return value ignored.

Usage

HookRegistry$run_stop(stop_reason = "completed", context = list())


Method run_pre_compact()

Fire PreCompact hooks before context compaction. Callback: function(level, context). Return value ignored.

Usage

HookRegistry$run_pre_compact(level = "unknown", context = list())


Method run_subagent_start()

Fire SubagentStart hooks when a sub-agent is launched. Callback: function(description, context). Return value ignored.

Usage

HookRegistry$run_subagent_start(description = "", context = list())


Method run_subagent_stop()

Fire SubagentStop hooks when a sub-agent completes. Callback: function(description, result, context). Return ignored.

Usage

HookRegistry$run_subagent_stop(
  description = "",
  result = NULL,
  context = list()
)


Method run_session_end()

Fire SessionEnd hooks when the agent loop terminates. Callback: function(reason, context). Return value ignored. reason mirrors CC's exit reasons where they map (e.g. "completed", "max_turns", "budget_exceeded", "error").

Usage

HookRegistry$run_session_end(reason = "completed", context = list())


Method run_post_compact()

Fire PostCompact hooks after context compaction completes. Callback: function(trigger, compact_summary, context). Return ignored.

Usage

HookRegistry$run_post_compact(
  trigger = "auto",
  compact_summary = "",
  context = list()
)


Method run_stop_failure()

Fire StopFailure hooks when the loop ends on an error. Callback: function(error, context). Return value ignored.

Usage

HookRegistry$run_stop_failure(error = "", context = list())


Method run_notification()

Fire Notification hooks for user-facing notifications. Callback: function(message, notification_type, context). Return ignored.

Usage

HookRegistry$run_notification(
  message = "",
  notification_type = "info",
  context = list()
)


Method run_task_created()

Fire TaskCreated hooks when a task is created. Callback: function(task_id, task_subject, context). Return ignored.

Usage

HookRegistry$run_task_created(
  task_id = "",
  task_subject = "",
  context = list()
)


Method run_task_completed()

Fire TaskCompleted hooks when a task becomes completed. Callback: function(task_id, task_subject, context). Return ignored.

Usage

HookRegistry$run_task_completed(
  task_id = "",
  task_subject = "",
  context = list()
)


Method run_worktree_create()

Fire WorktreeCreate hooks when a sub-agent worktree is made. Callback: function(name, context). Return value ignored.

Usage

HookRegistry$run_worktree_create(name = "", context = list())


Method run_worktree_remove()

Fire WorktreeRemove hooks when a sub-agent worktree is removed. Callback: function(worktree_path, context). Return value ignored.

Usage

HookRegistry$run_worktree_remove(worktree_path = "", context = list())


Method run_instructions_loaded()

Fire InstructionsLoaded hooks when a CLAUDE.md file loads. Callback: function(file_path, memory_type, load_reason, context). Return ignored. NOTE: memory_type is a best-effort approximation (User/Project by path prefix; no Managed concept) and load_reason is always "session_start" – codeagent has no nested/glob/include/compact load paths, so these fields are NOT field-for-field equal to CC.

Usage

HookRegistry$run_instructions_loaded(
  file_path = "",
  memory_type = "Project",
  load_reason = "session_start",
  context = list()
)


Method run_file_changed()

Fire FileChanged hooks (Shiny-only; watcher-driven). Callback: function(file_path, event, context) where event is one of "change"/"add"/"unlink". Return value ignored. Not fired on the CLI – the synchronous CLI loop cannot pump the later queue watcher needs.

Usage

HookRegistry$run_file_changed(
  file_path = "",
  event = "change",
  context = list()
)


Method run_config_change()

Fire ConfigChange hooks (Shiny-only; watcher-driven). Callback: function(source, file_path, context). Return value ignored. Not fired on the CLI (see the run_file_changed() method note).

Usage

HookRegistry$run_config_change(
  source = "user_settings",
  file_path = "",
  context = list()
)


Method clear()

Remove all registered hooks.

Usage

HookRegistry$clear()


Method count()

Count total registered hooks across all events.

Usage

HookRegistry$count()


Method has_hooks()

TRUE if at least one hook is registered for event.

Usage

HookRegistry$has_hooks(event)

Arguments

event

Character. One of HookEvent values.