NAME

CLI::Simple - a minimalist object oriented base class for CLI applications

SYNOPSIS

#!/usr/bin/env perl

package MyScript;

use strict;
use warnings;

use CLI::Simple::Constants qw(:booleans :chars);
use CLI::Simple qw($AUTO_HELP $AUTO_DEFAULT);

use parent qw(CLI::Simple);

sub execute {
  my ($self) = @_;

  # retrieve a CLI option   
  my $file = $self->get_file;
  ...
}

sub list { 
  my ($self) = @_

  # retrieve a command argument
  my ($file) = $self->get_args();
  ...
}

sub main {

  # Disable auto-default for single commands, enable auto-help
  $AUTO_DEFAULT = 0;
  $AUTO_HELP = 1;

  my $cli = MyScript->new(
   option_specs    => [ qw( help format=s file=s) ],
   default_options => { format => 'json' }, # set some defaults
   extra_options   => [ qw( content ) ], # non-option, setter/getter
   commands        => { execute => \&execute, list => \&list,  }
   alias           => { options => { fmt => format }, commands => { ls => list } },
  );

  return $cli->run();
}

exit main();

1;

DESCRIPTION

Tired of writing the same 'ol boilerplate code for command line scripts? Want a standard, simple way to create a Perl script that takes options and commands? CLI::Simple makes it easy to create scripts that take options, commands and arguments.

For common constant values (like $TRUE, $DASH, or $SUCCESS), see CLI::Simple::Constants, which pairs naturally with this module.

VERSION

This documentation refers to version 1.0.10.

Changes from Version 1.0.8

Features

Command line scripts often take options, sometimes a command and perhaps arguments to those commands. For example, consider the script myscript that takes options and implements a few commands (send-message, receive-message) that also take arguments.

myscript [options] command args

or

myscript command [options] args

Examples:

myscript --foo bar --log-level debug send-message "Hello World" now

myscript --bar --log-level info receive-message

Using CLI::Simple to implement this script looks like this...

package MyScript;

use parent qw(CLI::Simple);

caller or __PACKAGE__->main();

sub send_message {...}

sub default {...}

sub receive_message {...}

sub main {
  return __PACKAGE__->new(
    option_specs => [
      qw(
        foo=s
        bar
        log-level
      )
    ],
    commands => {
      send    => \&send_message,
      receive => \&receive_message,
    },
  )->run;
}

1;

PHILOSOPHY AND DESIGN PRINCIPLES

CLI::Simple is intentionally minimalist. It provides just enough structure to build command-line tools with subcommands, option parsing, and help handling -- but without enforcing any particular framework or lifecycle.

Not a Framework

This module is not App::Cmd, MooseX::Getopt, or a full application toolkit. Instead, it offers:

The philosophy is: provide just enough infrastructure, then get out of your way.

Validation, Defaults, and Configuration

CLI::Simple does not impose a validation model. You may:

The lifecycle is explicit and under your control. You decide how much structure you want to add on top of it.

When to Use

CLI::Simple is ideal for:

For more advanced features - like command trees, plugin support, or interactive CLI handling - consider heavier modules like App::Cmd, CLI::Framework, or MooX::Options.

The init-run Lifecycle

CLI::Simple is built on a flexible, two-phase lifecycle that separates application setup from command execution.

"opt-in" Default Command

By design, CLI::Simple does not impose a default command. This provides total flexibility for the application author:

This "no default by default" behavior is what enables a powerful "setup-only" execution mode. A user can run your script without specifying a command. This will:

This provides an ideal hook for applications that need to perform "on-demand initialization" (e.g., seeding a database, authenticating) by checking for a specific flag inside init(), without also triggering an unwanted command.

$AUTO_HELP and $AUTO_DEFAULT

Two package variables can be used to further control the lifecycle. By default, the framework provides no default command as explained in the sections above. Some scripters may want default behaviors that assume a command or provide usage if no command is provided.

CONSTANTS

CLI::Simple does not define its own constants directly, but it is often used in conjunction with CLI::Simple::Constants, which provides a collection of exportable values commonly needed in command-line scripts.

These include:

To use them in your script:

use CLI::Simple::Constants qw(:all);

ADDITIONAL NOTES

METHODS AND SUBROUTINES

new

new( args )

Instantiates a new CLI::Simple instance, parses options, optionally initializes logging, and makes options available via dynamically generated accessors.

Note: The new() constructor uses Getopt::Long's GetOptions, which directly modifies @ARGV by removing any recognized options. The remaining elements of @ARGV are treated as the command name and its arguments.

args is a hash or hash reference containing the following keys:

command

command
command(command)

Get or sets the command to execute. Usually this is the first argument on the command line after all options have been parsed. There are times when you might want to override the argument. You can pass a new command that will be executed when you call the run() method.

commands

commands
commands(command, handler)

Returns the hash you passed in the constructor as commands or can be used to insert a new command into the commands hash. handler should be a code reference.

commands(foo => sub { return 'foo' });

run

Execute the script with the given options, commands and arguments. The run method interprets the command line and passes control to your command subroutines. Your subroutines should return a 0 for success and a non-zero value for failure. This error code is passed to the shell as the script return code.

get_args

Return the arguments that follow the command.

get_args(NAME, ... )     # with names
get_args()               # raw positional args

With names:

- In scalar context, returns a hash reference mapping each NAME to the corresponding positional argument. - In list context, returns a flat list of (name = value)> pairs.

With no names:

- Returns the command's positional arguments (array in list context; array reference in scalar context).

Example:

sub send_message {
  my ($self) = @_;

  my %args = $self->get_args(qw(message email));

  _send_message($args{message}, $args{email});
}

When you call get_args with a list of names, values are assigned in order: the first name gets the first argument, the second name gets the second argument, and so on. If you only want specific positions, you may use undef as a placeholder:

my %args = $self->get_args('message', undef, 'cc');  # args 1 and 3

If there are fewer positional arguments than names, the remaining names are set to undef. Extra positional arguments (beyond the provided names) are ignored.

init

If you define your own init() method, it will be called by the constructor. Use this method to perform any actions you require before you execute the run() method.

USING PACKAGE VARIABLES

You can pass the necessary parameter required to implement your command line scripts in the constructor or some people prefer to see them clearly defined in the code. Accordingly, you can use package variables with the same name as the constructor arguments (in upper case).

our $OPTION_SPECS = [
  qw(
    help|h
    log-level=s|L
    debug|d
  )
];

our $COMMANDS = {
  foo => \&foo,
  bar => \&bar,
};

COMMAND LINE OPTIONS

Command-line options are defined using Getopt::Long-style specifications. You pass these into the constructor via the option_specs parameter:

my $cli = CLI::Simple->new(
  option_specs => [ qw( help|h foo-bar=s log-level=s ) ]
);

In your command subroutines, you can access these values using automatically generated getter methods:

$cli->get_foo();
$cli->get_log_level();

Option names that contain dashes (-) are automatically converted to snake_case for the accessor methods. For example:

option_specs => [ 'foo-bar=s' ]

...results in:

$cli->get_foo_bar();

COMMAND ARGUMENTS

If your commands accept positional arguments, you can retrieve them using the get_args method.

You may optionally provide a list of argument names, in which case the arguments will be returned as a hash (or hashref in scalar context) with named values.

Example:

sub send_message {
  my ($self) = @_;

  my %args = $self->get_args(qw(phone_number message));

  send_sms_message($args{phone_number}, $args{message});
}

If you call get_args() without any argument names, it simply returns all remaining arguments as a list:

my ($phone_number, $message) = $self->get_args;

Note: When called with names, get_args returns a hash in list context and a hash reference in scalar context.

CUSTOM ERROR HANDLER

By default, CLI::Simple will exit if GetOptions returns a false value, indicating an error while parsing options. You can override this behavior in one of two ways:

SETTING DEFAULT VALUES FOR OPTIONS

To assign default values to your options, pass a hash reference as the default_options argument to the constructor. These values will be used unless explicitly overridden by the user on the command line.

Example:

my $cli = CLI::Simple->new(
  default_options => { foo => 'bar' },
  option_specs    => [ qw(foo=s bar=s) ],
  commands        => {
    foo => \&foo,
    bar => \&bar,
  },
);

