# Dependencies, JSR, and npm

## Add dependencies

```bash
deno install jsr:@std/assert
deno install npm:express
```

Since Deno 2.8, an unprefixed CLI package name defaults to npm, so `deno install express` equals `deno install npm:express`. Import specifiers still need `npm:` unless mapped by `imports` or `package.json`; JSR packages remain explicit as `jsr:` in the CLI.

The command updates `imports` in `deno.json`, allowing mapped names in code:

```ts
import { assertEquals } from "@std/assert";
import express from "express";
import { readFile } from "node:fs/promises";
```

## Four sources of project state

| Location | Responsibility |
| --- | --- |
| `deno.json(c)` | import mappings, tasks, workspace, and tool settings |
| `package.json` | npm scripts/dependencies and Node ecosystem metadata; may coexist |
| `deno.lock` | resolved versions and integrity; commit it |
| Deno cache / `node_modules` | local materialization, not the review source of truth |

CI should use the committed lockfile and fail on inconsistent resolution. Do not hide resolution conflicts by deleting it.

```bash
deno ci          # Deno 2.8+: require lockfile, wipe node_modules, frozen install
deno ci --prod   # skip package.json devDependencies
```

## Choose a source

- Preserve the repository's existing source and import conventions.
- Check JSR first for TypeScript-native libraries and the standard library.
- Use npm for Node ecosystem packages; spell built-ins with `node:`.
- URL imports can pin web modules, but team projects usually centralize them through `imports`.
- Deno 2.9 adds `deno list` for declared dependencies and `deno link` / `unlink` for local package links.

When resolution fails, use `deno info` to inspect the graph and cache before checking proxies, private registries, and certificates.

Official references: [Modules and dependencies](https://docs.deno.com/runtime/fundamentals/modules/) and [Packages](https://docs.deno.com/runtime/packages/).
