Skip to main content

How to check npm scripts in current directory

As a front-end engineer, I spend a lot of time jumping in-between JavaScript projects. Often times I want to run a command from those projects to start watchmode or spin up a service.

The commands that I want to use are in the package.json under "scripts". When I haven’t memorized the common commands, I need to either open the file in my editor or use a Unix utility like cat.

# In my editor
code package.json

# In the terminal
cat package.json

Both of these commands work, but they are slow. package.json files can be massive, including dozens of dependencies, dev depenendencies, and other fields. To find the scripts, I need to sort through the cruft to find the information that I want. This isn’t very efficient.

Instead, I wrote a short bash scripts to quickly do the work for me. Here is the code in all of its glory:

#!/bin/bash

if [[ -f "package.json" ]]; then
    node -pe "JSON.parse(require('fs').readFileSync('package.json').toString()).scripts"
else
    echo "There is no `package.json` in this directory"
fi

First, I let the computer know to run this file with bash. Then I set up an if block: if there is a package.json file in this directory, then run the following code; if not, then print a “can’t find it” message.

The code to run, inspired by a StackOverflow comment, is a node process with two flags:

Within the script, I am using JSON to parse the results of a fs.readFileSync() of the package.json, then diving down to the scripts key.

I set it up by running chmod with two flags on the file in a scripts/ directory:

chmod u+x ~/scripts/npm-scripts

Then I could resource my terminal and run the command with npm-scripts. Bish bash bosh.

Everything worked fine, but I wanted an easier way to share my script with others. The chmod command and flags are hard to remember, so it would be easier if the script could be compressed into a one-liner that could be aliased in their ~/.bash_profile.

To do that, I removed all the new lines and added semicolons to separate the statements. The alias needed to be wrapped in quotes, so I escaped all the double quotes within the script.

Now I had a handy alias to share:

alias ns="if [[ -f \"package.json\" ]]; then node -pe \"JSON.parse(require('fs').readFileSync('package.json').toString()).scripts\"; else echo \"There is no package.json in this directory\"; fi"

Overall, I’m pretty happy with this utility. Going forward, I would like to extend it so that you can lookup and key on package.json by passing an argument.

Update – Apr 4, 2020

I created a new script to which you could pass an argument to pick a key from the package.json. This script is in zsh, but I think it ports to bash:

# rpj - Read package.json
function rpj () {
  if [[ -f "package.json" ]]; then
      node -pe "JSON.parse(require('fs').readFileSync('package.json').toString())['$1' || 'scripts']"
  else
      echo "There is no `package.json` in this directory"
  fi
}

Note how the shell arguments need to be wrapped in '' in order to work. Otherwise JavaScript thinkgs that it is looking for a variable, which is undefined.

If no argument is provided, then it falls back to printing the scripts which is probably the most common use case for me.

I also named the new function rpj for “Read package.json” to avoid any confusion with name servers.

For the next iteration, I would like to handle errors, but that is a project for another day.



About the author

Sean McPherson is a software engineer for Khan Academy who specializes in web and mobile app development. He lives with his wife, sons, and dog in Pittsburgh, PA.