class HookConfig
Bases:BaseModel
Configuration for all hooks.
Hooks can be configured either by loading from .openhands/hooks.json or
by directly instantiating with typed fields:
Direct instantiation with typed fields()
config = HookConfig( pre_tool_use=[ : HookMatcher( : matcher=”terminal”, hooks=[HookDefinition(command=”block_dangerous.sh”)] ) ] )Load from JSON file:
config = HookConfig.load(“.openhands/hooks.json”)Properties
model_config: = (configuration object) Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].post_tool_use: list[HookMatcher]pre_tool_use: list[HookMatcher]session_end: list[HookMatcher]session_start: list[HookMatcher]stop: list[HookMatcher]user_prompt_submit: list[HookMatcher]
Methods
classmethod from_dict()
Create HookConfig from a dictionary. Supports both legacy format with “hooks” wrapper and direct format: : # Legacy format: (JSON configuration object)Direct format:
(JSON configuration object)get_hooks_for_event()
Get all hooks that should run for an event.has_hooks_for_event()
Check if there are any hooks configured for an event type.is_empty()
Check if this config has no hooks configured.classmethod load()
Load config from path or search .openhands/hooks.json locations.- Parameters:
path– Explicit path to hooks.json file. If provided, working_dir is ignored.working_dir– Project directory for discovering .openhands/hooks.json. Falls back to cwd if not provided.
classmethod merge()
Merge multiple hook configs by concatenating handlers per event type. Each hook config may have multiple event types (pre_tool_use, post_tool_use, etc.). This method combines all matchers from all configs for each event type.- Parameters:
configs– List of HookConfig objects to merge. - Returns: A merged HookConfig with all matchers concatenated, or None if no configs or if the result is empty.
save()
Save hook configuration to a JSON file using snake_case field names.class HookDecision
Bases:str, Enum
Decisions a hook can make about an operation.
Methods
ALLOW = ‘allow’
DENY = ‘deny’
class HookDefinition
Bases:BaseModel
A single hook definition.
Properties
async_: boolcommand: strmodel_config: = (configuration object) Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].timeout: inttype: HookType
class HookEvent
Bases:BaseModel
Data passed to hook scripts via stdin as JSON.
Properties
event_type: HookEventTypemessage: str | Nonemetadata: dict[str, Any]model_config: = (configuration object) Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].session_id: str | Nonetool_input: dict[str, Any] | Nonetool_name: str | Nonetool_response: dict[str, Any] | Noneworking_dir: str | None
class HookEventProcessor
Bases:object
Processes events and runs hooks at appropriate points.
Call set_conversation_state() after creating Conversation for blocking to work.
HookExecutionEvent is emitted for each hook execution when emit_hook_events=True,
providing full observability into hook execution for clients.
Methods
init()
is_action_blocked()
Check if an action was blocked by a hook.is_message_blocked()
Check if a message was blocked by a hook.on_event()
Process an event and run appropriate hooks.run_session_end()
Run SessionEnd hooks. Call before conversation is closed.run_session_start()
Run SessionStart hooks. Call after conversation is created.run_stop()
Run Stop hooks. Returns (should_stop, feedback).set_conversation_state()
Set conversation state for blocking support.class HookEventType
Bases:str, Enum
Types of hook events that can trigger hooks.
Methods
POST_TOOL_USE = ‘PostToolUse’
PRE_TOOL_USE = ‘PreToolUse’
SESSION_END = ‘SessionEnd’
SESSION_START = ‘SessionStart’
STOP = ‘Stop’
USER_PROMPT_SUBMIT = ‘UserPromptSubmit’
class HookExecutor
Bases:object
Executes hook commands with JSON I/O.
Methods
init()
execute()
Execute a single hook.execute_all()
Execute multiple hooks in order, optionally stopping on block.class HookManager
Bases:object
Manages hook execution for a conversation.
Methods
init()
cleanup_async_processes()
Cleanup all background hook processes.get_blocking_reason()
Get the reason for blocking from hook results.has_hooks()
Check if there are hooks configured for an event type.run_post_tool_use()
Run PostToolUse hooks after a tool completes.run_pre_tool_use()
Run PreToolUse hooks. Returns (should_continue, results).run_session_end()
Run SessionEnd hooks when a conversation ends.run_session_start()
Run SessionStart hooks when a conversation begins.run_stop()
Run Stop hooks. Returns (should_stop, results).run_user_prompt_submit()
Run UserPromptSubmit hooks.class HookMatcher
Bases:BaseModel
Matches events to hooks based on patterns.
Supports exact match, wildcard (*), and regex (auto-detected or /pattern/).
Properties
hooks: list[HookDefinition]matcher: str
Methods
matches()
Check if this matcher matches the given tool name.model_config = (configuration object)
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].model_post_init()
This function is meant to behave like a BaseModel method to initialise private attributes. It takes context as an argument since that’s what pydantic-core passes when calling it.- Parameters:
self– The BaseModel instance.context– The context.
class HookResult
Bases:BaseModel
Result from executing a hook.
Exit code 0 = success, exit code 2 = block operation.
Properties
additional_context: str | Noneasync_started: boolblocked: booldecision: HookDecision | Noneerror: str | Noneexit_code: intreason: str | Noneshould_continue: bool Whether the operation should continue after this hook.stderr: strstdout: strsuccess: bool
Methods
model_config = (configuration object)
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].class HookType
Bases:str, Enum
Types of hooks that can be executed.

