Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>Package License ViewerNew to Visual Studio Code? Get it now.
Package License Viewer

Package License Viewer

otoneko1102

|
1 install
| (1) | Free
Shows the license of each dependency inline, dimmed at the end of the line in package.json and deno.json.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Package License Viewer

Shows the license of every dependency inline, dimmed at the end of the line.

// package.json
{
  "dependencies": {
    "lodash": "^4.17.21",        // MIT
    "@babel/core": "^7.0.0",     // MIT
    "left-pad": "1.3.0"          // WTFPL
  },
  "devDependencies": {
    "typescript": "^5.7.2"       // Apache-2.0
  }
}
// deno.json
{
  "imports": {
    "@std/fs": "jsr:@std/fs@^1.0.0",   // MIT
    "chalk": "npm:chalk@^5.3.0"        // MIT
  }
}

Hover an annotation to see the resolved version, where the information came from, and a link to the package homepage.

Manifest Sections read
package.json dependencies, devDependencies, peerDependencies, optionalDependencies, and any other *Dependencies section
deno.json, deno.jsonc, jsr.json, import_map.json imports — both jsr: and npm: specifiers

How a license is resolved

  1. The installed package, first. node_modules/<name>/package.json, walking up parent directories. Instant, works offline, and reflects the version that is actually installed.
  2. The lockfile. Gives the exact pinned version even when nothing is installed yet. package-lock.json carries the license itself, so npm projects can resolve with no network access at all.
  3. The registry. registry.npmjs.org for npm, jsr.io for JSR. Results are cached on disk for a week.

Specifiers that cannot be resolved — file:, link:, workspace:, git+…, user/repo, tarball URLs, https:// imports — are left un-annotated rather than marked unknown. npm: aliases are followed to their target. JSR packages inside package.json are recognized either way they show up — the npm-compatibility alias @jsr/scope__name, or the native jsr:<range> / jsr:@scope/name@<range> specifier pnpm ≥10.9 and Yarn ≥4.9 write directly — and routed to JSR automatically, since the npm-compatibility registry never publishes a license for them, installed or not.

The hover title links to the npmjs.org package page for dependencies that really are npm registry packages (following an npm: alias to its actual target), and to the matching JSR page for JSR packages — never to npmjs.org for those, since they aren't published there under their JSR or npm-compatibility name.

Package managers

Every layout below was verified by actually installing with that package manager.

Layout How it resolves
npm hoisted real directories node_modules
yarn classic hoisted real directories node_modules
bun hoisted real directories node_modules
pnpm node_modules/<name> symlinks into node_modules/.pnpm/… node_modules — reads follow the symlink, and pnpm links exactly the direct dependencies, which is what gets annotated
yarn berry (nodeLinker: node-modules) real directories node_modules
yarn berry (PnP) no node_modules at all yarn.lock for the pinned version, then the registry for its license

So no per-package-manager branching is needed for the common case — the only real gap is Yarn PnP, which the lockfile layer covers. The same layer also handles a freshly cloned repository where npm install has not run yet.

Lockfile formats understood: package-lock.json (v1/v2/v3, including workspaces), npm-shrinkwrap.json, pnpm-lock.yaml (v5/v6/v9), yarn.lock (classic and berry), and bun.lock. bun.lockb is binary and is skipped — bun installs into node_modules, so that path covers it.

Commands

Command Description
Package License Viewer: Refresh License Annotations Re-read node_modules and lockfiles, then redraw. Use after npm install.
Package License Viewer: Clear License Cache Drop everything cached from the registries.
Package License Viewer: Toggle Inline License Annotations Turn the annotations on or off.

Settings

Setting Default Description
packageLicenseViewer.enabled true Show inline license annotations.
packageLicenseViewer.format ${license} Annotation template. Placeholders: ${license}, ${version}, ${name}, ${source}.
packageLicenseViewer.showResolvedVersion false Append the resolved version, e.g. MIT · 4.17.21.
packageLicenseViewer.unknownText "" Text shown when the license is unknown. Empty means show nothing.
packageLicenseViewer.annotationColor editorCodeLens.foreground Theme color id, or a CSS color such as #88888899.
packageLicenseViewer.margin 0 0 0 1.5em CSS margin before the annotation.
packageLicenseViewer.cacheTtlHours 168 Lifetime of cached registry results. 0 disables the on-disk cache.
packageLicenseViewer.requestTimeoutMs 8000 Timeout of a single registry request.
packageLicenseViewer.maxConcurrentRequests 8 Parallel registry requests.
packageLicenseViewer.npm.enabled true Enable annotations for package.json.
packageLicenseViewer.npm.registry https://registry.npmjs.org Registry base URL.
packageLicenseViewer.npm.useRegistry true Allow registry lookups. Set to false to stay fully offline.
packageLicenseViewer.npm.useLockfiles true Read lockfiles for exact pinned versions.
packageLicenseViewer.npm.sections 4 standard sections Sections that are always annotated.
packageLicenseViewer.npm.autoDetectSections true Also annotate other top-level objects whose key ends with dependencies.
packageLicenseViewer.jsr.enabled true Enable annotations for Deno / import map manifests.
packageLicenseViewer.jsr.registry https://jsr.io JSR registry base URL.
packageLicenseViewer.jsr.apiUrl https://api.jsr.io JSR API base URL, where the license lives.

A note on JSR licenses

JSR only exposes a license for a version if the package declared one in its deno.json / jsr.json. Many packages have not, and for those the API returns null — the hover then says "the package declares no license on JSR". This is a gap in the published metadata, not in the lookup; nothing else in JSR's API carries the information (the npm-compatibility endpoint at npm.jsr.io does not include a license field either).

deno.lock is not read yet, so a jsr: range resolves against the registry rather than the version pinned in the lockfile.

Other languages

npm and JSR are covered today. Python (PyPI), Rust (crates.io) and Go are planned — the extension is built around a provider interface specifically so an ecosystem is one class away, without touching rendering, caching or scheduling. Every ecosystem is expected to link the hover title to its own registry page too, the same way npm and JSR already do. See CONTRIBUTING.md if you'd like to add one, or just want to see how it's structured.

Author

otoneko. https://github.com/otnc

License

MIT

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft