npm Scripts Reference

Lifecycle npm script hooks in execution order with use cases.

Reference for npm lifecycle scripts — preinstall, install, postinstall, prepare, prepublishOnly, pretest, prestart and more — in execution order, with what triggers each and the pre/post hook naming convention. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

What is the difference between prepare and postinstall?

postinstall runs after dependencies are installed for any install. prepare runs on local installs AND before the package is packed or published, but is skipped when installing the package as a dependency in production. Use prepare to build before publish and to install git hooks.

npm lifecycle scripts, in order

npm runs special scripts at defined points in the install, test, start, stop and publish lifecycles. This reference lists each lifecycle script in execution order with what triggers it and a typical use case, plus the pre/post naming convention that lets you hook around any command. Search by name or keyword.

How lifecycle scripts work

Scripts live in the scripts field of package.json. Some names are reserved lifecycle hooks that npm invokes automatically — you do not need to call them with npm run. The three main flows:

Install flow (triggered by npm install or npm ci):

preinstall → install → postinstall → prepare

prepare also runs in this sequence but is not run when installing the package as a dependency of another project (only runs locally and before pack/publish).

Publish flow (triggered by npm publish):

prepublishOnly → prepare → prepack → [tarball built] → postpack → publish → postpublish

Test / start / stop flows each fire their pre and post hooks around the named command automatically.

The pre/post naming convention

For any script x, npm automatically runs prex before it and postx after it. This works for built-in lifecycle names and your own custom scripts:

{
  "scripts": {
    "prebuild": "rimraf dist",
    "build": "tsc",
    "postbuild": "echo Build complete"
  }
}

Running npm run build fires all three in order without any extra configuration.

prepare vs. postinstall — the key distinction

postinstallprepare
Runs after npm install locallyYesYes
Runs when installed as a dependencyYesNo
Runs before npm publishNoYes
Typical useNative addon compilation, code generationBuild steps, Husky git-hook setup

The most important rule: use prepare for build steps that should run before publishing and on local install, but not when downstream projects install your package as a dependency. Use postinstall only when you genuinely need to run something in the consumer’s environment — patching, native bindings, etc. Overusing postinstall causes security concerns and slows down everyone who installs your package.

prepublishOnly — publish gate

prepublishOnly runs only before npm publish, never on install. It is the right place to run your full test suite and linter as a final guard before the package ships. Many teams who skipped this script have published broken releases.

{
  "scripts": {
    "prepublishOnly": "npm test && npm run lint"
  }
}

Complete typical library configuration

{
  "scripts": {
    "build": "tsc",
    "prebuild": "rimraf dist",
    "test": "vitest run",
    "pretest": "eslint .",
    "prepare": "npm run build",
    "prepublishOnly": "npm test"
  }
}
  • prebuild cleans dist before every build via the naming convention alone.
  • pretest lints before every test run.
  • prepare builds on local install and before publishing.
  • prepublishOnly gates every publish behind a passing test run.

Skipping scripts safely

To install without running any lifecycle scripts — useful in CI or when installing untrusted packages:

npm install --ignore-scripts

For Husky or similar tools that install git hooks via prepare, guard the script with a CI check:

{
  "scripts": {
    "prepare": "is-ci || husky install"
  }
}

npm v7+ tightened the pre/post auto-hook behaviour for workspaces. In a monorepo, test that scripts fire as expected in the workspace root versus individual package directories.