Skip to content

/commands/deno/deno-add-npm-package

deno add npm:package: add an npm or JSR dependency to a Deno project

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
tool
Deno
versions
Deno 2.x
os
any

deno add npm:express adds an npm package to a Deno project, and deno add jsr:@std/path adds a package from JSR. Deno writes the dependency to the imports map of deno.json (creating the file if needed), records the exact resolved version in deno.lock, and downloads the package, so code can then import it by its bare name: import express from "express".

Add a package

bash
export NO_COLOR=1
npx --yes deno@2 add npm:is-odd@3 2>&1 | grep -E "^(Created|Add)"
cat deno.json
cat > main.ts <<'EOF'
import isOdd from "is-odd";
console.log(isOdd(7));
EOF
npx --yes deno@2 run main.ts

Output

Created deno.json configuration file.
Add npm:is-odd@3.0.1
{
  "imports": {
    "is-odd": "npm:is-odd@^3.0.1"
  }
}
true

Deno resolved is-odd@3 to the newest 3.x release and stored a caret range (^3.0.1) in the import map, so later lock refreshes stay within 3.x. The example runs Deno through npx deno@2 so it needs only Node.js; with Deno installed the commands are deno add and deno run.

In a project with package.json

bash
export NO_COLOR=1
echo '{ "name": "app", "private": true }' > package.json
npx --yes deno@2 add npm:is-odd@3.0.1 2>&1 | grep -E "^(Created|Add)"
cat package.json
ls -d node_modules

Output

Add npm:is-odd@3.0.1
{
  "name": "app",
  "private": true,
  "dependencies": {
    "is-odd": "3.0.1"
  }
}
node_modules

When the folder has a package.json and no deno.json, Deno adds npm packages to its dependencies, like npm install, and installs them into node_modules. This keeps the project usable by Node.js tools too. With an exact version the entry is exact; with a range or no version Deno writes a caret range.

Variants

CommandWhat it does
deno add npm:expressLatest version from npm, saved as ^x.y.z
deno add npm:express@4Newest 4.x release
deno add jsr:@std/assertA package from the JSR registry
deno add jsr:@std/path npm:chalkSeveral packages in one command
deno add --dev npm:vitestdevDependencies in package.json; with deno.json the entry goes to imports as usual
deno add npm:@types/nodeScoped npm packages work the same way
deno remove npm:is-oddRemoves the entry from deno.json or package.json
deno installInstalls everything listed, for example after a fresh clone

Pitfalls

  • Missing prefix. Current Deno 2 releases accept a bare name (deno add is-odd was recorded as npm:is-odd), but older 2.x releases require the prefix, and a name can exist on both registries. Write npm: or jsr: to say which package you mean.
  • Imports without an entry. Importing a bare name that is not in the import map fails with Import "x" not a dependency; deno add is the fix.
  • Lock file conflicts. deno.lock pins the exact versions. Commit it, and run CI with --frozen-lockfile (for example deno install --frozen-lockfile) to fail when it would change.

How to confirm it worked

cat deno.json (or package.json) shows the new entry, deno.lock contains the resolved version, and deno run main.ts runs without asking for the package again. deno info main.ts prints the dependency graph of a file with the version that was used.

FAQ

Do I need deno add to use an npm package?

No. You can import npm:package@version directly in code. deno add puts the version in one place (the import map in deno.json or package.json) so every file can use the bare name and the version is updated in one line.

Does deno add create node_modules?

Only when the project uses a package.json, or when nodeModulesDir is set in deno.json. With a plain deno.json, npm packages are kept in the global Deno cache and no node_modules folder appears.

How do I upgrade a package added with deno add?

Run deno add again with the new version, or use deno outdated to list newer versions and deno outdated --update to bump them.

Sources