Acme-Claude-Shell
view release on metacpan or search on metacpan
lib/Acme/Claude/Shell/Hooks.pm view on Meta::CPAN
hooks => [sub {
my ($input, $tool_use_id, $context) = @_;
# Stop the execution spinner
if ($session->_spinner) {
stop_spinner($session->_spinner);
$session->_spinner(undef);
}
# Track tool usage
$session->{_tool_count}++;
return Claude::Agent::Hook::Result->proceed();
}],
),
],
# PostToolUseFailure: Handle tool failures gracefully
PostToolUseFailure => [
Claude::Agent::Hook::Matcher->new(
matcher => $any_shell_tool,
hooks => [sub {
my ($input, $tool_use_id, $context) = @_;
my $tool_name = $input->{tool_name} // 'unknown';
my $error = $input->{error} // 'Unknown error';
# Extract short tool name
my $short_name = $tool_name;
$short_name =~ s/^mcp__shell-tools__//;
# Track error count
$session->{_tool_errors}++;
# Show error to user
if ($session->colorful) {
status('error', "Tool '$short_name' failed: $error");
}
else {
print "[ERROR] Tool '$short_name' failed: $error\n";
}
return Claude::Agent::Hook::Result->proceed();
}],
),
],
# Stop: Show session statistics when the agent stops
Stop => [
Claude::Agent::Hook::Matcher->new(
matcher => '.*', # Match any stop reason
hooks => [sub {
my ($input, $tool_use_id, $context) = @_;
my $duration = time() - ($session->{_session_start} // time());
my $tool_count = $session->{_tool_count} // 0;
my $tool_errors = $session->{_tool_errors} // 0;
my $history_count = scalar(@{$session->_history // []});
if ($session->colorful) {
print "\n";
print colored(['cyan'], "â" x 40) . "\n";
status('info', "Session Statistics");
printf " Duration: %.1f seconds\n", $duration;
printf " Tools used: %d\n", $tool_count;
printf " Tool errors: %d\n", $tool_errors if $tool_errors > 0;
printf " Commands in history: %d\n", $history_count;
print colored(['cyan'], "â" x 40) . "\n";
}
else {
print "\n--- Session Statistics ---\n";
printf "Duration: %.1f seconds\n", $duration;
printf "Tools used: %d\n", $tool_count;
printf "Tool errors: %d\n", $tool_errors if $tool_errors > 0;
printf "Commands in history: %d\n", $history_count;
print "--------------------------\n";
}
return Claude::Agent::Hook::Result->proceed();
}],
),
],
# Notification: Log important events
Notification => [
Claude::Agent::Hook::Matcher->new(
matcher => '.*', # Match all notifications
hooks => [sub {
my ($input, $tool_use_id, $context) = @_;
my $type = $input->{notification_type} // 'unknown';
my $data = $input->{data} // {};
# Log certain notification types if verbose mode is on
if ($session->{verbose}) {
if ($session->colorful) {
status('info', "Notification: $type");
}
else {
print "[Notification] $type\n";
}
}
return Claude::Agent::Hook::Result->proceed();
}],
),
],
};
}
=head1 AUTHOR
LNATION, C<< <email at lnation.org> >>
=head1 LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by LNATION.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)
=cut
1;
( run in 0.788 second using v1.01-cache-2.11-cpan-39bf76dae61 )