Search code examples
npmcommand-linescriptingcommandcommander

with the node package "commander", "args" and others, my options are never recognized when running it from npm run


When using an args processor like commander, I can get arguments, but not options if I make a script for it.

package.json...

{
  "name": "example",
  "version": "0.0.1",
  "description": "This app's CLI is going to have problems",
  "main": "src/app.js",
  "scripts": {
    "serve": "node src/app.js",
    "command": "node src/cli.js",
  },
  "dependencies": {
    "commander": "^12.1.0"
  },
}

... this works fine if I run npm run command foo; src/cli.js gets passed foo as an arg. However, if I run npm run command foo --force; the --force option is never passed.


Solution

  • npm will process and remove all options from the command-line, whether recognised or not. You can stop the option processing (so the arguments remain) by using an argument of --. This is a common pattern supported by many cli programs.

    So in your case you could use:

    npm run -- command foo --force
    

    The work-around is mentioned in the npm documentation for npm-run-script:

    Any positional arguments are passed to the specified script. Use -- to pass --prefixed flags and options which would otherwise be parsed by npm.

    For example:

    npm run test -- --grep="pattern"

    It causes so much confusion that Commander also has a specific section in its README for npm-run-script

    By default, when you call your program using run-script, npm will parse any options on the command-line and they will not reach your program. Use -- to stop the npm option parsing and pass through all the arguments.

    The synopsis for npm run-script explicitly shows the -- for this reason:

    npm run-script <command> [-- <args>]