DEV Community

Iulian Preda
Iulian Preda

Posted on

Run your NPX script directly from Github. Create your own CLI commands and other stories

This will be a short read, probably, I can't promise you that though, but at least I'll make it as entertaining as it can get.

First, what is NPX, and what are CLI commands?
NPX is a command-line tool meant to run NPM packages containing CLI scripts.
A CLI command is a program that can be run from the command line by name, for example, gcc or cd or ls, etc.

In NodeJs you have the option to create CLI commands that can be run only from NPM scripts, remember npm run <script name>?
A good example of this is tsc or babel or webpack that unless installed globally (and added to the path) they can be only
summoned from inside a script from the scripts section in the package.json.

We will need NodeJs and NPX installed as a global package for the rest of the article. Any NodeJs > v5.0 should have NPX already installed but if it doesn't work you can always run npm install -g npx.

From NPX's Github page, we can get the following command to run in a terminal: npx github:piuccio/cowsay JavaScript FTW!.
It should prompt us with something like this:

< JavaScript FTW! >
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
Enter fullscreen mode Exit fullscreen mode

This command installed the package in a temporary folder and run the command with the same name as the repository.

Just to mention the npx cowsay JavaScript FTW! command will work just fine because the package exists on NPM as well.

As we just covered how to use it, next we should learn how to write a command that can be used from the CLI (or using NPM).

To save some time I will list the instructions:

  • Create a new folder
  • Open a terminal in the folder
  • package.json - for that we use can use npm --init and accept the defaults or customize the inputs like name, description, license, etc.
  • Create the main file of the application - create, let's say, a file named index.js
  • In the package.json we will add the commands section:
"bin": {
        "awesome-command": "index.js",
Enter fullscreen mode Exit fullscreen mode
  • Add in the index.js on the first line #!/usr/bin/env node For example:
#!/usr/bin/env node
console.log("Awesome Command");
Enter fullscreen mode Exit fullscreen mode
  • Good job, now if we publish the package and install it, we will be able to use it, but... Let's say we are in a hurry and we just want to see if it works, so, what can we do? We npm link. This command will add it to the global packages like it would have installed it with the -g flag.

  • Run awesome-command from any terminal and it will print Awesome Command

Sooo, how does the NPX helps? We already are able to run the command from any terminal. Well, that is true, but only now and definitely not always.

If we would have installed the package locally, then we wouldn't have been able to run awesome-command in a terminal and expect it to work. We would have had to add it to the scripts section in the package.json like this:

"scripts": {
    "awesome": awesome-command
Enter fullscreen mode Exit fullscreen mode

and then npm run awesome or... run npx awesome-command.

Now comes the good part, what if we want to make the command available over the internet?

Well then we publish the npm package and anyone can choose to
npm -install <package> it or npx <package>. Remember only to have one of the commands match the name of the package.

But what if we don't want to publish the package?
Then we can just host the package on Github in a new repository and anyone will be able to install it using npm -install user/<repository> or run it using npx github:<user>/<repository>. Again remember to have one of the commands in the bin section match the name of the repository.

Ending thoughts, if the command accepts extra arguments we can always add them after the command name, for example npx github:<user>/<repository> arg1 arg2.

I hope you enjoyed reading the article as much as I enjoyed writing it.

Top comments (7)

timrohrer profile image

I’m finding npx github:piuccio/cowsay doesn’t execute, and I can’t figure out why. I started researching this because I could not get another package on GitHub to execute, so now I’m trying to figure out why.

I’m using v8.5.5 of npx and would love it if some others could test this and see if it is a version issue?

timrohrer profile image

I got it to work, but I’ll need to research GitHub for bug reports.

I had to run the non-aliased form first: npm exec github:piuccio/cowsay, and then I could run npx …

The same behavior occurred with my project. Once I ran npm exec … first, npx works correctly.

douglasnaphas profile image
Douglas Naphas • Edited

@timrohrer Did you ever figure out why npm exec github:piuccio/cowsay works, but npx github:piuccio/cowsay doesn't? That is the behavior I'm seeing.

Thread Thread
timrohrer profile image

Nope. I just run npm exec first. Afterwards, I can often use npx but no solid pattern.

saadbashar profile image

Great read!

alienpr84 profile image
Alien Padilla Rodriguez

For me was usefull this simple line:
#!/usr/bin/env node

Keep it simple stupid (Clean code)

Thanks...Lulian Preda

tertek profile image

Thank you!!!