Acme-Claude-Shell

 view release on metacpan or  search on metacpan

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

    '_client==.',
    '_history==.'  => sub { [] },
    '_spinner==.',
    '_pending_approval==.';  # Future for tool approval (set by hooks, awaited by tool handler)

use Claude::Agent qw(session create_sdk_mcp_server);
use Claude::Agent::Options;
use Claude::Agent::CLI qw(
    start_spinner stop_spinner
    header divider status choose_from
);
use Acme::Claude::Shell::Tools qw(shell_tools);
use Acme::Claude::Shell::Hooks qw(safety_hooks);
use Future::AsyncAwait;
use Term::ReadLine;
use Term::ANSIColor qw(colored);
use File::Spec;

# History file location
my $HISTORY_FILE = File::Spec->catfile($ENV{HOME} // '.', '.acme_claude_shell_history');
my $MAX_HISTORY  = 1000;  # Maximum lines to keep

# Fun spinner styles with matching colors
my @SPINNERS = (
    { spinner => 'moon',          spinner_color => 'yellow' },
    { spinner => 'earth',         spinner_color => 'cyan' },
    { spinner => 'clock',         spinner_color => 'blue' },
    { spinner => 'dots',          spinner_color => 'magenta' },
    { spinner => 'material',      spinner_color => 'green' },
    { spinner => 'circle_half',   spinner_color => 'cyan' },
    { spinner => 'color_circles', spinner_color => 'white' },
);

sub _random_spinner {
    return %{ $SPINNERS[rand @SPINNERS] };
}

=head1 NAME

Acme::Claude::Shell::Session - Multi-turn session for Acme::Claude::Shell

=head1 SYNOPSIS

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

    my $loop = IO::Async::Loop->new;

    my $session = Acme::Claude::Shell::Session->new(
        loop      => $loop,
        dry_run   => 0,
        safe_mode => 1,
    );

    $session->run->get;

=head1 DESCRIPTION

Runs an interactive REPL using Claude's session() function for multi-turn
conversations. Claude remembers context from previous commands, so you can
say things like "now compress those files" after a find command.

Uses Claude::Agent SDK features:

=over 4

=item * C<session()> - Multi-turn conversation with context

=item * SDK MCP tools - execute_command, read_file, list_directory, search_files, get_system_info, get_working_directory

=item * Hooks - PreToolUse (audit), PostToolUse (stats), PostToolUseFailure (errors), Stop (statistics), Notification (logging)

=item * CLI utilities - Spinners, menus, colored output

=back

=head2 Attributes

=over 4

=item * C<loop> (required) - IO::Async::Loop instance

=item * C<dry_run> - Preview mode, don't execute commands (default: 0)

=item * C<safe_mode> - Confirm dangerous commands (default: 1)

=item * C<working_dir> - Starting directory (default: '.')

=item * C<colorful> - Use colored output (default: 1)

=item * C<model> - Claude model to use (optional)

=back

=head2 Built-in Commands

=over 4

=item * C<help> - Show help message

=item * C<history> - Select and re-run previous commands

=item * C<clear> - Clear the screen

=item * C<exit> / C<quit> - Exit the shell

=back

=head2 History

Command history is persisted to C<~/.acme_claude_shell_history> and loaded
on startup. Maximum 1000 lines are kept.

=cut

# Query cursor row position via /dev/tty (works even after Term::ReadLine)
# This avoids Term::ProgressSpinner's STDIN-based query which fails after readline
sub _get_cursor_row {
    my $row;
    eval {
        require Term::ReadKey;



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