Claude-Agent

 view release on metacpan or  search on metacpan

META.json  view on Meta::CPAN

            "Crypt::URandom" : "0.54",
            "File::Which" : "1.27",
            "Future::AsyncAwait" : "0.60",
            "IO::Async" : "0.80",
            "JSON::Lines" : "1.10",
            "Log::Any" : "1.710",
            "Marlin" : "0.007000",
            "Term::Choose" : "1.7",
            "Term::ProgressSpinner" : "1.02",
            "Term::ReadKey" : "2.38",
            "Try::Tiny" : "0.30",
            "Type::Tiny" : "2.0",
            "Types::Common" : "2.0",
            "namespace::clean" : "0.27",
            "perl" : "5.020"
         }
      },
      "test" : {
         "requires" : {
            "Test::Deep" : "1.0",
            "Test::Exception" : "0.43",

META.yml  view on Meta::CPAN

  Crypt::URandom: '0.54'
  File::Which: '1.27'
  Future::AsyncAwait: '0.60'
  IO::Async: '0.80'
  JSON::Lines: '1.10'
  Log::Any: '1.710'
  Marlin: '0.007000'
  Term::Choose: '1.7'
  Term::ProgressSpinner: '1.02'
  Term::ReadKey: '2.38'
  Try::Tiny: '0.30'
  Type::Tiny: '2.0'
  Types::Common: '2.0'
  namespace::clean: '0.27'
  perl: '5.020'
resources:
  repository: https://github.com/lnation/Claude-Agent.git
version: '0.13'
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'

Makefile.PL  view on Meta::CPAN

        'Test::Exception' => '0.43',
        'Test::Deep'      => '1.0',
    },
    PREREQ_PM => {
        'Marlin'                => '0.007000',
        'JSON::Lines'           => '1.10',
        'IO::Async'             => '0.80',
        'Future::AsyncAwait'    => '0.60',
        'Type::Tiny'            => '2.0',
        'Types::Common'         => '2.0',
        'Try::Tiny'             => '0.30',
        'File::Which'           => '1.27',
        'Const::XS'             => '1.03',
        'namespace::clean'      => '0.27',
        'Crypt::URandom'        => '0.54',
        'Log::Any'              => '1.710',
        # CLI utilities (Claude::Agent::CLI)
        'Term::Choose'          => '1.7',
        'Term::ReadKey'         => '2.38',
        'Term::ProgressSpinner' => '1.02',
    },

README  view on Meta::CPAN

    - Valid Anthropic API key or Claude subscription

DEPENDENCIES

    - Marlin (fast Moo-compatible OO)
    - IO::Async
    - Future::AsyncAwait
    - Cpanel::JSON::XS
    - JSON::Lines
    - Types::Common
    - Try::Tiny
    - File::Which

INSTALLATION

To install this module, run the following commands:

    perl Makefile.PL
    make
    make test
    make install

examples/09-error-handling.pl  view on Meta::CPAN

#

use 5.020;
use strict;
use warnings;

use lib 'lib';
use Claude::Agent qw(query);
use Claude::Agent::Options;
use Claude::Agent::Error;
use Try::Tiny;

# Example 1: Handle CLI not found
say "Example 1: Handling CLI errors";
say "-" x 50;

try {
    my $options = Claude::Agent::Options->new(
        allowed_tools   => ['Read'],
        permission_mode => 'bypassPermissions',
    );

lib/Claude/Agent/Error.pm  view on Meta::CPAN

use Marlin
    'message!' => Str;

=head1 NAME

Claude::Agent::Error - Exception classes for Claude Agent SDK

=head1 SYNOPSIS

    use Claude::Agent::Error;
    use Try::Tiny;

    try {
        # ... code that might fail ...
    }
    catch {
        if ($_->isa('Claude::Agent::Error::CLINotFound')) {
            die "Please install Claude CLI first";
        }
    };

lib/Claude/Agent/Hook/Executor.pm  view on Meta::CPAN

package Claude::Agent::Hook::Executor;

use 5.020;
use strict;
use warnings;

use Claude::Agent::Logger '$log';
use Types::Common -types;
use Scalar::Util qw(blessed);
use Try::Tiny;
use Future;

use Claude::Agent::Hook;
use Claude::Agent::Hook::Context;
use Claude::Agent::Hook::Result;

use Marlin
    'hooks'       => sub { {} },      # Event name => arrayref of matchers
    'session_id==.',                  # Read-write, set after init message
    'cwd?',

lib/Claude/Agent/Hook/Matcher.pm  view on Meta::CPAN

package Claude::Agent::Hook::Matcher;

use 5.020;
use strict;
use warnings;

use Claude::Agent::Logger '$log';
use Scalar::Util qw(blessed);
use Try::Tiny;
use Future;
use Types::Common -types;
use Marlin
    'matcher',                    # Regex pattern for tool names (optional)
    'hooks'   => sub { [] },      # ArrayRef of coderefs
    'timeout' => sub { 60 };      # Timeout in seconds

=head1 NAME

Claude::Agent::Hook::Matcher - Hook matcher for Claude Agent SDK

lib/Claude/Agent/Hook/Matcher.pm  view on Meta::CPAN


    my $pattern = $self->matcher;

    # If it's a simple string (no regex metacharacters), do exact match
    # Use quotemeta to reliably detect plain strings vs regex patterns
    if ($pattern eq quotemeta($pattern)) {
        return $tool_name eq $pattern;
    }

    # Otherwise treat as regex with timeout protection against ReDoS
    # Use Try::Tiny with finally to ensure alarm is always cleared
    my $result;
    try {
        # Validate pattern length to mitigate ReDoS
        if (length($pattern) > 1000) {
            die "Pattern too long\n";
        }

        # Detect potentially dangerous ReDoS patterns (works on all platforms)
        # Look for nested quantifiers like (a+)+ or (a*)*
        if ($pattern =~ /\([^)]*[+*][^)]*\)[+*]/ ||

lib/Claude/Agent/MCP/SDKRunner.pm  view on Meta::CPAN


use 5.020;
use strict;
use warnings;

use Claude::Agent::Logger '$log';
use IO::Socket::UNIX;
use IO::Async::Loop;
use IO::Async::Stream;
use JSON::Lines;
use Try::Tiny;

=head1 NAME

Claude::Agent::MCP::SDKRunner - MCP server runner for SDK tools

=head1 DESCRIPTION

This module implements the MCP server protocol and forwards tool calls
to the parent Perl process via a Unix socket. It is spawned as a child
process by the Claude CLI.

lib/Claude/Agent/MCP/SDKServer.pm  view on Meta::CPAN

use strict;
use warnings;

use Claude::Agent::Logger '$log';
use Errno qw(ENOENT);
use IO::Socket::UNIX;
use JSON::Lines;
use File::Temp qw(tempdir);
use File::Spec;
use Cwd qw(abs_path);
use Try::Tiny;

=head1 NAME

Claude::Agent::MCP::SDKServer - Socket-based MCP server for SDK tools

=head1 DESCRIPTION

This module manages the IPC between the Perl SDK and the MCP server runner.
It creates a Unix socket, spawns the runner as a stdio MCP server, and
handles tool call requests from the runner by executing the local handlers.

lib/Claude/Agent/Query.pm  view on Meta::CPAN

                return;
            },
        )
    };

