Packages and scripts

Add, remove, and update packages

Change project dependencies with Bun while keeping package.json and bun.lock synchronized.

Our notes API will accept JSON from clients, and we’ll validate it with Zod. Let’s add it to the project:

bun add zod

Bun installs the package, adds it to dependencies in package.json, and updates bun.lock. The output ends with a line like installed zod@4.1.3, so you always see which version you got.

Development tools belong in devDependencies. These are packages the application does not need at runtime, only while you work on it. We already installed TypeScript this way:

bun add --dev typescript

You can install a specific version when the project requires it:

bun add zod@4.1.0

Without a version, Bun picks the latest release and writes a caret range like ^4.1.3 into package.json.

Remove a package

Use the package name to remove it:

bun remove zod

Bun deletes the entry from package.json, updates the lockfile, and removes the installed files when nothing else depends on them. Three files change together, and that’s the point. You never end up with a package.json that lies about what’s installed.

Add Zod again before continuing:

bun add zod

Update dependencies

First, see what’s behind:

bun outdated

Bun prints a table with the current version, the newest version allowed by your range, and the latest version published. That table tells you how big each jump is before you make it.

Update every package within the ranges declared in package.json:

bun update

Update one package with:

bun update zod

Both commands respect your ranges. If package.json says ^4.1.0, you’ll get the newest 4.x, never 5.0.

bun update --latest is different. It ignores the ranges and jumps to the newest published version of each package, rewriting package.json along the way. That’s how a library moves from 4.x to 5.x in one command, and 5.x may have changed its API. Your code compiles against the old API, tests fail, and you’re reading a migration guide you didn’t plan to read today.

My advice is to update a small group at a time. Read the release notes, run the tests, and commit the matching package.json and bun.lock changes together. Small, boring updates are easy to revert. One giant update is not.

Lesson completed