SimplGy
SimplGy

Reputation: 20437

Locally-installed cli NPM project that is easy to execute

I'm building a cli node module. I would like people to be able to npm install it and use it right away with a command like npm my-project --arg=foo. It's meant for local project CLI use as a dev tool, not global installation.

It seems like the standard is to use bin in the package.json, but I don't understand some things about it:

  1. When should I use bin and when should I use scripts?
  2. How to I run the command in the including project? npm my-project doesn't do it.

Here is what I am doing now in package.json:

{
  "name": "my-project",
  "bin": "./cli.js"
}

And I can run it locally:

node cli.js --arg=foo

But when I npm-install my-project somewhere else, I don't know how to run the script it puts in bin (npm run my-project doesn't work), or if I'm using this correctly.

Upvotes: 1

Views: 5319

Answers (1)

robertklep
robertklep

Reputation: 203306

Let's start by explaining the difference between bin and scripts: the former you use if you want to provide a command line tool, the latter you use if you want to provide an additional command to npm (with some caveats though, see below).

In your situation, I think you want to use bin. However, instead of the user using npm my-project --arg=foo, they will use my-project --arg=foo, provided that your script is called my-project. To make that happen, your package.json will contain something like this:

"bin" : "./bin/my-project"

During installation, this will copy ./bin/my-project to a "bin" directory (usually /usr/local/bin on Unix-like OS'es). During development, you can call it as node bin/my-project, or even just ./bin/my-project, provided that it has correct permissions and "shebang".

EDIT: so I forgot that npm will use the package name, and not the name of the file in ./bin, as the executable name (if bin is a string). If your package is called my-project, and you install the package (you need to use the -g flag before npm will install the executable), it will create an executable called my-project, regardless of where the bin property points to.

In other words:

package.json:
  "name" : "my-project"
  "bin"  : "./cli.js"

npm install -g:
   copies ./cli.js to /usr/local/bin/my-project and sets executable permissions

END EDIT

FWIW, storing CLI tools in ./bin is convention, but not mandatory.

The scripts directive is useful for more internal purposes. For instance, you can use it to run a test suite, or linters, or pre/post install scripts.

Lastly, there are various modules available to help with command line parsing. I like docopt, but other often-used modules are commander or nomnom. You already mentioned yargs.

Upvotes: 4

Related Questions