| last_modified | 2026-06-12 |
|---|---|
| title | Add and remove dependencies |
| description | Manage project dependencies with deno add and deno remove: npm and JSR packages, version pinning, dev dependencies, and aliasing packages in your import map. |
| url | /examples/add_remove_dependencies_tutorial/ |
Deno manages dependencies through your project's deno.json import map, or
through package.json when you have one. The deno add and deno remove
commands edit those files for you, and deno install with a package argument
does the same.
Unprefixed package names are treated as npm packages. Use the jsr: prefix for
JSR packages:
$ deno add express jsr:@std/path
Add npm:[email protected]
Add jsr:@std/[email protected]deno install express is equivalent: it records the dependency the same way and
installs everything in one step.
Both end up in the imports map of deno.json, with a semver-compatible caret
range:
{
"imports": {
"@std/path": "jsr:@std/path@^1.1.5",
"express": "npm:express@^5.2.1"
}
}Import them by their bare name anywhere in the project:
import express from "express";
import { join } from "@std/path";To pin an exact version instead of a caret range, pass --save-exact. To
request a specific version or tag, spell it out:
deno add --save-exact npm:[email protected]
deno add npm:typescript@nextIf the project contains a package.json, npm packages are added to its
dependencies instead of deno.json, which is handy in projects shared with
Node.js tooling. You can force this with --package-json.
Dev dependencies only exist in the package.json world:
deno add --dev npm:typescript:::note
Without a package.json, the --dev flag has no effect: deno.json has a
single imports map, so the package is added as a regular import.
:::
The import map maps any name you like to any specifier. This installs a fork under the name of the original, so existing imports keep working:
{
"imports": {
"lodash": "npm:lodash-es@^4.17.21"
}
}Aliases are also the way to use two versions of one package side by side:
{
"imports": {
"preact": "npm:preact@^10.27.2",
"preact-canary": "npm:[email protected]"
}
}The import map only names your direct dependencies. To force a specific version
of a package somewhere deeper in the tree, use the overrides field in
package.json, the same way npm does:
{
"dependencies": {
"debug": "4.4.3"
},
"overrides": {
"ms": "2.1.2"
}
}deno install resolves ms to 2.1.2 everywhere it appears, and records that in
the lockfile. For overriding with a local copy of a package, or remapping your
own imports rather than the dependency tree, see
Overriding dependencies and
Re-map import paths.
deno remove deletes the entry by its import-map name (not the package name, if
they differ):
$ deno remove express
Removed expressThe lockfile keeps records of removed packages until you run deno install
again; see
the lockfile documentation
for how deno.lock tracks all of this.