Claude-Agent

 view release on metacpan or  search on metacpan

examples/03-hooks.pl  view on Meta::CPAN

#!/usr/bin/env perl
#
# Perl Hooks Example
#
# This example demonstrates how to use Perl hook callbacks
# to intercept and control tool execution.
#

use 5.020;
use strict;
use warnings;

use lib 'lib';
use Claude::Agent qw(query);
use Claude::Agent::Options;
use Claude::Agent::Hook::Matcher;
use Claude::Agent::Hook::Result;

# Define PreToolUse hooks that run BEFORE a tool executes
my $pre_tool_hooks = [
    # Hook for all tools - log every tool call
    Claude::Agent::Hook::Matcher->new(
        hooks => [sub {
            my ($input, $tool_use_id, $context) = @_;
            my $tool_name = $input->{tool_name};
            say "[LOG] Tool called: $tool_name";
            return Claude::Agent::Hook::Result->proceed();
        }],
    ),

    # Hook for Glob tool - modify the pattern
    Claude::Agent::Hook::Matcher->new(
        matcher => 'Glob',
        hooks   => [sub {
            my ($input, $tool_use_id, $context) = @_;
            my $pattern = $input->{tool_input}{pattern} // '';
            say "[HOOK] Glob pattern requested: $pattern";

            # Example: could modify the pattern here
            # return Claude::Agent::Hook::Result->allow(
            #     updated_input => { pattern => '*.pm' },
            #     reason => 'Modified pattern',
            # );

            return Claude::Agent::Hook::Result->proceed();
        }],
    ),

    # Hook for Read tool - block reading certain files
    Claude::Agent::Hook::Matcher->new(
        matcher => 'Read',
        hooks   => [sub {
            my ($input, $tool_use_id, $context) = @_;
            my $file_path = $input->{tool_input}{file_path} // '';

            # Block reading .env files (security example)
            if ($file_path =~ /\.env$/i) {
                say "[HOOK] BLOCKED: Cannot read .env files!";
                return Claude::Agent::Hook::Result->deny(
                    reason => 'Reading .env files is not allowed',
                );
            }

            say "[HOOK] Allowing read: $file_path";
            return Claude::Agent::Hook::Result->proceed();



( run in 1.650 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )