Last updated: 2026-09-14

npm Basics

npm — short for Node Package Manager — is the tool that manages the external code your project depends on. It is installed automatically alongside Node.js, and it is the interface to the npm registry: a public collection of over two million open-source JavaScript packages, available to be installed into any project with a single command.

Almost no Node.js project is built entirely from scratch. Express, database drivers, testing frameworks, utility libraries — all of it arrives through npm. Understanding npm well is not optional knowledge for working in this ecosystem; it is daily-use knowledge.


What npm Actually Is

npm is three things at once, and it is worth being clear about the distinction:

  1. A registry — a public server hosting millions of published packages
  2. A CLI tool — the npm command, used to install, update, and manage packages
  3. A package format and convention — the rules that define what a "package" is, expressed through package.json

When you run npm install express, the CLI tool contacts the registry, downloads the express package and everything it depends on, and places it in your project according to the conventions npm defines.


Initialising a Project

Every npm-managed project begins with a package.json file — the manifest that describes the project and its dependencies. To create one:

npm init

This runs an interactive prompt asking for the project name, version, description, entry point, and other metadata. To skip the prompts and accept sensible defaults immediately:

npm init -y

This produces a minimal package.json:

{
  "name": "my-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

package.json is covered in full depth in its own dedicated topic next in this series — this topic focuses on the npm commands used to work with it.


Installing Packages

Installing a Package

npm install express

This downloads express and every package it depends on, places them inside a node_modules folder in the project root, and adds express to the dependencies section of package.json.

npm i is a shorter alias for npm install and behaves identically.

Installing a Specific Version

npm install express@4.18.2

Installing Multiple Packages at Once

npm install express mongoose dotenv

Installing as a Development Dependency

Some packages are only needed during development — testing frameworks, linters, build tools — and are never required when the application actually runs in production. The --save-dev flag (or its shorthand -D) records this distinction:

npm install --save-dev nodemon
npm install -D jest

These are recorded in a separate devDependencies section of package.json. The distinction matters in production: deployment processes typically install only dependencies, skipping devDependencies entirely, which keeps the deployed application smaller and avoids installing tools that serve no purpose once the code is running live.

Installing a Package Globally

npm install -g typescript

A global installation makes a package's command-line tool available system-wide, outside of any specific project — for example, running tsc from any directory. Global installs are appropriate for CLI tools you use across many projects; they are not appropriate for packages your application code actually imports and depends on, which should always be installed locally to the project instead.


Removing Packages

npm uninstall express

This removes the package from node_modules and deletes its entry from package.json.


Updating Packages

npm update

This updates every installed package to the latest version permitted by the version ranges specified in package.json (version ranges are explained in the package.json topic). To check which installed packages have newer versions available, beyond what npm update would apply:

npm outdated

To update a single specific package:

npm update express

node_modules

node_modules is the folder where every installed package actually lives — its source code, its own dependencies, everything needed for it to run. It is created automatically the first time you install a package, and it grows substantially as more dependencies are added, since most packages depend on other packages, which depend on still more packages.

node_modules should never be committed to version control. It is large, it is entirely reproducible from package.json and the lock file, and committing it bloats a repository for no benefit. The standard practice is to add it to .gitignore:

# .gitignore
node_modules/

Anyone cloning the project runs npm install, and node_modules is rebuilt locally from the dependency information already recorded in package.json.


Reinstalling Dependencies from Scratch

After cloning a project, or whenever package.json already exists and simply needs its dependencies installed:

npm install

Run with no package name specified, npm install reads package.json and installs every listed dependency, recreating node_modules entirely. This is the command run immediately after cloning any Node.js project for the first time.


Running Scripts

The scripts section of package.json defines named shortcuts for commands — most commonly, starting the application or running tests.

{
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js",
    "test": "jest"
  }
}

Run any of these with npm run:

npm run dev
npm run test

Two scripts have a shorthand that drops the word run: npm start and npm test work without run, because these two are treated as special, conventional script names. Every other script name requires the full npm run <script-name> form.

npm start   # equivalent to npm run start
npm test    # equivalent to npm run test
npm run dev # "run" is required here — "dev" is not a special name

npx — Running Packages Without Installing Them Globally

npx is a separate tool, bundled with npm, that runs a package's command-line tool directly — either using a version already installed locally in the project, or downloading it temporarily if it is not installed at all.

npx create-react-app my-app

This downloads and runs create-react-app without permanently installing it anywhere. For one-off commands — scaffolding a new project, running a tool you only need once — npx avoids cluttering the system with global installs that will rarely be used again.

npx is also commonly used to run a project's locally-installed CLI tools without needing them installed globally:

npx jest
npx eslint .

Semantic Versioning

npm package versions follow semantic versioning (semver) — a MAJOR.MINOR.PATCH format that communicates the nature of a change.

4.18.2
│  │  │
│  │  └── PATCH — bug fixes, no breaking changes
│  └───── MINOR — new features, backward compatible
└──────── MAJOR — breaking changes
SegmentMeaningExample
MAJORBreaking changes — existing code may need updating3.0.0 → 4.0.0
MINORNew functionality, fully backward compatible4.17.0 → 4.18.0
PATCHBug fixes, no new functionality, fully backward compatible4.18.1 → 4.18.2

This convention is what makes version ranges in package.json — ^4.18.2, ~4.18.2 — meaningful, since they specify which kinds of updates are considered safe to apply automatically. Version ranges are covered in depth in the package.json topic.


Checking Installed Versions

npm --version          # the version of npm itself
npm list                # every package installed in the current project, with versions
npm list express        # check the installed version of one specific package
npm list -g             # globally installed packages

Security Auditing

npm includes a built-in tool for checking installed packages against a database of known security vulnerabilities:

npm audit

This reports any known vulnerabilities found in the project's dependencies, along with their severity. To attempt automatic fixes where possible:

npm audit fix

Running npm audit periodically — and especially before deploying to production — is a basic but meaningful security practice, since vulnerabilities are regularly discovered in widely-used packages well after they have already been installed in thousands of projects.


Summary

TaskCommand
Create a package.jsonnpm init -y
Install a packagenpm install <package>
Install as a dev dependencynpm install -D <package>
Install globallynpm install -g <package>
Remove a packagenpm uninstall <package>
Install everything from package.jsonnpm install
Update packagesnpm update
Check for outdated packagesnpm outdated
Run a scriptnpm run <script-name>
Run a package without installing itnpx <package>
Check for vulnerabilitiesnpm audit
List installed packagesnpm list