commander.js: standalone flags doesn't seem to work in a command driven app powered by commander.js

Say we’ve a command driven app:-

program
  .option('-n,--name <name>');

program
  .command('sample')
  .option('-a,--action <action>')
  .action((options) => {
    console.log(options.action);
  });

program.parse(process.argv);

Use cases

  • [cli-name] -n <name> (standalone option)
  • [cli-name] sample -a <value> (command)

The first use case doesn’t seem to work.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 17

Most upvoted comments

no action handler to call on the main program

@shadowspawn can you please elaborate on this?

Your first/root command chain doesn’t specify an action handler so it doesn’t do anything.
I.e. this part of your example

program
  .option('-n,--name <name>');

It’s probably expecting:

program
  .option('-n,--name <name>');
  .action((options) => console.log(options.name));

[...]

You might also be interested in the “default” command support if --name is not intended to be global (and used by sample). When a subcommand is not specified, including when there are no arguments, the “default” command is called.

Well that is probably way more info that you were expecting! Hopefully some of it is useful and gets you going past your original question and beyond. Sorry you stumbled over a built-in behaviour.

For a program with subcommands and no action handler, Commander assumes the most useful thing to do is display the help when there are no arguments. If you want different behaviour then just add an action handler (even an empty one!) so Commander can tell you have it covered.

const { program } = require('commander');

program
  .storeOptionsAsProperties(false)
  .passCommandToAction(false);
  
program
   .option('-n,--name <name>')
   .action((options) => {
    console.log(options.name);
  });
 
program
   .command('sample')
   .option('-a,--action <action>')
   .action((options) => {
     console.log(options.action);
   });
 
 program.parse(process.argv);
% node my-way.js -n John
John
% node my-way.js sample --action jump
jump

For a program with no subcommands, Commander leaves it up to you what to do when there are no arguments. Your program may not require any options to be specified, like the ls command. Often the program logic will be after the call to parse rather than putting it into an action handler

program
  .option('-t, --test', 'run all tests');
program.parse();
console.log(program.opts());
$ node simple.js 
{ test: undefined }

$ node simple.js -t
{ test: true }