I am trying to start my cli tool via the package.json bin
property.
I have the following:
...
"name": "mycli",
"bin": "./bin/mycli",
...
When I open the cmd in the package path and type: "mycli" it says that the command is not recognized.
Should I run an npm command? or use the scripts property? am I trying to access the bin property incorrectly?
Try to specify the name of your cli
tool in the bin
property, like:
"bin": {
"mycli": "./bin/mycli" // or "/bin/mycli.js" if it's a .js file
}
Then, run npm link
, from inside your project folder, to create a global symbolic link to the current folder.
Don't forget to add the "preferGlobal": "true"
property just before the bin
property in your package.json
file, in order to warn users to install your module globally.
Whenever I was trying to get my app to link, I kept running into problems on Windows where the generated scripts that would execute on path would try to run the *.js
file using the default Windows executable (I don't know what that would be). I'm not sure why. I think it might be because it is a JavaScript file. However, I compared the generated scripts to some of the other modules I had installed, and figured out that if I made the bin
file referenced by the package.json
act as though it were to be executed on a *nix
machine, npm
would automatically try and add the call to node.
For example:
If my package.json
looks like this:
myapp/package.json
"name": "myapp",
"bin": {
"myapp": "./bin/myapp"
}
My referenced bin file looks like this:
myapp/bin/myapp
#!/usr/bin/env node
require("../server.js");
The 2 generated executable files that appear in %APPDATA%\npm
show up as follows by running the command npm link
from within the myapp
directory (which would have package.json
in the root):
myapp
#!/bin/sh
basedir=`dirname "$0"`
case `uname` in
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
esac
if [ -x "$basedir/node" ]; then
"$basedir/node" "$basedir/node_modules/myapp/bin/myapp" "$@"
ret=$?
else
node "$basedir/node_modules/myapp/bin/myapp" "$@"
ret=$?
fi
exit $ret
myapp.cmd
@IF EXIST "%~dp0\node.exe" (
"%~dp0\node.exe" "%~dp0\node_modules\myapp\bin\myapp" %*
) ELSE (
node "%~dp0\node_modules\myapp\bin\myapp" %*
)
Bear in mind, I didn't need to make the 2 files above explicitly, I just needed to have the file to be executed as the bin
file in the package.json
. npm
did the file creation.
Line Endings
One other thing to note that I ran into while using this method, make absolutely sure that your line endings are correct. I noticed that my bin was erroring with: ": No such file or directory" whenever I installed on *nix machines because there was an incorrect line ending. Thanks to View line-endings in a text file for example of how to print visible line endings.
For example, if you run cat -e PATH_TO_BIN
and get something like this:
#!/usr/bin/env node^M$
^M$
require("../index.js");^M$
You're using the wrong line endings. If you get something like this:
#!/usr/bin/env node$
$
require("../index.js");$
Those should be the right line endings.
Answer from Rodrigo Medeiros works for me, but only if I have too the shebang line at the .js file.
There I had another issue. I have node.js installed at c:\Program files\nodejs, and this was my shebang line:
#!c:/program files/nodejs/node
This didn't work, because the blank space. This was the correct one:
#!c:/progra~1/nodejs/node
If you put
#!/usr/bin/env node
in the first line of your script, npm will create the necessary wrapper scripts.