use IO::Async::Loop;
use IO::Async::Process;
use Future;
use Future::AsyncAwait;
use JSON::Lines;
use Try::Tiny;
use File::Which qw(which);
use File::Spec;

use Claude::Agent::Options;
use Claude::Agent::Message;
use Claude::Agent::Error;
use Claude::Agent::MCP::SDKServer;
use Claude::Agent::Hook::Executor;
use Claude::Agent::DryRun qw(create_dry_run_hooks);

t/10-errors.t  view on Meta::CPAN

isa_ok($@, 'Claude::Agent::Error', 'PermissionDenied can be caught as Error');

eval { die $hook_error };
isa_ok($@, 'Claude::Agent::Error', 'HookError can be caught as Error');

# Test throw() class method
eval { Claude::Agent::Error::CLINotFound->throw(message => 'not found') };
isa_ok($@, 'Claude::Agent::Error::CLINotFound', 'throw() creates and dies with error');

# Test using errors in try/catch pattern
use Try::Tiny;

my $caught_type;
try {
    die Claude::Agent::Error::CLINotFound->new(message => 'not found');
}
catch {
    if ($_->isa('Claude::Agent::Error::CLINotFound')) {
        $caught_type = 'cli_not_found';
    }
    elsif ($_->isa('Claude::Agent::Error')) {



( run in 2.504 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )