Perinci::CmdLine::Base - Base class for Perinci::CmdLine{::Classic,::Lite}


This document describes version 1.929 of Perinci::CmdLine::Base (from Perl distribution Perinci-CmdLine-Lite), released on 2023-11-23.


Perinci::CmdLine is a command-line application framework. It allows you to create full-featured CLI applications easily and quickly.

See Perinci::CmdLine::Manual for more details.

There is also a blog post series on Perinci::CmdLine tutorial:


Perinci::CmdLine is plugin-based since 1.900.

My long-term goal is to have ScriptX (which is a plugin-oriented framework) as a replacement for Perinci::CmdLine. Since ScriptX is still in early development, I am also adding plugin support to Perinci::CmdLine in the mean time. Plugin support is similar to how ScriptX does plugins.

These are the characteristics of the plugin system, which make the system a very flexible one:

  • for an event, multiple plugins can be registered to run

    Plugins will be run in the order of their priority (highest first = lower numbered first). A plugin can choose to make the remaining plugins to be skipped by returning status code 201 (this is similar to how Apache plugins work.)

  • you can customize at which event(s) any plugin runs

    A plugin by default is set to run at predetermined event. For example the Debug::DumpArgs plugin plugin by default is set to run after the validate_args event, but you can also run it at other event(s). You can run a plugin in multiple events and have the same plugin runs more than once at a single event.

  • you can customize the priority of each plugin for an event

    This can change the order of plugins being run for an event.

  • you can disable an activate plugin

    The special Plugin::Disable plugin can be used to disable any plugin.

  • there are "before_<name>" events that can be used to cancel the "<name>" events

  • there are "after_<name>" events that can be used to repeat the "<name>" events

Plugin events

Below are events which are available to run plugins at. In addition to these, note that there are the two additional before_$event and after_$event (included below for ease of search).

  • activate_plugin

    This event can be used to disable other plugins (see Perinci::CmdLine::Plugin::Disable) or do things when a plugin is loaded.

  • before_activate_plugin

  • after_activate_plugin

  • validate_args

    Before this event, $r->{args} is already set to the input arguments, but they are not validated yet.

    After this event, $r->{args} should have already been validated.

  • before_validate_args

  • after_validate_args

  • action

    After this event, $r->{res} should have already been set to the result.

  • before_action

  • after_action

Plugin module

A plugin module is Perl module under the Perinci::CmdLine::Plugin:: namespace. The name should be further divided by category, e.g. Perinci::CmdLine::Plugin::Debug::DumpArgs.

It should be a subclass of Perinci::CmdLine::PluginBase. It must have a meta method returning metadata information.

It should have one or more on_*, before_*, or after_* methods to handle an event. A handler must return an enveloped result (an arrayref: [STATUS, MESSAGE, PAYLOAD]) where the status determine control flow. 100 means to decline and let the next plugin handle the event; 200 means success; 201 means success and skip the rest of the plugins to end the event early; 601 means to cancel the NAME event (returned by a before_NAME event handler); 602 means to repeat the NAME event (returned by an after_NAME event handler).

See an existing plugin for more details.

Activating plugins

  • From the source code

    (Currently no public API, but you can see the source code, particularly the _plugin_activate_plugins() method).

  • From configuration file (special parameter -plugins)

    Special parameters -plugins will activate plugins, e.g.:

     -plugins = -Debug::DumpArgs

    another example:

     -plugins = ["-Debug::DumpArgs", "-Debug::DumpRes"]
  • From configuration file ([plugin=...] sections)

    For example:

     plugins = Debug::DumpArgs,Debug::DumpConfig
  • From environment variable



If you execute run(), then one of these plugins will run Run::Normal plugin, Run::Completion plugin, or Run::DumpObject plugin. Please see the documentation of each plugin for more detail.


If read_env attribute is set to true, and there is environment variable defined to set default options (see documentation on read_env and env_name attributes) then the environment variable is parsed and prepended first to the command-line, so it can be parsed together. For example, if your program is called foo and environment variable FOO_OPT is set to --opt1 --opt2 val. When you execute:

 % foo --no-opt1 --trace 1 2

then @ARGV will be set to ('--opt1', '--opt2', 'val', '--no-opt1', '--trace', 1, 2). This way, command-line arguments can have a higher precedence and override settings from the environment variable (in this example, --opt1 is negated by --no-opt1).

Currently, parsing is done in two steps. The first step is to extract subcommand name. Because we want to allow e.g. cmd --verbose subcmd in addition to cmd subcmd (that is, user is allowed to specify options before subcommand name) we cannot simply get subcommand name from the first element of @ARGV but must parse command-line options. Also, we want to allow user specifying subcommand name from option cmd --cmd subcmd because we want to support the notion of "default subcommand" (subcommand that takes effect if there is no subcommand specified).

In the first step, since we do not know the subcommand yet, we only parse common options and strip them. Unknown options at this time will be passed through.

If user specifies common option like --help or --version, then action will be set to (respectively) help and version and the second step will be skipped. Otherwise we continue the second step and action by default is set to call.

At the end of the first step, we already know the subcommand name (of course, if subcommand name is unknown, we exit with error) along with subcommand spec: its URL, per-subcommand settings, and so on (see the subcommands attribute). If there are no subcommands, subcommand name is set to '' (empty string) and the subcommand spec is filled from the attributes, e.g. url, summary, <tags>, and so on.

We then perform a meta Riap request to the URL to get the Rinci metadata. After that, hook_after_get_meta is run if provided. From the Rinci metadata we get list of arguments (the args property). From this, we generate a spec of command-line options to feed to Getopt::Long. There are some conversions being done, e.g. an argument called foo_bar will become command-line option --foo-bar. Command-line aliases from metadata are also added to the Getopt::Long spec.

Config file: It is also at this step that we read config file (if read_config attribute is true). We run hook_before_read_config_file first. Some ideas to do in this hook: setting default config profile. For each found config section, we also run hook_config_file_section first. The hook will be fed ($r, $section_name, $section_content) and should return 200 status or 204 (no content) to skip this config section or 4xx/5xx to terminate config reading with an error message. After config files are read, we run hook_after_read_config_file.

We then pass the spec to Getopt::Long::GetOptions, we get function arguments.

We then run hook_after_parse_argv. Some ideas to do in this hook: XXX.

Function arguments that are still missing can be filled from STDIN or files, if the metadata specifies cmdline_src property (see Rinci::function for more details).


The various values in the $r hash/stash.

  • orig_argv => array

    Original @ARGV at the beginning of run().

  • common_opts => hash

    Value of common_opts attribute, for convenience.

  • action => str

    Selected action to use. Usually set from the common options.

  • format => str

    Selected format to use. Usually set from the common option --format.

  • read_config => bool

    This is set in run() to signify that we have tried to read config file (this is set to true even though config file does not exist). This is never set to true when read_config attribute is set, which means that we never try to read any config file.

  • read_env => bool

    This is set in run() to signify that we will try to read env for default options. This setting can be turned off e.g. in common option no_env. This is never set to true when read_env attribute is set to false, which means that we never try to read environment.

  • config => hash

    This is set in the routine that reads config file, containing the config hash. It might be an empty hash (if there is on config file to read), or a hash with sections as keys and hashrefs as values (configuration for each section). The data can be merged from several existing config files.

  • read_config_files => array

    This is set in the routine that reads config file, containing the list of config files actually read, in order.

  • config_paths => array of str

  • config_profile => str

  • parse_argv_res => array

    Enveloped result of parse_argv().

  • ignore_missing_config_profile_section => bool (default 1)

    This is checked in the parse_argv(). To aid error checking, when a user specifies a profile (e.g. via --config-profile FOO) and config file exists but the said profile section is not found in the config file, an error is returned. This is to notify user that perhaps she mistypes the profile name.

    But this checking can be turned off with this setting. This is sometimes used when e.g. a subclass wants to pick a config profile automatically by setting $r->{config_profile} somewhere before reading config file, but do not want to fail execution when config profile is not found. An example of code that does this is Perinci::CmdLine::depak.

  • subcommand_name => str

    Also set by parse_argv(). The subcommand name in effect, either set explicitly by user using --cmd or the first command-line argument, or set implicitly with the default_subcommand attribute. Undef if there is no subcommand name in effect.

  • subcommand_name_from => str

    Also set by parse_argv(). Tells how the subcommand_name request key is set. Value is either --cmd (if set through --cmd common option), arg (if set through first command-line argument), default_subcommand (if set to default_subcommand attribute), or undef if there is no subcommand_name set.

  • subcommand_data => hash

    Also set by parse_argv(). Subcommand data, including its URL, summary (if exists), and so on. Note that if there is no subcommand, this will contain data for the main command, i.e. URL will be set from url attribute, summary from summary attribute, and so on. This is a convenient way to get what URL and summary to use, and so on.

  • skip_parse_subcommand_argv => bool

    Checked by parse_argv(). Can be set to 1, e.g. in common option handler for --help or --version to skip parsing @ARGV for per-subcommand options.

  • args => hash

    Also taken from parse_argv() result.

  • meta => hash

    Result of get_meta().

  • dry_run => bool

    Whether to pass -dry_run special argument to function.

  • res => array

    Enveloped result of action_ACTION().

  • fres => str

    Result from hook_format_result().

  • output_handle => handle

    Set by select_output_handle() to choose output handle. Normally it's STDOUT but can also be pipe to pager (if paging is turned on).

  • naked_res => bool

    Set to true if user specifies --naked-res.

  • viewer => str

    Program to use as external viewer.

  • viewer_temp_path => str

    Set to temporary filename created to store the result to view to external viewer program.

  • page_result => bool

  • pager => str


All hooks will receive the argument $r, a per-request hash/stash. The list below is by order of calling.


Called at the start of run(). Can be used to set some initial values of other $r keys. Or setup the logger.


Only called when read_config attribute is true.


Only called when read_config attribute is true.


Called after the get_meta method gets function metadata, which normally happens during parsing argument, because parsing function arguments require the metadata (list of arguments, etc).

PC:Lite as well as PC:Classic use this hook to insert a common option --dry-run if function metadata expresses that function supports dry-run mode.

PC:Lite also checks the deps property here. PC:Classic doesn't do this because it uses function wrapper (Perinci::Sub::Wrapper) which does this.


Called after run() calls parse_argv() and before it checks the result. $r-{parse_argv_res}> will contain the result of parse_argv(). The hook gets a chance to, e.g. fill missing arguments from other source.

Note that for sources specified in the cmdline_src property, this base class will do the filling in after running this hook, so no need to do that here.

PC:Lite uses this hook to give default values to function arguments $r->{args} from the Rinci metadata. PC:Classic doesn't do this because it uses function wrapper (Perinci::Sub::Wrapper) which will do this as well as some other stuffs (validate function arguments, etc).


Called before calling the action_ACTION method. Some ideas to do in this hook: modifying action to run ($r->{action}), last check of arguments ($r->{args}) before passing them to function.

PC:Lite uses this hook to validate function arguments. PC:Classic does not do this because it uses function wrapper which already does this.


Called after calling action_ACTION method. Some ideas to do in this hook: preformatting result ($r->{res}).


The hook is supposed to format result in $res-{res}> (an array).

All direct subclasses of PC:Base do the formatting here.


The hook is supposed to display the formatted result (stored in $r-{fres}>) to STDOUT. But in the case of streaming output, this hook can also set it up.

All direct subclasses of PC:Base do the formatting here.


Called at the end of run(), right before it exits (if exit attribute is true) or returns $r-{res}>. The hook has a chance to modify exit code or result.


Below is list of special arguments that may be passed to your function by the framework. Per Rinci specification, these are prefixed by - (dash).

-dry_run => bool

Only when in dry run mode, to notify function that we are in dry run mode.

-cmdline => obj

Only when pass_cmdline_object attribute is set to true. This can be useful for the function to know about various stuffs, by probing the framework object.

-cmdline_r => hash

Only when pass_cmdline_object attribute is set to true. Contains the $r per-request hash/stash. This can be useful for the function to know about various stuffs, e.g. parsed configuration data, etc.

-cmdline_src_ARGNAME => str

This will be set if argument is retrieved from file, stdin, stdin_or_file, stdin_or_files, or stdin_line.

-cmdline_srcfilenames_ARGNAME => array

An extra information if argument value is retrieved from file(s), so the function can know the filename(s).


This module observes the following Rinci metadata property attributes:

cmdline.default_format => STR

Set default output format (if user does not specify via --format command-line option).

cmdline.skip_format => bool

If you set it to 1, you specify that function's result never needs formatting (i.e. the function outputs raw text to be outputted directly), so no formatting will be done. See also: skip_format attribute, cmdline.skip_format result metadata attribute.



This module interprets the following result metadata property/attribute:

attribute: cmdline.exit_code => int

Instruct to use this exit code, instead of using (function status - 300).

attribute: cmdline.result => any

Replace result. Can be useful for example in this case:

 sub is_palindrome {
     my %args = @_;
     my $str = $args{str};
     my $is_palindrome = $str eq reverse($str);
     [200, "OK", $is_palindrome,
      {"cmdline.result" => ($is_palindrome ? "Palindrome" : "Not palindrome")}];

When called as a normal function we return boolean value. But as a CLI, we display a more user-friendly message.

attribute: cmdline.result.interactive => any

Like cmdline.result but when script is run interactively.

attribute: cmdline.result.noninteractive => any

Like cmdline.result but when script is run non-interactively (in a pipeline).

attribute: cmdline.default_format => str

Default format to use. Can be useful when you want to display the result using a certain format by default, but still allows user to override the default.

attribute: cmdline.page_result => bool

If you want to filter the result through pager (currently defaults to $ENV{PAGER} or less -FRSX), you can set cmdline.page_result in result metadata to true.

For example:

 $SPEC{doc} = { ... };
 sub doc {
     [200, "OK", $doc, {"cmdline.page_result"=>1}];

attribute: cmdline.pager => STR

Instruct to use specified pager instead of $ENV{PAGER} or the default less or more.

attribute: cmdline.view_result => bool

Aside from using a pager, you can also use a viewer. The difference is, when we use a pager we pipe the output directly to the pager, but when we use a viewer we write to a temporary file then call the viewer with that temporary filename as argument. Viewer settings override pager settings.

If this attribute is set to true, will view result using external viewer (external viewer program is set either from cmdline.viewer or VIEWER or BROWSER. An error is raised when there is no viewer set.)

attribute: cmdline.viewer => STR

Instruct to use specified viewer instead of $ENV{VIEWER} or $ENV{BROWSER}.

attribute: cmdline.skip_format => bool (default: 0)

When we want the command-line framework to just print the result without any formatting. See also: skip_format attribute, cmdline.skip_format function metadata attribute.

attribute: x.perinci.cmdline.base.exit_code => int

This is added by this module, so exit code can be tested.




actions => array

Contains a list of known actions and their metadata. Keys should be action names, values should be metadata. Metadata is a hash containing these keys:

common_opts => hash

A hash of common options, which are command-line options that are not associated with any subcommand. Each option is itself a specification hash containing these keys:

  • category (str)

    Optional, for grouping options in help/usage message, defaults to Common options.

  • getopt (str)

    Required, for Getopt::Long specification.

  • handler (code)

    Required, for Getopt::Long specification. Note that the handler will receive ($geopt, $val, $r) (an extra $r).

  • usage (str)

    Optional, displayed in usage line in help/usage text.

  • summary (str)

    Optional, displayed in description of the option in help/usage text.

  • show_in_usage (bool or code, default: 1)

    A flag, can be set to 0 if we want to skip showing this option in usage in --help, to save some space. The default is to show all, except --subcommand when we are executing a subcommand (obviously).

  • show_in_options (bool or code, default: 1)

    A flag, can be set to 0 if we want to skip showing this option in options in --help. The default is to 0 for --help and --version in compact help. Or --subcommands, if we are executing a subcommand (obviously).

  • order (int)

    Optional, for ordering. Lower number means higher precedence, defaults to 1.

A partial example from the default set by the framework:

     help => {
         category        => 'Common options',
         getopt          => 'help|h|?',
         usage           => '--help (or -h, -?)',
         handler         => sub { ... },
         order           => 0,
         show_in_options => sub { $ENV{VERBOSE} },
     format => {
         category    => 'Common options',
         getopt      => 'format=s',
         summary     => 'Choose output format, e.g. json, text',
         handler     => sub { ... },
     undo => {
         category => 'Undo options',
         getopt   => 'undo',

The default contains: help (getopt help|h|?), version (getopt version|v), action (getopt action), format (getopt format=s), format_options (getopt format-options=s), json). If there are more than one subcommands, this will also be added: list (getopt list|l). If dry-run is supported by function, there will also be: dry_run (getopt dry-run). If undo is turned on, there will also be: undo (getopt undo), redo (getopt redo), history (getopt history), clear_history (getopt clear-history).

Sometimes you do not want some options, e.g. to remove format and format_options:

 delete $cmd->common_opts->{format};
 delete $cmd->common_opts->{format_options};

Sometimes you want to rename some command-line options, e.g. to change version to use capital -V instead of -v:

 $cmd->common_opts->{version}{getopt} = 'version|V';

Sometimes you want to add subcommands as common options instead. For example:

 $cmd->common_opts->{halt} = {
     category    => 'Server options',
     getopt      => 'halt',
     summary     => 'Halt the server',
     handler     => sub {
         my ($go, $val, $r) = @_;
         $r->{subcommand_name} = 'shutdown';

This will make:

 % cmd --halt

equivalent to executing the 'shutdown' subcommand:

 % cmd shutdown

completion => code

Will be passed to Perinci::Sub::Complete's complete_cli_arg(). See its documentation for more details.

default_subcommand => str

Set subcommand to this if user does not specify which to use (either via first command-line argument or --cmd option). See also: get_subcommand_from_arg.

auto_abbrev_subcommand => bool (default: 1)

If set to yes, then if a partial subcommand name is given on the command-line and unambiguously completes to an existing subcommand name, it will be assumed to be the complete subcommand name. This is like the auto_abbrev behavior of Getopt::Long. For example:

 % myapp c

If there are subcommands create, modify, move, delete, then c is assumed to be create. But if:

 % myapp mo

then it results in an unknown subcommand error because mo is ambiguous between modify and move.

Note that subcommand name in config section must be specified in full. This option is about convenience at the command-line only.

get_subcommand_from_arg => int (default: 1)

The default is 1, which is to get subcommand from the first command-line argument except when there is default_subcommand defined. Other valid values are: 0 (not getting from first command-line argument), 2 (get from first command-line argument even though there is default_subcommand defined).

description => str

A short description of the application.

exit => bool (default: 1)

Define the application exit behaviour. A false value here allows hook code normally run directly before the application exits to be skipped.

formats => array

Available output formats.

default_format => str

Default format.

allow_unknown_opts => bool (default: 0)

Whether to allow unknown options.

pass_cmdline_object => bool (default: 0)

Whether to pass special argument -cmdline containing the cmdline object to function. This can be overridden using the pass_cmdline_object on a per-subcommand basis.

In addition to -cmdline, -cmdline_r will also be passed, containing the $r per-request stash/hash (see "REQUEST KEYS").

Passing the cmdline object can be useful, e.g. to call action_help(), to get the settings of the Perinci::CmdLine, etc.

per_arg_json => bool (default: 1 in ::Lite)

This will be passed to Perinci::Sub::GetArgs::Argv.

per_arg_yaml => bool (default: 0 in ::Lite)

This will be passed to Perinci::Sub::GetArgs::Argv.

program_name => str

Default is from PERINCI_CMDLINE_PROGRAM_NAME environment or from $0.

riap_version => float (default: 1.1)

Specify Riap protocol version to use. Will be passed to Riap client constructor (unless you already provide a Riap client object, see riap_client).

riap_client => obj

Set to Riap client instance, should you want to create one yourself. Otherwise will be set Perinci::Access (in PC:Classic), or Perinci::Access::Lite (in PC:Lite).

riap_client_args => hash

Arguments to pass to Riap client constructor. Will be used unless you create your own Riap client object (see riap_client). One of the things this attribute is used is to pass HTTP basic authentication to Riap client (Perinci::Access::HTTP::Client):

 riap_client_args => {handler_args => {user=>$USER, password=>$PASS}}

subcommands => hash | code

Should be a hash of subcommand specifications or a coderef.

Each subcommand specification is also a hash(ref) and should contain these keys:

  • url (str, required)

    Location of function (accessed via Riap).

  • summary (str, optional)

    Will be retrieved from function metadata at url if unset

  • description (str, optional)

    Shown in verbose help message, if description from function metadata is unset.

  • tags (array of str, optional)

    For grouping or categorizing subcommands, e.g. when displaying list of subcommands.

  • use_utf8 (bool, optional)

    Whether to issue use open, ":utf8". Alternative: use_locale. Takes precedence over use_locale.

  • use_locale (bool, optional)

    Whether to issue use open, ":locale". Alternative: use_utf8.

  • undo (bool, optional)

    Can be set to 0 to disable transaction for this subcommand; this is only relevant when undo attribute is set to true.

  • show_in_help (bool, optional, default 1)

    If you have lots of subcommands, and want to show only some of them in --help message, set this to 0 for subcommands that you do not want to show.

  • pass_cmdline_object (bool, optional, default 0)

    To override pass_cmdline_object attribute on a per-subcommand basis.

  • args (hash, optional)

    If specified, will send the arguments (as well as arguments specified via the command-line). This can be useful for a function that serves more than one subcommand, e.g.:

     subcommands => {
         sub1 => {
             summary => 'Subcommand one',
             url     => '/some/func',
             args    => {flag=>'one'},
         sub2 => {
             summary => 'Subcommand two',
             url     => '/some/func',
             args    => {flag=>'two'},

    In the example above, both subcommand sub1 and sub2 point to function at /some/func. But the function can differentiate between the two via the flag argument being sent.

     % cmdprog sub1 --foo 1 --bar 2
     % cmdprog sub2 --foo 2

    In the first invocation, function will receive arguments {foo=>1, bar=>2, flag=>'one'} and for the second: {foo=>2, flag=>'two'}.

Subcommands can also be a coderef, for dynamic list of subcommands. The coderef will be called as a method with hash arguments. It can be called in two cases. First, if called without argument name (usually when doing --subcommands) it must return a hashref of subcommand specifications. If called with argument name it must return subcommand specification for subcommand with the requested name only.

summary => str

Optional, displayed in description of the option in help/usage text.

tags => array of str

For grouping or categorizing subcommands, e.g. when displaying list of subcommands.

url => str

Required if you only want to run one function. URL should point to a function entity.

Alternatively you can provide multiple functions from which the user can select using the first argument (see subcommands).

read_env => bool (default: 1)

Whether to read environment variable for default options.

env_name => str

Environment name to read default options from. Default is from program name, upper-cased, sequences of dashes/nonalphanums replaced with a single underscore, plus a _OPT suffix. So if your program name is called cpandb-cpanmeta the default environment name is CPANDB_CPANMETA_OPT.

read_config => bool (default: 1)

Whether to read configuration files.

config_filename => str|array[str]|array[hash]

Configuration filename(s). The default is program_name . ".conf". For example, if your program is named foo-bar, config_filename will be foo-bar.conf.

You can specify an array of filename strings, which will be checked in order, e.g.: ["myapp.conf", "myapp.ini"].

You can also specify an array of hashrefs, for more complex scenario. Each hash can contain these keys: filename, section. For example:

     {filename => 'mysuite.conf', section=>'myapp1'},
     {filename => 'myapp1.conf'}, # section = GLOBAL (default)

This means, configuration will be searched in mysuite.conf under the section myapp1, and then in myapp1.conf in the default/global section.

config_dirs => array of str

Which directories to look for configuration file. The default is to look at the user's home and then system location. On Unix, it's [ "$ENV{HOME}/.config", $ENV{HOME}, "/etc"]. If $ENV{HOME} is empty, getpwuid() is used to get home directory entry.

cleanser => obj

Object to cleanse result for JSON output. By default this is an instance of Data::Clean::ForJSON and should not be set to other value in most cases.

use_cleanser => bool (default: 1)

When a function returns result, and the user wants to display the result as JSON, the result might need to be cleansed first (using Data::Clean::ForJSON by default) before it can be encoded to JSON, for example it might contain Perl objects or scalar references or other stuffs. If you are sure that your function does not produce those kinds of data, you can set this to false to produce a more lightweight script.

extra_urls_for_version => array of str

An array of extra URLs for which version information is to be displayed for the action being performed.

skip_format => bool

If set to 1, assume that function returns raw text that need not be translated, and so will not offer common command-line options --format, --json, as well as --naked-res.

As an alternative to this, can also be done on a per-function level by setting function metadata property cmdline.skip_format to true. Or, can also be done on a per-function result basis by returning result metadata cmdline.skip_format set to true.

use_utf8 => bool (default: from env UTF8, or 0)

Whether or not to set utf8 flag on output. If undef, will default to UTF8 environment. If that is also undef, will default to 0.

default_dry_run => bool (default: 0)

If set to 1, then dry-mode will be turned on by default unless user uses DRY_RUN=0 or --no-dry-run.

log => bool

Whether to enable logging. Default is off. If true, will load Log::ger::App.

log_level => str

Set default log level. Will be overridden by $r->{log_level} which is set from command-line options like --log-level, --trace, etc.


$cmd->run() => ENVRES

The main method to run your application. See "PROGRAM FLOW (NORMAL)" for more details on what this method does.

$cmd->do_completion() => ENVRES

Called by run().

$cmd->parse_argv() => ENVRES

Called by run().

$cmd->get_meta($r, $url) => ENVRES

Called by parse_argv() or do_completion(). Subclass has to implement this.



String. When "VIEWER" is not set, then this environment variable will be used to select external viewer program.


Boolean. If set to true, will dump parsed configuration at the trace level.


Boolean. Can be set to 1 to force paging of result. Can be set to 0 to explicitly disable paging even though cmd.page_result result metadata attribute is active.

See also: "PAGER".


String. Like in other programs, can be set to select the pager program (when cmdline.page_result result metadata is active). Can also be set to '' or 0 to explicitly disable paging even though cmd.page_result result metadata is active.


String. If set, then aside from displaying output as usual, the unformatted result (enveloped result) will also be saved as JSON to an output directory. The filename will be UTC timestamp in ISO8601 format.out, e.g.:

 2017-12-11T123456.000000000Z.out.1 (if the same filename already exists)

or each output (.out) file there will also be a corresponding .meta file that contains information like: command-line arguments, PID, etc. Some notes:

Output directory must already exist, or Perinci::CmdLine will display a warning and then skip saving output.

Data that is not representable as JSON will be cleansed using Data::Clean::ForJSON.

Streaming output will not be saved appropriately, because streaming output contains coderef that will be called repeatedly during the normal displaying of result.


String. A list of plugins to load at the start of program. If it begins with a C>[> (opening square bracket), it will be assumed to be in JSON encoding:

 ["PluginName1",{"arg1name":"arg1val","arg2name":"arg2val",...},"PluginName2", ...]

otherwise it is assumed to be a comma-separated string in this syntax:


Plugin name is module name without the Perinci::CmdLine::Plugin:: prefix. The argument list can be skipped if you don't want to pass arguments to a plugin.


String. Can be used to set CLI program name.


Boolean. To set default for use_utf8 attribute.


Boolean. Can be set to 1 to force using viewer to view result. Can be set to 0 to explicitly disable using viewer to view result even though cmdline.view_result result metadata attribute is active.


String. Can be set to select the viewer program to override cmdline.viewer. Can also be set to '' or 0 to explicitly disable using viewer to view result even though cmdline.view_result result metadata attribute is active.

See also "BROWSER".


Please visit the project's homepage at


Source repository is at


perlancar <>


To contribute, you can send patches by email/via RT, or send pull requests on GitHub.

Most of the time, you don't need to build the distribution yourself. You can simply modify the code, then test via:

 % prove -l

If you want to build the distribution (e.g. to try to install it locally on your system), you can install Dist::Zilla, Dist::Zilla::PluginBundle::Author::PERLANCAR, Pod::Weaver::PluginBundle::Author::PERLANCAR, and sometimes one or two other Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps required beyond that are considered a bug and can be reported to me.


This software is copyright (c) 2023, 2022, 2021, 2020, 2019, 2018, 2017, 2016, 2015, 2014 by perlancar <>.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.


Please report any bugs or feature requests on the bugtracker website

When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.