Acme-Claude-Shell

 view release on metacpan or  search on metacpan

lib/Acme/Claude/Shell.pm  view on Meta::CPAN

our $VERSION = '0.03';

=head1 NAME

Acme::Claude::Shell - AI-powered interactive shell using Claude Agent SDK

=head1 VERSION

Version 0.03

=head1 SYNOPSIS

    use Acme::Claude::Shell qw(shell run);

    # Interactive session mode (uses session() for multi-turn context)
    shell();

    # Single-shot query mode (uses query())
    my $result = run("find all large log files");

    # With options
    shell(
        dry_run   => 1,      # Preview mode - show commands without executing
        safe_mode => 0,      # Disable dangerous command warnings
        colorful  => 1,      # Force colors (default: auto-detect)
    );

=head1 DESCRIPTION

Acme::Claude::Shell is an AI-enhanced interactive shell that showcases
all Claude::Agent SDK features:

=over 4

=item * C<query()> for single-shot commands

=item * C<session()> for multi-turn conversations with context

=item * SDK MCP tools for shell operations

=item * Hooks for safety (confirm destructive commands)

=item * Dry-run mode to preview

=item * Async with IO::Async

=item * CLI utilities (spinners, colored output, menus)

=back

Describe what you want in natural language, and Claude figures out the
shell commands, explains them, and executes them (with your approval).

=head1 EXPORTS

=head2 shell

    shell(%options);

Start an interactive REPL session. Claude remembers context from previous
commands, so you can say things like "now compress those files".

Options:

    dry_run     - Preview mode, don't execute commands
    safe_mode   - Confirm dangerous commands (default: 1)
    working_dir - Starting directory (default: current)
    colorful    - Force colors on/off (default: auto-detect)

=head2 run

    my $result = run($prompt, %options);

Execute a single command and return the result. Does not maintain
session context between calls.

=cut

use Acme::Claude::Shell::Session;
use Acme::Claude::Shell::Query;
use IO::Async::Loop;

sub shell {
    my (%args) = @_;

    my $loop = $args{loop} // IO::Async::Loop->new;

    my $session = Acme::Claude::Shell::Session->new(
        loop        => $loop,
        dry_run     => $args{dry_run} // 0,
        safe_mode   => $args{safe_mode} // 1,
        working_dir => $args{working_dir} // '.',
        colorful    => $args{colorful} // _detect_color(),
        ($args{model} ? (model => $args{model}) : ()),
    );

    return $session->run->get;
}

sub run {
    my ($prompt, %args) = @_;

    my $loop = $args{loop} // IO::Async::Loop->new;

    my $query = Acme::Claude::Shell::Query->new(
        loop        => $loop,
        dry_run     => $args{dry_run} // 0,
        safe_mode   => $args{safe_mode} // 1,
        working_dir => $args{working_dir} // '.',
        colorful    => $args{colorful} // _detect_color(),
        ($args{model} ? (model => $args{model}) : ()),
    );

    return $query->run($prompt)->get;
}

sub _detect_color {
    return -t STDOUT ? 1 : 0;
}

=head1 EXAMPLE SESSION



( run in 0.687 second using v1.01-cache-2.11-cpan-b85c58fdc1d )