A package manager is a tool that installs, updates, and keeps track of the code libraries your project depends on. Instead of hunting down a library, downloading it, and manually wiring it in, you run one command and the package manager fetches it, along with everything that library itself needs. It is the plumbing that makes modern development practical, because almost no project is built entirely from scratch in 2026.
How a package manager works
You declare what your project needs in a manifest file, then run an install command. The package manager reads the manifest, contacts a registry (a central server hosting packages), downloads the requested libraries, and places them where your code can import them.
The clever part is dependency resolution. The library you asked for likely depends on other libraries, which depend on still others. The package manager walks that whole tree, figures out compatible versions, and installs everything. Doing this by hand for a real project would be impossible. If you are new to all of this, learning to code as a beginner will have you running install commands within the first hour.
-- add a library; the manager fetches it and its dependencies
npm install lodash
-- Python equivalent with a modern tool
uv add requests
What a lockfile does
The manifest often allows a range of versions, such as "anything compatible with 4.x." That flexibility is convenient but dangerous: two installs at different times could pull different versions. A lockfile solves this by recording the exact version of every package that was installed, including the deep dependencies.
| File |
Purpose |
Commit it? |
| Manifest (package.json, pyproject.toml) |
What you want, with version ranges |
Yes |
| Lockfile (package-lock.json, uv.lock) |
Exact resolved versions |
Yes |
| Installed folder (node_modules) |
The actual downloaded code |
No |
With a committed lockfile, every teammate and every server installs the identical set of versions, so "works on my machine" stops being a mystery.
The tools you will meet in 2026
- JavaScript and TypeScript: npm ships with Node; pnpm and yarn are popular alternatives, with pnpm valued for disk efficiency and speed.
- Python: pip is the classic; uv has become a fast, increasingly common choice that handles installing and locking quickly.
- Rust: Cargo is built in and widely admired for being smooth.
- Other ecosystems: Go modules, Maven and Gradle for Java, Composer for PHP, and system managers like apt and Homebrew for software outside a single language.
How to use one safely
- Commit the manifest and the lockfile. Together they let anyone reproduce your exact dependency set.
- Do not commit the installed folder. Add it to your ignore file; the manager rebuilds it from the lockfile.
- Understand version ranges. Semantic versioning uses major, minor, and patch numbers; a major bump can break things, so review before allowing it.
- Audit for vulnerabilities. Run the built-in audit command periodically and update flagged packages.
- Update deliberately. Bump dependencies on purpose, run tests, and avoid letting everything drift to the newest version unchecked.
Common mistakes
- Committing node_modules or the equivalent. It bloats the repo and is unnecessary; the lockfile is the source of truth.
- Ignoring the lockfile. Without it, installs are not reproducible and bugs appear that depend on which version happened to install.
- Adding huge dependencies for tiny needs. Pulling in a large library to do one small thing inflates your project and your security surface.
What to skip
- Manually downloading libraries. Let the package manager and registry handle it so versions and dependencies stay consistent.
- Blindly running update-everything. Mass updates without testing are a common way to break a working project. Update with intent.
- Mixing two package managers in one project. Pick one per project to avoid conflicting lockfiles and confusing state.
FAQ
What is the difference between a package manager and a registry?
The package manager is the tool on your machine that installs and tracks dependencies. The registry is the central server it downloads packages from, such as the npm registry or PyPI.
Why should I commit the lockfile?
The lockfile records exact versions so everyone installs the same code. Without it, different machines can pull different versions and produce inconsistent, hard-to-debug behavior.
What is semantic versioning?
A convention where versions read as major.minor.patch. A patch is a bug fix, a minor adds features without breaking, and a major may break compatibility. Package managers use it to resolve compatible versions.
Do I commit the installed packages folder?
No. Add it to your ignore file. The package manager rebuilds it from the manifest and lockfile, so storing it in version control only bloats the repository.
Where to go next
See npm versus yarn compared, what a monorepo is and when to use one, and what an environment variable is.