Defaulted options are accessible through their corresponding getter methods, just like options set via the command line.

ADDING USAGE TO YOUR SCRIPTS

To provide built-in usage/help output, include a =head1 USAGE section in your script's POD:

=head1 USAGE

  usage: myscript [options] command args

  Options
  -------
  --help, -h      Display help
  ...

If the user supplies the command help, or the --help option, CLI::Simple will display this section automatically:

perl myscript.pm --help
perl myscript.pm help

Custom help() Method

If you need full control over the help output, you can define a custom help method and assign it as a command:

commands => {
  help => \&help,
  ...
}

This is useful if your module follows the modulino pattern and you want to present usage information that differs from the embedded POD. Without a custom handler, CLI::Simple defaults to displaying the USAGE POD section.

ADDING ADDITIONAL SETTERS

All command-line options are automatically available through getter methods named get_*.

If you need to create additional accessors (getters and setters) for values that are not derived from the command line, use the extra_options parameter.

This is useful for passing runtime configuration or computed values throughout your application.

Example:

my $cli = CLI::Simple->new(
  default_options => { foo => 'bar' },
  option_specs    => [ qw(foo=s bar=s) ],
  extra_options   => [ qw(biz buz baz) ],
  commands        => {
    foo => \&foo,
    bar => \&bar,
  },
);

This will generate get_biz, set_biz, get_buz, etc., for internal use.

LOGGING

CLI::Simple integrates with Log::Log4perl to provide structured logging for your scripts.

To enable logging, call the class method use_log4perl() in your module or script:

__PACKAGE__->use_log4perl(
  level  => 'info',
  config => $log4perl_config_string
);

If you do not explicitly include a log-level option in your option_specs, CLI::Simple will automatically add one for you.

Once enabled, you can access the logger instance via:

my $logger = $self->get_logger;

This logger supports the standard Log4perl methods like info, debug, warn, etc.

Per Command Log Levels

Some commands may require more verbose logging than others. For example, certain commands might perform complex actions that benefit from detailed logs, while others are designed solely to produce clean, structured output.

To assign a custom log level to a command, use an array reference as the value for that command in the commands hash passed to the constructor.

The array reference should contain at least two elements:

Example:

CLI::Simple->new(
  option_specs    => [qw( help format=s )],
  default_options => { format => 'json' },  # set some defaults
  extra_options   => [qw( content )],       # non-option, setter/getter
  commands        => {
    execute => \&execute,
    list    => [ \&list, 'error' ],
  }
)->run;

TIP: add other elements to the array for your command to process.

FAQ

ALIASING OPTIONS AND COMMANDS

CLI::Simple lets you define short, human-friendly aliases for both option names and command names. Use the alias parameter to new():

my $app = CLI::Simple->new(
  option_specs    => [ qw(config=s verbose!) ],
  commands        => { list => \&list, execute => \&execute },
  alias => {
    options  => { cfg => 'config', v => 'verbose' },
    commands => { ls  => 'list'   }
  },
);

How option aliases work

How command aliases work

Usage examples

# Using an option alias
script.pl --cfg app.json execute

# Using a command alias
script.pl ls

After parsing, both get_config() and get_cfg() will return the same value. If the user passes both --config and --cfg, the value from --cfg (the alias) is used.

Recommendations

ERRORS/EXIT CODES

When you execute the run() method it passes control to the method that implements the command specified on the command line. Your method is expected to return 0 for success or an error code that you can the pass to the shell on exit.

exit CLI::Simple->new(commands => { foo => \&cmd_foo })->run();

Exit Codes

CLI::Simple uses conventional exit codes so that calling scripts can distinguish between normal completion and error conditions.

EXAMPLE

Run the shell script that comes with the distribution to output a working example.

cli-simple-example > example.pl

LICENSE AND COPYRIGHT

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See https://dev.perl.org/licenses/ for more information.

SEE ALSO

Getopt::Long, CLI::Simple::Utils, Pod::Usage, App::Cmd, CLI::Framework, MooX::Options

AUTHOR

Rob Lauer - bigfoot@cpan.org