What Is package.json?
What is package.json and package-lock.json. The files that list a JavaScript project's packages and commands. The node_modules folder built by npm.
Open almost any JavaScript project and you'll find package.json, package-lock.json, and a node_modules folder at the top. Of the three, package.json is the one to read, because it lists the packages the project needs (the "dependencies") and the commands that run it.
For JavaScript beginners, these files and this folder are mysterious clutter in a project. Experienced developers look at package.json before anything else in a JavaScript project, because its list of scripts tells them how to start, build, and test it. They also know node_modules is a huge, disposable folder that npm can rebuild from the lock file. Once you know what the three are for, you can open a project from GitHub or with an AI agent and quickly see how to run it. You can also clear out node_modules folders you no longer need without worrying.
What's in a Project Folder?, the first article in this series, covers the other common files you'll find beside package.json in a project. JavaScript files are one of the things you might work with when you set up a Mac for development.
JavaScript explained
First, for beginners: JavaScript is the programming language of web pages and web apps. Node.js (the node command) is used when JavaScript runs outside a browser, on your Mac. Developers use Node for command-line tools, web servers, and the tools that build websites. npm, short for "Node Package Manager", comes with Node. It downloads packages, ready-made code that other developers have shared, from the npm registry, a warehouse of shared code. How to install Node.js with mise shows how to get Node on a Mac.
What's in a package.json file
package.json is a text file in JSON, a strict format for writing data with names and values in double quotes. According to npm's documentation, it "must be actual JSON". The file is easily broken. A missing comma or an extra one stops npm from reading it. Missing or extra commas are difficult for humans to find, so just ask an AI agent if the file is valid JSON and ask for a fix.
Here is a small example:
{
"name": "my-app",
"version": "1.0.0",
"private": true,
"scripts": {
"start": "node server.js",
"dev": "node --watch server.js",
"test": "node --test",
"lint": "eslint ."
},
"dependencies": {
"express": "^5.1.0"
},
"devDependencies": {
"eslint": "^9.0.0"
}
}
Each part has one job:
- name and version - the project's name and version number. You need them only if you publish the project as a package for others to install; for your own project they are optional.
- private - with
true, npm won't publish the project, so you can't publish it by accident. - scripts - the project's commands, each with a short name.
- dependencies - the packages the project needs to run, each with a range of versions it accepts.
- devDependencies - packages you need only while you work on the project, such as test and lint (code-checking) tools. The npm documentation asks you to keep those out of
dependencies.
The ^ in "^5.1.0" means version 5.1.0 or any later 5.x version. That range lets you get bug fixes without editing the file, but it also means two installs a month apart can get different versions. The lock file, below, takes care of that.
The names package.json, package-lock.json, and node_modules don't start with a dot, so the Finder shows all three. Adjacent hidden files, such as .gitignore and .npmrc, appear only after you show hidden files on Mac.
Run a project's scripts
The scripts section is the most useful part of the file when you open a project for the first time. To run the scripts, you'll need Node.js, which includes npm. The article mise install node shows how to install Node with mise, which can switch Node versions for each project. Homebrew also installs Node.
First, open a terminal application and change to the project folder. Run npm run alone to see the project's scripts:
$ npm run
Then run a script by its name. In the example above, this starts the app and restarts it whenever you change a file:
$ npm run dev
Two names have shortcuts, so npm test and npm start run the scripts named test and start. A script can use any command-line tool the project installed, such as eslint in the lint script, because npm makes those tools available to scripts from inside the node_modules folder.
What is package-lock.json?
Whenever npm installs, updates, or removes a package, it writes package-lock.json. Where package.json says "Express 5.1.0 or a later 5.x version", the lock file records the exact version npm installed, and the exact version of every package that Express needs in turn. You don't edit it yourself; npm keeps it up to date.
Should you commit package-lock.json?
Commit package-lock.json to Git with the rest of your project. The npm documentation says the file "is intended to be committed into source repositories". Then everyone who works on the project, and every test run or deployment, installs exactly the same packages.
To install exactly what the lock file lists, use npm ci in place of npm install. It stops with an error if the lock file and package.json disagree, removes any existing node_modules folder first, and never changes either file:
$ npm ci
Can you delete package-lock.json?
You can delete package-lock.json, because the next npm install writes a new one. But npm may then choose newer versions within the ranges in package.json, so the project may no longer run exactly as before. In a project you share, or one that works, leave it in place.
Other package managers read the same package.json but keep their own lock file, such as yarn.lock for Yarn, pnpm-lock.yaml for pnpm and bun.lock for Bun.
What is the node_modules folder?
node_modules is where npm puts the packages it installs. It holds every package in package.json, plus every package those packages need, each in its own folder, so it often holds many more packages than the few the project lists. The npm tool also puts the packages' command-line tools in node_modules/.bin, which is how scripts find them.
The folder node_modules can be huge, eating up hundreds of megabytes in each project. On my own Mac, for a single website that lists just six packages in package.json, npm installs 182 packages, which use up 234 MB of storage. With a dozen JavaScript projects on your Mac, the node_modules folders can add up to gigabytes. Luckily, they can be deleted for any project you're not actively developing.
Never commit node_modules to Git. The .gitignore file article explains how to keep it out. The lock file is what should go into Git, because npm can rebuild the whole folder from it.
Can you delete node_modules?
You can delete node_modules whenever you need the space. Move the folder to the Trash and empty the Trash. Run npm ci or npm install in the project folder when you need to rebuild it:
$ npm install
Because the folder can always be rebuilt, you can delete it from projects you aren't working on to free space on your Mac.
AI agents and package.json
An AI agent reads package.json for the same reason you read it, to find out how to start, build, and test the project. The documentation for Anthropic Claude suggests pointing Claude to package.json to learn available npm commands. Claude's /init command writes the build and test commands it finds into CLAUDE.md, the project's instructions file for Claude. Obvious script names, such as dev, build, test, and lint, help an AI agent as much as they help you. To tell any AI agent which commands to use, put them in AGENTS.md, as explained in Agent Instructions.
When an AI agent installs a package with npm install <package>, npm changes both package.json and package-lock.json. Look at those changes before you commit them, as you would any other change.
Python projects keep a similar list of dependencies in pyproject.toml, which What Is pyproject.toml? explains.
Now you can open a JavaScript project on your Mac, read its scripts to see how to run it, keep the right files in Git, and delete node_modules folders whenever you need to free space.
Continue setting up your Mac
Don't miss the full visual roadmap and checklist that shows how to set up a Mac for software development, with all the essential tools and settings you might not yet know about.