NAME

Claude::Agent::Hook::Registry - Register hook callbacks with the CLI and run them

SYNOPSIS

my $registry = Claude::Agent::Hook::Registry->new(
    hooks => { PreToolUse => [ $matcher, ... ] },
    loop  => $loop,
    query => $query,
);

my $config = $registry->to_initialize_config;
my $future = $registry->run('hook_0', $input, $tool_use_id);

DESCRIPTION

A query builds one registry from its hooks option. The registry gives every callback an id, produces the hooks entry of the SDK initialize request, and runs the callback the CLI names in a hook_callback control request.

ATTRIBUTES

hooks

HashRef of event name to ArrayRef of Claude::Agent::Hook::Matcher.

loop

The IO::Async::Loop, used for timeouts and handed to callbacks.

query

The Claude::Agent::Query, handed to callbacks through the context.

METHODS

new

Takes a flat list of name/value pairs. Unknown names are ignored. Ids are assigned in event name order, then matcher order, then callback order: hook_0, hook_1, and so on.

callback_ids

ArrayRef of every id, in registration order.

to_initialize_config

my $config = $registry->to_initialize_config;

{ Event => [ { matcher => $pattern, hookCallbackIds => [...], timeout => $seconds }, ... ] }. matcher is undef for a matcher with none; timeout is present only when the matcher sets one.

run

my $future = $registry->run($callback_id, $input, $tool_use_id);

Runs one callback with the CLI's hook input and returns a Future of the hook output hashref. An unknown id, a callback that dies, a Future that fails, or a callback that outruns its matcher's timeout (when a loop is set) all fail the Future. A callback returning undef yields an empty hash; a callback returning the 0.13 { decision => ... } shape is translated to the CLI's shape, with a warning the first time.

AUTHOR

LNATION, <email at lnation.org>

LICENSE

This software is Copyright (c) 2026 by LNATION.

This is free software, licensed under The Artistic License 2.0 (GPL Compatible).