Class: RubynCode::Hooks::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/rubyn_code/hooks/runner.rb

Overview

Executes registered hooks for a given event in priority order.

Hook execution is defensive: exceptions raised by individual hooks are caught and logged rather than allowed to crash the agent. Special semantics apply to :pre_tool_use (deny gating) and :post_tool_use (output transformation).

The runner can also fan out to an external hook dispatcher (see ExternalDispatcher) which spawns Claude Code-style hook commands configured in settings.json. External hooks participate in the same deny/block decisions as in-process hooks.

Instance Method Summary collapse

Constructor Details

#initialize(registry: Registry.new, external_dispatcher: nil) ⇒ Runner

Returns a new instance of Runner.

Parameters:

  • registry (Hooks::Registry) (defaults to: Registry.new)

    the hook registry to draw from

  • external_dispatcher (Hooks::ExternalDispatcher, nil) (defaults to: nil)

    optional dispatcher for Claude Code-style external hook commands



20
21
22
23
# File 'lib/rubyn_code/hooks/runner.rb', line 20

def initialize(registry: Registry.new, external_dispatcher: nil)
  @registry = registry
  @external_dispatcher = external_dispatcher
end

Instance Method Details

#fire(event, **context) ⇒ Hash, ...

Fires all hooks for the given event with the supplied context.

Parameters:

  • event (Symbol)

    the event type

  • context (Hash)

    keyword arguments passed to each hook

Returns:

  • (Hash, Object, nil)

    depends on event semantics:

    • :pre_tool_use => { deny: true, reason: “…” } if any hook denies, else nil

    • :post_tool_use => the (possibly transformed) output

    • all others => nil



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/rubyn_code/hooks/runner.rb', line 33

def fire(event, **context)
  hooks = @registry.hooks_for(event)
  external_response = fire_external(event, **context)

  case event
  when :pre_tool_use
    merge_pre_tool_use(fire_pre_tool_use(hooks, context), external_response)
  when :post_tool_use
    # External hooks contribute additionalContext (read by the LLM
    # caller) but do not transform tool output — that's a job for
    # in-process hooks only.
    fire_post_tool_use(hooks, context)
  when :stop
    merge_stop(fire_stop(hooks, context), external_response)
  else
    fire_generic(hooks, event, context)
    external_response&.additional_context
  end
end