NAME

Langertha::Raider::Hooks::Result - Internal value of one hook event: the merged answer of its hooks and a report per run

VERSION

version 0.504

SYNOPSIS

# Internal to Langertha-Raider -- no API promise.
my $r = await $hooks->run_f( PreToolUse => { tool_name => 'bash', tool_input => { command => 'ls' } } );
return deny( $r->reason ) if ( $r->decision // '' ) eq 'deny';
$args = $r->updated_input if $r->updated_input;
journal( 'hook.ran', %$_ ) for @{ $r->runs };

DESCRIPTION

Internal module. Its interface may change without notice.

What "run_f" in Langertha::Raider::Hooks answers for one event: every hook that ran is one entry of "runs", and their outputs are merged into one answer. Which fields an event uses is the caller's business; the runner only fills them the way Claude Code reads them:

event

The event name, e.g. PreToolUse.

runs

One hash ref per hook the event selected, in configuration order, including the ones skipped (duplicate, native briefing, unsupported type) and async hooks still running:

{
  event       => 'PreToolUse',
  source      => '.claude/settings.json' | 'plugin:loadguard',
  plugin      => 'loadguard' | undef,
  matcher     => 'Bash' | undef,
  command     => '${CLAUDE_PLUGIN_ROOT}/hooks/loadguard',   # as configured
  args        => [ '${CLAUDE_PLUGIN_DATA}' ] | undef,       # as configured
  argv        => [ '/abs/hooks/loadguard', '/abs/data' ],   # what was started
  form        => 'exec' | 'shell',
  async       => 0 | 1,
  timeout     => 5,                                         # seconds; undef for async
  outcome     => 'success' | 'block' | 'error' | 'timeout' | 'skipped' | 'running' | 'cancelled',
  message     => undef | 'why it is an error or was skipped',
  exit        => 0, signal => 0,                            # undef when not started
  duration_ms => 12,
  stdout      => '...', stderr => '...',
  output      => 'empty' | 'text' | 'json' | 'invalid',
  json        => { ... } | undef,                           # the decoded stdout
}

errors

Non-blocking errors, one line each in Claude Code's words (PreToolUse:Bash hook error: [cmd]: Failed with non-blocking status code: ...), plus configuration problems (an invalid matcher). The action goes ahead.

decision

PreToolUse only: deny, ask, allow or undef (no hook decided). Exit code 2 is deny.

reasons

The reasons that go with "decision" (permissionDecisionReason, the stderr of an exit 2) or with "blocked" (reason, the stderr of an exit 2), in configuration order.

deny_messages

PreToolUse only, with a "decision" of deny: what the model is told, one entry per denying hook, in Claude Code's words (ADR 0022). A hook that blocked by exit code 2 is PreToolUse:Tool hook error: STDERR, a hook that gave a reason in JSON hands the reason through as it stands, a denial without a reason is PreToolUse:Tool hook blocked the tool call.

blocked

True when a hook blocked an event that can be blocked (decision: "block" or exit code 2): see "DESCRIPTION" for what it means per event. PreToolUse uses "decision" instead.

additional_context

Text for the model: every hookSpecificOutput.additionalContext, and the plain stdout of UserPromptSubmit and SessionStart hooks, in configuration order.

system_messages

Every systemMessage, for the user.

stopped

True when a hook answered continue: false; then nothing else counts.

stop_reason

The first stopReason of a stopping hook, else undef.

updated_input

PreToolUse only: the tool arguments a hook replaced, in raider form (translated back by "raider_input" in Langertha::Raider::ToolNames), or undef. Never set when "decision" is deny.

reason

my $why = $r->reason;   # L</reasons> joined with newlines, or undef

deny_message

my $text = $r->deny_message;   # L</deny_messages> joined with newlines, or undef

context

my $text = $r->context;   # L</additional_context> joined with blank lines, or undef

ran

The number of hooks that were started (not skipped).

SEE ALSO

SUPPORT

Issues

Please report bugs and feature requests at https://github.com/Getty/langertha-raider/issues.

IRC

Join #langertha on irc.perl.org or message Getty directly.

CONTRIBUTING

Contributions are welcome! Please fork the repository and submit a pull request.

AUTHOR

Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Torsten Raudssus.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

https://raudssus.de/